From b50d35e5fa7666e26bf28e2d7d91be78d1ce1860 Mon Sep 17 00:00:00 2001 From: Coracle-Bot Date: Tue, 8 Sep 2026 23:51:29 +0000 Subject: [PATCH] Reduce the home inbox to unread conversations and restyle the dashboard --- e2e/USER_STORIES.md | 11 +++++------ e2e/specs/notifications.spec.ts | 13 +++++-------- src/app/components/HomeInbox.svelte | 18 +++++++++--------- src/app/components/HomeInboxItem.svelte | 6 +++--- src/app/components/HomeSection.svelte | 4 ++-- src/app/inbox.ts | 15 ++++++--------- src/routes/home/+page.svelte | 4 ++-- 7 files changed, 32 insertions(+), 39 deletions(-) diff --git a/e2e/USER_STORIES.md b/e2e/USER_STORIES.md index 9a6263a3..d7bfc83b 100644 --- a/e2e/USER_STORIES.md +++ b/e2e/USER_STORIES.md @@ -1563,15 +1563,14 @@ that I don't have to walk every space to find out. Acceptance: -- The inbox lists each room and conversation with unread activity, naming the - room and space and showing the latest message, newest first. It holds messages - only. +- The inbox lists each room and conversation with unread activity as a card, + naming the room and space and showing the latest message, newest first. It + holds messages only, and only while they are unread. - Activity is a row of one card per space, counting what that space has waiting that isn't a message - threads, events, classifieds and the rest. A card disappears once its space is read. -- A conversation with unread activity carries an unread dot, and "Mark all read" - clears every dot on the page. -- Selecting a conversation opens it, and it stays in the inbox once read. +- A conversation carries an unread dot, and "Mark all read" empties the inbox. +- Selecting a conversation opens it. - Relay health checks are listed alongside the inbox, with the recommendation each one applies. - Hosting is offered whether or not she hosts a space: a shortcut to the hosting diff --git a/e2e/specs/notifications.spec.ts b/e2e/specs/notifications.spec.ts index 5903f869..8a14ad8c 100644 --- a/e2e/specs/notifications.spec.ts +++ b/e2e/specs/notifications.spec.ts @@ -405,17 +405,14 @@ test("US-116 read the home dashboard", async ({seed, as}) => { // Hosting shows even though alice hosts nothing, as an invitation to start a space await expect(page.getByRole("button", {name: "Start a space"})).toBeVisible() + await expect(conversation).toHaveAttribute("href", roomPath(space.url, "general")) + + // The inbox is the badges, so a conversation leaves the list once it has nothing unread await page.getByRole("button", {name: "Mark all read"}).click() - await expect(unreadDot(conversation)).toHaveCount(0) - - // Unlike a conversation, a space's activity card is a count of what's new, so reading it empties + await expect(conversation).toHaveCount(0) await expect(activity).toHaveCount(0) - - // A conversation stays in the inbox once it's read - it's a list of where things are, not a queue - await conversation.click() - - await expect(page).toHaveURL(pattern(roomPath(space.url, "general"))) + await expect(page.getByText("You're all caught up")).toBeVisible() }) test("US-106 share text into the app", async ({seed, as}) => { diff --git a/src/app/components/HomeInbox.svelte b/src/app/components/HomeInbox.svelte index e54ee749..788de973 100644 --- a/src/app/components/HomeInbox.svelte +++ b/src/app/components/HomeInbox.svelte @@ -24,11 +24,17 @@ {/if} {/snippet} - {#if conversations.length === 0} + {#if conversations.length > 0} +
+ {#each conversations as conversation (conversation.path)} + + {/each} +
+ {:else}
-

Nothing in your inbox yet

+

You're all caught up

- The rooms, space chats and direct messages you belong to show their latest message here. + The rooms, space chats and direct messages you belong to show what's unread here.

@@ -41,11 +47,5 @@
- {:else} -
- {#each conversations as conversation (conversation.path)} - - {/each} -
{/if} diff --git a/src/app/components/HomeInboxItem.svelte b/src/app/components/HomeInboxItem.svelte index a3b6f2d3..2269324a 100644 --- a/src/app/components/HomeInboxItem.svelte +++ b/src/app/components/HomeInboxItem.svelte @@ -9,10 +9,10 @@ import NoteContentMinimal from "@app/components/NoteContentMinimal.svelte" import UnreadDot from "@app/components/UnreadDot.svelte" import {user} from "@app/core" - import type {InboxConversation} from "@app/inbox" + import type {Activity} from "@app/notifications" type Props = { - conversation: InboxConversation + conversation: Activity } const {conversation}: Props = $props() @@ -24,7 +24,7 @@ const others = $derived(uniq(remove($user.pubkey, conversation.pubkeys ?? []))) - + {#if url} {:else} diff --git a/src/app/components/HomeSection.svelte b/src/app/components/HomeSection.svelte index 28c76ff1..57ecdcde 100644 --- a/src/app/components/HomeSection.svelte +++ b/src/app/components/HomeSection.svelte @@ -14,8 +14,8 @@
-

- +

+ {title}

{@render action?.()} diff --git a/src/app/inbox.ts b/src/app/inbox.ts index 003a00ac..4fb4e554 100644 --- a/src/app/inbox.ts +++ b/src/app/inbox.ts @@ -1,20 +1,17 @@ import {derived} from "svelte/store" import {sortBy} from "@welshman/lib" -import type {Activity} from "@app/notifications" import {allNotifications, latestActivityByPath} from "@app/notifications" -export type InboxConversation = Activity & {unread: boolean} - -// Every room, space chat and direct message the user can see, newest first, whether or not it -// has anything unread - an inbox that hid what has been read would be empty for anyone caught up. +// Every room, space chat and direct message with something unread, newest first. The inbox shows +// exactly what the badges show, so reading a conversation is what takes it out of the list. export const inboxConversations = derived( [latestActivityByPath, allNotifications], ([$latestActivityByPath, $allNotifications]) => sortBy( - conversation => -conversation.event.created_at, - [...$latestActivityByPath.values()] - .filter(activity => !activity.contentKind) - .map(activity => ({...activity, unread: $allNotifications.has(activity.path)})), + activity => -activity.event.created_at, + [...$latestActivityByPath.values()].filter( + activity => !activity.contentKind && $allNotifications.has(activity.path), + ), ), ) diff --git a/src/routes/home/+page.svelte b/src/routes/home/+page.svelte index 90a70b33..7903e33a 100644 --- a/src/routes/home/+page.svelte +++ b/src/routes/home/+page.svelte @@ -38,9 +38,9 @@

- +
-
+