feat: allow users to override color scheme (closes #138)
This commit is contained in:
@@ -1,18 +1,18 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import React, { PropsWithChildren, useEffect } from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import TrackPlayer, { Capability } from 'react-native-track-player';
|
||||
import { PersistGate } from 'redux-persist/integration/react';
|
||||
import Routes from '../screens';
|
||||
import store, { persistedStore } from 'store';
|
||||
import store, { persistedStore, useTypedSelector } from 'store';
|
||||
import {
|
||||
NavigationContainer,
|
||||
DefaultTheme,
|
||||
DarkTheme as BaseDarkTheme,
|
||||
} from '@react-navigation/native';
|
||||
import { useColorScheme } from 'react-native';
|
||||
import { ColorSchemeContext, themes } from './Colors';
|
||||
import { ColorSchemeProvider, themes } from './Colors';
|
||||
import DownloadManager from './DownloadManager';
|
||||
// import ErrorReportingAlert from 'utility/ErrorReportingAlert';
|
||||
import { useColorScheme } from 'react-native';
|
||||
import { ColorScheme } from 'store/settings/types';
|
||||
|
||||
const LightTheme = {
|
||||
...DefaultTheme,
|
||||
@@ -30,14 +30,29 @@ const DarkTheme = {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a convenience wrapper for NavigationContainer that ensures that the
|
||||
* right theme is selected based on OS color scheme settings along with user preferences.
|
||||
*/
|
||||
function ThemedNavigationContainer({ children }: PropsWithChildren<{}>) {
|
||||
const systemScheme = useColorScheme();
|
||||
const userScheme = useTypedSelector((state) => state.settings.colorScheme);
|
||||
const scheme = userScheme === ColorScheme.System ? systemScheme : userScheme;
|
||||
|
||||
return (
|
||||
<NavigationContainer
|
||||
theme={scheme === 'dark' ? DarkTheme : LightTheme}
|
||||
>
|
||||
{children}
|
||||
</NavigationContainer>
|
||||
);
|
||||
}
|
||||
|
||||
// Track whether the player has already been setup, so that we don't
|
||||
// accidentally do it twice.
|
||||
let hasSetupPlayer = false;
|
||||
|
||||
export default function App(): JSX.Element {
|
||||
const colorScheme = useColorScheme();
|
||||
const theme = themes[colorScheme || 'light'];
|
||||
|
||||
useEffect(() => {
|
||||
async function setupTrackPlayer() {
|
||||
await TrackPlayer.setupPlayer();
|
||||
@@ -63,14 +78,12 @@ export default function App(): JSX.Element {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<PersistGate loading={null} persistor={persistedStore}>
|
||||
<ColorSchemeContext.Provider value={theme}>
|
||||
<NavigationContainer
|
||||
theme={colorScheme === 'dark' ? DarkTheme : LightTheme}
|
||||
>
|
||||
<ColorSchemeProvider>
|
||||
<ThemedNavigationContainer>
|
||||
<Routes />
|
||||
<DownloadManager />
|
||||
</NavigationContainer>
|
||||
</ColorSchemeContext.Provider>
|
||||
</ThemedNavigationContainer>
|
||||
</ColorSchemeProvider>
|
||||
</PersistGate>
|
||||
</Provider>
|
||||
);
|
||||
|
||||
@@ -3,6 +3,8 @@ import { THEME_COLOR } from 'CONSTANTS';
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { useContext } from 'react';
|
||||
import { ColorSchemeName, Platform, StyleSheet, View, useColorScheme } from 'react-native';
|
||||
import { useTypedSelector } from 'store';
|
||||
import { ColorScheme } from 'store/settings/types';
|
||||
|
||||
const majorPlatformVersion = typeof Platform.Version === 'string' ? parseInt(Platform.Version, 10) : Platform.Version;
|
||||
|
||||
@@ -77,6 +79,22 @@ export const themes: Record<'dark' | 'light', ReturnType<typeof generateStyles>>
|
||||
// Create context for supplying the theming information
|
||||
export const ColorSchemeContext = React.createContext(themes.dark);
|
||||
|
||||
/**
|
||||
* This provider contains the logic for settings the right theme on the ColorSchemeContext.
|
||||
*/
|
||||
export function ColorSchemeProvider({ children }: PropsWithChildren<{}>) {
|
||||
const systemScheme = useColorScheme();
|
||||
const userScheme = useTypedSelector((state) => state.settings.colorScheme);
|
||||
const scheme = userScheme === ColorScheme.System ? systemScheme : userScheme;
|
||||
const theme = themes[scheme || 'light'];
|
||||
|
||||
return (
|
||||
<ColorSchemeContext.Provider value={theme}>
|
||||
{children}
|
||||
</ColorSchemeContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the default styles object in hook form
|
||||
*/
|
||||
@@ -98,13 +116,15 @@ export function DefaultStylesProvider(props: DefaultStylesProviderProps) {
|
||||
}
|
||||
|
||||
export function ColoredBlurView(props: PropsWithChildren<BlurViewProps>) {
|
||||
const scheme = useColorScheme();
|
||||
const systemScheme = useColorScheme();
|
||||
const userScheme = useTypedSelector((state) => state.settings.colorScheme);
|
||||
const scheme = userScheme === ColorScheme.System ? systemScheme : userScheme;
|
||||
|
||||
return Platform.OS === 'ios' ? (
|
||||
<BlurView
|
||||
{...props}
|
||||
blurType={Platform.OS === 'ios' && majorPlatformVersion >= 13
|
||||
? 'material'
|
||||
? scheme === 'dark' ? 'materialDark' : 'materialLight'
|
||||
: scheme === 'dark' ? 'extraDark' : 'xlight'
|
||||
} />
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user