b789f4b10d
Drops the manual backup-string flow; replaces it with PIN change, recovery-code regeneration, and identity reset (all sealed via the new user_keys table).
70 lines
2.5 KiB
TypeScript
70 lines
2.5 KiB
TypeScript
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 { ensureInstallId } from '../lib/installId';
|
|
import { ensureNotificationPermission } from '../lib/osNotify';
|
|
import { cachedUserKey } from '../lib/userIdentity';
|
|
import { CallUI } from './CallUI';
|
|
import { DeviceApprovalBanner } from './DeviceApprovalBanner';
|
|
import { Sidebar } from './Sidebar';
|
|
|
|
export function AppShell() {
|
|
const { session } = 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) return;
|
|
const userId = session.user.id;
|
|
// Per-install id replaces the per-device record now that crypto is
|
|
// user-keyed. The legacy conv-key-sync and device-approval subsystems
|
|
// still take a "deviceId" argument for telemetry / row identity; passing
|
|
// the install id keeps those wires intact until they are themselves
|
|
// reworked in later tasks (Task 16/17/19 territory).
|
|
const installId = ensureInstallId();
|
|
const stopKeySync = startConversationKeySync(userId, installId);
|
|
const stopApproval = startDeviceApprovalListener({
|
|
ownUserId: userId,
|
|
ownDeviceId: installId,
|
|
getPriv: () => cachedUserKey(userId),
|
|
});
|
|
return () => {
|
|
stopKeySync();
|
|
stopApproval();
|
|
};
|
|
}, [session?.user.id]);
|
|
|
|
return (
|
|
<div className="relative flex min-h-screen overflow-hidden bg-surface text-fg">
|
|
<ShellBackground />
|
|
<div className="relative z-10 flex min-h-screen w-full">
|
|
<Sidebar />
|
|
<main className="relative flex-1 overflow-hidden">
|
|
<div className="h-screen overflow-y-auto">
|
|
<Outlet />
|
|
</div>
|
|
</main>
|
|
</div>
|
|
<CallUI />
|
|
<DeviceApprovalBanner />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Subtle desktop texture for dark mode. The panels carry the depth; the
|
|
// background stays quiet so chat content remains the focus.
|
|
function ShellBackground() {
|
|
return (
|
|
<div aria-hidden="true" className="pointer-events-none absolute inset-0 hidden dark:block">
|
|
<div className="bg-grid absolute inset-0 opacity-[0.08]" />
|
|
<div className="absolute inset-0 bg-[linear-gradient(180deg,rgba(30,31,34,0.94),rgba(17,18,20,0.98))]" />
|
|
</div>
|
|
);
|
|
}
|