diff --git a/app/index.js b/app/index.js index 694d20beb..de6ddb957 100644 --- a/app/index.js +++ b/app/index.js @@ -30,6 +30,9 @@ import { KEY_COMMAND } from './commands'; import Tablet, { initTabletNav } from './tablet'; import { SplitContext } from './split'; import AppContainer from './AppContainer'; +import TwoFactor from './containers/TwoFactor'; +import ScreenLockedView from './views/ScreenLockedView'; +import ChangePasscodeView from './views/ChangePasscodeView'; RNScreens.enableScreens(); @@ -188,6 +191,9 @@ export default class Root extends React.Component { }} > {content} + + + diff --git a/app/lib/ShareNavigation.js b/app/lib/ShareNavigation.js index 35abac7d9..bc2361611 100644 --- a/app/lib/ShareNavigation.js +++ b/app/lib/ShareNavigation.js @@ -1,21 +1,12 @@ -import { NavigationActions } from '@react-navigation/native'; +import * as React from 'react'; -let _shareNavigator; +const navigationRef = React.createRef(); -function setTopLevelNavigator(navigatorRef) { - _shareNavigator = navigatorRef; -} - -function navigate(routeName, params) { - _shareNavigator.dispatch( - NavigationActions.navigate({ - routeName, - params - }) - ); +function navigate(name, params) { + navigationRef.current?.navigate(name, params); } export default { - navigate, - setTopLevelNavigator + navigationRef, + navigate }; diff --git a/app/share.js b/app/share.js index 90dd5a9e0..5cc2b40c9 100644 --- a/app/share.js +++ b/app/share.js @@ -1,5 +1,6 @@ import React, { useState, useContext } from 'react'; import { View } from 'react-native'; +import PropTypes from 'prop-types'; import { NavigationContainer } from '@react-navigation/native'; import { AppearanceProvider } from 'react-native-appearance'; import { createStackNavigator } from '@react-navigation/stack'; @@ -14,14 +15,12 @@ import { } from './utils/theme'; import Navigation from './lib/ShareNavigation'; import store from './lib/createStore'; -import sharedStyles from './views/Styles'; -import { isNotch, isIOS, supportSystemTheme } from './utils/deviceInfo'; +import { isIOS, supportSystemTheme } from './utils/deviceInfo'; import { defaultHeader, onNavigationStateChange, themedHeader } from './utils/navigation'; import RocketChat, { THEME_PREFERENCES_KEY } from './lib/rocketchat'; import { ThemeContext } from './theme'; // Outside Stack -import AuthLoadingView from './views/AuthLoadingView'; import WithoutServersView from './views/WithoutServersView'; // Inside Stack @@ -33,17 +32,25 @@ const Inside = createStackNavigator(); const InsideStack = () => { const { theme } = useContext(ThemeContext); + const screenOptions = { + ...defaultHeader, + ...themedHeader(theme) + }; + screenOptions.headerStyle = { + ...screenOptions.headerStyle, + // TODO: fix on multiple files PR :) + height: 57 + }; + return ( - + ShareListView.navigationOptions({ ...props, theme })} /> { ); }; -const AuthContext = React.createContext(); - // App const Stack = createStackNavigator(); -export const App = () => { - const [loading] = useState(false); +export const App = ({ root }) => { + if (!root) { + return null; + } return ( - - - {loading ? ( + + <> + {root === 'outside' ? ( - ) : ( - <> - - - - )} - - + ) : null} + {root === 'inside' ? ( + + ) : null} + + ); }; +App.propTypes = { + root: PropTypes.string +}; + class Root extends React.Component { constructor(props) { super(props); this.state = { - isLandscape: false, theme: defaultTheme(), themePreferences: { currentTheme: supportSystemTheme() ? 'automatic' : 'light', darkLevel: 'dark' - } + }, + root: '' }; this.init(); } @@ -129,10 +135,10 @@ class Root extends React.Component { const token = await RNUserDefaults.get(RocketChat.TOKEN_KEY); if (currentServer && token) { - await Navigation.navigate('InsideStack'); + this.setState({ root: 'inside' }); await RocketChat.shareExtensionInit(currentServer); } else { - await Navigation.navigate('OutsideStack'); + this.setState({ root: 'outside' }); } } @@ -145,32 +151,20 @@ class Root extends React.Component { }); } - handleLayout = (event) => { - const { width, height } = event.nativeEvent.layout; - this.setState({ isLandscape: width > height }); - } - render() { - const { isLandscape, theme } = this.state; + const { theme, root } = this.state; return ( - - - - { - Navigation.setTopLevelNavigator(navigatorRef); - }} - onNavigationStateChange={onNavigationStateChange} - > - - - - - + + + + + + + ); } diff --git a/app/utils/navigation.js b/app/utils/navigation.js index f3946e33c..c31fbb25c 100644 --- a/app/utils/navigation.js +++ b/app/utils/navigation.js @@ -3,7 +3,6 @@ import { TransitionPresets } from '@react-navigation/stack'; import { analytics, leaveBreadcrumb } from './log'; import { themes } from '../constants/colors'; -import { isIOS } from './deviceInfo'; export const defaultHeader = { headerBackTitleVisible: false, diff --git a/app/views/SelectServerView.js b/app/views/SelectServerView.js index 56d960b55..b8767261b 100644 --- a/app/views/SelectServerView.js +++ b/app/views/SelectServerView.js @@ -36,14 +36,14 @@ class SelectServerView extends React.Component { static propTypes = { server: PropTypes.string, - navigation: PropTypes.object, + route: PropTypes.object, theme: PropTypes.string } constructor(props) { super(props); - const { navigation } = this.props; - const servers = navigation.getParam('servers', []); + const { route } = this.props; + const servers = route.params?.servers ?? []; const filteredServers = servers.filter(server => server.roomsUpdatedAt); this.state = { servers: filteredServers diff --git a/app/views/ShareListView/index.js b/app/views/ShareListView/index.js index 1c6529baa..eb496d982 100644 --- a/app/views/ShareListView/index.js +++ b/app/views/ShareListView/index.js @@ -12,7 +12,7 @@ import { Q } from '@nozbe/watermelondb'; import Navigation from '../../lib/ShareNavigation'; import database from '../../lib/database'; -import { isIOS, isAndroid } from '../../utils/deviceInfo'; +import { isIOS } from '../../utils/deviceInfo'; import I18n from '../../i18n'; import { CustomIcon } from '../../lib/Icons'; import log from '../../utils/log'; @@ -35,53 +35,6 @@ const getItemLayout = (data, index) => ({ length: ROW_HEIGHT, offset: ROW_HEIGHT const keyExtractor = item => item.rid; class ShareListView extends React.Component { - static navigationOptions = ({ route, theme }) => { - const searching = route.params?.searching; - const initSearch = route.params?.initSearch ?? (() => {}); - const cancelSearch = route.params?.cancelSearch ?? (() => {}); - const search = route.params?.search ?? (() => {}); - - if (isIOS) { - return { - headerStyle: { backgroundColor: themes[theme].headerBackground }, - headerTitle: () => ( - - ) - }; - } - - return { - headerLeft: () => (searching - ? ( - - - - ) - : ( - - )), - headerTitle: () => , - headerRight: () => ( - searching - ? null - : ( - - {isAndroid ? : null} - - ) - ) - }; - } - static propTypes = { navigation: PropTypes.object, server: PropTypes.string, @@ -107,18 +60,13 @@ class ShareListView extends React.Component { loading: true, serverInfo: null }; + this.setHeader(); this.didFocusListener = props.navigation.addListener('didFocus', () => BackHandler.addEventListener('hardwareBackPress', this.handleBackPress)); this.willBlurListener = props.navigation.addListener('willBlur', () => BackHandler.addEventListener('hardwareBackPress', this.handleBackPress)); } componentDidMount() { - const { navigation, server } = this.props; - navigation.setParams({ - initSearch: this.initSearch, - cancelSearch: this.cancelSearch, - search: this.search - }); - + const { server } = this.props; setTimeout(async() => { try { const { value, type } = await ShareExtension.data(); @@ -181,6 +129,51 @@ class ShareListView extends React.Component { return false; } + setHeader = () => { + const { searching } = this.state; + const { navigation, theme } = this.props; + + if (isIOS) { + navigation.setOptions({ + header: () => ( + + ) + }); + return; + } + + navigation.setOptions({ + headerLeft: () => (searching + ? ( + + + + ) + : ( + + )), + headerTitle: () => , + headerRight: () => ( + searching + ? null + : ( + + + + ) + ) + }); + } + // eslint-disable-next-line react/sort-comp internalSetState = (...args) => { const { navigation } = this.props; @@ -259,15 +252,11 @@ class ShareListView extends React.Component { initSearch = () => { const { chats } = this.state; - const { navigation } = this.props; - this.setState({ searching: true, searchResults: chats }); - navigation.setParams({ searching: true }); + this.setState({ searching: true, searchResults: chats }, () => this.setHeader()); } cancelSearch = () => { - const { navigation } = this.props; - this.internalSetState({ searching: false, searchResults: [], searchText: '' }); - navigation.setParams({ searching: false }); + this.internalSetState({ searching: false, searchResults: [], searchText: '' }, () => this.setHeader()); Keyboard.dismiss(); } diff --git a/app/views/ShareView/index.js b/app/views/ShareView/index.js index c803572c7..0d627360b 100644 --- a/app/views/ShareView/index.js +++ b/app/views/ShareView/index.js @@ -18,29 +18,9 @@ import { isReadOnly } from '../../utils/isReadOnly'; import { withTheme } from '../../theme'; class ShareView extends React.Component { - static navigationOptions = ({ route }) => { - const canSend = route.params?.canSend ?? true; - - return ({ - title: I18n.t('Share'), - headerRight: - () => (canSend - ? ( - - - - ) - : null) - }); - } - static propTypes = { navigation: PropTypes.object, + route: PropTypes.object, theme: PropTypes.string, user: PropTypes.shape({ id: PropTypes.string.isRequired, @@ -52,13 +32,13 @@ class ShareView extends React.Component { constructor(props) { super(props); - const { navigation } = this.props; - const rid = navigation.getParam('rid', ''); - const name = navigation.getParam('name', ''); - const value = navigation.getParam('value', ''); - const isMedia = navigation.getParam('isMedia', false); - const fileInfo = navigation.getParam('fileInfo', {}); - const room = navigation.getParam('room', { rid }); + const { route } = this.props; + const rid = route.params?.rid; + const name = route.params?.name; + const value = route.params?.value; + const isMedia = route.params?.isMedia ?? false; + const fileInfo = route.params?.fileInfo ?? {}; + const room = route.params?.room ?? { rid }; this.state = { rid, @@ -72,30 +52,49 @@ class ShareView extends React.Component { file: { name: fileInfo ? fileInfo.name : '', description: '' - } + }, + canSend: false }; this.setReadOnly(); + this.setHeader(); } - componentDidMount() { + setHeader = () => { + const { canSend } = this.state; const { navigation } = this.props; - navigation.setParams({ sendMessage: this._sendMessage }); + + navigation.setOptions({ + title: I18n.t('Share'), + headerRight: + () => (canSend + ? ( + + + + ) + : null) + }); } setReadOnly = async() => { const { room } = this.state; - const { navigation, user } = this.props; + const { user } = this.props; const { username } = user; const readOnly = await isReadOnly(room, { username }); - this.setState({ readOnly }); - navigation.setParams({ canSend: !(readOnly || isBlocked(room)) }); + this.setState({ readOnly, canSend: !(readOnly || isBlocked(room)) }); + this.setHeader(); } bytesToSize = bytes => `${ (bytes / 1048576).toFixed(2) }MB`; - _sendMessage = async() => { + sendMessage = async() => { const { isMedia, loading } = this.state; if (loading) { return; diff --git a/app/views/WithoutServersView.js b/app/views/WithoutServersView.js index dd866ace8..e5756ea79 100644 --- a/app/views/WithoutServersView.js +++ b/app/views/WithoutServersView.js @@ -31,6 +31,7 @@ const styles = StyleSheet.create({ class WithoutServerView extends React.Component { static navigationOptions = { + title: 'Rocket.Chat', headerLeft: () => ( require('./app/index.js').default); -// AppRegistry.registerComponent(shareName, () => require('./app/share.js').default); +AppRegistry.registerComponent(shareName, () => require('./app/share.js').default); // For storybook, comment everything above and uncomment below // import './storybook';