diff --git a/kez-chat/web/src/App.svelte b/kez-chat/web/src/App.svelte index 0445c4c..736b89a 100644 --- a/kez-chat/web/src/App.svelte +++ b/kez-chat/web/src/App.svelte @@ -4,14 +4,16 @@ import { hasStoredIdentity } from "./lib/identity-store.js"; import { session } from "./lib/store.svelte.js"; import { inboxService } from "./lib/inbox-service.svelte.js"; + import Wordmark from "./lib/Wordmark.svelte"; import Landing from "./routes/Landing.svelte"; import CreateAccount from "./routes/CreateAccount.svelte"; import Restore from "./routes/Restore.svelte"; import Unlock from "./routes/Unlock.svelte"; - import Dashboard from "./routes/Dashboard.svelte"; + import Identity from "./routes/Identity.svelte"; import Claims from "./routes/Claims.svelte"; import AddClaim from "./routes/AddClaim.svelte"; + import Settings from "./routes/Settings.svelte"; import Messages from "./routes/Messages.svelte"; const routes = { @@ -19,83 +21,109 @@ "/create": CreateAccount, "/restore": Restore, "/unlock": Unlock, - "/dashboard": Dashboard, + "/chats": Messages, + "/identity": Identity, "/claims": Claims, "/claims/add": AddClaim, - "/messages": Messages, + "/settings": Settings, }; - // First-load: if there's a stored identity but session is locked, - // bounce to /unlock. If no stored identity and on a protected page, - // bounce to /. + // App routes show the nav chrome; everything else (auth flow) is full-bleed. + const APP_ROUTES = ["/chats", "/identity", "/claims", "/claims/add", "/settings"]; + const showNav = $derived(!!session.unlocked && APP_ROUTES.includes($location)); + onMount(async () => { const stored = await hasStoredIdentity(); - const protectedRoutes = ["/dashboard", "/claims", "/claims/add", "/messages"]; - if (!stored && protectedRoutes.includes($location)) { + // Redirect legacy paths. + if ($location === "/dashboard") return push(session.unlocked ? "/identity" : "/unlock"); + if ($location === "/messages") return push(session.unlocked ? "/chats" : "/unlock"); + if (!stored && APP_ROUTES.includes($location)) { push("/"); - } else if (stored && !session.unlocked && protectedRoutes.includes($location)) { + } else if (stored && !session.unlocked && APP_ROUTES.includes($location)) { push("/unlock"); } }); + + // Nav destinations — Chats / Identity / Settings. + const nav = [ + { path: "/chats", label: "Chats", badge: true }, + { path: "/identity", label: "Identity", badge: false }, + { path: "/settings", label: "Settings", badge: false }, + ]; + + function isActive(path: string): boolean { + if (path === "/identity") return $location === "/identity" || $location.startsWith("/claims"); + return $location === path; + } -
-
- - 🔑 kez-chat - - {#if session.unlocked} -
+ {/each} + -
- -
+ +
+
+ +
+
- +{:else} + +
+
+
+ +
+
+
+ +
+
+{/if} diff --git a/kez-chat/web/src/routes/Identity.svelte b/kez-chat/web/src/routes/Identity.svelte new file mode 100644 index 0000000..8e17437 --- /dev/null +++ b/kez-chat/web/src/routes/Identity.svelte @@ -0,0 +1,186 @@ + + +{#if session.unlocked} +
+ +
+
+ +
+
+ + {session.unlocked.handle}@{session.unlocked.server} + + +
+

Key fingerprint

+

+ {fingerprint(session.unlocked.primary)} +

+ {#if registryRecord} +

+ Registered {new Date(registryRecord.registered_at).toLocaleDateString()} +

+ {/if} +
+
+
+ + +
+
+
+

Proofs

+

+ Other accounts cryptographically linked to your KEZ. Anyone can + verify these without trusting the server. +

+
+
+ {#if claims.length > 0} + + {/if} + + + Add proof + +
+
+ + {#if claims.length === 0} +
+

No proofs yet.

+

+ Link GitHub, your domain, nostr, Bluesky — prove the accounts you control. +

+
+ {:else} + + Manage proofs → + {/if} +
+
+{/if} diff --git a/kez-chat/web/src/routes/Messages.svelte b/kez-chat/web/src/routes/Messages.svelte index ace91e6..0236e49 100644 --- a/kez-chat/web/src/routes/Messages.svelte +++ b/kez-chat/web/src/routes/Messages.svelte @@ -6,6 +6,7 @@ import { lookup, ApiError } from "../lib/api.js"; import { inboxService } from "../lib/inbox-service.svelte.js"; import EmojiButton from "../lib/EmojiButton.svelte"; + import Avatar from "../lib/Avatar.svelte"; import { appendOutbound, ensureConversation, @@ -245,210 +246,171 @@ } -
- -