mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 02:44:02 +00:00
85 lines
2.5 KiB
JavaScript
85 lines
2.5 KiB
JavaScript
import {
|
|
DEFAULT_VOICE_TIER,
|
|
isKnownVoiceTier,
|
|
normalizeCostLimits,
|
|
resolveVoiceModel,
|
|
serializeCostLimits,
|
|
} from './voiceCost.js';
|
|
|
|
// Voice cost control (repo-wide `godsEyeView.<feature>.<field>` convention;
|
|
// the neighbouring ERROR_STORAGE_KEY predates it).
|
|
export const VOICE_TIER_STORAGE_KEY = 'godsEyeView.voiceCost.tier';
|
|
|
|
export const VOICE_LIMITS_STORAGE_KEY = 'godsEyeView.voiceCost.limits';
|
|
|
|
/** Best-effort localStorage handle; absent in tests and locked-down browsers. */
|
|
export function voiceStorage(storage) {
|
|
if (storage) return storage;
|
|
try {
|
|
return typeof localStorage === 'undefined' ? null : localStorage;
|
|
} catch {
|
|
return null; // privacy modes throw on mere access
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Read the persisted voice model tier. Unknown/corrupt values resolve to the
|
|
* default, so a hand-edited localStorage entry can never pick a bad model.
|
|
*/
|
|
export function readStoredVoiceTier(storage) {
|
|
try {
|
|
const raw = voiceStorage(storage)?.getItem(VOICE_TIER_STORAGE_KEY);
|
|
return isKnownVoiceTier(raw)
|
|
? resolveVoiceModel(raw).tier
|
|
: DEFAULT_VOICE_TIER;
|
|
} catch {
|
|
return DEFAULT_VOICE_TIER;
|
|
}
|
|
}
|
|
|
|
/** Persist the voice model tier. Never throws. */
|
|
export function writeStoredVoiceTier(tier, storage) {
|
|
const resolved = resolveVoiceModel(tier).tier;
|
|
try {
|
|
voiceStorage(storage)?.setItem(VOICE_TIER_STORAGE_KEY, resolved);
|
|
} catch {
|
|
/* best effort */
|
|
}
|
|
return resolved;
|
|
}
|
|
|
|
/**
|
|
* Read the persisted spend thresholds, falling back to the generous defaults.
|
|
* Stored as `{"warnUsd":2,"capUsd":5}` under one key so both move together.
|
|
*/
|
|
export function readStoredVoiceLimits(storage) {
|
|
try {
|
|
const raw = voiceStorage(storage)?.getItem(VOICE_LIMITS_STORAGE_KEY);
|
|
if (!raw) return normalizeCostLimits(null);
|
|
return normalizeCostLimits(JSON.parse(raw));
|
|
} catch {
|
|
return normalizeCostLimits(null); // corrupt JSON must not disable the cap
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Persist spend thresholds. Never throws.
|
|
*
|
|
* Serialized through `serializeCostLimits` because a DISABLED threshold is
|
|
* Infinity, and `JSON.stringify(Infinity)` is `null` — which reads back as
|
|
* "absent" and silently restores the default, re-arming a cap the user turned
|
|
* off. The 'off' sentinel round-trips instead.
|
|
*/
|
|
export function writeStoredVoiceLimits(limits, storage) {
|
|
const normalized = normalizeCostLimits(limits);
|
|
try {
|
|
voiceStorage(storage)?.setItem(
|
|
VOICE_LIMITS_STORAGE_KEY,
|
|
JSON.stringify(serializeCostLimits(normalized)),
|
|
);
|
|
} catch {
|
|
/* best effort */
|
|
}
|
|
return normalized;
|
|
}
|