Goon — self-hosted aggregator for adult-content scene metadata. Indexes scenes from TPDB, StashDB, and 30+ public adult tube sites. Cross-source deduplication via perceptual hash + Levenshtein distance. FastAPI backend + APScheduler worker + React Native (Expo) mobile client. FOSS, ad-free, donation-funded. See README for details.
39 lines
1.1 KiB
TypeScript
39 lines
1.1 KiB
TypeScript
import * as SecureStore from 'expo-secure-store';
|
|
|
|
// Bump when DISCLAIMER / ToS materially changes — forces re-acceptance.
|
|
// Minor wording fixes (typos, formatting) don't bump.
|
|
export const CURRENT_TOS_VERSION = '1';
|
|
|
|
const KEY = 'goon.age_gate.accepted_version';
|
|
|
|
/** Returns true if user already accepted ToS at the current version.
|
|
*
|
|
* Fail-safe: any error reading SecureStore (no lockscreen on Android, keychain
|
|
* quirk) is treated as not-accepted. Cost is minor (user re-accepts), benefit
|
|
* is correctness — we never silently bypass the gate.
|
|
*/
|
|
export async function isAccepted(): Promise<boolean> {
|
|
try {
|
|
const v = await SecureStore.getItemAsync(KEY);
|
|
return v === CURRENT_TOS_VERSION;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export async function markAccepted(): Promise<void> {
|
|
try {
|
|
await SecureStore.setItemAsync(KEY, CURRENT_TOS_VERSION);
|
|
} catch {
|
|
// Best-effort; if we can't persist, the user will see the gate again next
|
|
// launch. No worse than not having a gate at all.
|
|
}
|
|
}
|
|
|
|
export async function clearAccepted(): Promise<void> {
|
|
try {
|
|
await SecureStore.deleteItemAsync(KEY);
|
|
} catch {
|
|
// ignore
|
|
}
|
|
}
|