managarten/apps/picture/apps/mobile/contexts/ThemeContext.tsx
Wuesteon d36b321d9d style: auto-format codebase with Prettier
Applied formatting to 1487+ files using pnpm format:write
  - TypeScript/JavaScript files
  - Svelte components
  - Astro pages
  - JSON configs
  - Markdown docs

  13 files still need manual review (Astro JSX comments)
2025-11-27 18:33:16 +01:00

56 lines
1.7 KiB
TypeScript

import React, { createContext, useContext, useEffect, ReactNode } from 'react';
import { StatusBar } from 'react-native';
import { useThemeStore, useTheme as useThemeHook } from '~/store/themeStore';
import type { NativeTheme as Theme, ThemeVariant, ColorMode } from '@picture/design-tokens/native';
// ThemeMode includes 'system' for automatic light/dark switching
type ThemeMode = ColorMode | 'system';
interface ThemeContextValue {
theme: Theme;
variant: ThemeVariant;
mode: ThemeMode;
actualMode: 'light' | 'dark';
isLoading: boolean;
setVariant: (variant: ThemeVariant) => Promise<void>;
setMode: (mode: ThemeMode) => Promise<void>;
toggleMode: () => void;
}
const ThemeContext = createContext<ThemeContextValue | undefined>(undefined);
interface ThemeProviderProps {
children: ReactNode;
}
export function ThemeProvider({ children }: ThemeProviderProps) {
const loadTheme = useThemeStore((state) => state.loadTheme);
const themeData = useThemeHook();
// Load theme on mount
useEffect(() => {
loadTheme();
}, []);
// Update StatusBar when theme changes
useEffect(() => {
if (!themeData.isLoading) {
StatusBar.setBarStyle(
themeData.actualMode === 'dark' ? 'light-content' : 'dark-content',
true
);
}
}, [themeData.actualMode, themeData.isLoading]);
return <ThemeContext.Provider value={themeData}>{children}</ThemeContext.Provider>;
}
export function useTheme(): ThemeContextValue {
const context = useContext(ThemeContext);
if (context === undefined) {
// During initial render, return the hook directly as fallback
// This prevents crashes when components render before ThemeProvider is ready
return useThemeHook();
}
return context;
}