Skip to content
191 changes: 88 additions & 103 deletions app/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { Dimensions, Linking } from 'react-native';
import { AppearanceProvider } from 'react-native-appearance';
import { KeyCommandsEmitter } from 'react-native-keycommands';
Expand All @@ -24,7 +24,7 @@ import parseQuery from './lib/methods/helpers/parseQuery';
import { initializePushNotifications, onNotification } from './lib/notifications';
import store from './lib/store';
import { initStore } from './lib/store/auxStore';
import { ThemeContext, TSupportedThemes } from './theme';
import { ThemeContext } from './theme';
import { debounce, isTablet } from './lib/methods/helpers';
import EventEmitter from './lib/methods/helpers/events';
import { toggleAnalyticsEventsReport, toggleCrashErrorsReport } from './lib/methods/helpers/log';
Expand All @@ -49,15 +49,6 @@ interface IDimensions {
fontScale: number;
}

interface IState {
theme: TSupportedThemes;
themePreferences: IThemePreference;
width: number;
height: number;
scale: number;
fontScale: number;
}

const parseDeepLinking = (url: string) => {
if (url) {
url = url.replace(/rocketchat:\/\/|https:\/\/go.rocket.chat\//, '');
Expand All @@ -81,57 +72,54 @@ const parseDeepLinking = (url: string) => {
return null;
};

export default class Root extends React.Component<{}, IState> {
private listenerTimeout!: any;
const Root = () => {
const { width: widthWindow, height: heightWindow, scale: scaleWindow, fontScale: fontScaleWindow } = Dimensions.get('window');
Comment thread
reinaldonetof marked this conversation as resolved.
Outdated
const [theme, setTheme] = useState(getTheme(initialTheme()));
Comment thread
reinaldonetof marked this conversation as resolved.
Outdated
const [themePreferences, setThemePreferences] = useState(initialTheme());
const [width, setWidth] = useState(widthWindow);
const [height, setHeight] = useState(heightWindow);
const [scale, setScale] = useState(scaleWindow);
const [fontScale, setFontScale] = useState(fontScaleWindow);

private onKeyCommands: any;
const listenerTimeout = useRef<any>();
const onKeyCommands = useRef<any>();
Comment thread
reinaldonetof marked this conversation as resolved.
Outdated

constructor(props: any) {
super(props);
this.init();
useEffect(() => {
init();
if (!isFDroidBuild) {
this.initCrashReport();
initCrashReport();
}
const { width, height, scale, fontScale } = Dimensions.get('window');
const theme = initialTheme();
this.state = {
theme: getTheme(theme),
themePreferences: theme,
width,
height,
scale,
fontScale
};
if (isTablet) {
this.initTablet();
initTablet();
}
setNativeTheme(theme);
}
}, []);

componentDidMount() {
this.listenerTimeout = setTimeout(() => {
useEffect(() => {
Comment thread
reinaldonetof marked this conversation as resolved.
Outdated
listenerTimeout.current = setTimeout(() => {
Linking.addEventListener('url', ({ url }) => {
const parsedDeepLinkingURL = parseDeepLinking(url);
if (parsedDeepLinkingURL) {
store.dispatch(deepLinkingOpen(parsedDeepLinkingURL));
}
});
}, 5000);
Dimensions.addEventListener('change', this.onDimensionsChange);
}
Dimensions.addEventListener('change', onDimensionsChange);

componentWillUnmount() {
clearTimeout(this.listenerTimeout);
Dimensions.removeEventListener('change', this.onDimensionsChange);
return () => {
Comment thread
reinaldonetof marked this conversation as resolved.
clearTimeout(listenerTimeout.current);
Dimensions.removeEventListener('change', onDimensionsChange);
Comment thread
reinaldonetof marked this conversation as resolved.
Outdated

unsubscribeTheme();
unsubscribeTheme();

if (this.onKeyCommands && this.onKeyCommands.remove) {
this.onKeyCommands.remove();
}
}
if (onKeyCommands.current && onKeyCommands.current.remove) {
Comment thread
reinaldonetof marked this conversation as resolved.
Outdated
onKeyCommands.current.remove();
Comment thread
reinaldonetof marked this conversation as resolved.
Outdated
}
};
}, []);

init = async () => {
const init = async () => {
store.dispatch(appInitLocalSettings());

// Open app from push notification
Expand All @@ -153,54 +141,54 @@ export default class Root extends React.Component<{}, IState> {
store.dispatch(appInit());
};

getMasterDetail = (width: number) => {
const getMasterDetail = (width: number) => {
if (!isTablet) {
return false;
}
return width > MIN_WIDTH_MASTER_DETAIL_LAYOUT;
};

setMasterDetail = (width: number) => {
const isMasterDetail = this.getMasterDetail(width);
const setMasterDetail = (width: number) => {
const isMasterDetail = getMasterDetail(width);
store.dispatch(setMasterDetailAction(isMasterDetail));
};

// Dimensions update fires twice
onDimensionsChange = debounce(({ window: { width, height, scale, fontScale } }: { window: IDimensions }) => {
this.setDimensions({
const onDimensionsChange = debounce(({ window: { width, height, scale, fontScale } }: { window: IDimensions }) => {
Comment thread
diegolmello marked this conversation as resolved.
Outdated
setDimensions({
width,
height,
scale,
fontScale
});
this.setMasterDetail(width);
setMasterDetail(width);
});

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);
}
const setThemeFunction = (newThemeObject = {}) => {
Comment thread
reinaldonetof marked this conversation as resolved.
Outdated
const { theme: newTheme, themePreferences: newThemePreferences } = newThemeState(
themePreferences,
newThemeObject as IThemePreference
);
setThemePreferences(newThemePreferences);
setTheme(newTheme);
subscribeTheme(themePreferences, setThemeFunction);
};

setDimensions = ({ width, height, scale, fontScale }: IDimensions) => {
this.setState({ width, height, scale, fontScale });
const setDimensions = ({ width, height, scale, fontScale }: IDimensions) => {
setWidth(width);
setHeight(height);
setScale(scale);
setFontScale(fontScale);
Comment thread
reinaldonetof marked this conversation as resolved.
Outdated
Comment thread
reinaldonetof marked this conversation as resolved.
Outdated
};

initTablet = () => {
const { width } = this.state;
this.setMasterDetail(width);
this.onKeyCommands = KeyCommandsEmitter.addListener('onKeyCommand', (command: ICommand) => {
const initTablet = () => {
setMasterDetail(width);
onKeyCommands.current = KeyCommandsEmitter.addListener('onKeyCommand', (command: ICommand) => {
EventEmitter.emit(KEY_COMMAND, { event: command });
});
};

initCrashReport = () => {
const initCrashReport = () => {
Comment thread
reinaldonetof marked this conversation as resolved.
Outdated
getAllowCrashReport().then(allowCrashReport => {
toggleCrashErrorsReport(allowCrashReport);
});
Expand All @@ -209,44 +197,41 @@ export default class Root extends React.Component<{}, IState> {
});
};

render() {
const { themePreferences, theme, width, height, scale, fontScale } = this.state;
return (
<SafeAreaProvider
initialMetrics={initialWindowMetrics}
style={{ backgroundColor: themes[this.state.theme].backgroundColor }}>
<AppearanceProvider>
<Provider store={store}>
<ThemeContext.Provider
return (
<SafeAreaProvider initialMetrics={initialWindowMetrics} style={{ backgroundColor: themes[theme].backgroundColor }}>
<AppearanceProvider>
<Provider store={store}>
<ThemeContext.Provider
value={{
theme,
themePreferences,
setTheme: setThemeFunction,
colors: colors[theme]
}}>
<DimensionsContext.Provider
value={{
theme,
themePreferences,
setTheme: this.setTheme,
colors: colors[theme]
width,
height,
scale,
fontScale,
setDimensions
}}>
<DimensionsContext.Provider
value={{
width,
height,
scale,
fontScale,
setDimensions: this.setDimensions
}}>
<GestureHandlerRootView style={{ flex: 1 }}>
<ActionSheetProvider>
<AppContainer />
<TwoFactor />
<ScreenLockedView />
<ChangePasscodeView />
<InAppNotification />
<Toast />
</ActionSheetProvider>
</GestureHandlerRootView>
</DimensionsContext.Provider>
</ThemeContext.Provider>
</Provider>
</AppearanceProvider>
</SafeAreaProvider>
);
}
}
<GestureHandlerRootView style={{ flex: 1 }}>
<ActionSheetProvider>
<AppContainer />
<TwoFactor />
<ScreenLockedView />
<ChangePasscodeView />
<InAppNotification />
<Toast />
</ActionSheetProvider>
</GestureHandlerRootView>
</DimensionsContext.Provider>
</ThemeContext.Provider>
</Provider>
</AppearanceProvider>
</SafeAreaProvider>
);
};

export default Root;
4 changes: 2 additions & 2 deletions app/lib/methods/helpers/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ export const getTheme = (themePreferences: IThemePreference): TSupportedThemes =
return theme === 'dark' ? darkLevel : 'light';
};

export const newThemeState = (prevState: { themePreferences: IThemePreference }, newTheme: IThemePreference) => {
export const newThemeState = (prevthemePreferences: IThemePreference, newTheme: IThemePreference) => {
Comment thread
reinaldonetof marked this conversation as resolved.
Outdated
// new theme preferences
const themePreferences = {
...prevState.themePreferences,
...prevthemePreferences,
...newTheme
};
// set new state of themePreferences
Expand Down
2 changes: 1 addition & 1 deletion app/share.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ class Root extends React.Component<{}, IState> {
setTheme = (newTheme = {}) => {
// change theme state
this.setState(
prevState => newThemeState(prevState, newTheme as IThemePreference),
prevState => newThemeState(prevState.themePreferences, newTheme as IThemePreference),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/RocketChat/Rocket.Chat.ReactNative/pull/4401/files#diff-b788f0c6b6e92a2a43dedd61dd4e596b4b0f981e30bcfd88e2f5d30b2de3a7dbR39

Because I changed the function newThemeState to receive only the property required, not the state completely.

() => {
const { themePreferences } = this.state;
// subscribe to Appearance changes
Expand Down