Open a note in a modal instead of on a page of its own (#628)

This commit is contained in:
Coracle-Bot 2026-09-23 03:48:52 +00:00 committed by hodlbod
parent cfc30803b4
commit 180ab5cb24
5 changed files with 56 additions and 47 deletions

View file

@ -6,8 +6,8 @@
import Reply from "@assets/icons/reply-2.svg?dataurl"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Page from "@lib/components/Page.svelte"
import PageContent from "@lib/components/PageContent.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import CommentCompose from "@app/components/CommentCompose.svelte"
import CommentTree from "@app/components/CommentTree.svelte"
@ -38,38 +38,34 @@
onDestroy(context.cleanup)
</script>
<Page>
<PageContent noPad class="flex flex-col">
<Modal label="Note">
<ModalBody>
{#if $event}
{@const note = $event}
{@const replyToNote = () => setReplyTo(note)}
<div class="border-b border-line bg-surface px-4 py-4">
<div class="mx-auto w-full max-w-[68ch]">
<NoteItem event={note} {context} card={false} showEntire>
{#if replyTo?.id !== note.id}
<Button class="button button-neutral button-xs" onclick={replyToNote}>
<Icon icon={Reply} size={4} />
Reply
</Button>
{/if}
</NoteItem>
</div>
</div>
<div class="mx-auto w-full max-w-[68ch] px-4 pt-4">
<div class="border-line flex flex-col gap-4 border-b pb-4">
<NoteItem event={note} {context} card={false} showEntire>
{#if replyTo?.id !== note.id}
<Button class="button button-neutral button-xs" onclick={replyToNote}>
<Icon icon={Reply} size={4} />
Reply
</Button>
{/if}
</NoteItem>
{#if replyTo?.id === note.id}
<div class="pb-4">
<CommentCompose
event={note}
noun="Reply"
onCancel={clearReplyTo}
onSubmit={clearReplyTo} />
</div>
<CommentCompose
event={note}
noun="Reply"
onCancel={clearReplyTo}
onSubmit={clearReplyTo} />
{/if}
</div>
<div class="flex flex-col">
{#each $replies as node (node.comment.id)}
<CommentTree {node} root={note} {replyTo} {setReplyTo} {context} />
{/each}
{#if $replies.length === 0 && replyTo?.id !== note.id}
<p class="py-6 text-sm opacity-75">No replies yet.</p>
{#if $replies.length === 0}
<p class="py-2 text-sm opacity-75">No replies yet.</p>
{/if}
</div>
{:else}
@ -81,5 +77,5 @@
{/await}
</div>
{/if}
</PageContent>
</Page>
</ModalBody>
</Modal>

View file

@ -25,7 +25,9 @@ import {entityLink, PLATFORM_URL, PLATFORM_RELAYS} from "@app/env"
import {decodeRelay, encodeRelay} from "@app/relays"
import {DM_KINDS} from "@app/content"
import {navigate, pushModal} from "@app/modal"
import type {NotePointer} from "@app/social"
import ChatEnable from "@app/components/ChatEnable.svelte"
import NoteDetail from "@app/components/NoteDetail.svelte"
// State
@ -267,8 +269,23 @@ export const scrollToEvent = (id: string) => {
return element instanceof HTMLElement
}
// A note opens over whatever is on screen rather than on a page of its own.
export const pushNote = (pointer: NotePointer) => pushModal(NoteDetail, {pointer}, {size: "large"})
// A url resolving to a note has nothing on screen to open it over, so the app goes behind it.
export const goToNote = (pointer: NotePointer) => {
pushNote(pointer)
return goToHome()
}
export const goToEvent = (event: TrustedEvent, options: Record<string, any> = {}) => {
const urls = Array.from(app.get().tracker.getRelays(event.id))
if (event.kind === NOTE) {
return pushNote({id: event.id, pubkey: event.pubkey, relays: urls})
}
const path = makeEventPath(event, urls)
if (path.includes("://")) {

View file

@ -2,13 +2,13 @@
import {onMount} from "svelte"
import * as nip19 from "nostr-tools/nip19"
import type {TrustedEvent} from "@welshman/util"
import {Address, getIdFilters} from "@welshman/util"
import {Address, NOTE, getIdFilters} from "@welshman/util"
import {LOCAL_RELAY_URL} from "@welshman/net"
import {goto} from "$app/navigation"
import {decodePubkey} from "@lib/util"
import Spinner from "@lib/components/Spinner.svelte"
import {network} from "@app/core"
import {goToEvent, makeProfilePath} from "@app/routes"
import {goToEvent, goToNote, makeProfilePath} from "@app/routes"
import type {PageProps} from "./$types"
const {params}: PageProps = $props()
@ -35,7 +35,12 @@
filters: getIdFilters([type === "nevent" ? data.id : Address.fromNaddr(bech32).toString()]),
onEvent: (event: TrustedEvent) => {
found = true
goToEvent(event, {replaceState: true})
if (event.kind === NOTE) {
goToNote({id: event.id, pubkey: event.pubkey, relays: data.relays})
} else {
goToEvent(event, {replaceState: true})
}
},
onClose: () => {
if (!found) {

View file

@ -1,9 +0,0 @@
<script lang="ts">
import type {LayoutProps} from "./$types"
const {children, params}: LayoutProps = $props()
</script>
{#key params.nevent}
{@render children?.()}
{/key}

View file

@ -1,7 +1,7 @@
<script lang="ts">
import {onMount} from "svelte"
import NotePage from "@app/components/NotePage.svelte"
import {navigate} from "@app/modal"
import Spinner from "@lib/components/Spinner.svelte"
import {goToHome, goToNote} from "@app/routes"
import {decodeNotePointer} from "@app/social"
import type {PageProps} from "./$types"
@ -10,12 +10,12 @@
const pointer = decodeNotePointer(params.nevent)
onMount(() => {
if (!pointer) {
navigate("/", {replaceState: true})
if (pointer) {
goToNote(pointer)
} else {
goToHome()
}
})
</script>
{#if pointer}
<NotePage {pointer} />
{/if}
<Spinner />