import React, { useContext } from 'react'; import { Dimensions } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { AppearanceProvider } from 'react-native-appearance'; import { createStackNavigator } from '@react-navigation/stack'; import { Provider } from 'react-redux'; import { getTheme, initialTheme, newThemeState, subscribeTheme, unsubscribeTheme } from './utils/theme'; import UserPreferences from './lib/userPreferences'; import Navigation from './lib/ShareNavigation'; import store from './lib/createStore'; import { initStore } from './lib/auxStore'; import { defaultHeader, getActiveRouteName, navigationTheme, themedHeader } from './utils/navigation'; import RocketChat from './lib/rocketchat'; import { ThemeContext } from './theme'; import { localAuthenticate } from './utils/localAuthentication'; import { IThemePreference } from './definitions/ITheme'; import ScreenLockedView from './views/ScreenLockedView'; // Outside Stack import WithoutServersView from './views/WithoutServersView'; // Inside Stack import ShareListView from './views/ShareListView'; import ShareView from './views/ShareView'; import SelectServerView from './views/SelectServerView'; import { setCurrentScreen } from './utils/log'; import AuthLoadingView from './views/AuthLoadingView'; import { DimensionsContext } from './dimensions'; import debounce from './utils/debounce'; import { ShareInsideStackParamList, ShareOutsideStackParamList, ShareAppStackParamList } from './definitions/navigationTypes'; initStore(store); interface IDimensions { width: number; height: number; scale: number; fontScale: number; } interface IState { theme: string; themePreferences: IThemePreference; root: any; width: number; height: number; scale: number; fontScale: number; } const Inside = createStackNavigator(); const InsideStack = () => { const { theme } = useContext(ThemeContext); const screenOptions = { ...defaultHeader, ...themedHeader(theme) }; screenOptions.headerStyle = { ...screenOptions.headerStyle, height: 57 }; return ( ); }; const Outside = createStackNavigator(); const OutsideStack = () => { const { theme } = useContext(ThemeContext); return ( ); }; // App const Stack = createStackNavigator(); export const App = ({ root }: any) => ( <> {!root ? : null} {root === 'outside' ? : null} {root === 'inside' ? : null} ); class Root extends React.Component<{}, IState> { constructor(props: any) { super(props); const { width, height, scale, fontScale } = Dimensions.get('screen'); const theme = initialTheme(); this.state = { theme: getTheme(theme), themePreferences: theme, root: '', width, height, scale, fontScale }; this.init(); } componentWillUnmount(): void { RocketChat.closeShareExtension(); unsubscribeTheme(); } init = async () => { const currentServer = UserPreferences.getString(RocketChat.CURRENT_SERVER); if (currentServer) { await localAuthenticate(currentServer); this.setState({ root: 'inside' }); await RocketChat.shareExtensionInit(currentServer); } else { this.setState({ root: 'outside' }); } const state = Navigation.navigationRef.current?.getRootState(); const currentRouteName = getActiveRouteName(state); Navigation.routeNameRef.current = currentRouteName; setCurrentScreen(currentRouteName); }; setTheme = (newTheme = {}) => { // change theme state this.setState( prevState => newThemeState(prevState, newTheme as IThemePreference), () => { const { themePreferences } = this.state; // subscribe to Appearance changes subscribeTheme(themePreferences, this.setTheme); } ); }; // Dimensions update fires twice onDimensionsChange = debounce(({ window: { width, height, scale, fontScale } }: { window: IDimensions }) => { this.setDimensions({ width, height, scale, fontScale }); }); setDimensions = ({ width, height, scale, fontScale }: IDimensions) => { this.setState({ width, height, scale, fontScale }); }; render() { const { theme, root, width, height, scale, fontScale } = this.state; const navTheme = navigationTheme(theme); return ( { const previousRouteName = Navigation.routeNameRef.current; const currentRouteName = getActiveRouteName(state); if (previousRouteName !== currentRouteName) { setCurrentScreen(currentRouteName); } Navigation.routeNameRef.current = currentRouteName; }}> ); } } export default Root;