Merge pull request #1451 from bluesky-social/eric/theme-switching-web

fix theme switching on web without refresh
zio/stable
Eric Bailey 2023-09-15 11:06:06 -05:00 committed by GitHub
commit 84b7edd9db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 37 additions and 25 deletions

View File

@ -1,8 +1,9 @@
import {isWeb} from 'platform/detection'
import React, {ReactNode, createContext, useContext} from 'react'
import {
AppState,
TextStyle,
useColorScheme,
useColorScheme as useColorScheme_BUGGY,
ViewStyle,
ColorSchemeName,
} from 'react-native'
@ -92,33 +93,44 @@ export const ThemeContext = createContext<Theme>(defaultTheme)
export const useTheme = () => useContext(ThemeContext)
function getTheme(theme: ColorSchemeName) {
return theme === 'dark' ? darkTheme : defaultTheme
}
/**
* With RN iOS, we can only "trust" the color scheme reported while the app is
* active. This is a workaround until the bug is fixed upstream.
*
* @see https://github.com/bluesky-social/social-app/pull/1417#issuecomment-1719868504
* @see https://github.com/facebook/react-native/pull/39439
*/
function useColorScheme_FIXED() {
const colorScheme = useColorScheme_BUGGY()
const [currentColorScheme, setCurrentColorScheme] =
React.useState<ColorSchemeName>(colorScheme)
React.useEffect(() => {
// we don't need to be updating state on web
if (isWeb) return
const subscription = AppState.addEventListener('change', state => {
const isActive = state === 'active'
if (!isActive) return
setCurrentColorScheme(colorScheme)
})
return () => subscription.remove()
}, [colorScheme])
return isWeb ? colorScheme : currentColorScheme
}
export const ThemeProvider: React.FC<ThemeProviderProps> = ({
theme,
children,
}) => {
const colorSchemeFromRN = useColorScheme()
const [nativeColorScheme, setNativeColorScheme] =
React.useState<ColorSchemeName>(colorSchemeFromRN)
const colorScheme = useColorScheme_FIXED()
const themeValue = getTheme(theme === 'system' ? colorScheme : theme)
React.useEffect(() => {
const subscription = AppState.addEventListener('change', state => {
const isActive = state === 'active'
if (!isActive) return
setNativeColorScheme(colorSchemeFromRN)
})
return () => subscription.remove()
}, [colorSchemeFromRN])
const value =
theme === 'system'
? nativeColorScheme === 'dark'
? darkTheme
: defaultTheme
: theme === 'dark'
? darkTheme
: defaultTheme
return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>
return (
<ThemeContext.Provider value={themeValue}>{children}</ThemeContext.Provider>
)
}