Skip to content

Commit b4561ba

Browse files
committed
refactor: extract useSystemColorScheme
1 parent 0525906 commit b4561ba

2 files changed

Lines changed: 30 additions & 35 deletions

File tree

src/core/PaperProvider.tsx

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import * as React from 'react';
2-
import { Appearance, ColorSchemeName } from 'react-native';
32

43
import SafeAreaProviderCompat from './SafeAreaProviderCompat';
54
import { Provider as SettingsProvider, Settings } from './settings';
65
import { defaultThemes, ThemeProvider } from './theming';
6+
import { useSystemColorScheme } from './useSystemColorScheme';
77
import MaterialCommunityIcon from '../components/MaterialCommunityIcon';
88
import PortalHost from '../components/Portal/PortalHost';
99
import { ReduceMotionContext } from '../theme/accessibility/ReduceMotionContext';
@@ -23,42 +23,9 @@ export type Props = {
2323
const PaperProvider = (props: Props) => {
2424
const { reduceMotion = 'auto' } = props;
2525

26-
const colorSchemeName =
27-
(!props.theme && Appearance?.getColorScheme()) || 'light';
28-
29-
const [colorScheme, setColorScheme] =
30-
React.useState<ColorSchemeName>(colorSchemeName);
31-
26+
const colorScheme = useSystemColorScheme(!props.theme);
3227
const resolvedReduceMotion = useResolvedReduceMotion(reduceMotion);
3328

34-
const handleAppearanceChange = (
35-
preferences: Appearance.AppearancePreferences
36-
) => {
37-
const { colorScheme } = preferences;
38-
setColorScheme(colorScheme);
39-
};
40-
41-
React.useEffect(() => {
42-
let appearanceSubscription:
43-
| ReturnType<typeof Appearance.addChangeListener>
44-
| undefined;
45-
if (!props.theme) {
46-
appearanceSubscription = Appearance?.addChangeListener(
47-
handleAppearanceChange
48-
) as typeof appearanceSubscription;
49-
}
50-
return () => {
51-
if (!props.theme) {
52-
if (appearanceSubscription) {
53-
appearanceSubscription.remove();
54-
} else {
55-
// @ts-expect-error: We keep deprecated listener remove method for backwards compat with old RN versions
56-
Appearance?.removeChangeListener(handleAppearanceChange);
57-
}
58-
}
59-
};
60-
}, [props.theme]);
61-
6229
const theme = React.useMemo<Theme>(() => {
6330
const scheme = colorScheme === 'dark' ? 'dark' : 'light';
6431
const base = defaultThemes[scheme];

src/core/useSystemColorScheme.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import * as React from 'react';
2+
import { Appearance, ColorSchemeName } from 'react-native';
3+
4+
/**
5+
* Subscribes to the OS color-scheme setting via `Appearance.addChangeListener`
6+
* and returns the current value.
7+
*
8+
* When `enabled` is false the hook does not subscribe and returns `'light'` —
9+
* used by `PaperProvider` to skip system tracking when the user has supplied
10+
* an explicit theme.
11+
*/
12+
export function useSystemColorScheme(enabled: boolean): ColorSchemeName {
13+
const [colorScheme, setColorScheme] = React.useState<ColorSchemeName>(() =>
14+
enabled ? Appearance?.getColorScheme() ?? 'light' : 'light'
15+
);
16+
17+
React.useEffect(() => {
18+
if (!enabled) return;
19+
const sub = Appearance?.addChangeListener((preferences) => {
20+
setColorScheme(preferences.colorScheme);
21+
});
22+
return () => {
23+
sub?.remove();
24+
};
25+
}, [enabled]);
26+
27+
return colorScheme;
28+
}

0 commit comments

Comments
 (0)