From 9964bf569ae71d911be4ccfef62dd3bd12e89ff3 Mon Sep 17 00:00:00 2001 From: div Date: Sat, 30 Nov 2024 20:04:59 +0530 Subject: [PATCH 1/6] [FIX] fixed #6031 migrate root component to react functional component --- .storybook/storybook.requires.ts | 4 +- app/index.tsx | 254 +++++++++++++++---------------- 2 files changed, 129 insertions(+), 129 deletions(-) diff --git a/.storybook/storybook.requires.ts b/.storybook/storybook.requires.ts index 79eb456c1b..4d2e29a1cf 100644 --- a/.storybook/storybook.requires.ts +++ b/.storybook/storybook.requires.ts @@ -12,12 +12,12 @@ const normalizedStories = [ directory: "./app", files: "**/*.stories.?(ts|tsx|js|jsx)", importPathMatcher: - /^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(?:ts|tsx|js|jsx)?)$/, + /^\.(?:(?:^|[\\/]|(?:(?:(?!(?:^|[\\/])\.).)*?)[\\/])(?!\.)(?=.)[^\\/]*?\.stories\.(?:ts|tsx|js|jsx)?)$/, // @ts-ignore req: require.context( "../app", true, - /^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(?:ts|tsx|js|jsx)?)$/ + /^\.(?:(?:^|[\\/]|(?:(?:(?!(?:^|[\\/])\.).)*?)[\\/])(?!\.)(?=.)[^\\/]*?\.stories\.(?:ts|tsx|js|jsx)?)$/ ), }, ]; diff --git a/app/index.tsx b/app/index.tsx index 89b0d6d5e9..b8d26cfc81 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { Dimensions, EmitterSubscription, Linking } from 'react-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { SafeAreaProvider, initialWindowMetrics } from 'react-native-safe-area-context'; @@ -78,34 +78,67 @@ const parseDeepLinking = (url: string) => { return null; }; -export default class Root extends React.Component<{}, IState> { - private listenerTimeout!: any; - private dimensionsListener?: EmitterSubscription; +const Root: React.FC = () => { + const [dimensions, setDimensions] = useState(Dimensions.get('window')); + const [state, setState] = useState<{ themePreferences: IThemePreference; theme: TSupportedThemes }>({ + themePreferences: initialTheme(), + theme: getTheme(initialTheme()) + }); + const initTheme = initialTheme(); + const [themeState, setThemeState] = useState({ + ...state, + width: dimensions.width, + height: dimensions.height, + scale: dimensions.scale, + fontScale: dimensions.fontScale + }); + + useEffect(() => { + // init function + const init = async () => { + store.dispatch(appInitLocalSettings()); + + // Open app from push notification + const notification = await initializePushNotifications(); + if (notification) { + onNotification(notification); + return; + } + + await getInitialNotification(); + + // Open app from deep linking + const deepLinking = await Linking.getInitialURL(); + const parsedDeepLinkingURL = parseDeepLinking(deepLinking!); + if (parsedDeepLinkingURL) { + store.dispatch(deepLinkingOpen(parsedDeepLinkingURL)); + return; + } + + // Open app from app icon + store.dispatch(appInit()); + }; + + const initTablet = () => { + const { width } = themeState; + setMasterDetail(width); + }; + + // initialize + init(); - constructor(props: any) { - super(props); - this.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(() => { + // Set the native theme for the app + setNativeTheme(initTheme); + + const timeout = setTimeout(() => { Linking.addEventListener('url', ({ url }) => { const parsedDeepLinkingURL = parseDeepLinking(url); if (parsedDeepLinkingURL) { @@ -113,128 +146,95 @@ export default class Root extends React.Component<{}, IState> { } }); }, 5000); - this.dimensionsListener = Dimensions.addEventListener('change', this.onDimensionsChange); - } - - componentWillUnmount() { - clearTimeout(this.listenerTimeout); - this.dimensionsListener?.remove?.(); - - unsubscribeTheme(); - } - init = async () => { - store.dispatch(appInitLocalSettings()); + const dimensionsListener: EmitterSubscription = Dimensions.addEventListener('change', onDimensionsChange); - // Open app from push notification - const notification = await initializePushNotifications(); - if (notification) { - onNotification(notification); - return; - } - - await getInitialNotification(); - - // Open app from deep linking - const deepLinking = await Linking.getInitialURL(); - const parsedDeepLinkingURL = parseDeepLinking(deepLinking!); - if (parsedDeepLinkingURL) { - store.dispatch(deepLinkingOpen(parsedDeepLinkingURL)); - return; - } - - // Open app from app icon - store.dispatch(appInit()); - }; + return () => { + clearTimeout(timeout); + dimensionsListener.remove(); + unsubscribeTheme(); + }; + }, []); - getMasterDetail = (width: number) => { - if (!isTablet) { - return false; - } - return width > MIN_WIDTH_MASTER_DETAIL_LAYOUT; - }; + useEffect(() => { + // Subscribe to Appearance changes whenever themePreferences changes + subscribeTheme(themePreferences, () => setTheme(themePreferences)); + }, [themeState.themePreferences]); // Dependency array ensures this runs when `themePreferences` changes - setMasterDetail = (width: number) => { - const isMasterDetail = this.getMasterDetail(width); - store.dispatch(setMasterDetailAction(isMasterDetail)); + const initCrashReport = () => { + getAllowCrashReport().then(allowCrashReport => { + toggleCrashErrorsReport(allowCrashReport); + }); + getAllowAnalyticsEvents().then(allowAnalyticsEvents => { + toggleAnalyticsEventsReport(allowAnalyticsEvents); + }); }; - // Dimensions update fires twice - onDimensionsChange = debounce(({ window: { width, height, scale, fontScale } }: { window: IDimensions }) => { - this.setDimensions({ + // Handle dimensions change + const onDimensionsChange = debounce(({ window: { width, height, scale, fontScale } }: { window: IDimensions }) => { + 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 setTheme = (newTheme?: {} | undefined) => { + if (!newTheme) { + return; + } - setDimensions = ({ width, height, scale, fontScale }: IDimensions) => { - this.setState({ width, height, scale, fontScale }); + // Typecast newTheme to IThemePreference when setting state + setState(prevState => newThemeState(prevState, newTheme as IThemePreference)); }; - initTablet = () => { - const { width } = this.state; - this.setMasterDetail(width); + const getMasterDetail = (width: number) => { + if (!isTablet) { + return false; + } + return width > MIN_WIDTH_MASTER_DETAIL_LAYOUT; }; - initCrashReport = () => { - getAllowCrashReport().then(allowCrashReport => { - toggleCrashErrorsReport(allowCrashReport); - }); - getAllowAnalyticsEvents().then(allowAnalyticsEvents => { - toggleAnalyticsEventsReport(allowAnalyticsEvents); - }); + const setMasterDetail = (width: number) => { + const isMasterDetail = getMasterDetail(width); + store.dispatch(setMasterDetailAction(isMasterDetail)); }; - - render() { - const { themePreferences, theme, width, height, scale, fontScale } = this.state; - return ( - - - + + + - - - - - - - - - - - - - - - - - ); - } -} + + + + + + + + + + + + + + + + ); +}; +export default Root; From 3dfc620b6c9666c630af134050b4bf580176247c Mon Sep 17 00:00:00 2001 From: div Date: Sat, 30 Nov 2024 20:45:34 +0530 Subject: [PATCH 2/6] fix lint error --- app/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/index.tsx b/app/index.tsx index b8d26cfc81..7a1232ddf3 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -85,7 +85,7 @@ const Root: React.FC = () => { theme: getTheme(initialTheme()) }); const initTheme = initialTheme(); - const [themeState, setThemeState] = useState({ + const [themeState] = useState({ ...state, width: dimensions.width, height: dimensions.height, From 51a3145a6acea991eb85f0aa003077100794fbd3 Mon Sep 17 00:00:00 2001 From: div Date: Sat, 30 Nov 2024 20:54:36 +0530 Subject: [PATCH 3/6] update state fix --- app/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/index.tsx b/app/index.tsx index 7a1232ddf3..516992082a 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -85,7 +85,7 @@ const Root: React.FC = () => { theme: getTheme(initialTheme()) }); const initTheme = initialTheme(); - const [themeState] = useState({ + const [themeState, setThemeState] = useState({ ...state, width: dimensions.width, height: dimensions.height, @@ -188,6 +188,7 @@ const Root: React.FC = () => { // Typecast newTheme to IThemePreference when setting state setState(prevState => newThemeState(prevState, newTheme as IThemePreference)); + setThemeState(prevstate => ({ ...prevstate, ...state })); }; const getMasterDetail = (width: number) => { From 7983cd34565100ca15bf173f8c23b17c3d593c5c Mon Sep 17 00:00:00 2001 From: div Date: Mon, 2 Dec 2024 23:16:49 +0530 Subject: [PATCH 4/6] removed unnecessary comments --- app/index.tsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/index.tsx b/app/index.tsx index 516992082a..ba278e8f78 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -94,7 +94,6 @@ const Root: React.FC = () => { }); useEffect(() => { - // init function const init = async () => { store.dispatch(appInitLocalSettings()); @@ -124,7 +123,6 @@ const Root: React.FC = () => { setMasterDetail(width); }; - // initialize init(); if (!isFDroidBuild) { @@ -157,9 +155,8 @@ const Root: React.FC = () => { }, []); useEffect(() => { - // Subscribe to Appearance changes whenever themePreferences changes subscribeTheme(themePreferences, () => setTheme(themePreferences)); - }, [themeState.themePreferences]); // Dependency array ensures this runs when `themePreferences` changes + }, [themeState.themePreferences]); const initCrashReport = () => { getAllowCrashReport().then(allowCrashReport => { @@ -170,7 +167,7 @@ const Root: React.FC = () => { }); }; - // Handle dimensions change + // Dimensions update fires twice const onDimensionsChange = debounce(({ window: { width, height, scale, fontScale } }: { window: IDimensions }) => { setDimensions({ width, @@ -186,7 +183,7 @@ const Root: React.FC = () => { return; } - // Typecast newTheme to IThemePreference when setting state + // Typecast newTheme to IThemePreference setState(prevState => newThemeState(prevState, newTheme as IThemePreference)); setThemeState(prevstate => ({ ...prevstate, ...state })); }; From f98a4a4e85e1955defc55a5ca8e966b65a54101d Mon Sep 17 00:00:00 2001 From: div Date: Tue, 3 Dec 2024 09:21:42 +0530 Subject: [PATCH 5/6] used useDebounce hook --- app/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/index.tsx b/app/index.tsx index ba278e8f78..f209421f00 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -17,7 +17,7 @@ import { IThemePreference } from './definitions/ITheme'; import { DimensionsContext } from './dimensions'; import { MIN_WIDTH_MASTER_DETAIL_LAYOUT, colors, isFDroidBuild, themes } from './lib/constants'; import { getAllowAnalyticsEvents, getAllowCrashReport } from './lib/methods'; -import { debounce, isTablet } from './lib/methods/helpers'; +import { isTablet, useDebounce } from './lib/methods/helpers'; import { toggleAnalyticsEventsReport, toggleCrashErrorsReport } from './lib/methods/helpers/log'; import parseQuery from './lib/methods/helpers/parseQuery'; import { @@ -168,7 +168,7 @@ const Root: React.FC = () => { }; // Dimensions update fires twice - const onDimensionsChange = debounce(({ window: { width, height, scale, fontScale } }: { window: IDimensions }) => { + const onDimensionsChange = useDebounce(({ window: { width, height, scale, fontScale } }: { window: IDimensions }) => { setDimensions({ width, height, @@ -176,7 +176,7 @@ const Root: React.FC = () => { fontScale }); setMasterDetail(width); - }); + }, 300); // TODO : review the wait value const setTheme = (newTheme?: {} | undefined) => { if (!newTheme) { From 62965884b75c9d9ddef307e0628bdb99f10f8bf3 Mon Sep 17 00:00:00 2001 From: div Date: Tue, 3 Dec 2024 18:03:11 +0530 Subject: [PATCH 6/6] cleanup: removed unnecessary comment --- app/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/app/index.tsx b/app/index.tsx index f209421f00..4172abee50 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -133,7 +133,6 @@ const Root: React.FC = () => { initTablet(); } - // Set the native theme for the app setNativeTheme(initTheme); const timeout = setTimeout(() => {