Give a comment the same send delay a chat message gets (#562)

This commit is contained in:
Coracle-Bot 2026-09-17 17:46:55 +00:00 committed by hodlbod
parent caab696d36
commit f30ef6d344
7 changed files with 36 additions and 17 deletions

View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -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")
})

View file

@ -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) {

View file

@ -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)

View file

@ -135,7 +135,7 @@
{/snippet}
{#snippet info()}
<p>
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"}.
</p>
{/snippet}