Add some loading icons

This commit is contained in:
Jonathan Staab 2022-11-30 20:47:53 -08:00
parent e5a4f86474
commit 7015ed136c
8 changed files with 83 additions and 37 deletions

11
package-lock.json generated
View File

@ -18,6 +18,7 @@
"hurdak": "github:ConsignCloud/hurdak",
"nostr-tools": "github:fiatjaf/nostr-tools#1b798b2",
"ramda": "^0.28.0",
"svelte-loading-spinners": "^0.3.4",
"svelte-routing": "^1.6.0",
"throttle-debounce": "^5.0.0",
"vite-plugin-node-polyfills": "^0.5.0"
@ -3471,6 +3472,11 @@
"svelte": ">=3.19.0"
}
},
"node_modules/svelte-loading-spinners": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/svelte-loading-spinners/-/svelte-loading-spinners-0.3.4.tgz",
"integrity": "sha512-vKaW71QMCBcTNijAGc0mUl8k3DQ66iYmp6MB8BMGCXyWk82bTrcLy8FOnSm9fE+8q6TwzD6PLUoYFHt0II93Xw=="
},
"node_modules/svelte-routing": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/svelte-routing/-/svelte-routing-1.6.0.tgz",
@ -6350,6 +6356,11 @@
"dev": true,
"requires": {}
},
"svelte-loading-spinners": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/svelte-loading-spinners/-/svelte-loading-spinners-0.3.4.tgz",
"integrity": "sha512-vKaW71QMCBcTNijAGc0mUl8k3DQ66iYmp6MB8BMGCXyWk82bTrcLy8FOnSm9fE+8q6TwzD6PLUoYFHt0II93Xw=="
},
"svelte-routing": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/svelte-routing/-/svelte-routing-1.6.0.tgz",

View File

@ -30,6 +30,7 @@
"hurdak": "github:ConsignCloud/hurdak",
"nostr-tools": "github:fiatjaf/nostr-tools#1b798b2",
"ramda": "^0.28.0",
"svelte-loading-spinners": "^0.3.4",
"svelte-routing": "^1.6.0",
"throttle-debounce": "^5.0.0",
"vite-plugin-node-polyfills": "^0.5.0"

View File

@ -50,10 +50,14 @@
modal.subscribe($modal => {
// Keep scroll position on body, but don't allow scrolling
if ($modal) {
scrollY = window.scrollY
document.body.style.top = `-${scrollY}px`
document.body.style.position = `fixed`
// This is not idempotent, so don't duplicate it
if (document.body.style.position !== 'fixed') {
scrollY = window.scrollY
document.body.style.top = `-${scrollY}px`
document.body.style.position = `fixed`
}
} else {
document.body.style = ''
window.scrollTo(0, scrollY)
@ -77,11 +81,15 @@
<Route path="/chat/new" component={ChatEdit} />
<Route path="/chat/:room" let:params>
{#key params.room}
<ChatRoom room={params.room} />
<ChatRoom {...params} />
{/key}
</Route>
<Route path="/chat/:room/edit" component={ChatEdit} />
<Route path="/users/:pubkey" component={UserDetail} />
<Route path="/users/:pubkey" let:params>
{#key params.pubkey}
<UserDetail {...params} />
{/key}
</Route>
<Route path="/settings/keys" component={Keys} />
<Route path="/settings/relays" component={RelayList} />
<Route path="/settings/profile" component={Profile} />

View File

@ -37,11 +37,8 @@
}
const showParent = async () => {
const notes = await annotateNotes(
await channels.getter.all({kinds: [1, 5, 7], ids: [parentId]})
)
modal.set({note: notes[0]})
modal.set({note: {id: parentId}})
}
const react = content => {

View File

@ -1,20 +1,28 @@
<script>
import {onMount} from 'svelte'
import {writable} from 'svelte/store'
import {fly} from 'svelte/transition'
import {find, propEq} from 'ramda'
import {Cursor} from "src/state/nostr"
import {notesListener, modal} from "src/state/app"
import Spinner from 'src/partials/Spinner.svelte'
import {Cursor, channels} from "src/state/nostr"
import {notesListener, annotateNotes, modal} from "src/state/app"
import {user} from "src/state/user"
import Note from 'src/partials/Note.svelte'
export let note
const notes = writable([note])
const notes = writable([])
let cursor
let listener
onMount(() => {
cursor = new Cursor({ids: [note.id]}, note.created_at)
channels.getter
.all({kinds: [1, 5, 7], ids: [note.id]})
.then(annotateNotes)
.then($notes => {
notes.set($notes)
})
listener = notesListener(notes, [
{kinds: [1, 5, 7], '#e': [note.id]},
// We can't target reaction deletes by e tag, so get them
@ -25,10 +33,6 @@
// Populate our initial empty space
listener.start()
const unsubNotes = notes.subscribe($notes => {
note = find(propEq('id', note.id), $notes)
})
// Unsubscribe when modal closes so that others can re-subscribe sooner
const unsubModal = modal.subscribe($modal => {
cursor?.stop()
@ -36,27 +40,30 @@
})
return () => {
unsubNotes()
unsubModal()
}
})
</script>
{#if note.pubkey}
<Note showEntire note={note} />
{#each note.replies as r (r.id)}
<div class="ml-4 border-l border-solid border-medium">
<Note interactive invertColors isReply note={r} />
{#each r.replies as r2 (r2.id)}
{#each $notes as note (note.id)}
<div n:fly={{y: 20}}>
<Note showEntire note={note} />
{#each note.replies as r (r.id)}
<div class="ml-4 border-l border-solid border-medium">
<Note interactive invertColors isReply note={r2} />
{#each r2.replies as r3 (r3.id)}
<Note interactive invertColors isReply note={r} />
{#each r.replies as r2 (r2.id)}
<div class="ml-4 border-l border-solid border-medium">
<Note interactive invertColors isReply note={r3} />
<Note interactive invertColors isReply note={r2} />
{#each r2.replies as r3 (r3.id)}
<div class="ml-4 border-l border-solid border-medium">
<Note interactive invertColors isReply note={r3} />
</div>
{/each}
</div>
{/each}
</div>
{/each}
</div>
</div>
{:else}
<Spinner />
{/each}
{/if}

View File

@ -134,7 +134,7 @@
<div class="flex gap-4 h-full">
<div class="sm:ml-56 w-full">
<div class="relative">
<div class="flex flex-col pt-20 pb-32">
<div class="flex flex-col py-32">
<ul class="p-4 max-h-full flex-grow flex flex-col-reverse" name="messages">
{#each annotatedMessages as m (m.id)}
<li in:fly={{y: 20}} class="py-1">

View File

@ -5,6 +5,7 @@
import {navigate} from "svelte-routing"
import {uniqBy, prop} from 'ramda'
import Anchor from "src/partials/Anchor.svelte"
import Spinner from "src/partials/Spinner.svelte"
import Note from "src/partials/Note.svelte"
import {relays, Cursor} from "src/state/nostr"
import {scroller, annotateNotes, notesListener, modal} from "src/state/app"
@ -31,7 +32,7 @@
scroll()
// When a modal opens, suspend our subscriptions
modal.subscribe(async $modal => {
const modalUnsub = modal.subscribe(async $modal => {
if ($modal) {
cursor.stop()
listener.stop()
@ -40,6 +41,10 @@
listener.start()
}
})
return () => {
modalUnsub()
}
})
onDestroy(() => {
@ -61,11 +66,10 @@
{/each}
</li>
{/each}
<li class="flex justify-center py-12" in:fly={{y: 20}}>
<p>Loading notes...</p>
</li>
</ul>
<!-- This will always be sitting at the bottom in case infinite scrolling can't keep up -->
<Spinner />
{#if $relays.length > 0}
<div class="fixed bottom-0 right-0 p-8">

View File

@ -4,7 +4,8 @@
import {uniqBy, prop} from 'ramda'
import {fly} from 'svelte/transition'
import Note from "src/partials/Note.svelte"
import {Cursor} from 'src/state/nostr'
import Spinner from "src/partials/Spinner.svelte"
import {Cursor, epoch} from 'src/state/nostr'
import {user as currentUser} from 'src/state/user'
import {accounts, scroller, notesListener, modal, annotateNotes} from "src/state/app"
@ -15,12 +16,15 @@
let cursor
let listener
let scroll
let interval
let loading = true
let modalUnsub
$: user = $accounts[pubkey]
onMount(async () => {
cursor = new Cursor({kinds: [1], authors: [pubkey]})
listener = await notesListener(notes, {kinds: [1, 5, 7], authors: [pubkey]})
listener = await notesListener(notes, [{kinds: [1], authors: [pubkey]}, {kinds: [5, 7]}])
scroll = scroller(cursor, async chunk => {
const annotated = await annotateNotes(chunk, {showParents: true})
@ -30,8 +34,13 @@
// Populate our initial empty space
scroll()
// Track loading based on cursor cutoff date
interval = setInterval(() => {
loading = cursor.since > epoch
}, 1000)
// When a modal opens, suspend our subscriptions
modal.subscribe(async $modal => {
modalUnsub = modal.subscribe(async $modal => {
if ($modal) {
cursor.stop()
listener.stop()
@ -45,7 +54,10 @@
onDestroy(() => {
cursor?.stop()
listener?.stop()
modalUnsub()
clearInterval(interval)
})
</script>
<svelte:window on:scroll={scroll} />
@ -81,6 +93,12 @@
</div>
{/each}
</li>
{:else}
{#if loading}
<li><Spinner /></li>
{:else}
<li class="p-20 text-center" in:fly={{y: 20}}>No notes found.</li>
{/if}
{/each}
</ul>
</div>