Fix scroll to event behavior
This commit is contained in:
+24
-2
@@ -2,6 +2,7 @@ import type {Page} from "@sveltejs/kit"
|
|||||||
import {get} from "svelte/store"
|
import {get} from "svelte/store"
|
||||||
import * as nip19 from "nostr-tools/nip19"
|
import * as nip19 from "nostr-tools/nip19"
|
||||||
import {goto} from "$app/navigation"
|
import {goto} from "$app/navigation"
|
||||||
|
import {page} from "$app/stores"
|
||||||
import {nthEq} from "@welshman/lib"
|
import {nthEq} from "@welshman/lib"
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import {getAddress} from "@welshman/util"
|
import {getAddress} from "@welshman/util"
|
||||||
@@ -99,14 +100,35 @@ export const getPrimaryNavItemIndex = ($page: Page) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const scrollToEvent = (id: string) => {
|
||||||
|
const element = document.querySelector(`[data-event="${id}"]`) as any
|
||||||
|
|
||||||
|
if (element) {
|
||||||
|
element.scrollIntoView({behavior: "smooth", block: "center"})
|
||||||
|
element.style = "filter: brightness(1.5); transition-property: all; transition-duration: 400ms;"
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
element.style = "transition-property: all; transition-duration: 300ms;"
|
||||||
|
}, 800)
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
element.style = ""
|
||||||
|
}, 800 + 400)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Boolean(element)
|
||||||
|
}
|
||||||
|
|
||||||
export const goToEvent = (event: TrustedEvent, options: Record<string, any> = {}) => {
|
export const goToEvent = (event: TrustedEvent, options: Record<string, any> = {}) => {
|
||||||
const urls = Array.from(tracker.getRelays(event.id))
|
const urls = Array.from(tracker.getRelays(event.id))
|
||||||
const path = getEventPath(event, urls)
|
const path = getEventPath(event, urls)
|
||||||
|
|
||||||
if (path.includes("://")) {
|
if (path.includes("://")) {
|
||||||
window.open(path)
|
window.open(path)
|
||||||
} else {
|
} else if (!scrollToEvent(event.id)) {
|
||||||
goto(path, options)
|
const replaceState = path.replace(/\?.*$/, "") === get(page).url.pathname
|
||||||
|
|
||||||
|
goto(path, {replaceState, ...options})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
import {page} from "$app/stores"
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#key $page.url.searchParams.get("at")}
|
||||||
|
<slot />
|
||||||
|
{/key}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
import {onMount, tick} from "svelte"
|
import {onMount, tick} from "svelte"
|
||||||
import {readable} from "svelte/store"
|
import {readable} from "svelte/store"
|
||||||
import {page} from "$app/stores"
|
import {page} from "$app/stores"
|
||||||
|
import {goto} from "$app/navigation"
|
||||||
import type {Readable} from "svelte/store"
|
import type {Readable} from "svelte/store"
|
||||||
import {pubkey, publishThunk, waitForThunkError, joinRoom, leaveRoom} from "@welshman/app"
|
import {pubkey, publishThunk, waitForThunkError, joinRoom, leaveRoom} from "@welshman/app"
|
||||||
import {now, int, formatTimestampAsDate, ago, MINUTE} from "@welshman/lib"
|
import {now, int, formatTimestampAsDate, ago, MINUTE} from "@welshman/lib"
|
||||||
@@ -60,6 +61,7 @@
|
|||||||
const room = deriveRoom(url, h)
|
const room = deriveRoom(url, h)
|
||||||
const shouldProtect = canEnforceNip70(url)
|
const shouldProtect = canEnforceNip70(url)
|
||||||
const membershipStatus = deriveUserRoomMembershipStatus(url, h)
|
const membershipStatus = deriveUserRoomMembershipStatus(url, h)
|
||||||
|
const at = $derived(parseInt($page.url.searchParams.get("at") || String(now())))
|
||||||
|
|
||||||
const showRoomDetail = () => pushModal(RoomDetail, {url, h})
|
const showRoomDetail = () => pushModal(RoomDetail, {url, h})
|
||||||
|
|
||||||
@@ -166,7 +168,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const manageScrollPosition = () => {
|
const manageScrollPosition = () => {
|
||||||
showScrollButton = Math.abs(element?.scrollTop || 0) > 1500
|
showScrollButton = Boolean(at) || Math.abs(element?.scrollTop || 0) > 1500
|
||||||
|
|
||||||
const newMessages = document.getElementById("new-messages")
|
const newMessages = document.getElementById("new-messages")
|
||||||
|
|
||||||
@@ -210,8 +212,7 @@
|
|||||||
|
|
||||||
const scrollToBottom = () => {
|
const scrollToBottom = () => {
|
||||||
if ($page.url.searchParams.get("at")) {
|
if ($page.url.searchParams.get("at")) {
|
||||||
at = now()
|
goto($page.url.pathname, {replaceState: true})
|
||||||
start()
|
|
||||||
} else {
|
} else {
|
||||||
element?.scrollTo({top: 0, behavior: "smooth"})
|
element?.scrollTo({top: 0, behavior: "smooth"})
|
||||||
}
|
}
|
||||||
@@ -223,7 +224,6 @@
|
|||||||
let isProgrammaticScroll = $state(false)
|
let isProgrammaticScroll = $state(false)
|
||||||
let loadingBackward = $state(true)
|
let loadingBackward = $state(true)
|
||||||
let loadingForward = $state(true)
|
let loadingForward = $state(true)
|
||||||
let at = $state(parseInt($page.url.searchParams.get("at") || String(now())))
|
|
||||||
let share = $state(popKey<TrustedEvent | undefined>("share"))
|
let share = $state(popKey<TrustedEvent | undefined>("share"))
|
||||||
let parent: TrustedEvent | undefined = $state()
|
let parent: TrustedEvent | undefined = $state()
|
||||||
let element: HTMLElement | undefined = $state()
|
let element: HTMLElement | undefined = $state()
|
||||||
@@ -353,6 +353,7 @@
|
|||||||
|
|
||||||
observer.observe(chatCompose!)
|
observer.observe(chatCompose!)
|
||||||
observer.observe(dynamicPadding!)
|
observer.observe(dynamicPadding!)
|
||||||
|
|
||||||
start()
|
start()
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {onMount, tick} from "svelte"
|
import {onMount, tick} from "svelte"
|
||||||
import {page} from "$app/stores"
|
import {page} from "$app/stores"
|
||||||
|
import {goto} from "$app/navigation"
|
||||||
import type {Readable} from "svelte/store"
|
import type {Readable} from "svelte/store"
|
||||||
import {readable} from "svelte/store"
|
import {readable} from "svelte/store"
|
||||||
import {now, int, formatTimestampAsDate, MINUTE, ago} from "@welshman/lib"
|
import {now, int, formatTimestampAsDate, MINUTE, ago} from "@welshman/lib"
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
const lastChecked = $checked[$page.url.pathname]
|
const lastChecked = $checked[$page.url.pathname]
|
||||||
const url = decodeRelay($page.params.relay!)
|
const url = decodeRelay($page.params.relay!)
|
||||||
const shouldProtect = canEnforceNip70(url)
|
const shouldProtect = canEnforceNip70(url)
|
||||||
|
const at = $derived(parseInt($page.url.searchParams.get("at") || String(now())))
|
||||||
|
|
||||||
const replyTo = (event: TrustedEvent) => {
|
const replyTo = (event: TrustedEvent) => {
|
||||||
parent = event
|
parent = event
|
||||||
@@ -104,7 +106,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const manageScrollPosition = () => {
|
const manageScrollPosition = () => {
|
||||||
showScrollButton = Math.abs(element?.scrollTop || 0) > 1500
|
showScrollButton = Boolean(at) || Math.abs(element?.scrollTop || 0) > 1500
|
||||||
|
|
||||||
const newMessages = document.getElementById("new-messages")
|
const newMessages = document.getElementById("new-messages")
|
||||||
|
|
||||||
@@ -148,8 +150,7 @@
|
|||||||
|
|
||||||
const scrollToBottom = () => {
|
const scrollToBottom = () => {
|
||||||
if ($page.url.searchParams.get("at")) {
|
if ($page.url.searchParams.get("at")) {
|
||||||
at = now()
|
goto($page.url.pathname, {replaceState: true})
|
||||||
start()
|
|
||||||
} else {
|
} else {
|
||||||
element?.scrollTo({top: 0, behavior: "smooth"})
|
element?.scrollTo({top: 0, behavior: "smooth"})
|
||||||
}
|
}
|
||||||
@@ -159,7 +160,6 @@
|
|||||||
let loadingForward = $state(true)
|
let loadingForward = $state(true)
|
||||||
let userHasScrolled = $state(false)
|
let userHasScrolled = $state(false)
|
||||||
let isProgrammaticScroll = $state(false)
|
let isProgrammaticScroll = $state(false)
|
||||||
let at = $state(parseInt($page.url.searchParams.get("at") || String(now())))
|
|
||||||
let share = $state(popKey<TrustedEvent | undefined>("share"))
|
let share = $state(popKey<TrustedEvent | undefined>("share"))
|
||||||
let parent: TrustedEvent | undefined = $state()
|
let parent: TrustedEvent | undefined = $state()
|
||||||
let element: HTMLElement | undefined = $state()
|
let element: HTMLElement | undefined = $state()
|
||||||
|
|||||||
Reference in New Issue
Block a user