diff --git a/src/app/components/ThunkStatusDetail.svelte b/src/app/components/ThunkStatusDetail.svelte
index cc8b2653..3da57bb4 100644
--- a/src/app/components/ThunkStatusDetail.svelte
+++ b/src/app/components/ThunkStatusDetail.svelte
@@ -2,6 +2,7 @@
import {PublishStatus} from "@welshman/net"
import {displayRelayUrl} from "@welshman/util"
import Button from "@lib/components/Button.svelte"
+ import {addPeriod} from "@lib/util"
interface Props {
url: string
@@ -25,7 +26,7 @@
- Failed to publish to {displayRelayUrl(url)}: {message}.
+ Failed to publish to {displayRelayUrl(url)}: {addPeriod(message)}
diff --git a/src/app/editor/index.ts b/src/app/editor/index.ts
index 2184f317..8ea78606 100644
--- a/src/app/editor/index.ts
+++ b/src/app/editor/index.ts
@@ -15,6 +15,7 @@ import {
} from "@welshman/app"
import type {FileAttributes} from "@welshman/editor"
import {Editor, MentionSuggestion, WelshmanExtension, editorProps} from "@welshman/editor"
+import {escapeHtml} from "@lib/html"
import {makeMentionNodeView} from "@app/editor/MentionNodeView"
import ProfileSuggestion from "@app/editor/ProfileSuggestion.svelte"
import {uploadFile} from "@app/core/commands"
@@ -82,7 +83,7 @@ export const makeEditor = async ({
)
return new Editor({
- content,
+ content: escapeHtml(content),
autofocus,
editorProps,
element: document.createElement("div"),
diff --git a/src/lib/html.ts b/src/lib/html.ts
index ec38e0d4..adfd6aca 100644
--- a/src/lib/html.ts
+++ b/src/lib/html.ts
@@ -164,3 +164,11 @@ export const compressFile = async (
})
})
}
+
+export const escapeHtml = (html: string) => {
+ const element = document.createElement("div")
+
+ element.innerText = html
+
+ return element.innerHTML
+}
diff --git a/src/lib/util.ts b/src/lib/util.ts
index a1ae8d5b..6a2248ec 100644
--- a/src/lib/util.ts
+++ b/src/lib/util.ts
@@ -26,3 +26,5 @@ export const buildUrl = (base: string | URL, ...pathname: string[]) => {
return url.toString()
}
+
+export const addPeriod = (s: string) => (s + ".").replace(/\.+$/, ".")
diff --git a/src/routes/spaces/[relay]/[h]/+page.svelte b/src/routes/spaces/[relay]/[h]/+page.svelte
index e93bf402..53dd5624 100644
--- a/src/routes/spaces/[relay]/[h]/+page.svelte
+++ b/src/routes/spaces/[relay]/[h]/+page.svelte
@@ -110,51 +110,58 @@
}
const onSubmit = async ({content, tags}: EventContent) => {
- tags.push(["h", h])
+ try {
+ tags.push(["h", h])
- if (await shouldProtect) {
- tags.push(PROTECTED)
- }
+ if (await shouldProtect) {
+ tags.push(PROTECTED)
+ }
- let template: EventContent & {created_at?: number} = {content, tags}
+ let template: EventContent & {created_at?: number} = {content, tags}
- if (eventToEdit) {
- // Delete previous message, to be republished with same timestamp
- template.created_at = eventToEdit.created_at
- publishDelete({
+ if (eventToEdit) {
+ // Don't do anything if message hasn't changed
+ if (eventToEdit.content === content) {
+ return
+ }
+
+ // Delete previous message, to be republished with same timestamp
+ template.created_at = eventToEdit.created_at
+ publishDelete({
+ relays: [url],
+ event: $state.snapshot(eventToEdit),
+ protect: await shouldProtect,
+ })
+ }
+
+ if (share) {
+ template = prependParent(share, template, url)
+ }
+
+ if (parent) {
+ template = prependParent(parent, template, url)
+ }
+
+ const thunk = publishThunk({
relays: [url],
- event: $state.snapshot(eventToEdit),
- protect: await shouldProtect,
+ event: makeEvent(MESSAGE, template),
+ delay: $userSettingsValues.send_delay,
})
+
+ if ($userSettingsValues.send_delay) {
+ pushToast({
+ timeout: 30_000,
+ children: {
+ component: ThunkToast,
+ props: {thunk},
+ },
+ })
+ }
+ } finally {
+ clearParent()
+ clearShare()
+ clearEventToEdit()
}
-
- if (share) {
- template = prependParent(share, template, url)
- }
-
- if (parent) {
- template = prependParent(parent, template, url)
- }
-
- const thunk = publishThunk({
- relays: [url],
- event: makeEvent(MESSAGE, template),
- delay: $userSettingsValues.send_delay,
- })
-
- if ($userSettingsValues.send_delay) {
- pushToast({
- timeout: 30_000,
- children: {
- component: ThunkToast,
- props: {thunk},
- },
- })
- }
-
- clearParent()
- clearShare()
- clearEventToEdit()
}
const onScroll = () => {
diff --git a/src/routes/spaces/[relay]/chat/+page.svelte b/src/routes/spaces/[relay]/chat/+page.svelte
index 3da1032e..596f1d1f 100644
--- a/src/routes/spaces/[relay]/chat/+page.svelte
+++ b/src/routes/spaces/[relay]/chat/+page.svelte
@@ -54,45 +54,52 @@
}
const onSubmit = async ({content, tags}: EventContent) => {
- let template: EventContent & {created_at?: number} = {content, tags}
+ try {
+ let template: EventContent & {created_at?: number} = {content, tags}
- if (eventToEdit) {
- // Delete previous message, to be republished with same timestamp
- template.created_at = eventToEdit.created_at
- publishDelete({relays: [url], event: eventToEdit, protect: await shouldProtect})
- }
+ if (eventToEdit) {
+ // Don't do anything if message hasn't changed
+ if (eventToEdit.content === content) {
+ return
+ }
- if (await shouldProtect) {
- tags.push(PROTECTED)
- }
+ // Delete previous message, to be republished with same timestamp
+ template.created_at = eventToEdit.created_at
+ publishDelete({relays: [url], event: eventToEdit, protect: await shouldProtect})
+ }
- if (share) {
- template = prependParent(share, template, url)
- }
+ if (await shouldProtect) {
+ tags.push(PROTECTED)
+ }
- if (parent) {
- template = prependParent(parent, template, url)
- }
+ if (share) {
+ template = prependParent(share, template, url)
+ }
- const thunk = publishThunk({
- relays: [url],
- event: makeEvent(MESSAGE, template),
- delay: $userSettingsValues.send_delay,
- })
+ if (parent) {
+ template = prependParent(parent, template, url)
+ }
- if ($userSettingsValues.send_delay) {
- pushToast({
- timeout: 30_000,
- children: {
- component: ThunkToast,
- props: {thunk},
- },
+ const thunk = publishThunk({
+ relays: [url],
+ event: makeEvent(MESSAGE, template),
+ delay: $userSettingsValues.send_delay,
})
- }
- clearParent()
- clearShare()
- clearEventToEdit()
+ if ($userSettingsValues.send_delay) {
+ pushToast({
+ timeout: 30_000,
+ children: {
+ component: ThunkToast,
+ props: {thunk},
+ },
+ })
+ }
+ } finally {
+ clearParent()
+ clearShare()
+ clearEventToEdit()
+ }
}
const onScroll = () => {