Fix thread permalinks
This commit is contained in:
parent
99be43f396
commit
8d7b640d0f
1 changed files with 30 additions and 24 deletions
|
|
@ -2,7 +2,7 @@
|
||||||
import * as nip19 from "nostr-tools/nip19"
|
import * as nip19 from "nostr-tools/nip19"
|
||||||
import {page} from "$app/stores"
|
import {page} from "$app/stores"
|
||||||
import {goto} from "$app/navigation"
|
import {goto} from "$app/navigation"
|
||||||
import {sleep, spec} from "@welshman/lib"
|
import {call, sleep, spec, tryCatch} from "@welshman/lib"
|
||||||
import type {MakeNonOptional} from "@welshman/lib"
|
import type {MakeNonOptional} from "@welshman/lib"
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import {deriveEventsAsc} from "@welshman/store"
|
import {deriveEventsAsc} from "@welshman/store"
|
||||||
|
|
@ -98,40 +98,46 @@
|
||||||
|
|
||||||
let showReply = $state(false)
|
let showReply = $state(false)
|
||||||
let replyTo: TrustedEvent | undefined = $state()
|
let replyTo: TrustedEvent | undefined = $state()
|
||||||
let hashHandled = $state(false)
|
|
||||||
|
|
||||||
$effect(() => {
|
|
||||||
if (hashHandled || posts.length === 0) return
|
|
||||||
|
|
||||||
|
// A permalink's target, read once because setPage drops the hash. Replies stream in newest
|
||||||
|
// first, so the post a permalink names is usually here long before the ones above it — its
|
||||||
|
// index, and the page it lands on, are only right once the thread has finished arriving. So
|
||||||
|
// this is kept and re-evaluated rather than acted on the first time the post shows up.
|
||||||
|
let target: string | undefined = $state(
|
||||||
|
call(() => {
|
||||||
const hash = window.location.hash.replace(/^#/, "")
|
const hash = window.location.hash.replace(/^#/, "")
|
||||||
|
|
||||||
if (!hash.startsWith("nevent1")) return
|
if (hash.startsWith("nevent1")) {
|
||||||
|
const decoded = tryCatch(() => nip19.decode(hash))
|
||||||
|
|
||||||
let eventId: string
|
if (decoded?.type === "nevent") {
|
||||||
|
return decoded.data.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
try {
|
// Paginating by hand hands control back to the reader.
|
||||||
const decoded = nip19.decode(hash)
|
const goToPage = (nextPage: number) => {
|
||||||
|
target = undefined
|
||||||
|
|
||||||
if (decoded.type !== "nevent") return
|
setPage(nextPage)
|
||||||
|
|
||||||
eventId = decoded.data.id
|
|
||||||
} catch {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = posts.findIndex(spec({id: eventId}))
|
$effect(() => {
|
||||||
|
if (!target) return
|
||||||
|
|
||||||
|
const index = posts.findIndex(spec({id: target}))
|
||||||
|
|
||||||
if (index < 0) return
|
if (index < 0) return
|
||||||
|
|
||||||
hashHandled = true
|
|
||||||
|
|
||||||
const targetPage = Math.ceil((index + 1) / POSTS_PER_PAGE)
|
const targetPage = Math.ceil((index + 1) / POSTS_PER_PAGE)
|
||||||
|
|
||||||
if (targetPage !== currentPage) {
|
if (targetPage !== currentPage) {
|
||||||
setPage(targetPage)
|
setPage(targetPage)
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => scrollToEvent(posts[index]!.id), 100)
|
setTimeout(() => scrollToEvent(target!), 100)
|
||||||
})
|
})
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
|
|
@ -170,7 +176,7 @@
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{#if pageCount > 1}
|
{#if pageCount > 1}
|
||||||
<ThreadPagination page={currentPage} {pageCount} onPage={setPage} />
|
<ThreadPagination page={currentPage} {pageCount} onPage={goToPage} />
|
||||||
{/if}
|
{/if}
|
||||||
{#if showReply && replyTo && $event}
|
{#if showReply && replyTo && $event}
|
||||||
<EventReply
|
<EventReply
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue