From 259091ba648d1c2742820b19870c5267ad7fa993 Mon Sep 17 00:00:00 2001 From: Coracle-Bot Date: Thu, 10 Sep 2026 23:14:52 +0000 Subject: [PATCH] Land on a page of the space after deleting the room you are in --- e2e/USER_STORIES.md | 12 ++++++++++ e2e/specs/rooms.spec.ts | 30 ++++++++++++++++++++++++ src/app/components/RoomDetailMenu.svelte | 4 +++- src/app/routes.ts | 13 +++++++--- 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/e2e/USER_STORIES.md b/e2e/USER_STORIES.md index e7c0027b..e8fe3c69 100644 --- a/e2e/USER_STORIES.md +++ b/e2e/USER_STORIES.md @@ -305,6 +305,18 @@ Acceptance: and removes it from the sidebar. - bob sees neither "Edit Room" nor "Delete Room" in the room's detail menu. +### US-121 — Land somewhere after deleting the room you are in + +As admin, I want deleting the room I am reading to put me on a page of the +space, so that I am not stranded on a screen with nothing on it. + +Acceptance: + +- Confirming the deletion leaves admin on a page below the space root, with the + space's remaining rooms listed beside it. +- Entering the space again from the rail lands on a page, rather than returning + to the room that was deleted or to the empty root. + ### US-021 — Request access to a private room and get approved As carol, I want to ask to join a closed room and be let in, so that I can read diff --git a/e2e/specs/rooms.spec.ts b/e2e/specs/rooms.spec.ts index 40dda716..0c665271 100644 --- a/e2e/specs/rooms.spec.ts +++ b/e2e/specs/rooms.spec.ts @@ -300,6 +300,36 @@ test("US-020 create, edit, and delete a room", async ({seed, as}) => { await expect(bob.getByRole("button", {name: "Delete Room"})).toHaveCount(0) }) +test("US-121 land somewhere after deleting the room you are in", async ({seed, as}) => { + const scenario = await seed(({relay, user}) => { + const space = relay("space") + + space.room("general", {name: "General"}) + space.room("wardroom", {name: "Wardroom"}) + space.join(user.admin, "general") + space.join(user.admin, "wardroom") + }) + + const {url} = scenario.space("space") + const admin = await as(users.admin, roomPath(url, "wardroom")) + + await openRoomDetail(admin) + await openRoomDetailMenu(admin) + await admin.getByRole("button", {name: "Delete Room"}).click() + await admin.getByRole("button", {name: "Confirm"}).click() + + // The space root renders nothing on a wide screen; it hands off to whichever page of the space + // was open last, and the room that was just deleted is the page it remembers. + await expect(admin).toHaveURL(pathPattern(spacePath(url) + "/")) + await expect(roomLink(admin, "General")).toBeVisible() + + // Entering the space from the rail reads the same memory, so it has to land somewhere too. + await admin.locator('.primary-nav [data-tip^="space"]').click() + + await expect(admin).toHaveURL(pathPattern(spacePath(url) + "/")) + await expect(roomLink(admin, "General")).toBeVisible() +}) + test("US-021 request access to a private room and get approved", async ({seed, as}) => { const scenario = await seed(({relay, user, at}) => { const space = relay("space") diff --git a/src/app/components/RoomDetailMenu.svelte b/src/app/components/RoomDetailMenu.svelte index 96efebb0..cb984f57 100644 --- a/src/app/components/RoomDetailMenu.svelte +++ b/src/app/components/RoomDetailMenu.svelte @@ -14,7 +14,7 @@ import {app, roomLists, rooms} from "@app/core" import {joinRoom, leaveRoom} from "@app/access" import {deriveUserIsRoomAdmin, deriveUserRoomMembershipStatus} from "@app/rooms" - import {makeSpacePath} from "@app/routes" + import {forgetSpacePage, makeSpacePath} from "@app/routes" import {navigate, pushModal} from "@app/modal" import {pushToast} from "@app/toast" @@ -62,6 +62,8 @@ pushToast({theme: "error", message}) } else { await $roomLists.removeRoom(h, url).then(publish) + + forgetSpacePage(url) navigate(makeSpacePath(url)) } }, diff --git a/src/app/routes.ts b/src/app/routes.ts index 14dc6b27..0481b61a 100644 --- a/src/app/routes.ts +++ b/src/app/routes.ts @@ -40,8 +40,13 @@ export const lastSpaceUrl = writable(undefined) export const setupHistory = () => page.subscribe($page => { if ($page.params.relay) { - lastPageBySpaceUrl.set($page.params.relay, $page.url.pathname) - lastSpaceUrl.set(decodeRelay($page.params.relay)) + const url = decodeRelay($page.params.relay) + + if ($page.url.pathname !== makeSpacePath(url)) { + lastPageBySpaceUrl.set(url, $page.url.pathname) + } + + lastSpaceUrl.set(url) } if ($page.params.chat) { @@ -88,8 +93,10 @@ export const makeSpacePath = (url: string, ...extra: (string | undefined)[]) => return path } +export const forgetSpacePage = (url: string) => lastPageBySpaceUrl.delete(url) + export const makeSpaceEntryPath = (url: string) => { - const prevPath = lastPageBySpaceUrl.get(encodeRelay(url)) + const prevPath = lastPageBySpaceUrl.get(url) if (prevPath) { return prevPath