From 872b392716e6a0babcadd055c18c9568412d7fef Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Sat, 16 Dec 2023 15:37:50 +0100 Subject: [PATCH 1/4] add back animation --- .../CustomStatusBarAndBackground/index.tsx | 49 +++++++++++++++---- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/src/components/CustomStatusBarAndBackground/index.tsx b/src/components/CustomStatusBarAndBackground/index.tsx index b84f9c6a6630..34362d571272 100644 --- a/src/components/CustomStatusBarAndBackground/index.tsx +++ b/src/components/CustomStatusBarAndBackground/index.tsx @@ -1,4 +1,5 @@ import React, {useCallback, useContext, useEffect, useRef, useState} from 'react'; +import {interpolateColor, runOnJS, useAnimatedReaction, useSharedValue, withDelay, withTiming} from 'react-native-reanimated'; import useTheme from '@hooks/useTheme'; import {navigationRef} from '@libs/Navigation/Navigation'; import StatusBar from '@libs/StatusBar'; @@ -33,6 +34,23 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack }; }, [disableRootStatusBar, isNested]); + const prevStatusBarBackgroundColor = useRef(theme.appBG); + const statusBarBackgroundColor = useRef(theme.appBG); + const statusBarAnimation = useSharedValue(0); + + useAnimatedReaction( + () => statusBarAnimation.value, + (current, previous) => { + // Do not run if either of the animated value is null + // or previous animated value is greater than or equal to the current one + if (previous === null || current === null || current <= previous) { + return; + } + const backgroundColor = interpolateColor(statusBarAnimation.value, [0, 1], [prevStatusBarBackgroundColor.current, statusBarBackgroundColor.current]); + runOnJS(updateStatusBarAppearance)({backgroundColor}); + }, + ); + const listenerCount = useRef(0); const updateStatusBarStyle = useCallback( (listenerId?: number) => { @@ -49,23 +67,36 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack currentRoute = navigationRef.getCurrentRoute(); } - let currentScreenBackgroundColor = theme.appBG; let newStatusBarStyle = theme.statusBarStyle; + let currentScreenBackgroundColor = theme.appBG; if (currentRoute && 'name' in currentRoute && currentRoute.name in theme.PAGE_THEMES) { - const screenTheme = theme.PAGE_THEMES[currentRoute.name]; - currentScreenBackgroundColor = screenTheme.backgroundColor; - newStatusBarStyle = screenTheme.statusBarStyle; + const pageTheme = theme.PAGE_THEMES[currentRoute.name]; + + newStatusBarStyle = pageTheme.statusBarStyle; + + const backgroundColorFromRoute = + currentRoute?.params && 'backgroundColor' in currentRoute.params && typeof currentRoute.params.backgroundColor === 'string' && currentRoute.params.backgroundColor; + + // 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 + currentScreenBackgroundColor = backgroundColorFromRoute || pageTheme.backgroundColor; + } + + prevStatusBarBackgroundColor.current = statusBarBackgroundColor.current; + statusBarBackgroundColor.current = currentScreenBackgroundColor; + + if (currentScreenBackgroundColor !== theme.appBG || prevStatusBarBackgroundColor.current !== theme.appBG) { + statusBarAnimation.value = 0; + statusBarAnimation.value = withDelay(300, withTiming(1)); } // Don't update the status bar style if it's the same as the current one, to prevent flashing. - if (newStatusBarStyle === statusBarStyle) { - updateStatusBarAppearance({backgroundColor: currentScreenBackgroundColor}); - } else { - updateStatusBarAppearance({backgroundColor: currentScreenBackgroundColor, statusBarStyle: newStatusBarStyle}); + if (newStatusBarStyle !== statusBarStyle) { + updateStatusBarAppearance({statusBarStyle: newStatusBarStyle}); setStatusBarStyle(newStatusBarStyle); } }, - [statusBarStyle, theme.PAGE_THEMES, theme.appBG, theme.statusBarStyle], + [statusBarAnimation, statusBarStyle, theme.PAGE_THEMES, theme.appBG, theme.statusBarStyle], ); // Add navigation state listeners to update the status bar every time the route changes From e3474d39890213034a6556ac085a1db395f3c6c0 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Sun, 24 Dec 2023 00:54:23 +0100 Subject: [PATCH 2/4] fix: comment --- src/components/CustomStatusBarAndBackground/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/CustomStatusBarAndBackground/index.tsx b/src/components/CustomStatusBarAndBackground/index.tsx index 34362d571272..73bed8653f9e 100644 --- a/src/components/CustomStatusBarAndBackground/index.tsx +++ b/src/components/CustomStatusBarAndBackground/index.tsx @@ -100,7 +100,7 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack ); // Add navigation state listeners to update the status bar every time the route changes - // We have to pass a count as the listener id, because "react-navigation" somehow doesn't remove listeners properyl + // We have to pass a count as the listener id, because "react-navigation" somehow doesn't remove listeners properly useEffect(() => { if (isDisabled) { return; From bebf6a952d8fd6863394682f0be61841e14b9588 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Sun, 24 Dec 2023 00:59:14 +0100 Subject: [PATCH 3/4] fix: remove unnecessary effect --- .../CustomStatusBarAndBackground/index.tsx | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/components/CustomStatusBarAndBackground/index.tsx b/src/components/CustomStatusBarAndBackground/index.tsx index 73bed8653f9e..74a12c836e91 100644 --- a/src/components/CustomStatusBarAndBackground/index.tsx +++ b/src/components/CustomStatusBarAndBackground/index.tsx @@ -41,6 +41,8 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack useAnimatedReaction( () => statusBarAnimation.value, (current, previous) => { + console.log('reaction'); + // Do not run if either of the animated value is null // or previous animated value is greater than or equal to the current one if (previous === null || current === null || current <= previous) { @@ -52,6 +54,9 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack ); const listenerCount = useRef(0); + + // Updates the status bar style and background color depending on the current route and theme + // This callback is triggered everytime the route changes or the theme changes const updateStatusBarStyle = useCallback( (listenerId?: number) => { // Check if this function is either called through the current navigation listener or the general useEffect which listens for theme changes. @@ -113,15 +118,6 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack return () => navigationRef.removeListener('state', listener); }, [isDisabled, theme.appBG, updateStatusBarStyle]); - // Update the status bar style everytime the theme changes - useEffect(() => { - if (isDisabled) { - return; - } - - updateStatusBarStyle(); - }, [isDisabled, theme, updateStatusBarStyle]); - // Update the global background (on web) everytime the theme changes. // The background of the html element needs to be updated, otherwise you will see a big contrast when resizing the window or when the keyboard is open on iOS web. useEffect(() => { From 1642c5dcdfa8fedb8316b4323142a33d83f9cb81 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Sun, 24 Dec 2023 00:59:23 +0100 Subject: [PATCH 4/4] remove log --- src/components/CustomStatusBarAndBackground/index.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/CustomStatusBarAndBackground/index.tsx b/src/components/CustomStatusBarAndBackground/index.tsx index 74a12c836e91..f66a0204ac5e 100644 --- a/src/components/CustomStatusBarAndBackground/index.tsx +++ b/src/components/CustomStatusBarAndBackground/index.tsx @@ -41,8 +41,6 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack useAnimatedReaction( () => statusBarAnimation.value, (current, previous) => { - console.log('reaction'); - // Do not run if either of the animated value is null // or previous animated value is greater than or equal to the current one if (previous === null || current === null || current <= previous) {