Improve scrolling, discover page

This commit is contained in:
Jon Staab
2024-10-17 14:26:53 -07:00
parent 9c31b12d48
commit 4683fc4203
12 changed files with 90 additions and 74 deletions
-9
View File
@@ -40,7 +40,6 @@
"nostr-editor": "^0.0.2",
"nostr-tools": "^2.7.2",
"prettier-plugin-tailwindcss": "^0.6.5",
"svelte-bricks": "^0.2.1",
"svelte-tiptap": "^1.1.3",
"throttle-debounce": "^5.0.2"
},
@@ -4862,14 +4861,6 @@
"node": ">=16"
}
},
"node_modules/svelte-bricks": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/svelte-bricks/-/svelte-bricks-0.2.1.tgz",
"integrity": "sha512-cc3XK3j5ViPyZ3K183+Sr53B2e8mJaiV3POyoJtjmm1dYc/TBMy7jOUMt8MW/snJzodpACfqwFzokBQbrZ297w==",
"dependencies": {
"svelte": "^4.2.1"
}
},
"node_modules/svelte-check": {
"version": "3.8.5",
"resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-3.8.5.tgz",
+8 -9
View File
@@ -48,15 +48,15 @@
"@tiptap/extension-text": "^2.6.6",
"@tiptap/suggestion": "^2.6.4",
"@types/throttle-debounce": "^5.0.2",
"@welshman/content": "~0.0.12",
"@welshman/lib": "~0.0.22",
"@welshman/util": "~0.0.39",
"@welshman/feeds": "~0.0.20",
"@welshman/store": "~0.0.10",
"@welshman/net": "~0.0.28",
"@welshman/dvm": "~0.0.10",
"@welshman/signer": "~0.0.9",
"@welshman/app": "~0.0.17",
"@welshman/content": "~0.0.12",
"@welshman/dvm": "~0.0.10",
"@welshman/feeds": "~0.0.20",
"@welshman/lib": "~0.0.22",
"@welshman/net": "~0.0.28",
"@welshman/signer": "~0.0.9",
"@welshman/store": "~0.0.10",
"@welshman/util": "~0.0.39",
"daisyui": "^4.12.10",
"date-picker-svelte": "^2.13.0",
"emoji-picker-element": "^1.22.8",
@@ -65,7 +65,6 @@
"nostr-editor": "^0.0.2",
"nostr-tools": "^2.7.2",
"prettier-plugin-tailwindcss": "^0.6.5",
"svelte-bricks": "^0.2.1",
"svelte-tiptap": "^1.1.3",
"throttle-debounce": "^5.0.2"
}
+1 -1
View File
@@ -29,7 +29,7 @@
onMount(() => {
const scroller = createScroller({
element: element.closest(".menu")!,
element,
onScroll: async () => {
const $loader = await loader
+1 -1
View File
@@ -16,8 +16,8 @@
onMount(() => {
const scroller = createScroller({
element,
delay: 300,
element: element.closest(".modal-box")!,
onScroll: () => {
limit += 20
},
+2 -1
View File
@@ -11,7 +11,8 @@
transition:fade
on:click={onClose} />
<div
class="relative card2 bg-alt absolute max-h-[90vh] w-[90vw] overflow-auto text-base-content sm:w-[520px]"
class="relative scroll-container card2 bg-alt absolute max-h-[90vh] w-[90vw] overflow-auto text-base-content sm:w-[520px]"
transition:fly={{duration: 300}}>
<slot />
</div>
+3 -3
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import {fade, slide} from "@lib/transition"
import {fade, translate} from "@lib/transition"
export let onClose
</script>
@@ -10,8 +10,8 @@
transition:fade
on:click={onClose} />
<div
class="absolute bottom-0 right-0 top-0 w-80 overflow-auto bg-base-200 text-base-content lg:w-96"
transition:slide={{axis: "x", duration: 300}}>
class="scroll-container absolute bottom-0 right-0 top-0 w-80 overflow-auto bg-base-200 text-base-content lg:w-96"
transition:translate={{axis: "x", duration: 300}}>
<slot />
</div>
</div>
+1 -1
View File
@@ -1,3 +1,3 @@
<div class="max-h-screen flex-grow overflow-auto bg-base-200 pb-14 sm:pb-0">
<div class="max-h-screen flex-grow overflow-auto bg-base-200 pb-14 sm:pb-0 scroll-container">
<slot />
</div>
+12 -8
View File
@@ -34,15 +34,19 @@ export const createScroller = ({
let done = false
const check = async () => {
// While we have empty space, fill it
const {scrollY, innerHeight} = window
const {scrollHeight, scrollTop} = element
const offset = Math.abs(scrollTop || scrollY)
const shouldLoad = offset + innerHeight + threshold > scrollHeight
const container = element.closest('.scroll-container')
// Only trigger loading the first time we reach the threshold
if (shouldLoad) {
await onScroll()
if (container) {
// While we have empty space, fill it
const {scrollY, innerHeight} = window
const {scrollHeight, scrollTop} = container
const offset = Math.abs(scrollTop || scrollY)
const shouldLoad = offset + innerHeight + threshold > scrollHeight
// Only trigger loading the first time we reach the threshold
if (shouldLoad) {
await onScroll()
}
}
// No need to check all that often
+28
View File
@@ -8,6 +8,34 @@ export {fade, slide} from "svelte/transition"
export const fly = (node: Element, params?: FlyParams | undefined) =>
baseFly(node, {y: 20, ...params})
export type TranslateParams = {
delay?: number,
duration?: number,
easing?: (t: number) => number
axis?: "x" | "y"
reverse?: boolean
}
export const translate = (
node: Element,
{delay = 0, duration = 400, easing = cubicOut, axis = "y", reverse = false}: TranslateParams = {}
) => {
return {
delay,
duration,
easing,
css: (t: number) => {
const p = reverse ? `${t * 100}%` : `${100 - t * 100}%`
if (axis === "x") {
return `transform: translateX(${p})`
} else {
return `transform: translateY(${p})`
}
}
}
}
// Copy-pasted and tweaked from slide source code
export function slideAndFade(
node: any,
+32 -39
View File
@@ -1,10 +1,9 @@
<script lang="ts">
import {onMount} from "svelte"
import {derived} from 'svelte/store'
import Masonry from "svelte-bricks"
import {addToMapKey, dec, gt, inc} from "@welshman/lib"
import type {Relay} from "@welshman/app"
import {relays, createSearch} from "@welshman/app"
import {relays, createSearch, relaySelections} from "@welshman/app"
import {createScroller} from "@lib/html"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
@@ -53,13 +52,12 @@
},
})
$: results = relaySearch.searchOptions(term).slice(0, limit)
onMount(() => {
discoverRelays($memberships)
discoverRelays($relaySelections)
const scroller = createScroller({
element: element.closest(".overflow-auto")!,
element,
onScroll: () => {
limit += 20
},
@@ -80,45 +78,40 @@
<Icon icon="magnifer" />
<input bind:value={term} class="grow" type="text" placeholder="Search for spaces..." />
</label>
<Masonry
animate={false}
items={results}
minColWidth={300}
maxColWidth={800}
gap={16}
idKey="url"
let:item={relay}>
{#each relaySearch.searchOptions(term).slice(0, limit) as relay (relay.url)}
<Button
class="card2 bg-alt flex flex-col gap-2 text-left shadow-xl transition-all hover:shadow-2xl hover:brightness-[1.1]"
class="card2 bg-alt col-4 text-left shadow-xl transition-all hover:shadow-2xl hover:brightness-[1.1]"
on:click={() => openSpace(relay.url)}>
<div class="flex gap-4 relative">
<div class="relative">
<div class="avatar relative">
<div
class="center !flex h-12 w-12 min-w-12 rounded-full border-2 border-solid border-base-300 bg-base-300">
{#if relay.profile?.icon}
<img alt="" src={relay.profile.icon} />
{:else}
<Icon icon="ghost" size={5} />
{/if}
<div class="col-2">
<div class="flex gap-4 relative">
<div class="relative">
<div class="avatar relative">
<div
class="center !flex h-12 w-12 min-w-12 rounded-full border-2 border-solid border-base-300 bg-base-300">
{#if relay.profile?.icon}
<img alt="" src={relay.profile.icon} />
{:else}
<Icon icon="ghost" size={5} />
{/if}
</div>
</div>
{#if getMembershipUrls($userMembership).includes(relay.url)}
<div
class="absolute -right-1 -top-1 tooltip h-5 w-5 rounded-full bg-primary"
data-tip="You are already a member of this space.">
<Icon icon="check-circle" class="scale-110" />
</div>
{/if}
</div>
<div>
<h2 class="text-xl ellipsize whitespace-nowrap">
<RelayName url={relay.url} />
</h2>
<p class="text-sm opacity-75">{relay.url}</p>
</div>
{#if getMembershipUrls($userMembership).includes(relay.url)}
<div
class="absolute -right-1 -top-1 tooltip h-5 w-5 rounded-full bg-primary"
data-tip="You are already a member of this space.">
<Icon icon="check-circle" class="scale-110" />
</div>
{/if}
</div>
<div>
<h2 class="text-xl ellipsize whitespace-nowrap">
<RelayName url={relay.url} />
</h2>
<p class="text-sm opacity-75">{relay.url}</p>
</div>
<RelayDescription url={relay.url} />
</div>
<RelayDescription url={relay.url} />
{#if gt($wotGraph.get(relay.url)?.size, 0)}
<div class="row-2 card2 card2-sm bg-alt">
Members:
@@ -126,5 +119,5 @@
</div>
{/if}
</Button>
</Masonry>
{/each}
</div>
+1 -1
View File
@@ -58,7 +58,7 @@
load({filters: [notesFilter, reactionsFilter], timeout: 30_000})
const scroller = createScroller({
element: element.closest(".overflow-auto")!,
element,
onScroll: () => {
const seen = new Set(events.map(e => e.id))
const eligible = sortBy(
+1 -1
View File
@@ -19,7 +19,7 @@
onMount(() => {
const scroller = createScroller({
element: element.closest(".overflow-auto")!,
element,
onScroll: () => {
limit += 10
},