/* * webview.ts — source 2: navigator.geolocation inside the WebView, and the * Android freshness nudge's reading hand (D-04, D-05). * ------------------------------------------------------------------- * maximumAge: 0 is load-bearing — D-05 requires the freshest fix, and a * cached position would silently defeat the freshness axis (the whole * point of the nudge is to force a NEW read, not to re-read a cache). * Success AND timeout both resolve; the error callback resolves null so * the chain advances instead of rejecting. Timeout present for the same * reason as the telegram wrapper: wedging ACQUIRING is never acceptable. */ import type { Fix } from "./types.ts"; export function webviewLocationSupported(): boolean { return typeof navigator !== "undefined" && typeof navigator.geolocation?.getCurrentPosition === "function"; } export function readWebviewFix(options: { timeoutMs?: number; nowMs?: () => number } = {}): Promise { const timeoutMs = options.timeoutMs ?? 8000; if (!webviewLocationSupported()) return Promise.resolve(null); // Desktop Telegram, plain browsers without permission return new Promise((resolve) => { let settled = false; const done = (fix: Fix | null): void => { if (settled) return; settled = true; clearTimeout(timer); resolve(fix); }; const timer = setTimeout(() => done(null), timeoutMs); navigator.geolocation.getCurrentPosition( (pos) => done({ lat: pos.coords.latitude, lng: pos.coords.longitude, accuracyM: pos.coords.accuracy ?? null, headingDeg: pos.coords.heading ?? null, ts: (options.nowMs ?? Date.now)(), source: "webview", }), () => done(null), // denial / unavailability = null; the chain's normal signal (no error object escapes) { enableHighAccuracy: true, timeout: timeoutMs, maximumAge: 0 }, ); }); }