Theme-switch in Settings (System/Light/Dark) jetzt App-weit wirksam für die
Core-Screens. Wave 2 dokumentiert (siehe unten).
Color-System:
- lib/theme.ts: refactored zu colors.light + colors.dark (gleiche keys)
Light: bg #fff, surface #fafafa, surfaceElevated #f5f5f5, border #e5e5e5,
text #0a0a0a, textMuted #737373
Dark: bg #000, surface #1c1c1e, surfaceElevated #2c2c2e, border #38383a,
text #fff, textMuted #8e8e93
brandOrange unverändert #007AFF (iOS system blue)
success/error variieren (light: #16a34a/#dc2626, dark: #30d158/#ff453a)
- legacy `colors` export bleibt als Light-Fallback für nicht-migrierte Files
- new `useColors()` hook → liest aktiven scheme aus useThemeStore
stores/theme.ts:
- Appearance.addChangeListener für live System-Theme-Updates (User schaltet
iOS Dark/Light → App reagiert sofort ohne Reload)
Wave 1 — migrated Files (Core Screens):
- app/_layout.tsx + app/(app)/_layout.tsx + app/(app)/index.tsx (root + home)
- app/settings.tsx (full theme-aware inkl. TrueSheet)
- app/profile/index.tsx (bg + dividers)
- app/devices.tsx (bg, surface, border, icons)
- app/lyra.tsx (chat container, backdrop, bubbles, ThinkingDots, LoadingPulse)
- components/AppHeader (Nativewind classes ersetzt durch theme-aware Styles)
- components/header/HeaderDropdownMenu
- components/profile/* (ProfileHeader, StatsBar, StreakSection, UrgeStatsCard,
ApprovedDomainsList, DemographicsAccordion)
Wave 2 (TODOs für separate Session):
- app/urge.tsx (~20 hardcoded colors, größter Screen)
- app/room.tsx, app/dm.tsx, app/(app)/chat.tsx, app/(app)/mail.tsx, app/(app)/coach.tsx
- app/games.tsx, app/profile/[userId].tsx
- Nativewind classes in PostCard, ComposeCard, PostCardSkeleton, NotificationsDropdown
StatusBar style dynamisch synchronisiert (light bei dark-mode, dark bei light).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
48 lines
1.3 KiB
TypeScript
48 lines
1.3 KiB
TypeScript
import { create } from 'zustand';
|
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
import { Appearance } from 'react-native';
|
|
|
|
export type ThemeMode = 'system' | 'light' | 'dark';
|
|
|
|
const STORAGE_KEY = '@rebreak/theme';
|
|
|
|
function resolveColorScheme(mode: ThemeMode): 'light' | 'dark' {
|
|
if (mode === 'system') {
|
|
return Appearance.getColorScheme() === 'dark' ? 'dark' : 'light';
|
|
}
|
|
return mode;
|
|
}
|
|
|
|
type ThemeState = {
|
|
mode: ThemeMode;
|
|
colorScheme: 'light' | 'dark';
|
|
setMode: (mode: ThemeMode) => Promise<void>;
|
|
init: () => Promise<void>;
|
|
};
|
|
|
|
export const useThemeStore = create<ThemeState>((set, get) => {
|
|
// Listen for OS-level theme changes and update store when mode === 'system'.
|
|
Appearance.addChangeListener(() => {
|
|
if (get().mode === 'system') {
|
|
set({ colorScheme: resolveColorScheme('system') });
|
|
}
|
|
});
|
|
|
|
return {
|
|
mode: 'system',
|
|
colorScheme: 'light',
|
|
|
|
init: async () => {
|
|
const stored = await AsyncStorage.getItem(STORAGE_KEY);
|
|
const mode: ThemeMode =
|
|
stored === 'light' || stored === 'dark' || stored === 'system' ? stored : 'system';
|
|
set({ mode, colorScheme: resolveColorScheme(mode) });
|
|
},
|
|
|
|
setMode: async (mode) => {
|
|
await AsyncStorage.setItem(STORAGE_KEY, mode);
|
|
set({ mode, colorScheme: resolveColorScheme(mode) });
|
|
},
|
|
};
|
|
});
|