- AppDelegate: NSLog for didUpdate token, didInvalidate, didReceiveIncomingPush - backend/push: log [push-token] register, [call-ring] receiver token-counts + expo-push-fanout for android-fallback - app/call.tsx: 250ms grace window before closeScreen on initial idle (fixes 'foreground call flashes briefly then disappears' race when dm.tsx startCall set() hasn't propagated through useCallStore selector yet)
87 lines
3.0 KiB
TypeScript
87 lines
3.0 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 };
|
|
/** iOS-CallKit: ReBreak-Calls in nat. "Anrufe"-App + iCloud-Sync.
|
|
* Default false (DSGVO/Art.9 — Sucht-Zielgruppe). Opt-in via Settings.
|
|
* Änderung wird erst nach App-Neustart wirksam. */
|
|
callsInRecents: boolean;
|
|
|
|
init: () => Promise<void>;
|
|
setPushEnabled: (value: boolean) => Promise<void>;
|
|
setStreakReminderEnabled: (value: boolean) => Promise<void>;
|
|
setStreakReminderTime: (hour: number, minute: number) => Promise<void>;
|
|
setCallsInRecents: (value: boolean) => Promise<void>;
|
|
reset: () => Promise<void>;
|
|
};
|
|
|
|
async function persist(patch: Partial<Pick<NotificationPrefsState, 'pushEnabled' | 'streakReminderEnabled' | 'streakReminderTime' | 'callsInRecents'>>) {
|
|
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: true,
|
|
streakReminderEnabled: false,
|
|
streakReminderTime: { hour: 9, minute: 0 },
|
|
callsInRecents: false,
|
|
|
|
init: async () => {
|
|
const stored = await AsyncStorage.getItem(STORAGE_KEY);
|
|
if (!stored) {
|
|
await persist({ pushEnabled: true });
|
|
return;
|
|
}
|
|
const parsed = JSON.parse(stored);
|
|
set({
|
|
pushEnabled: parsed.pushEnabled ?? true,
|
|
streakReminderEnabled: parsed.streakReminderEnabled ?? false,
|
|
streakReminderTime: parsed.streakReminderTime ?? { hour: 9, minute: 0 },
|
|
callsInRecents: parsed.callsInRecents ?? false,
|
|
});
|
|
},
|
|
|
|
// 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 });
|
|
},
|
|
|
|
setCallsInRecents: async (value) => {
|
|
set({ callsInRecents: value });
|
|
await persist({ callsInRecents: value });
|
|
},
|
|
|
|
reset: async () => {
|
|
set({ pushEnabled: false, streakReminderEnabled: false, streakReminderTime: { hour: 9, minute: 0 }, callsInRecents: false });
|
|
try {
|
|
await AsyncStorage.removeItem(STORAGE_KEY);
|
|
} catch {}
|
|
},
|
|
}));
|