Waseel: driver app, dispatch, POI suggestions, map fixes
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
import * as SecureStore from "expo-secure-store";
|
||||
import { create } from "zustand";
|
||||
|
||||
/**
|
||||
* Theme, language, keep-awake, and the overlay-permission flag are the only
|
||||
* non-secret app preferences. SecureStore is used (not AsyncStorage) because
|
||||
* AsyncStorage isn't actually installed in this project and SecureStore already
|
||||
* backs the session — one small JSON blob stays well under its 2 KB value cap.
|
||||
*/
|
||||
const SETTINGS_KEY = "waseel_settings";
|
||||
|
||||
export type ThemeMode = "light" | "dark" | "system";
|
||||
export type Lang = "en" | "ar" | "fr";
|
||||
|
||||
type PersistedSettings = Pick<
|
||||
SettingsState,
|
||||
"mode" | "lang" | "keepAwake" | "overlayRequested"
|
||||
>;
|
||||
|
||||
type SettingsState = {
|
||||
/** False until hydrate() has merged SecureStore values into the store. */
|
||||
hydrated: boolean;
|
||||
mode: ThemeMode;
|
||||
lang: Lang;
|
||||
keepAwake: boolean;
|
||||
/**
|
||||
* Only records that we sent the user to the system screen — SYSTEM_ALERT_WINDOW
|
||||
* can't be queried from JS, so this is not a granted/denied signal.
|
||||
*/
|
||||
overlayRequested: boolean;
|
||||
|
||||
setMode: (mode: ThemeMode) => void;
|
||||
setLang: (lang: Lang) => void;
|
||||
setKeepAwake: (value: boolean) => void;
|
||||
setOverlayRequested: (value: boolean) => void;
|
||||
hydrate: () => Promise<void>;
|
||||
};
|
||||
|
||||
const write = async (state: SettingsState) => {
|
||||
const blob: PersistedSettings = {
|
||||
mode: state.mode,
|
||||
lang: state.lang,
|
||||
keepAwake: state.keepAwake,
|
||||
overlayRequested: state.overlayRequested,
|
||||
};
|
||||
|
||||
await SecureStore.setItemAsync(SETTINGS_KEY, JSON.stringify(blob));
|
||||
};
|
||||
|
||||
export const useSettingsStore = create<SettingsState>((set, get) => ({
|
||||
hydrated: false,
|
||||
mode: "system",
|
||||
lang: "en",
|
||||
keepAwake: false,
|
||||
overlayRequested: false,
|
||||
|
||||
setMode: (mode) => {
|
||||
set({ mode });
|
||||
void write(get());
|
||||
},
|
||||
setLang: (lang) => {
|
||||
set({ lang });
|
||||
void write(get());
|
||||
},
|
||||
setKeepAwake: (value) => {
|
||||
set({ keepAwake: value });
|
||||
void write(get());
|
||||
},
|
||||
setOverlayRequested: (value) => {
|
||||
set({ overlayRequested: value });
|
||||
void write(get());
|
||||
},
|
||||
|
||||
hydrate: async () => {
|
||||
try {
|
||||
const stored = await SecureStore.getItemAsync(SETTINGS_KEY);
|
||||
|
||||
if (stored) {
|
||||
const parsed = JSON.parse(stored) as Partial<PersistedSettings>;
|
||||
|
||||
set({
|
||||
mode: parsed.mode ?? "system",
|
||||
lang: parsed.lang ?? "en",
|
||||
keepAwake: parsed.keepAwake ?? false,
|
||||
overlayRequested: parsed.overlayRequested ?? false,
|
||||
hydrated: true,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("[SETTINGS hydrate]: ", error);
|
||||
}
|
||||
|
||||
set({ hydrated: true });
|
||||
},
|
||||
}));
|
||||
Reference in New Issue
Block a user