- Phase 3 PW-Reset: 3 screens (forgot-password → reset-otp → new-password),
verifyOtp({type:'recovery'}), new updatePassword() action
- Custom Brevo-Mail templates (backend/public/templates/) — 5 HTMLs with
go-template i18n (de/en/fr/ar incl. RTL for AR), OTP-only (no link),
ReBreak branding
- signUp metadata.data.locale aus i18n.language → templates resolven Sprache
- Account-Switch-Bug fix: signOut() resettet alle 10 user-spezifischen stores
+ invalidateMe()
60 lines
1.5 KiB
TypeScript
60 lines
1.5 KiB
TypeScript
import { create } from 'zustand';
|
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
|
|
/**
|
|
* Persistente User-Preference für Lyra-TTS-Auto-Play.
|
|
*
|
|
* Default OFF — User aktiviert einmal in der Welcome-Slide via Audio-Button,
|
|
* danach playt Lyra auf jeder Slide automatisch. Erneutes Tappen disabled
|
|
* + stoppt aktuelles Playback.
|
|
*
|
|
* Persistence: AsyncStorage @rebreak/lyraVoiceEnabled. Init beim App-Start
|
|
* via `init()` (analog zu language/theme/appLock-Stores).
|
|
*/
|
|
|
|
const STORAGE_KEY = '@rebreak/lyraVoiceEnabled';
|
|
|
|
type LyraVoiceState = {
|
|
enabled: boolean;
|
|
ready: boolean;
|
|
init: () => Promise<void>;
|
|
setEnabled: (enabled: boolean) => Promise<void>;
|
|
toggle: () => Promise<void>;
|
|
reset: () => Promise<void>;
|
|
};
|
|
|
|
export const useLyraVoiceStore = create<LyraVoiceState>((set, get) => ({
|
|
enabled: false,
|
|
ready: false,
|
|
|
|
init: async () => {
|
|
try {
|
|
const stored = await AsyncStorage.getItem(STORAGE_KEY);
|
|
set({ enabled: stored === '1', ready: true });
|
|
} catch {
|
|
set({ enabled: false, ready: true });
|
|
}
|
|
},
|
|
|
|
setEnabled: async (enabled: boolean) => {
|
|
set({ enabled });
|
|
try {
|
|
await AsyncStorage.setItem(STORAGE_KEY, enabled ? '1' : '0');
|
|
} catch {
|
|
// ignore — in-memory state ist wichtiger
|
|
}
|
|
},
|
|
|
|
toggle: async () => {
|
|
const next = !get().enabled;
|
|
await get().setEnabled(next);
|
|
},
|
|
|
|
reset: async () => {
|
|
set({ enabled: false });
|
|
try {
|
|
await AsyncStorage.removeItem(STORAGE_KEY);
|
|
} catch {}
|
|
},
|
|
}));
|