53 lines
1.6 KiB
TypeScript
53 lines
1.6 KiB
TypeScript
import {
|
|
activateKeepAwakeAsync,
|
|
deactivateKeepAwake,
|
|
} from "expo-keep-awake";
|
|
import { I18nManager } from "react-native";
|
|
import { useEffect, type ReactNode } from "react";
|
|
|
|
import { useSettingsStore } from "@/lib/settings";
|
|
|
|
const KEEP_AWAKE_TAG = "waseel-settings";
|
|
|
|
/**
|
|
* Boots the settings store and owns the two cross-cutting side-effects that
|
|
* must run for the whole app lifetime regardless of which screen is mounted:
|
|
* the keep-awake wake lock (imperative, so it survives navigation away from
|
|
* Settings) and the Arabic RTL flip.
|
|
*/
|
|
export const SettingsProvider = ({ children }: { children: ReactNode }) => {
|
|
const hydrated = useSettingsStore((state) => state.hydrated);
|
|
const keepAwake = useSettingsStore((state) => state.keepAwake);
|
|
const lang = useSettingsStore((state) => state.lang);
|
|
const hydrate = useSettingsStore((state) => state.hydrate);
|
|
|
|
useEffect(() => {
|
|
void hydrate();
|
|
}, [hydrate]);
|
|
|
|
useEffect(() => {
|
|
if (keepAwake) {
|
|
activateKeepAwakeAsync(KEEP_AWAKE_TAG).catch((error) =>
|
|
console.warn("[KEEP_AWAKE]: ", error),
|
|
);
|
|
} else {
|
|
deactivateKeepAwake(KEEP_AWAKE_TAG);
|
|
}
|
|
}, [keepAwake]);
|
|
|
|
useEffect(() => {
|
|
const shouldRTL = lang === "ar";
|
|
|
|
if (I18nManager.isRTL !== shouldRTL) {
|
|
I18nManager.forceRTL(shouldRTL);
|
|
I18nManager.swapLeftAndRightInRTL(shouldRTL);
|
|
}
|
|
}, [lang]);
|
|
|
|
// Until SecureStore has been read we'd otherwise flash the defaults
|
|
// (English / light) before the persisted values apply. The root layout
|
|
// already gates on fonts; gating here too avoids the theme/lang flash.
|
|
if (!hydrated) return null;
|
|
|
|
return <>{children}</>;
|
|
}; |