import { useDeviceId } from "@/shared/hooks/use-device-id" import { useFollows } from "@/shared/hooks/use-follows" import { usePush } from "@/shared/hooks/use-push" import { usePwaUpdate } from "@/shared/hooks/use-pwa-update" import { fetchTopics } from "@/shared/lib/aw-api" import { BACKEND_URL, VAPID_PUBLIC_KEY } from "@/shared/lib/constants" import { BlockTitle, Button, List, ListItem, Navbar, Preloader, Toggle } from "konsta/react" import { useCallback, useEffect, useState } from "react" import { type GeoResult, clearGeoCache, detectFromCoords, loadCachedResult } from "../../location/lib/geo" import { NotificationGuide } from "./notification-guide" function formatCacheAge(cachedAt: number): string { const minutes = Math.floor((Date.now() - cachedAt) / 60_000) if (minutes < 1) return "gerade eben" if (minutes < 60) return `vor ${minutes} Min.` const hours = Math.floor(minutes / 60) if (hours < 24) return `vor ${hours} Std.` const days = Math.floor(hours / 24) return `vor ${days} T.` } function isStandalone(): boolean { if (typeof window === "undefined") return false return ( window.matchMedia("(display-mode: standalone)").matches || ("standalone" in navigator && (navigator as { standalone?: boolean }).standalone === true) ) } export function SettingsPage() { const deviceId = useDeviceId() const { needRefresh, checkForUpdate, applyUpdate } = usePwaUpdate() const push = usePush() const { follow } = useFollows() const [checking, setChecking] = useState(false) const [loading, setLoading] = useState(false) const [result, setResult] = useState(null) const [errorMsg, setErrorMsg] = useState(null) const [showGuide, setShowGuide] = useState(false) const [devHealth, setDevHealth] = useState(null) const [devPush, setDevPush] = useState(null) const [devTopics, setDevTopics] = useState(null) const [devPoliticians, setDevPoliticians] = useState(null) useEffect(() => { const cached = loadCachedResult() if (cached) setResult(cached) }, []) const detect = useCallback((skipCache: boolean) => { if (!navigator.geolocation) { setErrorMsg("Standortbestimmung wird nicht unterstützt") return } setLoading(true) setErrorMsg(null) navigator.geolocation.getCurrentPosition( async (pos) => { try { const r = await detectFromCoords(pos.coords.latitude, pos.coords.longitude, skipCache) setResult(r) } catch (e) { setErrorMsg(String(e)) } finally { setLoading(false) } }, (err) => { setErrorMsg(err.message) setLoading(false) }, ) }, []) function handleClearCache() { clearGeoCache() setResult(null) } async function handleCheckUpdate() { setChecking(true) try { await checkForUpdate() } finally { setChecking(false) } } const hasLocation = result && result.mandates.length > 0 const standalone = isStandalone() if (showGuide) { return setShowGuide(false)} /> } return (
{/* --- Notifications --- */} {VAPID_PUBLIC_KEY && ( <> Benachrichtigungen {push.permission === "denied" ? ( Benachrichtigungen sind blockiert. Bitte in den Systemeinstellungen aktivieren. } /> ) : ( { if (push.subscribed) push.unsubscribe() else push.subscribe() }} /> } /> )} {!standalone && setShowGuide(true)} />} )} {/* --- Location --- */} Standort {hasLocation && result.bundesland ? ( {result.landtag_label && } {result.cachedAt && } ) : null} {loading && (
{hasLocation ? "Aktualisiere…" : "Erkenne…"}
)} {errorMsg && (
{errorMsg}
)}
{!hasLocation && !loading && ( )} {hasLocation && ( <> )}
{/* --- App Update --- */} App-Update {needRefresh ? ( Jetzt aktualisieren } /> ) : ( {checking ? "Prüfe…" : "Prüfen"} } /> )} {/* --- About --- */} Info abgeordnetenwatch.de } /> {deviceId}} /> {/* --- Developer --- */} Entwickler {devHealth && ( {devHealth} )}
} /> {devPush && ( {devPush} )} } /> {devTopics && {devTopics}} } /> {devPoliticians && {devPoliticians}} } /> ) }