import { useState } from 'react'; import { type AutoLockMinutes, getAutoLockMinutes, notifyAutoLockChanged, setAutoLockMinutes, } from '../lib/autoLockSettings'; import { isWipeOnCloseEnabled, setWipeOnClose } from '../lib/memoryWipeSettings'; import { changePin, type LegacyMigrationReport, regenerateRecoveryCode, resetIdentity, retryLegacyMigration, } from '../lib/userIdentity'; import { PinInput } from './PinInput'; import { ShieldIcon, SpinnerIcon } from './icons'; interface Props { userId: string } export function SecurityCenter({ userId }: Props) { const [pinOld, setPinOld] = useState(''); const [pinNew, setPinNew] = useState(''); const [busy, setBusy] = useState(false); const [msg, setMsg] = useState(null); const [recovery, setRecovery] = useState(null); const [migration, setMigration] = useState(null); const [wipeOnClose, setWipeOnCloseState] = useState(() => isWipeOnCloseEnabled()); const [autoLockMinutes, setAutoLockMinutesState] = useState(() => getAutoLockMinutes()); async function handleRetryMigration() { setBusy(true); setMsg(null); setMigration(null); try { const report = await retryLegacyMigration(userId); setMigration(report); } catch (err) { setMsg(err instanceof Error ? err.message : String(err)); } finally { setBusy(false); } } async function handleChangePin() { setBusy(true); setMsg(null); try { await changePin({ userId, oldPin: pinOld, newPin: pinNew }); setMsg('PIN geändert.'); setPinOld(''); setPinNew(''); } catch (err) { setMsg(err instanceof Error ? err.message : String(err)); } finally { setBusy(false); } } async function handleRegenerateRecovery() { setBusy(true); setMsg(null); try { setRecovery(await regenerateRecoveryCode({ userId })); } catch (err) { setMsg(err instanceof Error ? err.message : String(err)); } finally { setBusy(false); } } async function handleReset() { if (!window.confirm('Identität wirklich zurücksetzen? Alle bisherigen Chats werden für dich unlesbar.')) return; setBusy(true); setMsg(null); try { const code = await resetIdentity({ userId, pin: pinNew || pinOld }); setRecovery(code); setMsg('Identität zurückgesetzt.'); } catch (err) { setMsg(err instanceof Error ? err.message : String(err)); } finally { setBusy(false); } } return (

Sicherheit

PIN ändern

Recovery-Code

{recovery && (
{recovery}
)}

Schlüssel-Migration reparieren

Versucht, alte Conversation-Schlüssel erneut für deine neue Identität zu re-wrappen. Sicher zu klicken wenn Nachrichten verschlüsselt bleiben oder du nicht senden kannst.

{migration && (
Geräte (Server): {migration.serverDevices}
Lokale Schlüssel im Vault: {migration.strongholdKeysFromServerDevices} {migration.strongholdKeysFromBundleScan > 0 && ( <> (+{migration.strongholdKeysFromBundleScan} aus Bundle-Scan) )}
Versucht: {migration.attempted}, Erfolgreich: {migration.migrated}
Übersprungen (kein lokaler Schlüssel): {migration.noStrongholdKey}
Entschlüsselung gescheitert: {migration.decryptFailed}
Server-Fehler: {migration.rpcFailed}
{migration.attempted > 0 && migration.migrated === 0 && (

Keine Bundles migriert. Vermutlich hast du den ursprünglichen Geräteschlüssel nicht mehr lokal. Nutze "Identität zurücksetzen" wenn du neu starten willst (alte Chats gehen verloren).

)}
)}

Cache beim Schließen leeren

Beim Beenden der App werden alle entschlüsselten Caches gelöscht. Beim nächsten Start musst du wieder deine PIN eingeben. Empfohlen für gemeinsam genutzte Rechner.

Auto-Lock nach Inaktivität

Verlangt erneute PIN-Eingabe nach der gewählten Inaktivitätsdauer. Empfohlen für gemeinsam genutzte Rechner.

Automatisch sperren
Verlangt erneute PIN-Eingabe nach X Minuten Inaktivität.

Identität zurücksetzen

Erstellt einen neuen Schlüssel. Alle alten Chats werden unlesbar.

{msg &&

{msg}

}
); }