[IMPROVE] migrate some navigation files, our index/share and low level files

This commit is contained in:
AlexAlexandre 2021-07-15 10:54:47 -03:00
parent fdcfd3e0ee
commit b6577de7c2
13 changed files with 151 additions and 146 deletions

View File

@ -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;

View File

@ -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

View File

@ -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>

View File

@ -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
};

25
app/lib/Navigation.ts Normal file
View File

@ -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
};

View File

@ -1,9 +0,0 @@
import { createRef } from 'react';
const navigationRef = createRef();
const routeNameRef = createRef();
export default {
navigationRef,
routeNameRef
};

View File

@ -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
};

View File

@ -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>

View File

@ -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);

25
app/theme.tsx Normal file
View File

@ -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);

View File

@ -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;

View File

@ -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 (