From f30ef6d34438318c3a3fa0cfd49df0ffc84bc79c Mon Sep 17 00:00:00 2001 From: Coracle-Bot Date: Thu, 17 Sep 2026 17:46:55 +0000 Subject: [PATCH] Give a comment the same send delay a chat message gets (#562) --- .agents/skills/flotilla-state/SKILL.md | 10 ++++++---- e2e/USER_STORIES.md | 4 ++-- e2e/specs/delivery.spec.ts | 11 ++++++++++- e2e/specs/settings.spec.ts | 6 +++--- src/app/components/CommentCompose.svelte | 10 +++++++--- src/app/components/EventReply.svelte | 10 +++++++--- src/routes/settings/content/+page.svelte | 2 +- 7 files changed, 36 insertions(+), 17 deletions(-) diff --git a/.agents/skills/flotilla-state/SKILL.md b/.agents/skills/flotilla-state/SKILL.md index bbd2ff39..48cf47bc 100644 --- a/.agents/skills/flotilla-state/SKILL.md +++ b/.agents/skills/flotilla-state/SKILL.md @@ -360,9 +360,10 @@ Plugin mutators already return a `Command`: `roomLists.get().addRelay(url).then( `forceLoad` before writing. A replaceable event you build yourself needs the same, as in `publishSettings`. -Some call sites call `thunks.get().publish({event, relays, delay})` directly. Room chat -(`RoomChat.svelte`) does, because `Command` cannot carry the `send_delay` window, and so do -`publishRoomQuote` in `rooms.ts`, the push adapters and `ProfileDelete.svelte`. DMs go through +Some call sites call `thunks.get().publish({event, relays, delay})` directly. Anything that +honours the `send_delay` window does, because `Command` cannot carry it: room chat +(`RoomChat.svelte`), the comment composers (`CommentCompose.svelte` and `EventReply.svelte`) and +`publishRoomQuote` in `rooms.ts`. So do the push adapters and `ProfileDelete.svelte`. DMs go through `wraps.get().publish({event, recipients})`, which returns a merged thunk (see `reactions.ts`). NIP-86 calls (`relayManagement.get().forUrl(url)`) are not thunks. They return `{result, error}`, and the caller handles `error`. @@ -373,7 +374,8 @@ NIP-86 calls (`relayManagement.get().forUrl(url)`) are not thunks. They return relays when it is enqueued, so every derived store sees it immediately. Signing then swaps the unsigned event for the signed one. - **Undo.** `thunk.abort()` during the `delay` removes the event from the repository and from - `history`. When `send_delay` is set, room chat shows a `ThunkToast` whose Cancel button aborts. + `history`. When `send_delay` is set, room chat shows a `ThunkToast` whose Cancel button aborts, + and a comment carries the same Cancel in the `ThunkPending` row under it. - **Editing.** Editing a message deletes it and republishes with the same `created_at` (see `RoomChat.svelte`). - **Status in rows.** Rows look up `$thunksByEventId.get(event.id) ?? noThunks` and pass diff --git a/e2e/USER_STORIES.md b/e2e/USER_STORIES.md index 8da7a707..3c32ed7e 100644 --- a/e2e/USER_STORIES.md +++ b/e2e/USER_STORIES.md @@ -1129,8 +1129,8 @@ Acceptance: confirms. - On confirmation the status disappears silently and the normal reaction and menu actions take its place. -- Cancelling removes the post entirely from the list or thread it was posted - into, and bob never sees it. +- Cancelling during the send delay removes the post entirely from the list or + thread it was posted into. - A failed post shows "Failed to send!" in the same row, opening the same per-relay detail popover. diff --git a/e2e/specs/delivery.spec.ts b/e2e/specs/delivery.spec.ts index 73519a5d..c929eea9 100644 --- a/e2e/specs/delivery.spec.ts +++ b/e2e/specs/delivery.spec.ts @@ -87,7 +87,11 @@ const setSendDelay = async (page: Page, seconds: number) => { await page.goto("/settings/content") await slider.fill(String(seconds * 1000)) - await expect(page.getByText(`Delay sending chat messages for ${seconds} seconds.`)).toBeVisible() + const unit = seconds === 1 ? "second" : "seconds" + + await expect( + page.getByText(`Delay sending messages and comments for ${seconds} ${unit}.`), + ).toBeVisible() await page.getByRole("button", {name: "Save Changes"}).click() @@ -337,6 +341,11 @@ test("US-071 content posts show delivery status in place", async ({seed, as}) => env: {VITE_BLOCKED_RELAYS: quiet}, }) + // A comment leaves after the send delay the way a chat message does, so the window in which its + // Cancel link is live is hers to set. + await setSendDelay(alice, 1) + await alice.goto(`${spacePath(url)}/articles`) + await writeArticle(alice, "Signals in the Noise", "Everything worth hearing is quiet.") // Publishing lands on the article's own page, where its status sits under the article itself. diff --git a/e2e/specs/settings.spec.ts b/e2e/specs/settings.spec.ts index 9fb833c5..3a733e8a 100644 --- a/e2e/specs/settings.spec.ts +++ b/e2e/specs/settings.spec.ts @@ -177,11 +177,11 @@ test("US-088 adjust send delay and media servers", async ({seed, as}) => { const sendDelay = page.locator('input[type="range"]') const servers = page.getByRole("listitem") - await expect(page.getByText("Delay sending chat messages for 0 seconds.")).toBeVisible() + await expect(page.getByText("Delay sending messages and comments for 0 seconds.")).toBeVisible() await sendDelay.fill("3000") - await expect(page.getByText("Delay sending chat messages for 3 seconds.")).toBeVisible() + await expect(page.getByText("Delay sending messages and comments for 3 seconds.")).toBeVisible() await expect(servers).toHaveCount(0) @@ -208,7 +208,7 @@ test("US-088 adjust send delay and media servers", async ({seed, as}) => { await waitForToastToClear(page) await page.reload() - await expect(page.getByText("Delay sending chat messages for 3 seconds.")).toBeVisible() + await expect(page.getByText("Delay sending messages and comments for 3 seconds.")).toBeVisible() await expect(page.locator('input[type="range"]')).toHaveValue("3000") }) diff --git a/src/app/components/CommentCompose.svelte b/src/app/components/CommentCompose.svelte index 684e9eff..c74eaca5 100644 --- a/src/app/components/CommentCompose.svelte +++ b/src/app/components/CommentCompose.svelte @@ -2,7 +2,6 @@ import {writable} from "svelte/store" import type {TrustedEvent} from "@welshman/util" import {tagSpec, tagValue} from "@welshman/util" - import {publishToRelays} from "@welshman/app" import {Comment} from "@welshman/domain" import {isMobile, preventDefault} from "@lib/html" import Paperclip from "@assets/icons/paperclip-2.svg?dataurl" @@ -10,9 +9,10 @@ import Button from "@lib/components/Button.svelte" import Spinner from "@lib/components/Spinner.svelte" import EditorContent from "@app/editor/EditorContent.svelte" - import {command, relays, writer} from "@app/core" + import {relays, thunks, writer} from "@app/core" import {DraftKey} from "@app/drafts" import {makeEditor} from "@app/editor" + import {getSetting} from "@app/settings" import {pushToast} from "@app/toast" type Values = { @@ -63,7 +63,11 @@ eventWriter.setRoom(url, h) } - const thunk = await command(eventWriter).then(publishToRelays([url])) + const thunk = $thunks.publish({ + relays: [url], + event: await eventWriter.renderTemplate(), + delay: getSetting("send_delay"), + }) const error = await thunk.waitForError() if (error) { diff --git a/src/app/components/EventReply.svelte b/src/app/components/EventReply.svelte index b2a6b73c..1779e57b 100644 --- a/src/app/components/EventReply.svelte +++ b/src/app/components/EventReply.svelte @@ -3,7 +3,6 @@ import {writable} from "svelte/store" import type {TrustedEvent} from "@welshman/util" import {tagSpec, tagValue} from "@welshman/util" - import {publishToRelays} from "@welshman/app" import {Comment} from "@welshman/domain" import {isMobile, preventDefault} from "@lib/html" import {fly} from "@lib/transition" @@ -17,7 +16,8 @@ import {makeEditor} from "@app/editor" import {DraftKey} from "@app/drafts" import {pushToast} from "@app/toast" - import {command, relays, writer} from "@app/core" + import {relays, thunks, writer} from "@app/core" + import {getSetting} from "@app/settings" type Values = { content?: string | object @@ -72,7 +72,11 @@ eventWriter.setRoom(url, h) } - const thunk = await command(eventWriter).then(publishToRelays([url])) + const thunk = $thunks.publish({ + relays: [url], + event: await eventWriter.renderTemplate(), + delay: getSetting("send_delay"), + }) draftKey.clear() onSubmit(thunk) diff --git a/src/routes/settings/content/+page.svelte b/src/routes/settings/content/+page.svelte index 7dbaf01d..3fb440a2 100644 --- a/src/routes/settings/content/+page.svelte +++ b/src/routes/settings/content/+page.svelte @@ -135,7 +135,7 @@ {/snippet} {#snippet info()}

- Delay sending chat messages for {$settings.send_delay / 1000} + Delay sending messages and comments for {$settings.send_delay / 1000} {$settings.send_delay === 1000 ? "second" : "seconds"}.

{/snippet}