diff --git a/carry-your-live/app/(tabs)/settings.tsx b/carry-your-live/app/(tabs)/settings.tsx index 8112adc..c24f068 100644 --- a/carry-your-live/app/(tabs)/settings.tsx +++ b/carry-your-live/app/(tabs)/settings.tsx @@ -74,7 +74,9 @@ export default function SettingsScreen() { loadSettingsFromServer, } = useSettings(); const categories = useCategories(); - const [picker, setPicker] = useState(null); + const [picker, setPicker] = useState< + null | 'category' | 'sort' | 'reminder' | 'todoAhead' | 'themeMode' + >(null); const [reminderTagPicker, setReminderTagPicker] = useState(null); const [editingCategory, setEditingCategory] = useState(null); const [syncVisible, setSyncVisible] = useState(false); @@ -245,7 +247,7 @@ export default function SettingsScreen() { rightElement={ { + onValueChange={async value => { setNotifications(value); if (!value) { const { cancelAllReminders } = await import('@/services/notifications'); @@ -358,6 +360,15 @@ export default function SettingsScreen() { onPress={openCustomAccent} showChevron /> + Theme + setPicker('themeMode')} + showChevron + /> Data setSyncVisible(true)} showChevron /> + { + try { + await syncSettingsToServer(); + Alert.alert('Success', 'Settings synced to server'); + } catch { + Alert.alert('Error', 'Failed to sync settings'); + } + }} + showChevron + /> + { + try { + await loadSettingsFromServer(); + Alert.alert('Success', 'Settings loaded from server'); + } catch { + Alert.alert('Error', 'Failed to load settings'); + } + }} + showChevron + /> setPicker(null)} /> + setThemeMode(value as ThemeMode)} + onClose={() => setPicker(null)} + /> + 0.5 ? '#111111' : '#FFFFFF'; } -export function colors(accent: string = DEFAULT_ACCENT, mode: ThemeMode = 'dark', opacity: number = 1): ThemeColors { +export function colors( + accent: string = DEFAULT_ACCENT, + mode: ThemeMode = 'dark', + opacity: number = 1 +): ThemeColors { const softAccent = desaturate(accent, 0.35); - const accentWithOpacity = opacity < 1 ? `${opacity.toString(16).padStart(2, '0')}${accent.slice(1)}` : accent; - + const accentWithOpacity = + opacity < 1 ? `${opacity.toString(16).padStart(2, '0')}${accent.slice(1)}` : accent; + if (mode === 'light') { return { background: '#FFFFFF', @@ -144,7 +157,7 @@ export function colors(accent: string = DEFAULT_ACCENT, mode: ThemeMode = 'dark' info: '#1E88E5', }; } - + // dark mode return { background: '#121212', @@ -289,34 +302,52 @@ export function SettingsProvider({ children }: { children: ReactNode }) { STORAGE_KEYS.reminderPreference, '15' ); - const [tagReminderPreferences, setTagReminderPreferences] = useStoredSetting( - STORAGE_KEYS.tagReminderPreferences, - {} - ); + const [tagReminderPreferences, setTagReminderPreferences] = + useStoredSetting(STORAGE_KEYS.tagReminderPreferences, {}); const [apiUrl, setApiUrl] = useStoredSetting(API_URL_KEY, DEFAULT_API_BASE_URL); - const [accentColor, setAccentColor] = useStoredSetting(STORAGE_KEYS.accentColor, DEFAULT_ACCENT); - const [accentOpacity, setAccentOpacity] = useStoredSetting(STORAGE_KEYS.accentOpacity, DEFAULT_ACCENT_OPACITY); - const [todoAheadDays, setTodoAheadDays] = useStoredSetting(STORAGE_KEYS.todoAheadDays, DEFAULT_TODO_AHEAD_DAYS); - const [showCompleted, setShowCompleted] = useStoredSetting(STORAGE_KEYS.showCompleted, false); - const [deleteBySwipe, setDeleteBySwipe] = useStoredSetting(STORAGE_KEYS.deleteBySwipe, false); + const [accentColor, setAccentColor] = useStoredSetting( + STORAGE_KEYS.accentColor, + DEFAULT_ACCENT + ); + const [accentOpacity, setAccentOpacity] = useStoredSetting( + STORAGE_KEYS.accentOpacity, + DEFAULT_ACCENT_OPACITY + ); + const [todoAheadDays, setTodoAheadDays] = useStoredSetting( + STORAGE_KEYS.todoAheadDays, + DEFAULT_TODO_AHEAD_DAYS + ); + const [showCompleted, setShowCompleted] = useStoredSetting( + STORAGE_KEYS.showCompleted, + false + ); + const [deleteBySwipe, setDeleteBySwipe] = useStoredSetting( + STORAGE_KEYS.deleteBySwipe, + false + ); const [themeMode, setThemeMode, themeModeLoaded] = useStoredSetting( STORAGE_KEYS.themeMode, 'system' ); - const effectiveMode = themeMode === 'system' - ? (Platform.OS === 'web' ? 'dark' : 'dark') // Will be updated by useColorScheme in real app - : themeMode; + const effectiveMode: 'light' | 'dark' = + themeMode === 'system' + ? 'dark' // Will be updated by useColorScheme in real app + : themeMode; - const theme = useMemo(() => colors(accentColor, effectiveMode, accentOpacity), [accentColor, effectiveMode, accentOpacity]); + const theme = useMemo( + () => colors(accentColor, effectiveMode, accentOpacity), + [accentColor, effectiveMode, accentOpacity] + ); const syncSettingsToServer = useCallback(async () => { const { getAuthToken } = await import('@/services/auth'); const token = await getAuthToken(); if (!token) return; - + + const isDark = effectiveMode === 'dark'; const settings = { - darkMode: effectiveMode === 'dark' || (themeMode === 'system' && effectiveMode === 'dark'), + darkMode: isDark, defaultCategoryId, sortOrder: sortBy, reminderPreference, @@ -325,13 +356,23 @@ export function SettingsProvider({ children }: { children: ReactNode }) { deleteBySwipe, }; await pushServerSettings(apiUrl, token, settings); - }, [apiUrl, effectiveMode, themeMode, defaultCategoryId, sortBy, reminderPreference, todoAheadDays, showCompleted, deleteBySwipe]); + }, [ + apiUrl, + effectiveMode, + themeMode, + defaultCategoryId, + sortBy, + reminderPreference, + todoAheadDays, + showCompleted, + deleteBySwipe, + ]); const loadSettingsFromServer = useCallback(async () => { const { getAuthToken } = await import('@/services/auth'); const token = await getAuthToken(); if (!token) return; - + const serverSettings = await fetchServerSettings(apiUrl, token); if (!serverSettings) return; @@ -344,7 +385,16 @@ export function SettingsProvider({ children }: { children: ReactNode }) { if (serverSettings.todoAheadDays !== undefined) setTodoAheadDays(serverSettings.todoAheadDays); if (serverSettings.showCompleted !== undefined) setShowCompleted(serverSettings.showCompleted); if (serverSettings.deleteBySwipe !== undefined) setDeleteBySwipe(serverSettings.deleteBySwipe); - }, [apiUrl, setThemeMode, setDefaultCategoryId, setSortBy, setReminderPreference, setTodoAheadDays, setShowCompleted, setDeleteBySwipe]); + }, [ + apiUrl, + setThemeMode, + setDefaultCategoryId, + setSortBy, + setReminderPreference, + setTodoAheadDays, + setShowCompleted, + setDeleteBySwipe, + ]); const value = useMemo( () => ({ @@ -407,11 +457,7 @@ export function SettingsProvider({ children }: { children: ReactNode }) { ] ); - return ( - - {children} - - ); + return {children}; } export function useSettings() { @@ -422,4 +468,4 @@ export function useSettings() { return context; } -export * from './theme/tokens'; \ No newline at end of file +export * from './theme/tokens';