fix: palette changes now propagate immediately via ThemeContext
Replace useSetting()-based useTheme() with a React context (ThemeProvider + useTheme/usePaletteControl). The context holds palette key in state so pressing a palette button in Settings re-renders all screens instantly. Persists to SQLite and reloads the stored value on mount.
This commit is contained in:
@@ -0,0 +1,51 @@
|
|||||||
|
import { createContext, useContext, useEffect, useState } from 'react';
|
||||||
|
import { useSQLiteContext } from 'expo-sqlite';
|
||||||
|
import { getSetting, setSetting } from '@/db/queries';
|
||||||
|
import { autoKey, PALETTES, type PaletteKey, type Theme } from '@/theme';
|
||||||
|
|
||||||
|
type ThemeCtx = {
|
||||||
|
theme: Theme;
|
||||||
|
paletteKey: PaletteKey;
|
||||||
|
setPaletteOverride: (key: PaletteKey) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ThemeContext = createContext<ThemeCtx>({
|
||||||
|
theme: PALETTES.default,
|
||||||
|
paletteKey: 'auto',
|
||||||
|
setPaletteOverride: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
||||||
|
const db = useSQLiteContext();
|
||||||
|
const [paletteKey, setPaletteKey] = useState<PaletteKey>('auto');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getSetting(db, 'palette_override').then(val => {
|
||||||
|
if (val) setPaletteKey(val as PaletteKey);
|
||||||
|
});
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function setPaletteOverride(key: PaletteKey) {
|
||||||
|
setPaletteKey(key);
|
||||||
|
setSetting(db, 'palette_override', key);
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolved = paletteKey === 'auto' ? autoKey() : paletteKey;
|
||||||
|
const theme = PALETTES[resolved as keyof typeof PALETTES] ?? PALETTES.default;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeContext.Provider value={{ theme, paletteKey, setPaletteOverride }}>
|
||||||
|
{children}
|
||||||
|
</ThemeContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useTheme(): Theme {
|
||||||
|
return useContext(ThemeContext).theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function usePaletteControl(): Pick<ThemeCtx, 'paletteKey' | 'setPaletteOverride'> {
|
||||||
|
const { paletteKey, setPaletteOverride } = useContext(ThemeContext);
|
||||||
|
return { paletteKey, setPaletteOverride };
|
||||||
|
}
|
||||||
@@ -5,7 +5,8 @@ import {
|
|||||||
Text, TextInput, View,
|
Text, TextInput, View,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { deleteRemoteActivities, getSetting, setSetting, useSetting } from '@/db/queries';
|
import { deleteRemoteActivities, getSetting, setSetting, useSetting } from '@/db/queries';
|
||||||
import { PALETTES, type PaletteKey, useTheme } from '@/theme';
|
import { PALETTES, type PaletteKey } from '@/theme';
|
||||||
|
import { useTheme, usePaletteControl } from '@/ThemeContext';
|
||||||
|
|
||||||
export default function SettingsScreen() {
|
export default function SettingsScreen() {
|
||||||
const db = useSQLiteContext();
|
const db = useSQLiteContext();
|
||||||
@@ -24,8 +25,7 @@ export default function SettingsScreen() {
|
|||||||
const [syncUpload, setSyncUpload] = useState(storedSyncUpload);
|
const [syncUpload, setSyncUpload] = useState(storedSyncUpload);
|
||||||
const [saved, setSaved] = useState(false);
|
const [saved, setSaved] = useState(false);
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const storedPalette = (useSetting('palette_override') ?? 'auto') as PaletteKey;
|
const { paletteKey: palette, setPaletteOverride } = usePaletteControl();
|
||||||
const [palette, setPalette] = useState<PaletteKey>(storedPalette);
|
|
||||||
|
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [connecting, setConnecting] = useState(false);
|
const [connecting, setConnecting] = useState(false);
|
||||||
@@ -225,10 +225,7 @@ export default function SettingsScreen() {
|
|||||||
active={palette === key}
|
active={palette === key}
|
||||||
accent={keyAccent}
|
accent={keyAccent}
|
||||||
dim={keyDim}
|
dim={keyDim}
|
||||||
onPress={() => {
|
onPress={() => setPaletteOverride(key)}
|
||||||
setPalette(key);
|
|
||||||
setSetting(db, 'palette_override', key);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -2,12 +2,15 @@ import { Stack } from 'expo-router';
|
|||||||
import { SQLiteProvider } from 'expo-sqlite';
|
import { SQLiteProvider } from 'expo-sqlite';
|
||||||
import { StatusBar } from 'expo-status-bar';
|
import { StatusBar } from 'expo-status-bar';
|
||||||
import { migrateDb } from '@/db';
|
import { migrateDb } from '@/db';
|
||||||
|
import { ThemeProvider } from '@/ThemeContext';
|
||||||
|
|
||||||
export default function RootLayout() {
|
export default function RootLayout() {
|
||||||
return (
|
return (
|
||||||
<SQLiteProvider databaseName="bincio.db" onInit={migrateDb}>
|
<SQLiteProvider databaseName="bincio.db" onInit={migrateDb}>
|
||||||
<StatusBar style="light" />
|
<ThemeProvider>
|
||||||
<Stack screenOptions={{ headerShown: false }} />
|
<StatusBar style="light" />
|
||||||
|
<Stack screenOptions={{ headerShown: false }} />
|
||||||
|
</ThemeProvider>
|
||||||
</SQLiteProvider>
|
</SQLiteProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { useSetting } from '@/db/queries';
|
|
||||||
|
|
||||||
export type PaletteKey = 'auto' | 'default' | 'giro' | 'tour' | 'vuelta';
|
export type PaletteKey = 'auto' | 'default' | 'giro' | 'tour' | 'vuelta';
|
||||||
|
|
||||||
export const PALETTES = {
|
export const PALETTES = {
|
||||||
@@ -29,8 +27,3 @@ export function autoKey(): Exclude<PaletteKey, 'auto'> {
|
|||||||
return 'default';
|
return 'default';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useTheme(): Theme {
|
|
||||||
const override = (useSetting('palette_override') ?? 'auto') as PaletteKey;
|
|
||||||
const key = override === 'auto' ? autoKey() : override;
|
|
||||||
return PALETTES[key as keyof typeof PALETTES] ?? PALETTES.default;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user