Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creation and Submission delay and status #457

Open
wants to merge 14 commits into
base: dev
Choose a base branch
from
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ VITE_INDEXER_RELAYS=wss://relay.nostr.band,wss://purplepag.es,wss://relay.damus.
VITE_DEFAULT_FOLLOWS=fe7f6bc6f7338b76bbf80db402ade65953e20b2f23e66e898204b63cc42539a3,f4db5270bd991b17bea1e6d035f45dee392919c29474bbac10342d223c74e0d0,180a6d42c7d64f8c3958d9d10dd5a4117eaaacea8e7f980781e9a53136cf5693,7bdef7be22dd8e59f4600e044aa53a1cf975a9dc7d27df5833bc77db784a5805,676ffea2ec31426a906d7795d7ebae2ba5e61f0b9fa815995b4a299dd085d510,4d5ce768123563bc583697db5e84841fb528f7b708d966f2e546286ce3c72077,eab0e756d32b80bcd464f3d844b8040303075a13eabc3599a762c9ac7ab91f4f,04c915daefee38317fa734444acee390a8269fe5810b2241e5e6dd343dfbecc9,85080d3bad70ccdcd7f74c29a44f55bb85cbcd3dd0cbb957da1d215bdb931204,74ffc51cc30150cf79b6cb316d3a15cf332ab29a38fec9eb484ab1551d6d1856,93518f91dfa51d8acf39217cdcd3d2ccd178433cb9e72368544aacd7412cb50c,f728d9e6e7048358e70930f5ca64b097770d989ccd86854fe618eda9c8a38106,91c9a5e1a9744114c6fe2d61ae4de82629eaaa0fb52f48288093c7e7e036f832,83e818dfbeccea56b0f551576b3fd39a7a50e1d8159343500368fa085ccd964b,090254801a7e8e5085b02e711622f0dfa1a85503493af246aa42af08f5e4d2df,472f440f29ef996e92a186b8d320ff180c855903882e59d50de1b8bd5669301e,7b3f7803750746f455413a221f80965eecb69ef308f2ead1da89cc2c8912e968,330fb1431ff9d8c250706bbcdc016d5495a3f744e047a408173e92ae7ee42dac,c4eabae1be3cf657bc1855ee05e69de9f059cb7a059227168b80b89761cbc4e0,a4cb51f4618cfcd16b2d3171c466179bed8e197c43b8598823b04de266cef110,f9acb0b034c4c1177e985f14639f317ef0fedee7657c060b146ee790024317ec,6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93,e88a691e98d9987c964521dff60025f60700378a4879180dcbbb4a5027850411,6389be6491e7b693e9f368ece88fcd145f07c068d2c1bbae4247b9b5ef439d32,e1ff3bfdd4e40315959b08b4fcc8245eaa514637e1d4ec2ae166b743341be1af,38dbb9b07d93861d40620ad62d44b1a8e8785df0997eeb4454f12d217048cd5c,064de2497ce621aee2a5b4b926a08b1ca01bce9da85b0c714e883e119375140c,aa5e6ccfc7cb7c3431d12b0ea4b83e5b35427602522080a6a8618950527f811b,97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322,676ffea2ec31426a906d7795d7ebae2ba5e61f0b9fa815995b4a299dd085d510,f783ba3b12b91e375aba6594015b90bd95f7e132b03cc8c4c52ce0a7c36aab52,9a4acdeb978565e27490dca65c83e9f65745eaec1d9a0405a52d198c1489913b,e5177ebf513530c2d0924083b64b7eadd7fb85efcc3e4dfb55c73a924c901ca7,5b0183ab6c3e322bf4d41c6b3aef98562a144847b7499543727c5539a114563e,958b754a1d3de5b5eca0fe31d2d555f451325f8498a83da1997b7fcd5c39e88c,5c508c34f58866ec7341aaf10cc1af52e9232bb9f859c8103ca5ecf2aa93bf78,26bd32c67232bdf16d05e763ec67d883015eb99fd1269025224c20c6cfdb0158,d307643547703537dfdef811c3dea96f1f9e84c8249e200353425924a9908cf8,604e96e099936a104883958b040b47672e0f048c98ac793f37ffe4c720279eb2,90b9bec74789688e515125596ab6350bfe646176ac75742275063922c5fea010,baf27a4cc4da49913e7fdecc951fd3b971c9279959af62b02b761a043c33384c,2edbcea694d164629854a52583458fd6d965b161e3c48b57d3aff01940558884,82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2,66bd8fed3590f2299ef0128f58d67879289e6a99a660e83ead94feab7606fd17,eeb11961b25442b16389fe6c7ebea9adf0ac36dd596816ea7119e521b8821b9e,61066504617ee79387021e18c89fb79d1ddbc3e7bff19cf2298f40466f8715e9,1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411,a9434ee165ed01b286becfc2771ef1705d3537d051b387288898cc00d5c885be,ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74,7bdef7be22dd8e59f4600e044aa53a1cf975a9dc7d27df5833bc77db784a5805,1577e4599dd10c863498fe3c20bd82aafaf829a595ce83c5cf8ac3463531b09b,1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef,fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52,cc8d072efdcc676fcbac14f6cd6825edc3576e55eb786a2a975ee034a6a026cb,d91191e30e00444b942c0e82cad470b32af171764c2275bee0bd99377efd4075,3335d373e6c1b5bc669b4b1220c08728ea8ce622e5a7cfeeb4c0001d91ded1de,0b118e40d6f3dfabb17f21a94a647701f140d8b063a9e84fe6e483644edc09cb,b83a28b7e4e5d20bd960c5faeb6625f95529166b8bdb045d42634a2f35919450,958b754a1d3de5b5eca0fe31d2d555f451325f8498a83da1997b7fcd5c39e88c,a4cb51f4618cfcd16b2d3171c466179bed8e197c43b8598823b04de266cef110,e56e7b4326618f3d626c0e398f5082c3b16732e469e0a048b7ddb544c2be294a,011c1b374c12fbd3633e98957d3c46bed67983abecef50706c73a77c171d0d2c,b9e76546ba06456ed301d9e52bc49fa48e70a6bf2282be7a1ae72947612023dc,b708f7392f588406212c3882e7b3bc0d9b08d62f95fa170d099127ece2770e5e,5c508c34f58866ec7341aaf10cc1af52e9232bb9f859c8103ca5ecf2aa93bf78,baf27a4cc4da49913e7fdecc951fd3b971c9279959af62b02b761a043c33384c,2edbcea694d164629854a52583458fd6d965b161e3c48b57d3aff01940558884,0fecf65daa26faf3f668e8143325a4c199a040b6345ed40a08614d7dd85b1823,1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411,f783ba3b12b91e375aba6594015b90bd95f7e132b03cc8c4c52ce0a7c36aab52,3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24,82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2,3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d,ee11a5dff40c19a555f41fe42b48f00e618c91225622ae37b6c2bb67b76c4e49,eab0e756d32b80bcd464f3d844b8040303075a13eabc3599a762c9ac7ab91f4f,58c741aa630c2da35a56a77c1d05381908bd10504fdd2d8b43f725efa6d23196,84dee6e676e5bb67b4ad4e042cf70cbd8681155db535942fcc6a0533858a7240,33bd77e5394520747faae1394a4af5fa47f404389676375b6dc7be865ed81452,21335073401a310cc9179fe3a77e9666710cfdf630dfd840f972c183a244b1ad,36732cc35fe56185af1b11160a393d6c73a1fe41ddf1184c10394c28ca5d627b,3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d,fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52,32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245,63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed,97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322,00000000827ffaa94bfea288c3dfce4422c794fbb96625b6b31e9049f729d700,3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24,e88a691e98d9987c964521dff60025f60700378a4879180dcbbb4a5027850411,82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2,e8ed3798c6ffebffa08501ac39e271662bfd160f688f94c45d692d8767dd345a,c5fb6ecc876e0458e3eca9918e370cbcd376901c58460512fe537a46e58c38bb,40b9c85fffeafc1cadf8c30a4e5c88660ff6e4971a0dc723d5ab674b5e61b451,a3eb29554bd27fca7f53f66272e4bb59d066f2f31708cf341540cb4729fbd841,460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c,0000005f87f64341c212cc93d6c266c03ae752c02660e78a6da1424f7b05c470,d61f3bc5b3eb4400efdae6169a5c17cabf3246b514361de939ce4a1a0da6ef4a,1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef,7adb520c3ac7cb6dc8253508df0ce1d975da49fefda9b5c956744a049d230ace,3335d373e6c1b5bc669b4b1220c08728ea8ce622e5a7cfeeb4c0001d91ded1de,266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5,17717ad4d20e2a425cda0a2195624a0a4a73c4f6975f16b1593fc87fa46f2d58,af9d70407464247d19fd243cf1bee81e6df1e639217dc66366bf37aa42d05d35,ddf03aca85ade039e6742d5bef3df352df199d0d31e22b9858e7eda85cb3bbbe,d36e8083fa7b36daee646cb8b3f99feaa3d89e5a396508741f003e21ac0b6bec,7fa56f5d6962ab1e3cd424e758c3002b8665f7b0d8dcee9fe9e288d7751ac194,cc8d072efdcc676fcbac14f6cd6825edc3576e55eb786a2a975ee034a6a026cb,d91191e30e00444b942c0e82cad470b32af171764c2275bee0bd99377efd4075,3d842afecd5e293f28b6627933704a3fb8ce153aa91d790ab11f6a752d44a42d,79c2cae114ea28a981e7559b4fe7854a473521a8d22a66bbab9fa248eb820ff6,17538dc2a62769d09443f18c37cbe358fab5bbf981173542aa7c5ff171ed77c4,ff27d01cb1e56fb58580306c7ba76bb037bf211c5b573c56e4e70ca858755af0,8fb140b4e8ddef97ce4b821d247278a1a4353362623f64021484b372f948000c,27797bd4e5ee52db0a197668c92b9a3e7e237e1f9fa73a10c38d731c294cfc9a,7cc328a08ddb2afdf9f9be77beff4c83489ff979721827d628a542f32a247c0e,c35ff8c340449f0d68af1aec4844bb44a9c0b8c1dd4f4d4efbc65e12039a348a,1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411,fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52,3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d,0b118e40d6f3dfabb17f21a94a647701f140d8b063a9e84fe6e483644edc09cb,2edbcea694d164629854a52583458fd6d965b161e3c48b57d3aff01940558884,1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef,eab0e756d32b80bcd464f3d844b8040303075a13eabc3599a762c9ac7ab91f4f,dace63b00c42e6e017d00dd190a9328386002ff597b841eb5ef91de4f1ce8491,76c71aae3a491f1d9eec47cba17e229cda4113a0bbb6e6ae1776d7643e29cafa,266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5,d91191e30e00444b942c0e82cad470b32af171764c2275bee0bd99377efd4075,7a3288f5b2a382317ddcbab9c0b6e9a22a999a064dfb9b7284508a0da3fa9114,6a72db8ef3f3b9ee5ecd808ed6d0631d1e4dda5c5dadf07887104d33957eba48
VITE_ONBOARDING_LISTS="30000:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:3121977322800018,30000:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:680038570738458,30000:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:33178290670580934,30000:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:49330924355910266,30000:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:9358486925304412,30000:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:3151213286926533"
VITE_NIP96_URLS=https://nostr.build,https://nostrcheck.me,https://sove.rent,https://void.cat
VITE_BLOSSOM_URLS=https://cdn.satellite.earth,https://blossom.hzrd149.com,https://blossom.f7z.io,https://void.cat
VITE_IMGPROXY_URL=https://imgproxy.coracle.social
VITE_DUFFLEPUD_URL=https://dufflepud.onrender.com
VITE_PLATFORM_ZAP_SPLIT=0
Expand Down
14 changes: 8 additions & 6 deletions src/app/MenuDesktop.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import {seconds} from "hurdak"
import {derived} from "svelte/store"
import {derived, get} from "svelte/store"
import {now} from "@welshman/lib"
import {PublishStatus} from "@welshman/net"
import {
Expand All @@ -9,6 +9,8 @@
sessions,
deriveProfileDisplay,
displayProfileByPubkey,
thunks,
type Thunk,
} from "@welshman/app"
import {toggleTheme, theme} from "src/partials/state"
import MenuItem from "src/partials/MenuItem.svelte"
Expand All @@ -20,21 +22,21 @@
import MenuDesktopSecondary from "src/app/MenuDesktopSecondary.svelte"
import {slowConnections} from "src/app/state"
import {router} from "src/app/util/router"
import {env, hasNewMessages, hasNewNotifications, publishes} from "src/engine"
import {env, hasNewMessages, hasNewNotifications} from "src/engine"

const {page} = router

const hud = derived(publishes, $publishes => {
const hud = derived(thunks, $thunks => {
const pending = []
const success = []
const failure = []

for (const {created_at, request, status} of Object.values($publishes)) {
if (created_at < now() - seconds(5, "minute")) {
for (const {event, request, status} of Object.values($thunks) as Thunk[]) {
if (event.created_at < now() - seconds(5, "minute")) {
continue
}

const statuses = Array.from(status.values())
const statuses = Object.values(get(status)).map(s => s.status)

if (statuses.includes(PublishStatus.Success)) {
success.push(request.event)
Expand Down
74 changes: 40 additions & 34 deletions src/app/shared/Note.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
getAncestorTagValues,
} from "@welshman/util"
import {repository, deriveZapperForPubkey, deriveZapper} from "@welshman/app"
import {identity, reject, whereEq, uniqBy, prop} from "ramda"
import {deriveEvents} from "@welshman/store"
import {identity, uniqBy, prop} from "ramda"
import {onMount} from "svelte"
import {quantify, batch} from "hurdak"
import {quantify} from "hurdak"
import {fly, slide} from "src/util/transition"
import {replyKinds, isLike} from "src/util/nostr"
import {formatTimestamp} from "src/util/misc"
import {formatTimestamp, timestamp1} from "src/util/misc"
import Popover from "src/partials/Popover.svelte"
import AltColor from "src/partials/AltColor.svelte"
import Spinner from "src/partials/Spinner.svelte"
Expand All @@ -30,6 +31,7 @@
import NoteReply from "src/app/shared/NoteReply.svelte"
import NoteActions from "src/app/shared/NoteActions.svelte"
import NoteContent from "src/app/shared/NoteContent.svelte"
import NotePending from "src/app/shared/NotePending.svelte"
import {router} from "src/app/util/router"
import {
env,
Expand All @@ -50,6 +52,8 @@
export let anchor = null
export let topLevel = false
export let isLastReply = false
export let isDraft = false
export let removeDraftCb = null
export let showParent = true
export let showLoading = false
export let showHidden = false
Expand All @@ -60,14 +64,19 @@
let replyCtrl = null
let replyIsActive = false
let showMutedReplies = false
let actions = null
let collapsed = depth === 0
let context = repository.query([{"#e": [event.id]}]).filter(e => isChildOf(e, event))
let showHiddenReplies = anchor === getIdOrAddress(event)
let draftEventId: string
let removeDraft: () => void

const showEntire = showHiddenReplies
const interactive = !anchor || !showEntire

const addDraftToContext = (event, cb) => {
draftEventId = event.id
removeDraft = () => cb() && repository.removeEvent(event.id)
}

const onClick = e => {
const target = (e.detail?.target || e.target) as HTMLElement

Expand Down Expand Up @@ -100,13 +109,9 @@
.at("thread")
.open()

const removeFromContext = e => {
context = reject(whereEq({id: e.id}), context)
}

const addToContext = events => {
context = context.concat(events)
}
const context = deriveEvents(repository, {
filters: [{"#e": [event.id]}],
})

$: ancestors = getAncestorTagValues(event.tags || [])
$: reply = ancestors.replies[0]
Expand All @@ -117,8 +122,7 @@
$: hidden = $isEventMuted(event, true)

// Find children in our context
$: children = context.filter(e => isChildOf(e, event))

$: children = $context.filter(e => isChildOf(e, event))
// Sort our replies
$: replies = sortEventsDesc(children.filter(e => replyKinds.includes(e.kind)))

Expand All @@ -134,7 +138,12 @@
mutedReplies.push(e)
} else if (collapsed) {
hiddenReplies.push(e)
} else if (!showHiddenReplies && filters && !matchFilters(filters, e)) {
} else if (
!showHiddenReplies &&
filters &&
!matchFilters(filters, e) &&
draftEventId !== e.id
) {
hiddenReplies.push(e)
} else {
visibleReplies.push(e)
Expand Down Expand Up @@ -200,9 +209,6 @@
load({
relays: ctx.app.router.Replies(event).getUrls(),
filters: getReplyFilters([event], {kinds}),
onEvent: batch(200, events => {
context = uniqBy(prop("id"), context.concat(events))
}),
})
}
})
Expand Down Expand Up @@ -284,18 +290,19 @@
<NoteContent note={event} {showEntire} {showMedia} />
{/if}
<div class="cy-note-click-target h-[2px]" />
<NoteActions
note={event}
zapper={$zapper}
bind:this={actions}
{removeFromContext}
{addToContext}
{replyCtrl}
{showHidden}
{replies}
{likes}
{zaps}
{muted} />
{#if !isDraft || event.created_at < $timestamp1 - 45}
ticruz38 marked this conversation as resolved.
Show resolved Hide resolved
<NoteActions
note={event}
zapper={$zapper}
{replyCtrl}
{showHidden}
{replies}
{likes}
{zaps}
{muted} />
{:else}
<NotePending {event} removeDraft={removeDraftCb} />
{/if}
</div>
</div>
</Card>
Expand Down Expand Up @@ -327,7 +334,7 @@
{/if}

<NoteReply
{addToContext}
{addDraftToContext}
parent={event}
showBorder={visibleReplies.length > 0}
bind:this={replyCtrl}
Expand All @@ -336,9 +343,6 @@
}}
on:reset={() => {
replyIsActive = false
}}
on:event={e => {
context = [e.detail, ...context]
}} />

{#if visibleReplies.length > 0 || hiddenReplies.length > 0 || mutedReplies.length > 0}
Expand Down Expand Up @@ -369,6 +373,8 @@
isLastReply={i === visibleReplies.length - 1}
showParent={false}
showHidden
isDraft={r.id === draftEventId}
removeDraftCb={removeDraft}
note={r}
depth={depth - 1}
{filters}
Expand Down
9 changes: 2 additions & 7 deletions src/app/shared/NoteActions.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@
export let muted
export let replyCtrl
export let showHidden
export let addToContext
export let removeFromContext
export let replies, likes, zaps
export let zapper

Expand Down Expand Up @@ -116,14 +114,11 @@

const tags = [...tagReactionTo(note), ...getClientTags()]
const template = createEvent(7, {content, tags})
const pub = await signAndPublish(template)

addToContext(pub.request.event)
await signAndPublish(template)
}

const deleteReaction = e => {
deleteEvent(e)
removeFromContext(e)
}

const startZap = () => {
Expand All @@ -138,7 +133,7 @@
id: note.id,
anonymous: Boolean(note.wrap),
})
.cx({callback: addToContext})
.cx({callback: repository.publish})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can actually be removed. We might be able to get rid of callback from Zap as well if it's not used anywhere else.

.open()
}

Expand Down
88 changes: 88 additions & 0 deletions src/app/shared/NotePending.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<style>
.loading-bar {
position: absolute;
top: 0;
left: 0;
height: 100%;
}

div.loading-bar::after {
content: "";
position: absolute;
top: 0;
right: -50px;
width: 50px;
height: 100%;
background: linear-gradient(to left, rgba(0, 0, 0, 0), var(--accent));
}

.loading-bar-content > * {
z-index: 1;
}
</style>

<script lang="ts">
import {thunks, type Thunk} from "@welshman/app"
import {PublishStatus} from "@welshman/net"
import type {SignedEvent} from "@welshman/util"
import {userSettings} from "src/engine"
import Anchor from "src/partials/Anchor.svelte"
import {timestamp1} from "src/util/misc"
import {spring} from "svelte/motion"

export let event: SignedEvent
export let removeDraft: () => void

$: thunk = $thunks[event.id] as Thunk

$: status = thunk?.status

$: pendings = Object.values($status || {}).filter(s => s.status === PublishStatus.Pending).length
$: failed = Object.values($status || {}).filter(
s => s.status === PublishStatus.Failure || s.status === PublishStatus.Aborted,
).length
$: timeout = Object.values($status || {}).filter(s => s.status === PublishStatus.Timeout).length
$: success = Object.values($status || {}).filter(s => s.status === PublishStatus.Success).length
$: total = thunk?.request?.relays.length || 0

const completed = spring(0)

$: {
if (thunk) {
$completed = ((total - pendings) / total) * 100
}
}

$: isPending = pendings > 0
$: isCompleted = total === success + failed + timeout
</script>

<div
class="loading-bar-content relative flex h-6 w-full items-center justify-between overflow-hidden rounded-md pl-4 text-sm"
class:border={!thunk}
on:click|stopPropagation>
{#if thunk && (isPending || isCompleted)}
<div class="loading-bar bg-accent" style="width: {$completed}%"></div>
{#if isPending}
<span>Publishing...</span>
<span>{total - pendings} of {total} relays</span>
{:else}
<span>Published to {success}/{total} ({failed} failed, {timeout} timed out)</span>
<Anchor
class="staatliches z-feature rounded-r-md bg-tinted-100-d px-4 py-1 uppercase text-tinted-700-d"
modal
href="/publishes">See details</Anchor>
{/if}
{:else if $userSettings.send_delay > 0}
<span
>Sending reply in {event.created_at +
Math.ceil($userSettings.send_delay / 1000) -
$timestamp1} seconds</span>

<button
class="ml-2 cursor-pointer rounded-md bg-neutral-100-d px-4 py-1 text-tinted-700-d"
on:click={() => {
removeDraft()
}}>Cancel</button>
{/if}
</div>
Loading