syncWebContentDomains (gespiegelt von syncBlocklist): holt die Domain-Liste vom Backend, cached sie als webcontent-domains.json im App-Group-Container, ETag/304, Reapply nach Sync wenn FC aktiv. loadWebContentDomains liest cache-first, faellt auf die gebuendelte gambling-domains.json zurueck (Offline-Seed). Getriggert am selben Punkt wie syncBlocklist (useBlocklistSync). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
81 lines
3.0 KiB
TypeScript
81 lines
3.0 KiB
TypeScript
import { useCallback, useState } from 'react';
|
|
import { Platform } from 'react-native';
|
|
import Constants from 'expo-constants';
|
|
import { supabase } from '../lib/supabase';
|
|
import { protection } from '../lib/protection';
|
|
|
|
type SyncResult = { ok: boolean; count?: number; plan?: string; error?: string };
|
|
|
|
/**
|
|
* Synct die binary Blocklist (`blocklist.bin`) vom Server in die App-Group.
|
|
* Die NEFilter-Extension memory-mapped diese Datei — ohne Sync = leere
|
|
* Blocklist = nichts wird geblockt.
|
|
*
|
|
* Triggers:
|
|
* - direkt nach activateUrlFilter() success
|
|
* - nach Domain-Add/-Submit/-Delete
|
|
* - bei App-Resume (in case Server-Updates kamen)
|
|
*
|
|
* Backend respondet 304 wenn ETag matched → kein Re-Download.
|
|
*
|
|
* iOS-Layer-2: am selben Trigger wird auch die kuratierte webContent-Gambling-
|
|
* Domain-Liste vom Backend gesynct (`syncWebContentDomains` →
|
|
* `webcontent-domains.json` im App-Group-Cache). Best-effort und entkoppelt:
|
|
* solange der Layer-2-Endpoint nicht deployed ist, schlägt dieser Sync fehl —
|
|
* das beeinflusst das Blocklist-Sync-Ergebnis NICHT (der native
|
|
* loadWebContentDomains fällt sauber auf die gebündelte JSON zurück).
|
|
*/
|
|
export function useBlocklistSync() {
|
|
const [syncing, setSyncing] = useState(false);
|
|
const [lastResult, setLastResult] = useState<SyncResult | null>(null);
|
|
|
|
const sync = useCallback(async (): Promise<SyncResult> => {
|
|
if (syncing) return { ok: false, error: 'already_syncing' };
|
|
setSyncing(true);
|
|
try {
|
|
const baseURL = Constants.expoConfig?.extra?.apiUrl as string;
|
|
const session = (await supabase.auth.getSession()).data.session;
|
|
const authToken = session?.access_token;
|
|
|
|
if (!baseURL || !authToken) {
|
|
const result = { ok: false, error: 'missing_baseURL_or_token' };
|
|
setLastResult(result);
|
|
return result;
|
|
}
|
|
|
|
// iOS-Layer-2: webContent-Domain-Liste am selben Trigger mitsyncen.
|
|
// Bewusst NICHT awaited mit dem Blocklist-Sync gekoppelt — ein
|
|
// Fehlschlag (z.B. Endpoint noch nicht deployed) darf das Blocklist-
|
|
// Ergebnis nicht kippen. Fallback auf die gebündelte JSON greift nativ.
|
|
if (Platform.OS === 'ios') {
|
|
protection
|
|
.syncWebContentDomains({ baseURL, authToken })
|
|
.then((res) =>
|
|
console.log('[webcontent-sync] ok:', JSON.stringify(res)),
|
|
)
|
|
.catch((e: any) =>
|
|
console.warn(
|
|
'[webcontent-sync] failed (bundled fallback active):',
|
|
e?.message ?? e,
|
|
),
|
|
);
|
|
}
|
|
|
|
const res = await protection.syncBlocklist({ baseURL, authToken });
|
|
const result = { ok: true, count: res.count, plan: res.plan };
|
|
setLastResult(result);
|
|
console.log('[blocklist-sync] ok:', res);
|
|
return result;
|
|
} catch (e: any) {
|
|
const result = { ok: false, error: e?.message ?? 'sync_failed' };
|
|
setLastResult(result);
|
|
console.error('[blocklist-sync] failed:', e);
|
|
return result;
|
|
} finally {
|
|
setSyncing(false);
|
|
}
|
|
}, [syncing]);
|
|
|
|
return { sync, syncing, lastResult };
|
|
}
|