diff --git a/src/app/components/CalendarEventActions.svelte b/src/app/components/CalendarEventActions.svelte index a932640a..3c3258c4 100644 --- a/src/app/components/CalendarEventActions.svelte +++ b/src/app/components/CalendarEventActions.svelte @@ -22,15 +22,17 @@ showActivity?: boolean } = $props() + const shouldProtect = canEnforceNip70(url) + const path = makeCalendarPath(url, event.id) const editEvent = () => pushModal(CalendarEventEdit, {url, event}) const deleteReaction = async (event: TrustedEvent) => - publishDelete({relays: [url], event, protect: await canEnforceNip70(url)}) + publishDelete({relays: [url], event, protect: await shouldProtect}) const createReaction = async (template: EventContent) => - publishReaction({...template, event, relays: [url], protect: await canEnforceNip70(url)}) + publishReaction({...template, event, relays: [url], protect: await shouldProtect})
diff --git a/src/app/components/CalendarEventForm.svelte b/src/app/components/CalendarEventForm.svelte index 8cc32e18..c32078b8 100644 --- a/src/app/components/CalendarEventForm.svelte +++ b/src/app/components/CalendarEventForm.svelte @@ -33,6 +33,8 @@ const {url, header, initialValues}: Props = $props() + const shouldProtect = canEnforceNip70(url) + const uploading = writable(false) const back = () => history.back() @@ -75,7 +77,7 @@ ...ed.storage.nostr.getEditorTags(), ] - if (await canEnforceNip70(url)) { + if (await shouldProtect) { tags.push(PROTECTED) } diff --git a/src/app/components/ChannelMessage.svelte b/src/app/components/ChannelMessage.svelte index c6a1db49..23a2e6c2 100644 --- a/src/app/components/ChannelMessage.svelte +++ b/src/app/components/ChannelMessage.svelte @@ -8,7 +8,7 @@ import Icon from "@lib/components/Icon.svelte" import Button from "@lib/components/Button.svelte" import Content from "@app/components/Content.svelte" - import ThunkStatus from "@app/components/ThunkStatus.svelte" + import ThunkFailure from "@app/components/ThunkFailure.svelte" import ProfileDetail from "@app/components/ProfileDetail.svelte" import ReactionSummary from "@app/components/ReactionSummary.svelte" import ChannelMessageZapButton from "@app/components/ChannelMessageZapButton.svelte" @@ -30,6 +30,7 @@ const {url, event, replyTo = undefined, showPubkey = false, inert = false}: Props = $props() const thunk = $thunks[event.id] + const shouldProtect = canEnforceNip70(url) const today = formatTimestampAsDate(now()) const profile = deriveProfile(event.pubkey, [url]) const profileDisplay = deriveProfileDisplay(event.pubkey, [url]) @@ -42,10 +43,10 @@ const openProfile = () => pushModal(ProfileDetail, {pubkey: event.pubkey, url}) const deleteReaction = async (event: TrustedEvent) => - publishDelete({relays: [url], event, protect: await canEnforceNip70(url)}) + publishDelete({relays: [url], event, protect: await shouldProtect}) const createReaction = async (template: EventContent) => - publishReaction({...template, event, relays: [url], protect: await canEnforceNip70(url)}) + publishReaction({...template, event, relays: [url], protect: await shouldProtect}) {#if thunk} - + {/if}
diff --git a/src/app/components/ChannelMessageEmojiButton.svelte b/src/app/components/ChannelMessageEmojiButton.svelte index 9847ae4c..fcafeef6 100644 --- a/src/app/components/ChannelMessageEmojiButton.svelte +++ b/src/app/components/ChannelMessageEmojiButton.svelte @@ -6,12 +6,14 @@ const {url, event} = $props() + const shouldProtect = canEnforceNip70(url) + const onEmoji = async (emoji: NativeEmoji) => publishReaction({ event, relays: [url], content: emoji.unicode, - protect: await canEnforceNip70(url), + protect: await shouldProtect, }) diff --git a/src/app/components/ChannelMessageMenuMobile.svelte b/src/app/components/ChannelMessageMenuMobile.svelte index 44be1921..50006c85 100644 --- a/src/app/components/ChannelMessageMenuMobile.svelte +++ b/src/app/components/ChannelMessageMenuMobile.svelte @@ -20,13 +20,15 @@ const {url, event, reply}: Props = $props() + const shouldProtect = canEnforceNip70(url) + const onEmoji = (async (event: TrustedEvent, url: string, emoji: NativeEmoji) => { history.back() publishReaction({ event, relays: [url], content: emoji.unicode, - protect: await canEnforceNip70(url), + protect: await shouldProtect, }) }).bind(undefined, event, url) diff --git a/src/app/components/Chat.svelte b/src/app/components/Chat.svelte index f69c7b9b..9da21ab0 100644 --- a/src/app/components/Chat.svelte +++ b/src/app/components/Chat.svelte @@ -26,9 +26,11 @@ pubkey, tagPubkey, sendWrapped, + mergeThunks, loadInboxRelaySelections, inboxRelaySelectionsByPubkey, } from "@welshman/app" + import type {AbstractThunk} from "@welshman/app" import Icon from "@lib/components/Icon.svelte" import Link from "@lib/components/Link.svelte" import Spinner from "@lib/components/Spinner.svelte" @@ -44,6 +46,7 @@ import ChatMessage from "@app/components/ChatMessage.svelte" import ChatCompose from "@app/components/ChatCompose.svelte" import ChatComposeParent from "@app/components/ChatComposeParent.svelte" + import ThunkToast from "@app/components/ThunkToast.svelte" import { INDEXER_RELAYS, userSettingValues, @@ -53,6 +56,7 @@ } from "@app/state" import {pushModal} from "@app/modal" import {prependParent} from "@app/commands" + import {pushToast} from "@app/toast" type Props = { id: string @@ -121,12 +125,23 @@ // Split the message into multiple pieces so that we can use kind 15 to send images per nip 17 // Sleep 1 second between each one to make sure timestamps are distinct + const thunks: AbstractThunk[] = [] for (let i = 0; i < templates.length; i++) { const template = templates[i] - await sendWrapped({pubkeys, template, delay: $userSettingValues.send_delay + ms(i)}) + thunks.push( + await sendWrapped({pubkeys, template, delay: $userSettingValues.send_delay + ms(i)}), + ) } + pushToast({ + timeout: 30_000, + children: { + component: ThunkToast, + props: {thunk: mergeThunks(thunks)}, + }, + }) + clearParent() } diff --git a/src/app/components/ChatMessage.svelte b/src/app/components/ChatMessage.svelte index 24640250..65687e23 100644 --- a/src/app/components/ChatMessage.svelte +++ b/src/app/components/ChatMessage.svelte @@ -11,7 +11,7 @@ import Avatar from "@lib/components/Avatar.svelte" import Content from "@app/components/Content.svelte" import ReactionSummary from "@app/components/ReactionSummary.svelte" - import ThunkStatus from "@app/components/ThunkStatus.svelte" + import ThunkFailure from "@app/components/ThunkFailure.svelte" import ProfileDetail from "@app/components/ProfileDetail.svelte" import ChatMessageMenu from "@app/components/ChatMessageMenu.svelte" import ChatMessageMenuMobile from "@app/components/ChatMessageMenuMobile.svelte" @@ -59,7 +59,7 @@ {#if thunk} - + {/if}
- publishDelete({relays: [url], event, protect: await canEnforceNip70(url)}) + publishDelete({relays: [url], event, protect: await shouldProtect}) const createReaction = async (template: EventContent) => - publishReaction({...template, event, relays: [url], protect: await canEnforceNip70(url)}) + publishReaction({...template, event, relays: [url], protect: await shouldProtect})
diff --git a/src/app/components/EventActions.svelte b/src/app/components/EventActions.svelte index ae9c7094..2c0f446f 100644 --- a/src/app/components/EventActions.svelte +++ b/src/app/components/EventActions.svelte @@ -22,6 +22,8 @@ const {url, noun, event, hideZap, customActions}: Props = $props() + const shouldProtect = canEnforceNip70(url) + const showPopover = () => popover?.show() const hidePopover = () => popover?.hide() @@ -31,7 +33,7 @@ event, content: emoji.unicode, relays: [url], - protect: await canEnforceNip70(url), + protect: await shouldProtect, }) let popover: Instance | undefined = $state() diff --git a/src/app/components/EventDeleteConfirm.svelte b/src/app/components/EventDeleteConfirm.svelte index 3ee9a951..c56bf86c 100644 --- a/src/app/components/EventDeleteConfirm.svelte +++ b/src/app/components/EventDeleteConfirm.svelte @@ -11,8 +11,10 @@ const {url, event}: Props = $props() + const shouldProtect = canEnforceNip70(url) + const confirm = async () => { - await publishDelete({event, relays: [url], protect: await canEnforceNip70(url)}) + await publishDelete({event, relays: [url], protect: await shouldProtect}) clearModals() } diff --git a/src/app/components/EventReply.svelte b/src/app/components/EventReply.svelte index b70bc439..698cf25e 100644 --- a/src/app/components/EventReply.svelte +++ b/src/app/components/EventReply.svelte @@ -14,6 +14,8 @@ const {url, event, onClose, onSubmit} = $props() + const shouldProtect = canEnforceNip70(url) + const uploading = writable(false) const selectFiles = () => editor.then(ed => ed.commands.selectFiles()) @@ -25,7 +27,7 @@ const content = ed.getText({blockSeparator: "\n"}).trim() const tags = ed.storage.nostr.getEditorTags() - if (await canEnforceNip70(url)) { + if (await shouldProtect) { tags.push(PROTECTED) } diff --git a/src/app/components/EventReportDetails.svelte b/src/app/components/EventReportDetails.svelte index 1bdfcc06..4ba6ef23 100644 --- a/src/app/components/EventReportDetails.svelte +++ b/src/app/components/EventReportDetails.svelte @@ -10,6 +10,8 @@ const {url, event} = $props() + const shouldProtect = canEnforceNip70(url) + const reports = deriveEvents(repository, { filters: [{kinds: [REPORT], "#e": [event.id]}], }) @@ -17,7 +19,7 @@ const back = () => history.back() const deleteReport = async (report: TrustedEvent) => { - publishDelete({event: report, relays: [url], protect: await canEnforceNip70(url)}) + publishDelete({event: report, relays: [url], protect: await shouldProtect}) if ($reports.length === 0) { history.back() diff --git a/src/app/components/GoalActions.svelte b/src/app/components/GoalActions.svelte index 012b57fc..ce1928b8 100644 --- a/src/app/components/GoalActions.svelte +++ b/src/app/components/GoalActions.svelte @@ -15,13 +15,15 @@ const {url, event, showActivity = false}: Props = $props() + const shouldProtect = canEnforceNip70(url) + const path = makeGoalPath(url, event.id) const deleteReaction = async (event: TrustedEvent) => - publishDelete({relays: [url], event, protect: await canEnforceNip70(url)}) + publishDelete({relays: [url], event, protect: await shouldProtect}) const createReaction = async (template: EventContent) => - publishReaction({...template, event, relays: [url], protect: await canEnforceNip70(url)}) + publishReaction({...template, event, relays: [url], protect: await shouldProtect})
diff --git a/src/app/components/GoalCreate.svelte b/src/app/components/GoalCreate.svelte index b51c3b5c..295b42f6 100644 --- a/src/app/components/GoalCreate.svelte +++ b/src/app/components/GoalCreate.svelte @@ -17,6 +17,8 @@ const {url} = $props() + const shouldProtect = canEnforceNip70(url) + const uploading = writable(false) const back = () => history.back() @@ -50,7 +52,7 @@ ["relays", url], ] - if (await canEnforceNip70(url)) { + if (await shouldProtect) { tags.push(PROTECTED) } diff --git a/src/app/components/NoteItem.svelte b/src/app/components/NoteItem.svelte index 5da49183..539a59a8 100644 --- a/src/app/components/NoteItem.svelte +++ b/src/app/components/NoteItem.svelte @@ -10,18 +10,20 @@ const {url, event} = $props() + const shouldProtect = canEnforceNip70(url) + const deleteReaction = async (event: TrustedEvent) => - publishDelete({relays: [url], event, protect: await canEnforceNip70(url)}) + publishDelete({relays: [url], event, protect: await shouldProtect}) const createReaction = async (template: EventContent) => - publishReaction({...template, event, relays: [url], protect: await canEnforceNip70(url)}) + publishReaction({...template, event, relays: [url], protect: await shouldProtect}) const onEmoji = async (emoji: NativeEmoji) => publishReaction({ event, content: emoji.unicode, relays: [url], - protect: await canEnforceNip70(url), + protect: await shouldProtect, }) diff --git a/src/app/components/ThreadActions.svelte b/src/app/components/ThreadActions.svelte index d26491a2..d3462b80 100644 --- a/src/app/components/ThreadActions.svelte +++ b/src/app/components/ThreadActions.svelte @@ -15,13 +15,15 @@ const {url, event, showActivity = false}: Props = $props() + const shouldProtect = canEnforceNip70(url) + const path = makeThreadPath(url, event.id) const deleteReaction = async (event: TrustedEvent) => - publishDelete({relays: [url], event, protect: await canEnforceNip70(url)}) + publishDelete({relays: [url], event, protect: await shouldProtect}) const createReaction = async (template: EventContent) => - publishReaction({...template, event, relays: [url], protect: await canEnforceNip70(url)}) + publishReaction({...template, event, relays: [url], protect: await shouldProtect})
diff --git a/src/app/components/ThreadCreate.svelte b/src/app/components/ThreadCreate.svelte index 1965b1e7..72b1bdf8 100644 --- a/src/app/components/ThreadCreate.svelte +++ b/src/app/components/ThreadCreate.svelte @@ -16,6 +16,8 @@ const {url} = $props() + const shouldProtect = canEnforceNip70(url) + const uploading = writable(false) const back = () => history.back() @@ -44,7 +46,7 @@ const tags = [...ed.storage.nostr.getEditorTags(), ["title", title]] - if (await canEnforceNip70(url)) { + if (await shouldProtect) { tags.push(PROTECTED) } diff --git a/src/app/components/ThunkFailure.svelte b/src/app/components/ThunkFailure.svelte new file mode 100644 index 00000000..569b8de1 --- /dev/null +++ b/src/app/components/ThunkFailure.svelte @@ -0,0 +1,66 @@ + + +{#if showFailure} + {@const url = failedUrls[0]} + {@const status = $thunk.status[url]} + {@const message = $thunk.details[url]} + +{/if} diff --git a/src/app/components/ThunkPending.svelte b/src/app/components/ThunkPending.svelte new file mode 100644 index 00000000..4223a96c --- /dev/null +++ b/src/app/components/ThunkPending.svelte @@ -0,0 +1,32 @@ + + +
+ + + Sending... + + +
diff --git a/src/app/components/ThunkStatus.svelte b/src/app/components/ThunkStatus.svelte index 9148acfb..5c24da04 100644 --- a/src/app/components/ThunkStatus.svelte +++ b/src/app/components/ThunkStatus.svelte @@ -1,95 +1,22 @@ {#if showFailure} - {@const url = failedUrls[0]} - {@const status = $thunk.status[url]} - {@const message = $thunk.details[url]} - + {:else if showPending} -
- - - Sending... - - -
+ {/if} diff --git a/src/app/components/ThunkToast.svelte b/src/app/components/ThunkToast.svelte new file mode 100644 index 00000000..d8fd74d9 --- /dev/null +++ b/src/app/components/ThunkToast.svelte @@ -0,0 +1,39 @@ + + +{#if !isComplete} + +{:else if !isFailure} +

Message sent!

+{/if} diff --git a/src/app/components/Toast.svelte b/src/app/components/Toast.svelte index d9cf3c83..4afeb7c0 100644 --- a/src/app/components/Toast.svelte +++ b/src/app/components/Toast.svelte @@ -21,12 +21,17 @@ class:bg-base-100={theme === "info"} class:text-base-content={theme === "info"} class:alert-error={theme === "error"}> -

- {@html renderAsHtml(parse({content: $toast.message}))} - {#if $toast.action} - +

+ {#if $toast.message} + {@html renderAsHtml(parse({content: $toast.message}))} + {#if $toast.action} + + {/if} + {:else if $toast.children} + {@const {component: Component, props} = $toast?.children || {}} + {/if}