[IMPROVE] migrate some navigation files, our index/share and low level files
This commit is contained in:
parent
fdcfd3e0ee
commit
b6577de7c2
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { NavigationContainer } from '@react-navigation/native';
|
||||
import { createStackNavigator } from '@react-navigation/stack';
|
||||
import { connect } from 'react-redux';
|
||||
|
@ -35,7 +34,7 @@ const SetUsernameStack = () => (
|
|||
|
||||
// App
|
||||
const Stack = createStackNavigator();
|
||||
const App = React.memo(({ root, isMasterDetail }) => {
|
||||
const App = React.memo(({ root, isMasterDetail }: {root: string, isMasterDetail: boolean}) => {
|
||||
if (!root) {
|
||||
return null;
|
||||
}
|
||||
|
@ -100,15 +99,10 @@ const App = React.memo(({ root, isMasterDetail }) => {
|
|||
</NavigationContainer>
|
||||
);
|
||||
});
|
||||
const mapStateToProps = state => ({
|
||||
const mapStateToProps = (state: any) => ({
|
||||
root: state.app.root,
|
||||
isMasterDetail: state.app.isMasterDetail
|
||||
});
|
||||
|
||||
App.propTypes = {
|
||||
root: PropTypes.string,
|
||||
isMasterDetail: PropTypes.bool
|
||||
};
|
||||
|
||||
const AppContainer = connect(mapStateToProps)(App);
|
||||
export default AppContainer;
|
|
@ -2,10 +2,18 @@ import React from 'react';
|
|||
import { Dimensions } from 'react-native';
|
||||
import hoistNonReactStatics from 'hoist-non-react-statics';
|
||||
|
||||
export const DimensionsContext = React.createContext(Dimensions.get('window'));
|
||||
interface IDimensionsContextProps {
|
||||
width: number;
|
||||
height: number;
|
||||
scale: number;
|
||||
fontScale: number;
|
||||
setDimensions: ({ width, height, scale, fontScale }: { width: number; height: number; scale: number; fontScale: number; }) => void;
|
||||
}
|
||||
|
||||
export function withDimensions(Component) {
|
||||
const DimensionsComponent = props => (
|
||||
export const DimensionsContext = React.createContext<Partial<IDimensionsContextProps>>(Dimensions.get('window'));
|
||||
|
||||
export function withDimensions(Component: any) {
|
||||
const DimensionsComponent = (props: any) => (
|
||||
<DimensionsContext.Consumer>
|
||||
{contexts => <Component {...props} {...contexts} />}
|
||||
</DimensionsContext.Consumer>
|
||||
|
@ -18,7 +26,7 @@ export const useDimensions = () => React.useContext(DimensionsContext);
|
|||
|
||||
export const useOrientation = () => {
|
||||
const { width, height } = React.useContext(DimensionsContext);
|
||||
const isPortrait = height > width;
|
||||
const isPortrait = (height)! > (width)!;
|
||||
return {
|
||||
isPortrait,
|
||||
isLandscape: !isPortrait
|
|
@ -6,12 +6,7 @@ import { KeyCommandsEmitter } from 'react-native-keycommands';
|
|||
import RNScreens from 'react-native-screens';
|
||||
import { SafeAreaProvider, initialWindowMetrics } from 'react-native-safe-area-context';
|
||||
|
||||
import {
|
||||
defaultTheme,
|
||||
newThemeState,
|
||||
subscribeTheme,
|
||||
unsubscribeTheme
|
||||
} from './utils/theme';
|
||||
import { defaultTheme, newThemeState, subscribeTheme, unsubscribeTheme } from './utils/theme';
|
||||
import UserPreferences from './lib/userPreferences';
|
||||
import EventEmitter from './utils/events';
|
||||
import { appInit, appInitLocalSettings, setMasterDetail as setMasterDetailAction } from './actions/app';
|
||||
|
@ -24,9 +19,7 @@ import { ThemeContext } from './theme';
|
|||
import { DimensionsContext } from './dimensions';
|
||||
import RocketChat, { THEME_PREFERENCES_KEY } from './lib/rocketchat';
|
||||
import { MIN_WIDTH_MASTER_DETAIL_LAYOUT } from './constants/tablet';
|
||||
import {
|
||||
isTablet, supportSystemTheme
|
||||
} from './utils/deviceInfo';
|
||||
import { isTablet, supportSystemTheme } from './utils/deviceInfo';
|
||||
import { KEY_COMMAND } from './commands';
|
||||
import AppContainer from './AppContainer';
|
||||
import TwoFactor from './containers/TwoFactor';
|
||||
|
@ -40,7 +33,26 @@ import { isFDroidBuild } from './constants/environment';
|
|||
|
||||
RNScreens.enableScreens();
|
||||
|
||||
const parseDeepLinking = (url) => {
|
||||
type TDimensions = {
|
||||
width: number,
|
||||
height: number,
|
||||
scale: number,
|
||||
fontScale: number
|
||||
}
|
||||
interface IProps {}
|
||||
interface IState {
|
||||
theme: string,
|
||||
themePreferences: {
|
||||
currentTheme: 'automatic' | 'light',
|
||||
darkLevel: string
|
||||
},
|
||||
width: number;
|
||||
height: number;
|
||||
scale: number;
|
||||
fontScale: number;
|
||||
}
|
||||
|
||||
const parseDeepLinking = (url: string) => {
|
||||
if (url) {
|
||||
url = url.replace(/rocketchat:\/\/|https:\/\/go.rocket.chat\//, '');
|
||||
const regex = /^(room|auth|invite)\?/;
|
||||
|
@ -61,16 +73,17 @@ const parseDeepLinking = (url) => {
|
|||
return null;
|
||||
};
|
||||
|
||||
export default class Root extends React.Component {
|
||||
constructor(props) {
|
||||
export default class Root extends React.Component<IProps, IState> {
|
||||
private listenerTimeout!: NodeJS.Timeout;
|
||||
private onKeyCommands: any;
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
this.init();
|
||||
if (!isFDroidBuild) {
|
||||
this.initCrashReport();
|
||||
}
|
||||
const {
|
||||
width, height, scale, fontScale
|
||||
} = Dimensions.get('window');
|
||||
const { width, height, scale, fontScale } = Dimensions.get('window');
|
||||
this.state = {
|
||||
theme: defaultTheme(),
|
||||
themePreferences: {
|
||||
|
@ -111,7 +124,7 @@ export default class Root extends React.Component {
|
|||
}
|
||||
|
||||
init = async() => {
|
||||
UserPreferences.getMapAsync(THEME_PREFERENCES_KEY).then(this.setTheme);
|
||||
UserPreferences.getMapAsync(THEME_PREFERENCES_KEY).then(() => this.setTheme());
|
||||
store.dispatch(appInitLocalSettings());
|
||||
|
||||
// Open app from push notification
|
||||
|
@ -123,7 +136,7 @@ export default class Root extends React.Component {
|
|||
|
||||
// Open app from deep linking
|
||||
const deepLinking = await Linking.getInitialURL();
|
||||
const parsedDeepLinkingURL = parseDeepLinking(deepLinking);
|
||||
const parsedDeepLinkingURL = parseDeepLinking(deepLinking!);
|
||||
if (parsedDeepLinkingURL) {
|
||||
store.dispatch(deepLinkingOpen(parsedDeepLinkingURL));
|
||||
return;
|
||||
|
@ -133,14 +146,14 @@ export default class Root extends React.Component {
|
|||
store.dispatch(appInit());
|
||||
}
|
||||
|
||||
getMasterDetail = (width) => {
|
||||
getMasterDetail = (width: number) => {
|
||||
if (!isTablet) {
|
||||
return false;
|
||||
}
|
||||
return width > MIN_WIDTH_MASTER_DETAIL_LAYOUT;
|
||||
}
|
||||
|
||||
setMasterDetail = (width) => {
|
||||
setMasterDetail = (width: number) => {
|
||||
const isMasterDetail = this.getMasterDetail(width);
|
||||
store.dispatch(setMasterDetailAction(isMasterDetail));
|
||||
};
|
||||
|
@ -150,7 +163,7 @@ export default class Root extends React.Component {
|
|||
window: {
|
||||
width, height, scale, fontScale
|
||||
}
|
||||
}) => {
|
||||
}: {window: TDimensions}) => {
|
||||
this.setDimensions({
|
||||
width, height, scale, fontScale
|
||||
});
|
||||
|
@ -166,12 +179,8 @@ export default class Root extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
setDimensions = ({
|
||||
width, height, scale, fontScale
|
||||
}) => {
|
||||
this.setState({
|
||||
width, height, scale, fontScale
|
||||
});
|
||||
setDimensions = ({width, height, scale, fontScale}: TDimensions) => {
|
||||
this.setState({width, height, scale, fontScale});
|
||||
}
|
||||
|
||||
initTablet = () => {
|
||||
|
@ -179,7 +188,7 @@ export default class Root extends React.Component {
|
|||
this.setMasterDetail(width);
|
||||
this.onKeyCommands = KeyCommandsEmitter.addListener(
|
||||
'onKeyCommand',
|
||||
(command) => {
|
||||
(command: unknown) => {
|
||||
EventEmitter.emit(KEY_COMMAND, { event: command });
|
||||
}
|
||||
);
|
||||
|
@ -197,9 +206,7 @@ export default class Root extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
themePreferences, theme, width, height, scale, fontScale
|
||||
} = this.state;
|
||||
const { themePreferences, theme, width, height, scale, fontScale } = this.state;
|
||||
return (
|
||||
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
|
||||
<AppearanceProvider>
|
|
@ -1,25 +0,0 @@
|
|||
import * as React from 'react';
|
||||
import { CommonActions, StackActions } from '@react-navigation/native';
|
||||
|
||||
const navigationRef = React.createRef();
|
||||
const routeNameRef = React.createRef();
|
||||
|
||||
function navigate(name, params) {
|
||||
navigationRef.current?.navigate(name, params);
|
||||
}
|
||||
|
||||
function back() {
|
||||
navigationRef.current?.dispatch(CommonActions.goBack());
|
||||
}
|
||||
|
||||
function replace(name, params) {
|
||||
navigationRef.current?.dispatch(StackActions.replace(name, params));
|
||||
}
|
||||
|
||||
export default {
|
||||
navigationRef,
|
||||
routeNameRef,
|
||||
navigate,
|
||||
back,
|
||||
replace
|
||||
};
|
|
@ -0,0 +1,25 @@
|
|||
import * as React from 'react';
|
||||
import { CommonActions, StackActions, NavigationContainerRef } from '@react-navigation/native';
|
||||
|
||||
const navigationRef = React.createRef<NavigationContainerRef>();
|
||||
const routeNameRef: React.MutableRefObject<NavigationContainerRef | null> = React.createRef();
|
||||
|
||||
function navigate(name: string, params: any) {
|
||||
navigationRef.current?.navigate(name, params);
|
||||
}
|
||||
|
||||
function back() {
|
||||
navigationRef.current?.dispatch(CommonActions.goBack());
|
||||
}
|
||||
|
||||
function replace(name: string, params: any) {
|
||||
navigationRef.current?.dispatch(StackActions.replace(name, params));
|
||||
}
|
||||
|
||||
export default {
|
||||
navigationRef,
|
||||
routeNameRef,
|
||||
navigate,
|
||||
back,
|
||||
replace
|
||||
};
|
|
@ -1,9 +0,0 @@
|
|||
import { createRef } from 'react';
|
||||
|
||||
const navigationRef = createRef();
|
||||
const routeNameRef = createRef();
|
||||
|
||||
export default {
|
||||
navigationRef,
|
||||
routeNameRef
|
||||
};
|
|
@ -0,0 +1,11 @@
|
|||
import * as React from 'react';
|
||||
import { NavigationContainerRef } from '@react-navigation/native';
|
||||
|
||||
|
||||
const navigationRef = React.createRef<NavigationContainerRef>();
|
||||
const routeNameRef: React.MutableRefObject<NavigationContainerRef | null> = React.createRef();
|
||||
|
||||
export default {
|
||||
navigationRef,
|
||||
routeNameRef
|
||||
};
|
|
@ -1,24 +1,16 @@
|
|||
import React, { useContext } from 'react';
|
||||
import { Dimensions } 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';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import {
|
||||
defaultTheme,
|
||||
newThemeState,
|
||||
subscribeTheme,
|
||||
unsubscribeTheme
|
||||
} from './utils/theme';
|
||||
import { defaultTheme, newThemeState, subscribeTheme, unsubscribeTheme } from './utils/theme';
|
||||
import UserPreferences from './lib/userPreferences';
|
||||
import Navigation from './lib/ShareNavigation';
|
||||
import store from './lib/createStore';
|
||||
import { supportSystemTheme } from './utils/deviceInfo';
|
||||
import {
|
||||
defaultHeader, themedHeader, getActiveRouteName, navigationTheme
|
||||
} from './utils/navigation';
|
||||
import { defaultHeader, themedHeader, getActiveRouteName, navigationTheme } from './utils/navigation';
|
||||
import RocketChat, { THEME_PREFERENCES_KEY } from './lib/rocketchat';
|
||||
import { ThemeContext } from './theme';
|
||||
import { localAuthenticate } from './utils/localAuthentication';
|
||||
|
@ -36,6 +28,26 @@ import AuthLoadingView from './views/AuthLoadingView';
|
|||
import { DimensionsContext } from './dimensions';
|
||||
import debounce from './utils/debounce';
|
||||
|
||||
type TDimensions = {
|
||||
width: number,
|
||||
height: number,
|
||||
scale: number,
|
||||
fontScale: number
|
||||
}
|
||||
interface IProps {}
|
||||
interface IState {
|
||||
theme: string,
|
||||
themePreferences: {
|
||||
currentTheme: 'automatic' | 'light',
|
||||
darkLevel: string
|
||||
},
|
||||
root: any;
|
||||
width: number;
|
||||
height: number;
|
||||
scale: number;
|
||||
fontScale: number;
|
||||
}
|
||||
|
||||
const Inside = createStackNavigator();
|
||||
const InsideStack = () => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
@ -44,10 +56,7 @@ const InsideStack = () => {
|
|||
...defaultHeader,
|
||||
...themedHeader(theme)
|
||||
};
|
||||
screenOptions.headerStyle = {
|
||||
...screenOptions.headerStyle,
|
||||
height: 57
|
||||
};
|
||||
screenOptions.headerStyle = {...screenOptions.headerStyle, height: 57};
|
||||
|
||||
return (
|
||||
<Inside.Navigator screenOptions={screenOptions}>
|
||||
|
@ -85,7 +94,7 @@ const OutsideStack = () => {
|
|||
|
||||
// App
|
||||
const Stack = createStackNavigator();
|
||||
export const App = ({ root }) => (
|
||||
export const App = ({ root }: any) => (
|
||||
<Stack.Navigator screenOptions={{ headerShown: false, animationEnabled: false }}>
|
||||
<>
|
||||
{!root ? (
|
||||
|
@ -110,16 +119,10 @@ export const App = ({ root }) => (
|
|||
</Stack.Navigator>
|
||||
);
|
||||
|
||||
App.propTypes = {
|
||||
root: PropTypes.string
|
||||
};
|
||||
|
||||
class Root extends React.Component {
|
||||
constructor(props) {
|
||||
class Root extends React.Component<IProps, IState> {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
const {
|
||||
width, height, scale, fontScale
|
||||
} = Dimensions.get('screen');
|
||||
const { width, height, scale, fontScale } = Dimensions.get('screen');
|
||||
this.state = {
|
||||
theme: defaultTheme(),
|
||||
themePreferences: {
|
||||
|
@ -141,7 +144,7 @@ class Root extends React.Component {
|
|||
}
|
||||
|
||||
init = async() => {
|
||||
UserPreferences.getMapAsync(THEME_PREFERENCES_KEY).then(this.setTheme);
|
||||
UserPreferences.getMapAsync(THEME_PREFERENCES_KEY).then(() => this.setTheme());
|
||||
|
||||
const currentServer = await UserPreferences.getStringAsync(RocketChat.CURRENT_SERVER);
|
||||
|
||||
|
@ -169,29 +172,18 @@ class Root extends React.Component {
|
|||
}
|
||||
|
||||
// Dimensions update fires twice
|
||||
onDimensionsChange = debounce(({
|
||||
window: {
|
||||
width, height, scale, fontScale
|
||||
}
|
||||
}) => {
|
||||
this.setDimensions({
|
||||
width, height, scale, fontScale
|
||||
});
|
||||
this.setMasterDetail(width);
|
||||
onDimensionsChange = debounce(({window: { width, height, scale, fontScale}}: {window: TDimensions}) => {
|
||||
this.setDimensions({ width, height, scale, fontScale });
|
||||
})
|
||||
|
||||
setDimensions = ({
|
||||
width, height, scale, fontScale
|
||||
}) => {
|
||||
setDimensions = ({ width, height, scale, fontScale }: TDimensions) => {
|
||||
this.setState({
|
||||
width, height, scale, fontScale
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
theme, root, width, height, scale, fontScale
|
||||
} = this.state;
|
||||
const { theme, root, width, height, scale, fontScale } = this.state;
|
||||
const navTheme = navigationTheme(theme);
|
||||
return (
|
||||
<AppearanceProvider>
|
16
app/theme.js
16
app/theme.js
|
@ -1,16 +0,0 @@
|
|||
import React from 'react';
|
||||
import hoistNonReactStatics from 'hoist-non-react-statics';
|
||||
|
||||
export const ThemeContext = React.createContext({ theme: 'light' });
|
||||
|
||||
export function withTheme(Component) {
|
||||
const ThemedComponent = props => (
|
||||
<ThemeContext.Consumer>
|
||||
{contexts => <Component {...props} {...contexts} />}
|
||||
</ThemeContext.Consumer>
|
||||
);
|
||||
hoistNonReactStatics(ThemedComponent, Component);
|
||||
return ThemedComponent;
|
||||
}
|
||||
|
||||
export const useTheme = () => React.useContext(ThemeContext);
|
|
@ -0,0 +1,25 @@
|
|||
import React from 'react';
|
||||
import hoistNonReactStatics from 'hoist-non-react-statics';
|
||||
|
||||
interface IThemeContextProps {
|
||||
theme: string,
|
||||
themePreferences: {
|
||||
currentTheme: 'automatic' | 'light',
|
||||
darkLevel: string
|
||||
},
|
||||
setTheme: (newTheme?: {}) => void;
|
||||
}
|
||||
|
||||
export const ThemeContext = React.createContext<Partial<IThemeContextProps>>({ theme: 'light' });
|
||||
|
||||
export function withTheme(Component: any) {
|
||||
const ThemedComponent = (props: any) => (
|
||||
<ThemeContext.Consumer>
|
||||
{contexts => <Component {...props} {...contexts} />}
|
||||
</ThemeContext.Consumer>
|
||||
);
|
||||
hoistNonReactStatics(ThemedComponent, Component);
|
||||
return ThemedComponent;
|
||||
}
|
||||
|
||||
export const useTheme = () => React.useContext(ThemeContext);
|
|
@ -16,13 +16,13 @@ export const cardStyle = {
|
|||
backgroundColor: 'rgba(0,0,0,0)'
|
||||
};
|
||||
|
||||
export const borderBottom = theme => ({
|
||||
export const borderBottom: any = (theme: any) => ({
|
||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||
borderBottomColor: themes[theme].headerBorder,
|
||||
elevation: 0
|
||||
});
|
||||
|
||||
export const themedHeader = theme => ({
|
||||
export const themedHeader = (theme: any) => ({
|
||||
headerStyle: {
|
||||
...borderBottom(theme),
|
||||
backgroundColor: themes[theme].headerBackground
|
||||
|
@ -31,7 +31,7 @@ export const themedHeader = theme => ({
|
|||
headerTitleStyle: { color: themes[theme].headerTitleColor }
|
||||
});
|
||||
|
||||
export const navigationTheme = (theme) => {
|
||||
export const navigationTheme = (theme: any) => {
|
||||
const defaultNavTheme = theme === 'light' ? DefaultTheme : DarkTheme;
|
||||
|
||||
return {
|
||||
|
@ -45,7 +45,7 @@ export const navigationTheme = (theme) => {
|
|||
};
|
||||
|
||||
// Gets the current screen from navigation state
|
||||
export const getActiveRoute = (state) => {
|
||||
export const getActiveRoute: any = (state: any) => {
|
||||
const route = state?.routes[state?.index];
|
||||
|
||||
if (route?.state) {
|
||||
|
@ -56,4 +56,4 @@ export const getActiveRoute = (state) => {
|
|||
return route;
|
||||
};
|
||||
|
||||
export const getActiveRouteName = state => getActiveRoute(state)?.name;
|
||||
export const getActiveRouteName = (state: any) => getActiveRoute(state)?.name;
|
|
@ -1,8 +1,5 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
StyleSheet, View, Text
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import { StyleSheet, View, Text } from 'react-native';
|
||||
import ShareExtension from 'rn-extensions-share';
|
||||
|
||||
import * as HeaderButton from '../containers/HeaderButton';
|
||||
|
@ -29,7 +26,7 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
class WithoutServerView extends React.Component {
|
||||
class WithoutServerView extends React.Component<any, any> {
|
||||
static navigationOptions = () => ({
|
||||
title: 'Rocket.Chat',
|
||||
headerLeft: () => (
|
||||
|
@ -40,10 +37,6 @@ class WithoutServerView extends React.Component {
|
|||
)
|
||||
})
|
||||
|
||||
static propTypes = {
|
||||
theme: PropTypes.string
|
||||
}
|
||||
|
||||
render() {
|
||||
const { theme } = this.props;
|
||||
return (
|
Loading…
Reference in New Issue