import { loadDevicePrivateKey } from '@chat-app/shared/auth'; import { useEffect } from 'react'; import { Outlet } from 'react-router-dom'; import { useAuth } from '../context/AuthContext'; import { startConversationKeySync } from '../lib/conversationKeySync'; import { startDeviceApprovalListener } from '../lib/deviceApproval'; import { ensureNotificationPermission } from '../lib/osNotify'; import { devLocalSecretStore } from '../lib/secretStore'; import { BackupPromptBanner } from './BackupPromptBanner'; import { CallUI } from './CallUI'; import { DeviceApprovalBanner } from './DeviceApprovalBanner'; import { Sidebar } from './Sidebar'; export function AppShell() { const { session, device } = useAuth(); useEffect(() => { // Prompt once per authenticated shell mount. Module-level guard prevents // re-asking if the user already responded this session. void ensureNotificationPermission(); }, []); useEffect(() => { if (!session?.user.id || !device?.id) return; const userId = session.user.id; const deviceId = device.id; const stopKeySync = startConversationKeySync(userId, deviceId); const stopApproval = startDeviceApprovalListener({ ownUserId: userId, ownDeviceId: deviceId, getPriv: () => loadDevicePrivateKey(devLocalSecretStore, userId, deviceId), }); return () => { stopKeySync(); stopApproval(); }; }, [session?.user.id, device?.id]); return (