Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 26 additions & 10 deletions src/components/CustomStatusBarAndBackground/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React, {useCallback, useContext, useEffect, useRef, useState} from 'react';
import {interpolateColor, runOnJS, useAnimatedReaction, useSharedValue, withDelay, withTiming} from 'react-native-reanimated';
import usePrevious from '@hooks/usePrevious';
import useTheme from '@hooks/useTheme';
import {navigationRef} from '@libs/Navigation/Navigation';
import StatusBar from '@libs/StatusBar';
import type {StatusBarStyle} from '@styles/index';
import CustomStatusBarAndBackgroundContext from './CustomStatusBarAndBackgroundContext';
import updateGlobalBackgroundColor from './updateGlobalBackgroundColor';
import updateStatusBarAppearance from './updateStatusBarAppearance';
Expand All @@ -16,7 +18,7 @@ type CustomStatusBarAndBackgroundProps = {
function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBackgroundProps) {
const {isRootStatusBarEnabled, setRootStatusBarEnabled} = useContext(CustomStatusBarAndBackgroundContext);
const theme = useTheme();
const [statusBarStyle, setStatusBarStyle] = useState(theme.statusBarStyle);
const [statusBarStyle, setStatusBarStyle] = useState<StatusBarStyle>();

const isDisabled = !isNested && !isRootStatusBarEnabled;

Expand All @@ -34,6 +36,8 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack
};
}, [isNested, setRootStatusBarEnabled]);

const didForceUpdateStatusBarRef = useRef(false);
const prevIsRootStatusBarEnabled = usePrevious(isRootStatusBarEnabled);
// The prev and current status bar background color refs are initialized with the splash screen background color so the status bar color is changed from the splash screen color to the expected color atleast once on first render - https://github.com/Expensify/App/issues/34154
const prevStatusBarBackgroundColor = useRef(theme.splashBG);
const statusBarBackgroundColor = useRef(theme.splashBG);
Expand All @@ -57,11 +61,11 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack
// 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) => {
(listenerID?: number) => {
// Check if this function is either called through the current navigation listener
// react-navigation library has a bug internally, where it can't keep track of the listeners, therefore, sometimes when the useEffect would re-render and we run navigationRef.removeListener the listener isn't removed and we end up with two or more listeners.
// https://github.com/Expensify/App/issues/34154#issuecomment-1898519399
if (listenerId !== undefined && listenerId !== listenerCount.current) {
if (listenerID !== undefined && listenerID !== listenerCount.current) {
return;
}

Expand Down Expand Up @@ -97,27 +101,39 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack
}

// Don't update the status bar style if it's the same as the current one, to prevent flashing.
if (newStatusBarStyle !== statusBarStyle) {
// Force update if the root status bar is back on active or it won't overwirte the nested status bar style
if ((!didForceUpdateStatusBarRef.current && !prevIsRootStatusBarEnabled && isRootStatusBarEnabled) || newStatusBarStyle !== statusBarStyle) {
updateStatusBarAppearance({statusBarStyle: newStatusBarStyle});
setStatusBarStyle(newStatusBarStyle);

if (!prevIsRootStatusBarEnabled && isRootStatusBarEnabled) {
didForceUpdateStatusBarRef.current = true;
}
}
},
[statusBarAnimation, statusBarStyle, theme.PAGE_THEMES, theme.appBG, theme.statusBarStyle],
[prevIsRootStatusBarEnabled, isRootStatusBarEnabled, statusBarAnimation, statusBarStyle, theme.PAGE_THEMES, theme.appBG, theme.statusBarStyle],
);

// 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 properly
useEffect(() => {
didForceUpdateStatusBarRef.current = false;
}, [isRootStatusBarEnabled]);

useEffect(() => {
if (isDisabled) {
return;
}

const listenerId = ++listenerCount.current;
const listener = () => updateStatusBarStyle(listenerId);
// Update status bar when theme changes
updateStatusBarStyle();
Comment thread
tienifr marked this conversation as resolved.

// 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 properly
const listenerID = ++listenerCount.current;
const listener = () => updateStatusBarStyle(listenerID);

navigationRef.addListener('state', listener);
return () => navigationRef.removeListener('state', listener);
}, [isDisabled, theme.appBG, updateStatusBarStyle]);
}, [isDisabled, updateStatusBarStyle]);

// Update the global background and status bar style (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.
Expand Down