forked from coracle/flotilla
Improve scrolling, discover page
This commit is contained in:
Generated
-9
@@ -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
@@ -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"
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
onMount(() => {
|
||||
const scroller = createScroller({
|
||||
element: element.closest(".menu")!,
|
||||
element,
|
||||
onScroll: async () => {
|
||||
const $loader = await loader
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
onMount(() => {
|
||||
const scroller = createScroller({
|
||||
element,
|
||||
delay: 300,
|
||||
element: element.closest(".modal-box")!,
|
||||
onScroll: () => {
|
||||
limit += 20
|
||||
},
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,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
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
onMount(() => {
|
||||
const scroller = createScroller({
|
||||
element: element.closest(".overflow-auto")!,
|
||||
element,
|
||||
onScroll: () => {
|
||||
limit += 10
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user