Compare commits

...

11 Commits

Author SHA1 Message Date
Reinaldo Neto 8b2046623a
Merge branch 'develop' into chore.hooks-app-index 2023-02-27 18:03:14 -03:00
Reinaldo Neto 1c5561255f minor tweak dimensionsChange and setNewTheme 2022-08-24 16:30:04 -03:00
Reinaldo Neto 80dc211911 tweaks 2022-08-24 16:10:23 -03:00
Reinaldo Neto 54fa594244 Merge branch 'develop' into chore.hooks-app-index 2022-08-23 23:54:55 -03:00
Reinaldo Neto 5cd6dfdc1d minor tweak 2022-08-10 16:23:18 -03:00
Reinaldo Neto 6415e88407 Merge develop 2022-08-10 11:15:50 -03:00
Reinaldo Neto b5ef8c880c added useCallback and refactor unstable 2022-08-02 11:36:02 -03:00
Reinaldo Neto b195b3ea07 completed and tested the keycommand 2022-08-01 22:43:27 -03:00
Reinaldo Neto d00dd897cf fix the multiple re-renders 2022-08-01 18:11:32 -03:00
Reinaldo Neto dcf1bc8a51 fix setTheme at share 2022-07-30 12:20:30 -03:00
Reinaldo Neto c18960efb7 Chore: Migrate App/index.tsx to hooks 2022-07-29 01:19:44 -03:00
3 changed files with 106 additions and 146 deletions

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { useCallback, useEffect, useRef, useState } from 'react';
import { Dimensions, Linking } from 'react-native'; import { Dimensions, Linking } from 'react-native';
import { KeyCommandsEmitter } from 'react-native-keycommands'; import { KeyCommandsEmitter } from 'react-native-keycommands';
import { initialWindowMetrics, SafeAreaProvider } from 'react-native-safe-area-context'; import { initialWindowMetrics, SafeAreaProvider } from 'react-native-safe-area-context';
@ -24,13 +24,13 @@ import parseQuery from './lib/methods/helpers/parseQuery';
import { initializePushNotifications, onNotification } from './lib/notifications'; import { initializePushNotifications, onNotification } from './lib/notifications';
import store from './lib/store'; import store from './lib/store';
import { initStore } from './lib/store/auxStore'; import { initStore } from './lib/store/auxStore';
import { ThemeContext, TSupportedThemes } from './theme'; import { ThemeContext } from './theme';
import { debounce, isTablet } from './lib/methods/helpers'; import { debounce, isTablet } from './lib/methods/helpers';
import EventEmitter from './lib/methods/helpers/events'; import EventEmitter from './lib/methods/helpers/events';
import { toggleAnalyticsEventsReport, toggleCrashErrorsReport } from './lib/methods/helpers/log'; import { toggleAnalyticsEventsReport, toggleCrashErrorsReport } from './lib/methods/helpers/log';
import { import {
getTheme, getTheme,
initialTheme, initialTheme as getInitialTheme,
newThemeState, newThemeState,
setNativeTheme, setNativeTheme,
subscribeTheme, subscribeTheme,
@ -49,16 +49,7 @@ interface IDimensions {
fontScale: number; fontScale: number;
} }
interface IState { const parseDeepLinking = (url: string | null) => {
theme: TSupportedThemes;
themePreferences: IThemePreference;
width: number;
height: number;
scale: number;
fontScale: number;
}
const parseDeepLinking = (url: string) => {
if (url) { if (url) {
url = url.replace(/rocketchat:\/\/|https:\/\/go.rocket.chat\//, ''); url = url.replace(/rocketchat:\/\/|https:\/\/go.rocket.chat\//, '');
const regex = /^(room|auth|invite)\?/; const regex = /^(room|auth|invite)\?/;
@ -81,35 +72,54 @@ const parseDeepLinking = (url: string) => {
return null; return null;
}; };
export default class Root extends React.Component<{}, IState> { const setMasterDetail = (width: number) => {
private listenerTimeout!: any; const isMasterDetail = getMasterDetail(width);
store.dispatch(setMasterDetailAction(isMasterDetail));
};
private onKeyCommands: any; const getMasterDetail = (width: number) => {
if (!isTablet) {
return false;
}
return width > MIN_WIDTH_MASTER_DETAIL_LAYOUT;
};
constructor(props: any) { const { width: widthWindow, height: heightWindow, scale: scaleWindow, fontScale: fontScaleWindow } = Dimensions.get('window');
super(props); const initialThemePreference = getInitialTheme();
this.init(); const initialTheme = getTheme(initialThemePreference);
const Root = () => {
const [theme, setTheme] = useState(initialTheme);
const [themePreferences, setThemePreferences] = useState(initialThemePreference);
const [dimensions, setDimensions] = useState<IDimensions>({
width: widthWindow,
height: heightWindow,
scale: scaleWindow,
fontScale: fontScaleWindow
});
const listenerTimeout = useRef<ReturnType<typeof setTimeout>>();
const onKeyCommands = useRef<any>();
useEffect(() => {
init();
if (!isFDroidBuild) { if (!isFDroidBuild) {
this.initCrashReport(); getAllowCrashReport().then(allowCrashReport => {
toggleCrashErrorsReport(allowCrashReport);
});
getAllowAnalyticsEvents().then(allowAnalyticsEvents => {
toggleAnalyticsEventsReport(allowAnalyticsEvents);
});
} }
const { width, height, scale, fontScale } = Dimensions.get('window');
const theme = initialTheme();
this.state = {
theme: getTheme(theme),
themePreferences: theme,
width,
height,
scale,
fontScale
};
if (isTablet) { if (isTablet) {
this.initTablet(); setMasterDetail(widthWindow);
} onKeyCommands.current = KeyCommandsEmitter.addListener('onKeyCommand', (command: ICommand) => {
setNativeTheme(theme); EventEmitter.emit(KEY_COMMAND, { event: command });
});
} }
setNativeTheme(initialThemePreference);
componentDidMount() { listenerTimeout.current = setTimeout(() => {
this.listenerTimeout = setTimeout(() => {
Linking.addEventListener('url', ({ url }) => { Linking.addEventListener('url', ({ url }) => {
const parsedDeepLinkingURL = parseDeepLinking(url); const parsedDeepLinkingURL = parseDeepLinking(url);
if (parsedDeepLinkingURL) { if (parsedDeepLinkingURL) {
@ -117,21 +127,21 @@ export default class Root extends React.Component<{}, IState> {
} }
}); });
}, 5000); }, 5000);
Dimensions.addEventListener('change', this.onDimensionsChange); const dimensionSubscription = Dimensions.addEventListener('change', onDimensionsChange);
}
componentWillUnmount() { return () => {
clearTimeout(this.listenerTimeout); clearTimeout(listenerTimeout.current as ReturnType<typeof setTimeout>);
Dimensions.removeEventListener('change', this.onDimensionsChange); dimensionSubscription.remove();
unsubscribeTheme(); unsubscribeTheme();
if (this.onKeyCommands && this.onKeyCommands.remove) { if (onKeyCommands?.current?.remove) {
this.onKeyCommands.remove(); onKeyCommands.current.remove?.();
}
} }
};
}, []);
init = async () => { const init = useCallback(async () => {
store.dispatch(appInitLocalSettings()); store.dispatch(appInitLocalSettings());
// Open app from push notification // Open app from push notification
@ -143,7 +153,7 @@ export default class Root extends React.Component<{}, IState> {
// Open app from deep linking // Open app from deep linking
const deepLinking = await Linking.getInitialURL(); const deepLinking = await Linking.getInitialURL();
const parsedDeepLinkingURL = parseDeepLinking(deepLinking!); const parsedDeepLinkingURL = parseDeepLinking(deepLinking);
if (parsedDeepLinkingURL) { if (parsedDeepLinkingURL) {
store.dispatch(deepLinkingOpen(parsedDeepLinkingURL)); store.dispatch(deepLinkingOpen(parsedDeepLinkingURL));
return; return;
@ -151,87 +161,36 @@ export default class Root extends React.Component<{}, IState> {
// Open app from app icon // Open app from app icon
store.dispatch(appInit()); store.dispatch(appInit());
}; }, []);
getMasterDetail = (width: number) => {
if (!isTablet) {
return false;
}
return width > MIN_WIDTH_MASTER_DETAIL_LAYOUT;
};
setMasterDetail = (width: number) => {
const isMasterDetail = this.getMasterDetail(width);
store.dispatch(setMasterDetailAction(isMasterDetail));
};
// Dimensions update fires twice // Dimensions update fires twice
onDimensionsChange = debounce(({ window: { width, height, scale, fontScale } }: { window: IDimensions }) => { const onDimensionsChange = debounce(({ window }: { window: IDimensions }) => {
this.setDimensions({ setDimensions(window);
width, setMasterDetail(window.width);
height,
scale,
fontScale
});
this.setMasterDetail(width);
}); });
setTheme = (newTheme = {}) => { const setNewTheme = (newThemePreference?: IThemePreference) => {
// change theme state const { theme: newTheme, themePreferences: newThemePreferences } = newThemeState(themePreferences, newThemePreference);
this.setState( setThemePreferences(newThemePreferences);
prevState => newThemeState(prevState, newTheme as IThemePreference), setTheme(newTheme);
() => { subscribeTheme(themePreferences, setNewTheme);
const { themePreferences } = this.state;
// subscribe to Appearance changes
subscribeTheme(themePreferences, this.setTheme);
}
);
}; };
setDimensions = ({ width, height, scale, fontScale }: IDimensions) => {
this.setState({ width, height, scale, fontScale });
};
initTablet = () => {
const { width } = this.state;
this.setMasterDetail(width);
this.onKeyCommands = KeyCommandsEmitter.addListener('onKeyCommand', (command: ICommand) => {
EventEmitter.emit(KEY_COMMAND, { event: command });
});
};
initCrashReport = () => {
getAllowCrashReport().then(allowCrashReport => {
toggleCrashErrorsReport(allowCrashReport);
});
getAllowAnalyticsEvents().then(allowAnalyticsEvents => {
toggleAnalyticsEventsReport(allowAnalyticsEvents);
});
};
render() {
const { themePreferences, theme, width, height, scale, fontScale } = this.state;
return ( return (
<SafeAreaProvider <SafeAreaProvider initialMetrics={initialWindowMetrics} style={{ backgroundColor: themes[theme].backgroundColor }}>
initialMetrics={initialWindowMetrics}
style={{ backgroundColor: themes[this.state.theme].backgroundColor }}
>
<Provider store={store}> <Provider store={store}>
<ThemeContext.Provider <ThemeContext.Provider
value={{ value={{
theme, theme,
themePreferences, themePreferences,
setTheme: this.setTheme, setTheme: setNewTheme,
colors: colors[theme] colors: colors[theme]
}} }}
> >
<DimensionsContext.Provider <DimensionsContext.Provider
value={{ value={{
width, ...dimensions,
height, setDimensions
scale,
fontScale,
setDimensions: this.setDimensions
}} }}
> >
<GestureHandlerRootView style={{ flex: 1 }}> <GestureHandlerRootView style={{ flex: 1 }}>
@ -250,5 +209,6 @@ export default class Root extends React.Component<{}, IState> {
</Provider> </Provider>
</SafeAreaProvider> </SafeAreaProvider>
); );
} };
}
export default Root;

View File

@ -36,10 +36,10 @@ export const getTheme = (themePreferences: IThemePreference): TSupportedThemes =
return theme === 'dark' ? darkLevel : 'light'; return theme === 'dark' ? darkLevel : 'light';
}; };
export const newThemeState = (prevState: { themePreferences: IThemePreference }, newTheme: IThemePreference) => { export const newThemeState = (prevThemePreferences: IThemePreference, newTheme?: IThemePreference) => {
// new theme preferences // new theme preferences
const themePreferences = { const themePreferences = {
...prevState.themePreferences, ...prevThemePreferences,
...newTheme ...newTheme
}; };
// set new state of themePreferences // set new state of themePreferences

View File

@ -11,7 +11,7 @@ export type TColors = typeof colors[TSupportedThemes];
export interface IThemeContextProps { export interface IThemeContextProps {
theme: TSupportedThemes; theme: TSupportedThemes;
themePreferences?: IThemePreference; themePreferences?: IThemePreference;
setTheme?: (newTheme?: {}) => void; setTheme?: (newTheme?: IThemePreference) => void;
colors: TColors; colors: TColors;
} }