2026-03-19 01:12:17 +08:00
|
|
|
import { Platform } from 'react-native';
|
|
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
deleteSecureItem,
|
|
|
|
|
getSecureItem,
|
|
|
|
|
setSecureItem,
|
|
|
|
|
} from '@/core/storage/secure';
|
|
|
|
|
|
|
|
|
|
import { supportedLanguages, type AppLanguage } from '@/i18n/resources';
|
|
|
|
|
|
|
|
|
|
import { THEME_NAMES, type ThemeName } from '@/constants/theme-bridge';
|
|
|
|
|
|
2026-05-15 17:23:02 +08:00
|
|
|
import {
|
|
|
|
|
mergeMemoirReadingPreferences,
|
|
|
|
|
parseMemoirReadingPreferences,
|
|
|
|
|
type MemoirReadingPreferences,
|
|
|
|
|
} from './memoir-reading-settings';
|
|
|
|
|
|
2026-03-19 01:12:17 +08:00
|
|
|
const KEY_LANGUAGE = 'app_settings_language';
|
|
|
|
|
const KEY_LARGE_TEXT = 'app_settings_large_text';
|
|
|
|
|
const KEY_DARK_MODE = 'app_settings_dark_mode';
|
|
|
|
|
const KEY_THEME_NAME = 'app_settings_theme_name';
|
2026-05-12 10:42:44 +08:00
|
|
|
const KEY_TTS_SPEAK_DEFAULT = 'app_settings_tts_speak_default';
|
2026-05-15 17:23:02 +08:00
|
|
|
const KEY_MEMOIR_READING = 'app_settings_memoir_reading';
|
2026-03-19 01:12:17 +08:00
|
|
|
|
|
|
|
|
const webFallback: Record<string, string> = {};
|
|
|
|
|
|
|
|
|
|
async function getStored(key: string): Promise<string | null> {
|
|
|
|
|
if (Platform.OS === 'web') return webFallback[key] ?? null;
|
|
|
|
|
return getSecureItem(key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function setStored(key: string, value: string): Promise<void> {
|
|
|
|
|
if (Platform.OS === 'web') {
|
|
|
|
|
webFallback[key] = value;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
await setSecureItem(key, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function deleteStored(key: string): Promise<void> {
|
|
|
|
|
if (Platform.OS === 'web') {
|
|
|
|
|
delete webFallback[key];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
await deleteSecureItem(key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function getAppLanguage(): Promise<AppLanguage | null> {
|
|
|
|
|
const v = await getStored(KEY_LANGUAGE);
|
|
|
|
|
if (!v) return null;
|
|
|
|
|
return supportedLanguages.includes(v as AppLanguage)
|
|
|
|
|
? (v as AppLanguage)
|
|
|
|
|
: null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function setAppLanguage(lang: AppLanguage): Promise<void> {
|
|
|
|
|
await setStored(KEY_LANGUAGE, lang);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function clearAppLanguage(): Promise<void> {
|
|
|
|
|
await deleteStored(KEY_LANGUAGE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function getLargeText(): Promise<boolean> {
|
|
|
|
|
const v = await getStored(KEY_LARGE_TEXT);
|
2026-03-20 15:15:35 +08:00
|
|
|
if (v == null || v === '') return true;
|
2026-03-19 01:12:17 +08:00
|
|
|
return v === 'true';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function setLargeText(value: boolean): Promise<void> {
|
|
|
|
|
await setStored(KEY_LARGE_TEXT, value ? 'true' : 'false');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function getDarkMode(): Promise<boolean> {
|
|
|
|
|
const v = await getStored(KEY_DARK_MODE);
|
|
|
|
|
return v === 'true';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function setDarkMode(value: boolean): Promise<void> {
|
|
|
|
|
await setStored(KEY_DARK_MODE, value ? 'true' : 'false');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function getThemeName(): Promise<ThemeName> {
|
|
|
|
|
const v = await getStored(KEY_THEME_NAME);
|
|
|
|
|
if (!v || !THEME_NAMES.includes(v as ThemeName)) return 'default';
|
|
|
|
|
return v as ThemeName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function setThemeName(value: ThemeName): Promise<void> {
|
|
|
|
|
await setStored(KEY_THEME_NAME, value);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-12 10:42:44 +08:00
|
|
|
/** 会话页「Speak / 本轮朗读」开关是否默认开启(跨会话记忆) */
|
|
|
|
|
export async function getTtsSpeakDefault(): Promise<boolean> {
|
|
|
|
|
const v = await getStored(KEY_TTS_SPEAK_DEFAULT);
|
|
|
|
|
if (v == null || v === '') return false;
|
|
|
|
|
return v === 'true';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function setTtsSpeakDefault(value: boolean): Promise<void> {
|
|
|
|
|
await setStored(KEY_TTS_SPEAK_DEFAULT, value ? 'true' : 'false');
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-15 17:23:02 +08:00
|
|
|
export async function getMemoirReadingPreferences(): Promise<MemoirReadingPreferences> {
|
|
|
|
|
const raw = await getStored(KEY_MEMOIR_READING);
|
|
|
|
|
return parseMemoirReadingPreferences(raw);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function setMemoirReadingPreferences(
|
|
|
|
|
patch: Partial<MemoirReadingPreferences>,
|
|
|
|
|
): Promise<void> {
|
|
|
|
|
const raw = await getStored(KEY_MEMOIR_READING);
|
|
|
|
|
const current = parseMemoirReadingPreferences(raw);
|
|
|
|
|
const next = mergeMemoirReadingPreferences(current, patch);
|
|
|
|
|
await setStored(KEY_MEMOIR_READING, JSON.stringify(next));
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-19 01:12:17 +08:00
|
|
|
export { supportedLanguages, THEME_NAMES };
|
|
|
|
|
export type { AppLanguage, ThemeName };
|
2026-05-15 17:23:02 +08:00
|
|
|
export type { MemoirReadingPreferences } from './memoir-reading-settings';
|