- Remove __DEV__ debug section from settings.tsx: Plan-Override-Row (4 rows: LLM, TTS, plan-override, realtime), PlanPickerSheetContent, planSheetRef, DEV_PLANS/DEV_PLAN_ACCENT, ActivityIndicator import. The debug.tsx page + realtimeDebug.ts store are kept — only UI entry points removed from settings. - Wire notifications section: pushEnabled/streakReminderEnabled toggles + streakReminderTime picker (hour/minute scroll, quarters). State persisted in AsyncStorage via new stores/notificationPrefs.ts. setPushEnabled calls Notifications.requestPermissionsAsync() — if denied, toggle stays off. scheduleNotificationAsync is a TODO (no backend endpoint yet). - Add _layout.tsx Stack.Screen entry for help/* route group. - i18n: new keys settings.notifications_push_sublabel, notifications_streak_time, notifications_hour/minute, section_help, help_faq/contact/about/crisis + descs in DE/EN/FR. TODO: expo-notifications scheduleNotificationAsync wiring once backend streak-reminder endpoint exists. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
64 lines
2.2 KiB
TypeScript
64 lines
2.2 KiB
TypeScript
import { create } from 'zustand';
|
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
import * as Notifications from 'expo-notifications';
|
|
|
|
const STORAGE_KEY = '@rebreak/notifications-prefs';
|
|
|
|
type NotificationPrefsState = {
|
|
pushEnabled: boolean;
|
|
streakReminderEnabled: boolean;
|
|
streakReminderTime: { hour: number; minute: number };
|
|
|
|
init: () => Promise<void>;
|
|
setPushEnabled: (value: boolean) => Promise<void>;
|
|
setStreakReminderEnabled: (value: boolean) => Promise<void>;
|
|
setStreakReminderTime: (hour: number, minute: number) => Promise<void>;
|
|
};
|
|
|
|
async function persist(patch: Partial<Pick<NotificationPrefsState, 'pushEnabled' | 'streakReminderEnabled' | 'streakReminderTime'>>) {
|
|
const existing = await AsyncStorage.getItem(STORAGE_KEY);
|
|
const current = existing ? JSON.parse(existing) : {};
|
|
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify({ ...current, ...patch }));
|
|
}
|
|
|
|
export const useNotificationPrefsStore = create<NotificationPrefsState>((set, get) => ({
|
|
pushEnabled: false,
|
|
streakReminderEnabled: false,
|
|
streakReminderTime: { hour: 9, minute: 0 },
|
|
|
|
init: async () => {
|
|
const stored = await AsyncStorage.getItem(STORAGE_KEY);
|
|
if (!stored) return;
|
|
const parsed = JSON.parse(stored);
|
|
set({
|
|
pushEnabled: parsed.pushEnabled ?? false,
|
|
streakReminderEnabled: parsed.streakReminderEnabled ?? false,
|
|
streakReminderTime: parsed.streakReminderTime ?? { hour: 9, minute: 0 },
|
|
});
|
|
},
|
|
|
|
// TODO: wire up expo-notifications requestPermissionsAsync + scheduleNotificationAsync
|
|
// once the streak reminder backend endpoint exists. Currently persists user intent only.
|
|
setPushEnabled: async (value) => {
|
|
if (value) {
|
|
const { status } = await Notifications.requestPermissionsAsync();
|
|
if (status !== 'granted') {
|
|
return;
|
|
}
|
|
}
|
|
set({ pushEnabled: value });
|
|
await persist({ pushEnabled: value });
|
|
},
|
|
|
|
setStreakReminderEnabled: async (value) => {
|
|
set({ streakReminderEnabled: value });
|
|
await persist({ streakReminderEnabled: value });
|
|
},
|
|
|
|
setStreakReminderTime: async (hour, minute) => {
|
|
const streakReminderTime = { hour, minute };
|
|
set({ streakReminderTime });
|
|
await persist({ streakReminderTime });
|
|
},
|
|
}));
|