feat(mobile): Implement persistent theme selection
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { StyleSheet, TouchableOpacity } from 'react-native';
|
||||
|
||||
import { ThemedText } from '@/components/themed-text';
|
||||
import { ThemedView } from '@/components/themed-view';
|
||||
import { IconSymbol } from '@/components/ui/icon-symbol';
|
||||
import { Colors } from '@/constants/theme';
|
||||
import { useTheme } from '@/context/ThemeContext';
|
||||
import { useColorScheme } from '@/hooks/use-color-scheme';
|
||||
|
||||
export default function SettingsScreen() {
|
||||
const colorScheme = useColorScheme();
|
||||
const { themeMode, setThemeMode } = useTheme();
|
||||
const theme = colorScheme ?? 'light';
|
||||
|
||||
const cardStyle = [
|
||||
@@ -25,21 +28,32 @@ export default function SettingsScreen() {
|
||||
</ThemedView>
|
||||
|
||||
<ThemedView style={styles.sectionHeader}>
|
||||
<ThemedText type="subtitle">Account</ThemedText>
|
||||
<ThemedText type="subtitle">Appearance</ThemedText>
|
||||
</ThemedView>
|
||||
<ThemedView style={cardStyle} variant="card">
|
||||
<ThemedText style={styles.item}>Profile</ThemedText>
|
||||
<ThemedText style={styles.item}>Notifications</ThemedText>
|
||||
<ThemedText style={[styles.item, styles.lastItem]}>Privacy</ThemedText>
|
||||
</ThemedView>
|
||||
<TouchableOpacity
|
||||
style={styles.item}
|
||||
onPress={() => setThemeMode('light')}
|
||||
>
|
||||
<ThemedText>Light Mode</ThemedText>
|
||||
{themeMode === 'light' && <IconSymbol name="checkmark" size={20} color={Colors[theme].tint} />}
|
||||
</TouchableOpacity>
|
||||
|
||||
<ThemedView style={styles.sectionHeader}>
|
||||
<ThemedText type="subtitle">General</ThemedText>
|
||||
</ThemedView>
|
||||
<ThemedView style={cardStyle} variant="card">
|
||||
<ThemedText style={styles.item}>About</ThemedText>
|
||||
<ThemedText style={styles.item}>Help & Support</ThemedText>
|
||||
<ThemedText style={[styles.item, styles.lastItem]}>Sign Out</ThemedText>
|
||||
<TouchableOpacity
|
||||
style={styles.item}
|
||||
onPress={() => setThemeMode('dark')}
|
||||
>
|
||||
<ThemedText>Dark Mode</ThemedText>
|
||||
{themeMode === 'dark' && <IconSymbol name="checkmark" size={20} color={Colors[theme].tint} />}
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
style={[styles.item, styles.lastItem]}
|
||||
onPress={() => setThemeMode('system')}
|
||||
>
|
||||
<ThemedText>System Default</ThemedText>
|
||||
{themeMode === 'system' && <IconSymbol name="checkmark" size={20} color={Colors[theme].tint} />}
|
||||
</TouchableOpacity>
|
||||
</ThemedView>
|
||||
</ThemedView>
|
||||
);
|
||||
@@ -71,6 +85,9 @@ const styles = StyleSheet.create({
|
||||
padding: 16,
|
||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||
borderBottomColor: 'rgba(0,0,0,0.05)',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
lastItem: {
|
||||
borderBottomWidth: 0,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
|
||||
import { DarkTheme, DefaultTheme, ThemeProvider as NavigationThemeProvider } from '@react-navigation/native';
|
||||
import { Stack } from 'expo-router';
|
||||
import { StatusBar } from 'expo-status-bar';
|
||||
import 'react-native-reanimated';
|
||||
|
||||
import { ThemeProvider } from '@/context/ThemeContext';
|
||||
import { useColorScheme } from '@/hooks/use-color-scheme';
|
||||
|
||||
export const unstable_settings = {
|
||||
@@ -10,15 +11,23 @@ export const unstable_settings = {
|
||||
};
|
||||
|
||||
export default function RootLayout() {
|
||||
return (
|
||||
<ThemeProvider>
|
||||
<RootLayoutNav />
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function RootLayoutNav() {
|
||||
const colorScheme = useColorScheme();
|
||||
|
||||
return (
|
||||
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
|
||||
<NavigationThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
|
||||
<Stack>
|
||||
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
||||
<Stack.Screen name="modal" options={{ presentation: 'modal', title: 'Modal' }} />
|
||||
</Stack>
|
||||
<StatusBar style="auto" />
|
||||
</ThemeProvider>
|
||||
</NavigationThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user