Fix key backup gating, mention alerts toggle, and silent load failures

This commit is contained in:
Jon Staab 2026-07-27 15:21:39 -07:00
parent 73f2fb0ec2
commit ed61081b01
7 changed files with 39 additions and 38 deletions

View file

@ -63,12 +63,16 @@
const isQuote = (p: Parsed) => isEvent(p) || isAddress(p) const isQuote = (p: Parsed) => isEvent(p) || isAddress(p)
let warningDismissed = $state(false)
const ignoreWarning = () => { const ignoreWarning = () => {
warning = undefined warningDismissed = true
} }
let warning = $state( const warning = $derived(
$userSettingsValues.hide_sensitive && event.tags.find(nthEq(0, "content-warning"))?.[1], warningDismissed
? undefined
: $userSettingsValues.hide_sensitive && event.tags.find(nthEq(0, "content-warning"))?.[1],
) )
const dropWhile = <T,>(f: (x: T) => boolean, xs: Iterable<T>) => { const dropWhile = <T,>(f: (x: T) => boolean, xs: Iterable<T>) => {

View file

@ -4,6 +4,7 @@
import {encrypt} from "nostr-tools/nip49" import {encrypt} from "nostr-tools/nip49"
import {hexToBytes} from "@welshman/lib" import {hexToBytes} from "@welshman/lib"
import {preventDefault, downloadText} from "@lib/html" import {preventDefault, downloadText} from "@lib/html"
import {errorMessage} from "@lib/util"
import Key from "@assets/icons/key-minimalistic.svg?dataurl" import Key from "@assets/icons/key-minimalistic.svg?dataurl"
import ArrowDown from "@assets/icons/arrow-down.svg?dataurl" import ArrowDown from "@assets/icons/arrow-down.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
@ -94,19 +95,15 @@
try { try {
await downloadText("Nostr Secret Key.txt", cleanupCopy(instructions)) await downloadText("Nostr Secret Key.txt", cleanupCopy(instructions))
didDownload = true
} catch (e) { } catch (e) {
// Dismissing the native share sheet rejects with "Share canceled" — leave // Dismissing the native share sheet rejects with "Share canceled" — leave
// the flow gated so the user can try again rather than showing an error. // the flow gated so the user can try again rather than showing an error.
if ( if (!errorMessage(e).toLowerCase().includes("cancel")) {
!String((e as any)?.message || e)
.toLowerCase()
.includes("cancel")
) {
pushToast({theme: "error", message: "We couldn't save your key. Please try again."}) pushToast({theme: "error", message: "We couldn't save your key. Please try again."})
} }
} }
didDownload = true
} }
const onPasswordChange = () => { const onPasswordChange = () => {

View file

@ -22,6 +22,7 @@
import Link from "@lib/components/Link.svelte" import Link from "@lib/components/Link.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import ProfileAbout from "@app/components/ProfileAbout.svelte"
import ProfileCircle from "@app/components/ProfileCircle.svelte" import ProfileCircle from "@app/components/ProfileCircle.svelte"
import ProfileTrust from "@app/components/ProfileTrust.svelte" import ProfileTrust from "@app/components/ProfileTrust.svelte"
import ProfileSharedSpaces from "@app/components/ProfileSharedSpaces.svelte" import ProfileSharedSpaces from "@app/components/ProfileSharedSpaces.svelte"
@ -29,7 +30,6 @@
import ProfileEdit from "@app/components/ProfileEdit.svelte" import ProfileEdit from "@app/components/ProfileEdit.svelte"
import ProfileMenu from "@app/components/ProfileMenu.svelte" import ProfileMenu from "@app/components/ProfileMenu.svelte"
import WotScore from "@app/components/WotScore.svelte" import WotScore from "@app/components/WotScore.svelte"
import Content from "@app/components/Content.svelte"
import {updateProfile} from "@app/profiles" import {updateProfile} from "@app/profiles"
import {compressFileForUpload, uploadFile} from "@app/uploads" import {compressFileForUpload, uploadFile} from "@app/uploads"
import {pushModal} from "@app/modal" import {pushModal} from "@app/modal"
@ -201,11 +201,7 @@
{/if} {/if}
{#if $profile?.about} {#if $profile?.about}
<Content <ProfileAbout pubkey={target} />
event={{content: $profile.about, tags: []}}
expandMode="block"
minLength={150}
maxLength={250} />
{/if} {/if}
</div> </div>
</div> </div>

View file

@ -118,8 +118,8 @@
{/if} {/if}
</div> </div>
</div> </div>
{#if $members !== undefined && $members.length > 0} <div class="card card-sm flex flex-col gap-3">
<div class="card card-sm flex flex-col gap-3"> {#if $members.length > 0}
<div class="flex items-center justify-between gap-4"> <div class="flex items-center justify-between gap-4">
<div class="flex min-w-0 items-center gap-4"> <div class="flex min-w-0 items-center gap-4">
<span class="shrink-0">Members:</span> <span class="shrink-0">Members:</span>
@ -128,18 +128,16 @@
<Button class="button button-neutral button-sm shrink-0" onclick={showMembers} <Button class="button button-neutral button-sm shrink-0" onclick={showMembers}
>View All</Button> >View All</Button>
</div> </div>
{#if $userIsAdmin} {:else}
<Button class="button button-neutral" onclick={createInvite}> <span class="opacity-75">No member list is available for this room.</span>
<Icon icon={LinkRound} /> {/if}
Create invite {#if $userIsAdmin}
</Button> <Button class="button button-neutral" onclick={createInvite}>
{/if} <Icon icon={LinkRound} />
</div> Create invite
{:else if $members === undefined} </Button>
<div class="card card-sm bg-surface flex items-center gap-4"> {/if}
<span class="text-error">Member list not available from this relay</span> </div>
</div>
{/if}
<div class="card card-sm flex flex-col gap-4"> <div class="card card-sm flex flex-col gap-4">
<strong class="text-lg">Room Settings</strong> <strong class="text-lg">Room Settings</strong>
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">

View file

@ -22,6 +22,7 @@
import {CONTENT_KINDS} from "@app/content" import {CONTENT_KINDS} from "@app/content"
import {deriveEventsForUrlDesc} from "@app/repository" import {deriveEventsForUrlDesc} from "@app/repository"
import {popModal} from "@app/modal" import {popModal} from "@app/modal"
import {pushToast} from "@app/toast"
import {goToEvent} from "@app/routes" import {goToEvent} from "@app/routes"
type Props = { type Props = {
@ -59,13 +60,16 @@
results = sortEventsDesc(uniqBy((e: TrustedEvent) => e.id, [...events, ...results])) results = sortEventsDesc(uniqBy((e: TrustedEvent) => e.id, [...events, ...results]))
} catch (error) { } catch (error) {
// Ignore aborts from superseded searches; surface anything else // Superseded searches abort; the search that replaced this one owns loading from here
if (!(error instanceof DOMException && error.name === "AbortError")) { if (error instanceof DOMException && error.name === "AbortError") {
throw error return
} }
} finally {
loading = false console.error(error)
pushToast({theme: "error", message: "Something went wrong while searching."})
} }
loading = false
}) })
const onInput = () => { const onInput = () => {

View file

@ -21,6 +21,7 @@
import PageContent from "@lib/components/PageContent.svelte" import PageContent from "@lib/components/PageContent.svelte"
import ProfilePage from "@app/components/ProfilePage.svelte" import ProfilePage from "@app/components/ProfilePage.svelte"
import {loadGroupList} from "@app/groups" import {loadGroupList} from "@app/groups"
import {pushToast} from "@app/toast"
const {npub} = $page.params as MakeNonOptional<typeof $page.params> const {npub} = $page.params as MakeNonOptional<typeof $page.params>
@ -58,8 +59,9 @@
relays: Router.get().FromPubkeys([pubkey]).getUrls(), relays: Router.get().FromPubkeys([pubkey]).getUrls(),
filters, filters,
}) })
} catch { } catch (e) {
goto("/people", {replaceState: true}) console.error(e)
pushToast({theme: "error", message: "Some of this profile could not be loaded."})
} }
}) })
</script> </script>

View file

@ -115,7 +115,7 @@
<p>Always notify me when mentioned</p> <p>Always notify me when mentioned</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<ToggleInput checked={settings.mentions} /> <ToggleInput bind:checked={settings.mentions} />
{/snippet} {/snippet}
</FieldInline> </FieldInline>
<FieldInline> <FieldInline>