Keep a room message in the composer and toast when sending it fails, instead of dropping it silently
This commit is contained in:
parent
790700dd9f
commit
326fb33bca
2 changed files with 69 additions and 58 deletions
|
|
@ -174,65 +174,64 @@
|
|||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const protect = await shouldProtect
|
||||
const protect = await shouldProtect
|
||||
|
||||
if (eventToEdit) {
|
||||
// Don't do anything if message hasn't changed
|
||||
if (eventToEdit.content === content) {
|
||||
return
|
||||
}
|
||||
|
||||
// Delete the previous message, to be republished below with the same timestamp
|
||||
const command = await $deletes.deleteEvent($state.snapshot(eventToEdit), w =>
|
||||
w.setProtected(protect),
|
||||
)
|
||||
|
||||
command.publishToRelays([url])
|
||||
if (eventToEdit) {
|
||||
// Don't do anything if message hasn't changed
|
||||
if (eventToEdit.content === content) {
|
||||
return clearEventToEdit()
|
||||
}
|
||||
|
||||
// A share is a quote rather than a reply, so setParent prepends the reply's own reference ahead of it.
|
||||
if (sharedEvent) {
|
||||
;({content, tags} = await prependParent(sharedEvent, {content, tags}, url))
|
||||
}
|
||||
// Delete the previous message, to be republished below with the same timestamp
|
||||
const command = await $deletes.deleteEvent($state.snapshot(eventToEdit), w =>
|
||||
w.setProtected(protect),
|
||||
)
|
||||
|
||||
const eventWriter = writer(Message)
|
||||
.setContent(content)
|
||||
.addTags(...tags)
|
||||
.setProtected(protect)
|
||||
|
||||
if (h) {
|
||||
eventWriter.setRoom(url, h)
|
||||
} else {
|
||||
eventWriter.forceRoutes(relay(url))
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
eventWriter.setParent(parent)
|
||||
}
|
||||
|
||||
const delay = await loadSendDelay()
|
||||
|
||||
const thunk = $thunks.publish({
|
||||
relays: [url],
|
||||
event: stamp(await eventWriter.renderTemplate(), eventToEdit?.created_at),
|
||||
delay,
|
||||
})
|
||||
|
||||
if (delay) {
|
||||
pushToast({
|
||||
timeout: 30_000,
|
||||
children: {
|
||||
component: ThunkToast,
|
||||
props: {thunk},
|
||||
},
|
||||
})
|
||||
}
|
||||
} finally {
|
||||
clearParent()
|
||||
clearShare()
|
||||
clearEventToEdit()
|
||||
command.publishToRelays([url])
|
||||
}
|
||||
|
||||
// A share is a quote rather than a reply, so setParent prepends the reply's own reference ahead of it.
|
||||
if (sharedEvent) {
|
||||
;({content, tags} = await prependParent(sharedEvent, {content, tags}, url))
|
||||
}
|
||||
|
||||
const eventWriter = writer(Message)
|
||||
.setContent(content)
|
||||
.addTags(...tags)
|
||||
.setProtected(protect)
|
||||
|
||||
if (h) {
|
||||
eventWriter.setRoom(url, h)
|
||||
} else {
|
||||
eventWriter.forceRoutes(relay(url))
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
eventWriter.setParent(parent)
|
||||
}
|
||||
|
||||
const delay = await loadSendDelay()
|
||||
|
||||
const thunk = $thunks.publish({
|
||||
relays: [url],
|
||||
event: stamp(await eventWriter.renderTemplate(), eventToEdit?.created_at),
|
||||
delay,
|
||||
})
|
||||
|
||||
if (delay) {
|
||||
pushToast({
|
||||
timeout: 30_000,
|
||||
children: {
|
||||
component: ThunkToast,
|
||||
props: {thunk},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Only once it's sent, so a failure leaves the reply or edit in place to try again.
|
||||
clearParent()
|
||||
clearShare()
|
||||
clearEventToEdit()
|
||||
}
|
||||
|
||||
const getElementKey = (element: {id: string}) => element.id
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import {writable} from "svelte/store"
|
||||
import type {Maybe} from "@welshman/lib"
|
||||
import type {Maybe, MaybeAsync} from "@welshman/lib"
|
||||
import {MESSAGE} from "@welshman/util"
|
||||
import type {EventContent} from "@welshman/util"
|
||||
import {escapeHtml, isMobile, preventDefault} from "@lib/html"
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
import {makeEditor} from "@app/editor"
|
||||
import {app} from "@app/core"
|
||||
import {getDictation} from "@app/dictation"
|
||||
import {pushToast} from "@app/toast"
|
||||
import {DraftKey, type Draft} from "@app/drafts"
|
||||
import type {Share} from "@app/share"
|
||||
import {onDestroy, onMount} from "svelte"
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
h?: string
|
||||
onEscape?: () => void
|
||||
onEditPrevious?: () => void
|
||||
onSubmit: (event: EventContent) => void
|
||||
onSubmit: (event: EventContent) => MaybeAsync<void>
|
||||
initialValues?: Share
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +101,7 @@
|
|||
const hidePopover = () => tippy?.hide()
|
||||
|
||||
const submit = async () => {
|
||||
if ($uploading) {
|
||||
if ($uploading || sending) {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -108,12 +109,23 @@
|
|||
const content = ed.getText({blockSeparator: "\n"}).trim()
|
||||
const tags = ed.storage.nostr.getEditorTags()
|
||||
|
||||
onSubmit({content, tags})
|
||||
sending = true
|
||||
|
||||
try {
|
||||
await onSubmit({content, tags})
|
||||
} catch (error) {
|
||||
console.error("Failed to send message", error)
|
||||
|
||||
return pushToast({theme: "error", message: "Failed to send your message."})
|
||||
} finally {
|
||||
sending = false
|
||||
}
|
||||
|
||||
draftKey?.clear()
|
||||
ed.chain().clearContent(true).run()
|
||||
}
|
||||
|
||||
let sending = false
|
||||
let tippy: Maybe<TippyController> = $state()
|
||||
let content = $state(
|
||||
initialValues?.type === "text" ? initialValues.value : (draftKey?.get()?.content ?? ""),
|
||||
|
|
|
|||
Loading…
Reference in a new issue