mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-30 00:41:12 +00:00
Finishing touches
This commit is contained in:
parent
46d2a52e67
commit
30270d331c
11
README.md
11
README.md
@ -34,18 +34,7 @@ Coracle is currently in _alpha_ - expect bugs, slow loading times, and rough edg
|
||||
|
||||
# Current update
|
||||
|
||||
- [ ] Re-implement muffle
|
||||
- Don't store muffled events, when muffle changes delete them
|
||||
- [ ] Delete old events
|
||||
- [ ] Make sure login/out, no user usage works
|
||||
- [ ] Add a re-sync/clear cache button
|
||||
- [ ] Note detail context not showing when navigating between note details (e.g. to parent)
|
||||
- [ ] Show reply to on feed
|
||||
- [ ] Write blog post
|
||||
- https://vitejs.dev/guide/features.html#web-workers
|
||||
- https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
|
||||
- https://web.dev/module-workers/
|
||||
|
||||
- [x] Sync user
|
||||
- [x] Based on petnames, sync network to 2 or 3 degrees of separation
|
||||
- When a user is added/removed, sync them and add to or remove from network
|
||||
|
@ -162,12 +162,12 @@
|
||||
{/if}
|
||||
</a>
|
||||
</li>
|
||||
{/if}
|
||||
<li class="cursor-pointer">
|
||||
<a class="block px-4 py-2 hover:bg-accent transition-all" href="/search/people">
|
||||
<i class="fa-solid fa-search mr-2" /> Search
|
||||
</a>
|
||||
</li>
|
||||
{/if}
|
||||
<li class="cursor-pointer">
|
||||
<a class="block px-4 py-2 hover:bg-accent transition-all" href="/notes/network">
|
||||
<i class="fa-solid fa-tag mr-2" /> Notes
|
||||
|
@ -16,7 +16,6 @@
|
||||
export let note
|
||||
export let depth = 0
|
||||
export let anchorId = null
|
||||
export let showParent = false
|
||||
export let invertColors = false
|
||||
|
||||
let reply = null
|
||||
@ -118,7 +117,7 @@
|
||||
<p class="text-sm text-light">{formatTimestamp(note.created_at)}</p>
|
||||
</div>
|
||||
<div class="ml-6 flex flex-col gap-2">
|
||||
{#if findReply(note) && showParent}
|
||||
{#if findReply(note)}
|
||||
<small class="text-light">
|
||||
Reply to <Anchor on:click={goToParent}>{findReply(note).slice(0, 8)}</Anchor>
|
||||
</small>
|
||||
|
@ -6,7 +6,6 @@
|
||||
import relay from 'src/relay'
|
||||
|
||||
export let loadNotes
|
||||
export let showParent = false
|
||||
|
||||
let notes
|
||||
let limit = 0
|
||||
@ -25,7 +24,7 @@
|
||||
{#if notes}
|
||||
<ul class="py-4 flex flex-col gap-2 max-w-xl m-auto">
|
||||
{#each ($notes || []) as n (n.id)}
|
||||
<li><Note note={n} depth={2} {showParent} /></li>
|
||||
<li><Note note={n} depth={2} /></li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
|
@ -2,15 +2,15 @@ import Dexie from 'dexie'
|
||||
import {writable, get} from 'svelte/store'
|
||||
import {groupBy, prop, flatten, pick} from 'ramda'
|
||||
import {ensurePlural, switcherFn} from 'hurdak/lib/hurdak'
|
||||
import {now, getLocalJson, setLocalJson} from 'src/util/misc'
|
||||
import {now, timedelta, getLocalJson, setLocalJson} from 'src/util/misc'
|
||||
import {filterTags, findReply, findRoot} from 'src/util/nostr'
|
||||
|
||||
export const db = new Dexie('coracle/relay')
|
||||
|
||||
db.version(4).stores({
|
||||
db.version(5).stores({
|
||||
relays: '++url, name',
|
||||
events: '++id, pubkey, created_at, kind, content, reply, root',
|
||||
tags: '++key, event, value',
|
||||
tags: '++key, event, value, created_at',
|
||||
})
|
||||
|
||||
window.db = db
|
||||
@ -39,7 +39,7 @@ db.events.process = async events => {
|
||||
// Persist notes and reactions
|
||||
if (notesAndReactions.length > 0) {
|
||||
const persistentEvents = notesAndReactions
|
||||
.map(e => ({...e, root: findRoot(e), reply: findReply(e), added_at: now()}))
|
||||
.map(e => ({...e, root: findRoot(e), reply: findReply(e), created_at: now()}))
|
||||
|
||||
db.events.bulkPut(persistentEvents)
|
||||
|
||||
@ -54,6 +54,7 @@ db.events.process = async events => {
|
||||
value: tag[1],
|
||||
relay: tag[2],
|
||||
mark: tag[3],
|
||||
created_at: e.created_at,
|
||||
})
|
||||
)
|
||||
)
|
||||
@ -102,3 +103,9 @@ db.events.process = async events => {
|
||||
return $people
|
||||
})
|
||||
}
|
||||
|
||||
// On initial load, delete old event data
|
||||
const threshold = now() - timedelta(30, 'days')
|
||||
|
||||
db.events.where('created_at').below(threshold).delete()
|
||||
db.tags.where('created_at').below(threshold).delete()
|
||||
|
@ -1,6 +1,6 @@
|
||||
import {liveQuery} from 'dexie'
|
||||
import {get} from 'svelte/store'
|
||||
import {pluck, take, uniqBy, groupBy, concat, without, prop, isNil, identity} from 'ramda'
|
||||
import {pluck, uniq, take, uniqBy, groupBy, concat, without, prop, isNil, identity} from 'ramda'
|
||||
import {ensurePlural, createMap, ellipsize} from 'hurdak/lib/hurdak'
|
||||
import {escapeHtml} from 'src/util/html'
|
||||
import {filterTags, findReply, findRoot} from 'src/util/nostr'
|
||||
@ -216,9 +216,17 @@ const loadNoteContext = async (note, {loadParent = false} = {}) => {
|
||||
filter.push({kinds: [0], authors: [note.pubkey]})
|
||||
}
|
||||
|
||||
await pool.loadEvents(filter)
|
||||
const replyId = findReply(note)
|
||||
// Load the events
|
||||
const events = await pool.loadEvents(filter)
|
||||
|
||||
// Load any related people we're missing
|
||||
const $people = get(people)
|
||||
await pool.loadPeople(
|
||||
uniq(pluck('pubkey', events)).filter(k => !$people[k])
|
||||
)
|
||||
|
||||
// Load the note's parent
|
||||
const replyId = findReply(note)
|
||||
if (loadParent && replyId) {
|
||||
await getOrLoadNote(replyId)
|
||||
}
|
||||
|
@ -207,5 +207,5 @@ const syncNetwork = async () => {
|
||||
|
||||
export default {
|
||||
getPubkey, getRelays, addRelay, removeRelay, setPrivateKey, setPublicKey,
|
||||
publishEvent, loadEvents, listenForEvents, syncNetwork,
|
||||
publishEvent, loadEvents, listenForEvents, syncNetwork, loadPeople,
|
||||
}
|
||||
|
@ -103,7 +103,7 @@
|
||||
{#if e.people}
|
||||
<li in:fly={{y: 20}}><Like note={e} /></li>
|
||||
{:else}
|
||||
<li in:fly={{y: 20}}><Note showParent note={e} /></li>
|
||||
<li in:fly={{y: 20}}><Note note={e} /></li>
|
||||
{/if}
|
||||
{/each}
|
||||
</ul>
|
||||
|
@ -63,15 +63,17 @@
|
||||
<div class="flex flex-col gap-4 max-w-2xl">
|
||||
<div class="flex justify-center items-center flex-col mb-4">
|
||||
<h1 class="staatliches text-6xl">Welcome!</h1>
|
||||
<i>To the Dogwood Social Network</i>
|
||||
<i>To the Nostr Protocol Network</i>
|
||||
</div>
|
||||
<div class="flex flex-col gap-4">
|
||||
<small>
|
||||
To log in to existing account, simply enter your private key. To create a new account, just
|
||||
let us generate one for you. You can also use
|
||||
a <Anchor href={nip07} external>compatible browser extension</Anchor> to
|
||||
sign events without having to paste your private key here.
|
||||
</small>
|
||||
<p>
|
||||
To log in to existing account, simply enter your private key below. To create a new account,
|
||||
just let us generate one for you.
|
||||
</p>
|
||||
<p>
|
||||
You can also use a <Anchor href={nip07} external>compatible browser extension</Anchor> to
|
||||
sign events without having to paste your private key here (recommended).
|
||||
</p>
|
||||
<div class="flex flex-col gap-1">
|
||||
<strong>Private Key</strong>
|
||||
<Input type="password" bind:value={privkey} placeholder="Enter your private key">
|
||||
|
@ -4,7 +4,7 @@
|
||||
import Tabs from "src/partials/Tabs.svelte"
|
||||
import Network from "src/views/notes/Network.svelte"
|
||||
import Global from "src/views/notes/Global.svelte"
|
||||
import {connections} from 'src/relay'
|
||||
import {connections, user} from 'src/relay'
|
||||
|
||||
export let activeTab
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
> to get started.
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
{:else if $user}
|
||||
<Tabs tabs={['network', 'global']} {activeTab} {setActiveTab} />
|
||||
{#if activeTab === 'network'}
|
||||
<Network />
|
||||
@ -34,5 +34,12 @@
|
||||
<span class="fa-sold fa-plus fa-2xl" />
|
||||
</a>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex w-full justify-center items-center py-16">
|
||||
<div class="text-center max-w-sm">
|
||||
Don't have an account? Click <Anchor href="/login">here</Anchor> to join the nostr network.
|
||||
</div>
|
||||
</div>
|
||||
<Global />
|
||||
{/if}
|
||||
|
||||
|
@ -111,7 +111,7 @@
|
||||
|
||||
<Tabs tabs={['notes', 'likes', 'network']} {activeTab} {setActiveTab} />
|
||||
{#if activeTab === 'notes'}
|
||||
<Notes showParent loadNotes={loadNotes} />
|
||||
<Notes loadNotes={loadNotes} />
|
||||
{:else if activeTab === 'likes'}
|
||||
<Notes loadNotes={loadLikes} />
|
||||
{:else if activeTab === 'network'}
|
||||
|
@ -100,7 +100,7 @@ export const getLastSync = (k, fallback) => {
|
||||
|
||||
export class Cursor {
|
||||
constructor(since, delta) {
|
||||
this.since = since || now() - delta,
|
||||
this.since = (since || now()) - delta,
|
||||
this.delta = delta
|
||||
}
|
||||
step() {
|
||||
|
@ -47,7 +47,7 @@
|
||||
</div>
|
||||
{:else if $observable}
|
||||
<div n:fly={{y: 20}}>
|
||||
<Note showParent invertColors anchorId={note.id} note={$observable} depth={2} />
|
||||
<Note invertColors anchorId={note.id} note={$observable} depth={2} />
|
||||
</div>
|
||||
{:else}
|
||||
<Spinner />
|
||||
|
@ -4,7 +4,6 @@
|
||||
import {fly} from 'svelte/transition'
|
||||
import Button from "src/partials/Button.svelte"
|
||||
import SelectButton from "src/partials/SelectButton.svelte"
|
||||
import {getTagValues} from "src/util/nostr"
|
||||
import {modal} from "src/state/app"
|
||||
import relay, {user} from 'src/relay'
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
import {onMount, onDestroy} from 'svelte'
|
||||
import Notes from "src/partials/Notes.svelte"
|
||||
import {timedelta, Cursor, getLastSync} from 'src/util/misc'
|
||||
import {getTagValues} from 'src/util/nostr'
|
||||
import relay, {user} from 'src/relay'
|
||||
|
||||
let sub
|
||||
|
@ -3,24 +3,33 @@
|
||||
import {onMount, onDestroy} from 'svelte'
|
||||
import Notes from "src/partials/Notes.svelte"
|
||||
import {timedelta, Cursor, getLastSync} from 'src/util/misc'
|
||||
import {getTagValues} from 'src/util/nostr'
|
||||
import relay, {user, network} from 'src/relay'
|
||||
|
||||
let sub
|
||||
let networkUnsub
|
||||
|
||||
const cursor = new Cursor(
|
||||
getLastSync('views/notes/Network'),
|
||||
timedelta(1, 'hours')
|
||||
)
|
||||
|
||||
onMount(async () => {
|
||||
sub = await relay.pool.listenForEvents(
|
||||
'views/notes/Network',
|
||||
[{kinds: [1, 5, 7], authors: $network, since: cursor.since}],
|
||||
when(propEq('kind', 1), relay.loadNoteContext)
|
||||
)
|
||||
onMount(() => {
|
||||
// We need to re-create the sub when network changes, since this is where
|
||||
// we land when we first log in, but before network is loaded, leading to
|
||||
// a forever spinner.
|
||||
networkUnsub = network.subscribe(async $network => {
|
||||
sub = await relay.pool.listenForEvents(
|
||||
'views/notes/Network',
|
||||
[{kinds: [1, 5, 7], authors: $network, since: cursor.since}],
|
||||
when(propEq('kind', 1), relay.loadNoteContext)
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
networkUnsub()
|
||||
|
||||
if (sub) {
|
||||
sub.unsub()
|
||||
}
|
||||
@ -46,4 +55,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- hack to reload notes when our network initiall loads, see onMount -->
|
||||
{#key $network.map(n => n[0]).join('')}
|
||||
<Notes shouldMuffle loadNotes={loadNotes} />
|
||||
{/key}
|
||||
|
Loading…
Reference in New Issue
Block a user