diff --git a/src/components/GrowlNotification/index.js b/src/components/GrowlNotification/index.js index 5fdbe205f87b..86850a8af96d 100644 --- a/src/components/GrowlNotification/index.js +++ b/src/components/GrowlNotification/index.js @@ -7,26 +7,11 @@ import * as Pressables from '@components/Pressable'; import Text from '@components/Text'; import * as Growl from '@libs/Growl'; import useNativeDriver from '@libs/useNativeDriver'; -import styles from '@styles/styles'; -import themeColors from '@styles/themes/default'; +import useTheme from '@styles/themes/useTheme'; +import useThemeStyles from '@styles/useThemeStyles'; import CONST from '@src/CONST'; import GrowlNotificationContainer from './GrowlNotificationContainer'; -const types = { - [CONST.GROWL.SUCCESS]: { - icon: Expensicons.Checkmark, - iconColor: themeColors.success, - }, - [CONST.GROWL.ERROR]: { - icon: Expensicons.Exclamation, - iconColor: themeColors.danger, - }, - [CONST.GROWL.WARNING]: { - icon: Expensicons.Exclamation, - iconColor: themeColors.warning, - }, -}; - const INACTIVE_POSITION_Y = -255; const PressableWithoutFeedback = Pressables.PressableWithoutFeedback; @@ -36,6 +21,23 @@ function GrowlNotification(_, ref) { const [bodyText, setBodyText] = useState(''); const [type, setType] = useState('success'); const [duration, setDuration] = useState(); + const styles = useThemeStyles(); + const theme = useTheme(); + + const types = { + [CONST.GROWL.SUCCESS]: { + icon: Expensicons.Checkmark, + iconColor: theme.success, + }, + [CONST.GROWL.ERROR]: { + icon: Expensicons.Exclamation, + iconColor: theme.danger, + }, + [CONST.GROWL.WARNING]: { + icon: Expensicons.Exclamation, + iconColor: theme.warning, + }, + }; /** * Show the growl notification diff --git a/src/components/ScreenWrapper/index.js b/src/components/ScreenWrapper/index.js index f9173c15da7d..16bf9ba0761c 100644 --- a/src/components/ScreenWrapper/index.js +++ b/src/components/ScreenWrapper/index.js @@ -16,7 +16,7 @@ import useKeyboardState from '@hooks/useKeyboardState'; import useNetwork from '@hooks/useNetwork'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as Browser from '@libs/Browser'; -import styles from '@styles/styles'; +import useThemeStyles from '@styles/useThemeStyles'; import toggleTestToolsModal from '@userActions/TestTool'; import CONST from '@src/CONST'; import {defaultProps, propTypes} from './propTypes'; @@ -44,6 +44,7 @@ const ScreenWrapper = React.forwardRef( ) => { const {windowHeight, isSmallScreenWidth} = useWindowDimensions(); const {initialHeight} = useInitialDimensions(); + const styles = useThemeStyles(); const keyboardState = useKeyboardState(); const {isDevelopment} = useEnvironment(); const {isOffline} = useNetwork(); @@ -59,14 +60,14 @@ const ScreenWrapper = React.forwardRef( const panResponder = useRef( PanResponder.create({ - onStartShouldSetPanResponderCapture: (e, gestureState) => gestureState.numberActiveTouches === CONST.TEST_TOOL.NUMBER_OF_TAPS, + onStartShouldSetPanResponderCapture: (_e, gestureState) => gestureState.numberActiveTouches === CONST.TEST_TOOL.NUMBER_OF_TAPS, onPanResponderRelease: toggleTestToolsModal, }), ).current; const keyboardDissmissPanResponder = useRef( PanResponder.create({ - onMoveShouldSetPanResponderCapture: (e, gestureState) => { + onMoveShouldSetPanResponderCapture: (_e, gestureState) => { const isHorizontalSwipe = Math.abs(gestureState.dx) > Math.abs(gestureState.dy); const shouldDismissKeyboard = shouldDismissKeyboardBeforeClose && isKeyboardShown && Browser.isMobile(); diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index aedb2fa8d741..4c610bc12099 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -144,7 +144,7 @@ const defaultProps = { function AuthScreens({isUsingMemoryOnlyKeys, lastUpdateIDAppliedToClient, session, lastOpenedPublicRoomID, demoInfo}) { const styles = useThemeStyles(); const {isSmallScreenWidth} = useWindowDimensions(); - const screenOptions = getRootNavigatorScreenOptions(isSmallScreenWidth); + const screenOptions = getRootNavigatorScreenOptions(isSmallScreenWidth, styles); const isInitialRender = useRef(true); if (isInitialRender.current) { diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js index 01573cb434b4..be803e62a98b 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js @@ -1,15 +1,9 @@ import {CardStyleInterpolators, createStackNavigator} from '@react-navigation/stack'; -import React from 'react'; +import React, {useMemo} from 'react'; import _ from 'underscore'; -import styles from '@styles/styles'; +import useThemeStyles from '@styles/useThemeStyles'; import SCREENS from '@src/SCREENS'; -const defaultSubRouteOptions = { - cardStyle: styles.navigationScreenCardStyle, - headerShown: false, - cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, -}; - /** * Create a modal stack navigator with an array of sub-screens. * @@ -20,6 +14,17 @@ function createModalStackNavigator(screens) { const ModalStackNavigator = createStackNavigator(); function ModalStack() { + const styles = useThemeStyles(); + + const defaultSubRouteOptions = useMemo( + () => ({ + cardStyle: styles.navigationScreenCardStyle, + headerShown: false, + cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, + }), + [styles], + ); + return ( {_.map(screens, (getComponent, name) => ( diff --git a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.js index a1646011e560..d23b03c8c73e 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.js +++ b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.js @@ -2,7 +2,7 @@ import {createStackNavigator} from '@react-navigation/stack'; import React from 'react'; import ReportScreenWrapper from '@libs/Navigation/AppNavigator/ReportScreenWrapper'; import getCurrentUrl from '@libs/Navigation/currentUrl'; -import styles from '@styles/styles'; +import useThemeStyles from '@styles/useThemeStyles'; import SCREENS from '@src/SCREENS'; const Stack = createStackNavigator(); @@ -11,6 +11,7 @@ const url = getCurrentUrl(); const openOnAdminRoom = url ? new URL(url).searchParams.get('openOnAdminRoom') : undefined; function BaseCentralPaneNavigator() { + const styles = useThemeStyles(); return ( RHPScreenOptions(styles), [styles]); return ( {!isSmallScreenWidth && } - + ({ headerShown: false, animationEnabled: true, gestureDirection: 'horizontal', cardStyle: styles.navigationScreenCardStyle, cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, -}; +}); export default RHPScreenOptions; diff --git a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js index 04784fb9d0e1..44fa7b6c0b09 100644 --- a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js +++ b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js @@ -1,5 +1,4 @@ import getNavigationModalCardStyle from '@styles/getNavigationModalCardStyles'; -import styles from '@styles/styles'; import variables from '@styles/variables'; import CONFIG from '@src/CONFIG'; import modalCardStyleInterpolator from './modalCardStyleInterpolator'; @@ -12,7 +11,7 @@ const commonScreenOptions = { animationTypeForReplace: 'push', }; -export default (isSmallScreenWidth) => ({ +export default (isSmallScreenWidth, styles) => ({ rightModalNavigator: { ...commonScreenOptions, cardStyleInterpolator: (props) => modalCardStyleInterpolator(isSmallScreenWidth, false, props), diff --git a/src/libs/Navigation/NavigationRoot.tsx b/src/libs/Navigation/NavigationRoot.tsx index b498bcdfdf4d..cbb2e62161f3 100644 --- a/src/libs/Navigation/NavigationRoot.tsx +++ b/src/libs/Navigation/NavigationRoot.tsx @@ -1,5 +1,5 @@ import {DefaultTheme, getPathFromState, NavigationContainer, NavigationState} from '@react-navigation/native'; -import React, {useEffect, useRef} from 'react'; +import React, {useEffect, useMemo, useRef} from 'react'; import {ColorValue} from 'react-native'; import {interpolateColor, runOnJS, useAnimatedReaction, useSharedValue, withDelay, withTiming} from 'react-native-reanimated'; import useCurrentReportID from '@hooks/useCurrentReportID'; @@ -7,20 +7,11 @@ import useFlipper from '@hooks/useFlipper'; import useWindowDimensions from '@hooks/useWindowDimensions'; import Log from '@libs/Log'; import StatusBar from '@libs/StatusBar'; -import themeColors from '@styles/themes/default'; +import useTheme from '@styles/themes/useTheme'; import AppNavigator from './AppNavigator'; import linkingConfig from './linkingConfig'; import Navigation, {navigationRef} from './Navigation'; -// https://reactnavigation.org/docs/themes -const navigationTheme = { - ...DefaultTheme, - colors: { - ...DefaultTheme.colors, - background: themeColors.appBG, - }, -}; - type NavigationRootProps = { /** Whether the current user is logged in with an authToken */ authenticated: boolean; @@ -51,11 +42,24 @@ function parseAndLogRoute(state: NavigationState) { function NavigationRoot({authenticated, onReady}: NavigationRootProps) { useFlipper(navigationRef); + const theme = useTheme(); const firstRenderRef = useRef(true); const currentReportIDValue = useCurrentReportID(); const {isSmallScreenWidth} = useWindowDimensions(); + // https://reactnavigation.org/docs/themes + const navigationTheme = useMemo( + () => ({ + ...DefaultTheme, + colors: { + ...DefaultTheme.colors, + background: theme.appBG, + }, + }), + [theme], + ); + useEffect(() => { if (firstRenderRef.current) { // we don't want to make the report back button go back to LHN if the user @@ -78,8 +82,8 @@ function NavigationRoot({authenticated, onReady}: NavigationRootProps) { navigationRef.resetRoot(navigationRef.getRootState()); }, [isSmallScreenWidth, authenticated]); - const prevStatusBarBackgroundColor = useRef(themeColors.appBG); - const statusBarBackgroundColor = useRef(themeColors.appBG); + const prevStatusBarBackgroundColor = useRef(theme.appBG); + const statusBarBackgroundColor = useRef(theme.appBG); const statusBarAnimation = useSharedValue(0); const updateStatusBarBackgroundColor = (color: ColorValue) => StatusBar.setBackgroundColor(color); @@ -101,7 +105,7 @@ function NavigationRoot({authenticated, onReady}: NavigationRootProps) { const backgroundColorFromRoute = currentRoute?.params && 'backgroundColor' in currentRoute.params && typeof currentRoute.params.backgroundColor === 'string' && currentRoute.params.backgroundColor; - const backgroundColorFallback = themeColors.PAGE_BACKGROUND_COLORS[currentRoute?.name as keyof typeof themeColors.PAGE_BACKGROUND_COLORS] || themeColors.appBG; + const backgroundColorFallback = currentRoute?.name ? theme.PAGE_BACKGROUND_COLORS[currentRoute.name] || theme.appBG : theme.appBG; // It's possible for backgroundColorFromRoute to be empty string, so we must use "||" to fallback to backgroundColorFallback. // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing @@ -110,7 +114,7 @@ function NavigationRoot({authenticated, onReady}: NavigationRootProps) { prevStatusBarBackgroundColor.current = statusBarBackgroundColor.current; statusBarBackgroundColor.current = currentScreenBackgroundColor; - if (currentScreenBackgroundColor === themeColors.appBG && prevStatusBarBackgroundColor.current === themeColors.appBG) { + if (currentScreenBackgroundColor === theme.appBG && prevStatusBarBackgroundColor.current === theme.appBG) { return; } diff --git a/src/pages/signin/SignInPageLayout/index.js b/src/pages/signin/SignInPageLayout/index.js index 1b5ac55c9da2..b6c82fc843cd 100644 --- a/src/pages/signin/SignInPageLayout/index.js +++ b/src/pages/signin/SignInPageLayout/index.js @@ -1,5 +1,5 @@ import PropTypes from 'prop-types'; -import React, {forwardRef, useEffect, useImperativeHandle, useRef} from 'react'; +import React, {forwardRef, useEffect, useImperativeHandle, useMemo, useRef} from 'react'; import {ScrollView, View} from 'react-native'; import {withSafeAreaInsets} from 'react-native-safe-area-context'; import SignInGradient from '@assets/images/home-fade-gradient.svg'; @@ -93,6 +93,8 @@ function SignInPageLayout(props) { scrollPageToTop(); }, [props.welcomeHeader, props.welcomeText, prevPreferredLocale, props.preferredLocale]); + const scrollViewStyles = useMemo(() => scrollViewContentContainerStyles(styles), [styles]); + return ( {!props.shouldShowSmallScreen ? ( @@ -152,7 +154,7 @@ function SignInPageLayout(props) { ) : ( diff --git a/src/pages/signin/SignInPageLayout/signInPageStyles/index.js b/src/pages/signin/SignInPageLayout/signInPageStyles/index.js index b058c78aca86..ac9b7b66851a 100644 --- a/src/pages/signin/SignInPageLayout/signInPageStyles/index.js +++ b/src/pages/signin/SignInPageLayout/signInPageStyles/index.js @@ -1,6 +1,4 @@ -import styles from '@styles/styles'; - // On web, we can use flex to fit the content to fit the viewport within a ScrollView. -const scrollViewContentContainerStyles = styles.flex1; +const scrollViewContentContainerStyles = (styles) => styles.flex1; export default scrollViewContentContainerStyles; diff --git a/src/pages/signin/SignInPageLayout/signInPageStyles/index.native.js b/src/pages/signin/SignInPageLayout/signInPageStyles/index.native.js index 76f847f638b9..1c474ab6c722 100644 --- a/src/pages/signin/SignInPageLayout/signInPageStyles/index.native.js +++ b/src/pages/signin/SignInPageLayout/signInPageStyles/index.native.js @@ -1,7 +1,5 @@ -import styles from '@styles/styles'; - // Using flexGrow on mobile allows the ScrollView container to grow to fit the content. // This is necessary because making the sign-in content fit exactly the viewheight causes the scroll to stop working on mobile. -const scrollViewContentContainerStyles = styles.flexGrow1; +const scrollViewContentContainerStyles = (styles) => styles.flexGrow1; export default scrollViewContentContainerStyles; diff --git a/src/pages/signin/Terms.js b/src/pages/signin/Terms.js index 13af9829305d..44e024208fc8 100644 --- a/src/pages/signin/Terms.js +++ b/src/pages/signin/Terms.js @@ -1,15 +1,22 @@ -import React from 'react'; +import React, {useMemo} from 'react'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; -import styles from '@styles/styles'; +import useThemeStyles from '@styles/useThemeStyles'; import CONST from '@src/CONST'; -const linkStyles = [styles.textExtraSmallSupporting, styles.link]; - function Terms(props) { + const styles = useThemeStyles(); + const [linkStyles, containerStyles] = useMemo( + () => [ + [styles.textExtraSmallSupporting, styles.link], + [styles.textExtraSmallSupporting, styles.mb4], + ], + [styles], + ); + return ( - + {props.translate('termsOfUse.phrase1')} const stylesGenerator = styles; const defaultStyles = styles(defaultTheme); +type ThemeStyle = typeof defaultStyles; + export default defaultStyles; -export {stylesGenerator, type Styles}; +export {stylesGenerator, type Styles, type ThemeStyle};