mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-30 00:41:12 +00:00
Fix all major bugs
This commit is contained in:
parent
d23742d33e
commit
78a85be7e5
@ -14,6 +14,7 @@ Coracle is currently in _alpha_ - expect bugs, slow loading times, and rough edg
|
|||||||
- [x] Notifications
|
- [x] Notifications
|
||||||
- [x] Link previews
|
- [x] Link previews
|
||||||
- [x] Add notes, follows, likes tab to profile
|
- [x] Add notes, follows, likes tab to profile
|
||||||
|
- [ ] Add a coracle relay
|
||||||
- [ ] Mentions - render done, now reference in compose
|
- [ ] Mentions - render done, now reference in compose
|
||||||
- [ ] Image uploads
|
- [ ] Image uploads
|
||||||
- [ ] An actual readme
|
- [ ] An actual readme
|
||||||
@ -40,11 +41,9 @@ Coracle is currently in _alpha_ - expect bugs, slow loading times, and rough edg
|
|||||||
|
|
||||||
- [ ] Check firefox - in dev it won't work, but it should in production
|
- [ ] Check firefox - in dev it won't work, but it should in production
|
||||||
- [ ] Re-implement muffle
|
- [ ] Re-implement muffle
|
||||||
- [ ] Move relays to db
|
- [ ] Delete old events
|
||||||
- [ ] Make user a livequery instead of a store
|
- [ ] Sync accounts to store to avoid loading jank
|
||||||
- [ ] Figure out if multiple relays congest response times because we wait for all eose
|
- [ ] Sync account updates to user for e.g. muffle settings
|
||||||
- [ ] Set default relay when storage is empty
|
|
||||||
- [ ] Are connections closed when a relay is removed?
|
|
||||||
- https://vitejs.dev/guide/features.html#web-workers
|
- https://vitejs.dev/guide/features.html#web-workers
|
||||||
- https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
|
- https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
|
||||||
- https://web.dev/module-workers/
|
- https://web.dev/module-workers/
|
||||||
|
@ -6,7 +6,8 @@ import {filterTags, findReply, findRoot} from 'src/util/nostr'
|
|||||||
|
|
||||||
export const db = new Dexie('coracle/relay')
|
export const db = new Dexie('coracle/relay')
|
||||||
|
|
||||||
db.version(3).stores({
|
db.version(4).stores({
|
||||||
|
relays: '++url, name',
|
||||||
events: '++id, pubkey, created_at, kind, content, reply, root',
|
events: '++id, pubkey, created_at, kind, content, reply, root',
|
||||||
people: '++pubkey, name, about',
|
people: '++pubkey, name, about',
|
||||||
tags: '++key, event, value',
|
tags: '++key, event, value',
|
||||||
|
@ -38,7 +38,7 @@ const ensureContext = async events => {
|
|||||||
|
|
||||||
if (ids.length > 0) {
|
if (ids.length > 0) {
|
||||||
promises.push(
|
promises.push(
|
||||||
pool.fetchEvents([
|
pool.loadEvents([
|
||||||
{kinds: [1, 5, 7], '#e': ids},
|
{kinds: [1, 5, 7], '#e': ids},
|
||||||
{kinds: [1, 5], ids},
|
{kinds: [1, 5], ids},
|
||||||
])
|
])
|
||||||
@ -107,6 +107,11 @@ const scroller = (filter, delta, onChunk) => {
|
|||||||
until -= delta
|
until -= delta
|
||||||
|
|
||||||
await onChunk(await getOrLoadChunk(filter, since, until))
|
await onChunk(await getOrLoadChunk(filter, since, until))
|
||||||
|
|
||||||
|
// Set a hard cutoff at 3 weeks back
|
||||||
|
if (since < now() - timedelta(21, 'days')) {
|
||||||
|
unsub()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return unsub
|
return unsub
|
||||||
@ -142,15 +147,13 @@ const findNote = async (id, giveUp = false) => {
|
|||||||
|
|
||||||
// If we don't have it, try to retrieve it
|
// If we don't have it, try to retrieve it
|
||||||
if (!note) {
|
if (!note) {
|
||||||
console.warning(`Failed to find context for note ${id}`)
|
console.warn(`Failed to find context for note ${id}`)
|
||||||
|
|
||||||
if (giveUp) {
|
if (giveUp) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
await ensureContext([
|
await ensureContext(await pool.loadEvents({ids: [id]}))
|
||||||
await pool.fetchEvents({ids: [id]}),
|
|
||||||
])
|
|
||||||
|
|
||||||
return findNote(id, true)
|
return findNote(id, true)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import {uniqBy, prop} from 'ramda'
|
import {uniqBy, without, prop} from 'ramda'
|
||||||
|
import {writable} from 'svelte/store'
|
||||||
import {relayPool, getPublicKey} from 'nostr-tools'
|
import {relayPool, getPublicKey} from 'nostr-tools'
|
||||||
import {noop, range} from 'hurdak/lib/hurdak'
|
import {noop, range} from 'hurdak/lib/hurdak'
|
||||||
import {now, randomChoice, timedelta, getLocalJson, setLocalJson} from "src/util/misc"
|
import {now, randomChoice, timedelta, getLocalJson, setLocalJson} from "src/util/misc"
|
||||||
@ -10,6 +11,16 @@ import {db} from 'src/relay/db'
|
|||||||
|
|
||||||
const pool = relayPool()
|
const pool = relayPool()
|
||||||
|
|
||||||
|
const relays = writable([])
|
||||||
|
|
||||||
|
const setup = () => {
|
||||||
|
for (const url of getLocalJson('pool/relays') || []) {
|
||||||
|
addRelay(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
relays.subscribe($relays => setLocalJson('pool/relays', $relays))
|
||||||
|
}
|
||||||
|
|
||||||
class Channel {
|
class Channel {
|
||||||
constructor(name) {
|
constructor(name) {
|
||||||
this.name = name
|
this.name = name
|
||||||
@ -77,10 +88,12 @@ const getPubkey = () => {
|
|||||||
|
|
||||||
const addRelay = url => {
|
const addRelay = url => {
|
||||||
pool.addRelay(url)
|
pool.addRelay(url)
|
||||||
|
relays.update($r => $r.concat(url))
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeRelay = url => {
|
const removeRelay = url => {
|
||||||
pool.removeRelay(url)
|
pool.removeRelay(url)
|
||||||
|
relays.update($r => without([url], $r))
|
||||||
}
|
}
|
||||||
|
|
||||||
const setPrivateKey = privkey => {
|
const setPrivateKey = privkey => {
|
||||||
@ -127,10 +140,6 @@ const syncPersonInfo = async person => {
|
|||||||
return await db.people.where('pubkey').equals(person.pubkey).first()
|
return await db.people.where('pubkey').equals(person.pubkey).first()
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchEvents = async filter => {
|
|
||||||
db.events.process(await req(filter))
|
|
||||||
}
|
|
||||||
|
|
||||||
let syncSub = null
|
let syncSub = null
|
||||||
let syncChan = new Channel('sync')
|
let syncChan = new Channel('sync')
|
||||||
|
|
||||||
@ -163,7 +172,9 @@ const sync = async person => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setup()
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getPubkey, addRelay, removeRelay, setPrivateKey, setPublicKey,
|
getPubkey, addRelay, removeRelay, setPrivateKey, setPublicKey,
|
||||||
publishEvent, loadEvents, syncPersonInfo, fetchEvents, sync,
|
publishEvent, loadEvents, syncPersonInfo, sync, relays,
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
import Input from "src/partials/Input.svelte"
|
import Input from "src/partials/Input.svelte"
|
||||||
import toast from "src/state/toast"
|
import toast from "src/state/toast"
|
||||||
import {dispatch} from "src/state/dispatch"
|
import {dispatch} from "src/state/dispatch"
|
||||||
import {relays, user} from "src/state/app"
|
import {user} from "src/state/app"
|
||||||
|
|
||||||
let privkey = ''
|
let privkey = ''
|
||||||
let hasExtension = false
|
let hasExtension = false
|
||||||
@ -32,19 +32,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const logIn = async ({privkey, pubkey}) => {
|
const logIn = async ({privkey, pubkey}) => {
|
||||||
console.log(1)
|
|
||||||
const person = await dispatch("user/init", pubkey)
|
const person = await dispatch("user/init", pubkey)
|
||||||
console.log(person)
|
|
||||||
|
|
||||||
user.set({...person, pubkey, privkey})
|
user.set({...person, pubkey, privkey})
|
||||||
|
|
||||||
if ($relays.length === 0) {
|
|
||||||
navigate('/relays')
|
|
||||||
} else if (user.name) {
|
|
||||||
navigate('/notes/global')
|
navigate('/notes/global')
|
||||||
} else {
|
|
||||||
navigate('/profile')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const logInWithExtension = async () => {
|
const logInWithExtension = async () => {
|
||||||
|
@ -4,11 +4,13 @@
|
|||||||
import Anchor from "src/partials/Anchor.svelte"
|
import Anchor from "src/partials/Anchor.svelte"
|
||||||
import Tabs from "src/partials/Tabs.svelte"
|
import Tabs from "src/partials/Tabs.svelte"
|
||||||
import Notes from "src/views/Notes.svelte"
|
import Notes from "src/views/Notes.svelte"
|
||||||
import {user, relays} from "src/state/app"
|
import {user} from "src/state/app"
|
||||||
import {timedelta} from 'src/util/misc'
|
import {timedelta} from 'src/util/misc'
|
||||||
|
import relay from 'src/relay'
|
||||||
|
|
||||||
export let activeTab
|
export let activeTab
|
||||||
|
|
||||||
|
const relays = relay.pool.relays
|
||||||
const authors = $user ? $user.petnames.map(t => t[1]) : []
|
const authors = $user ? $user.petnames.map(t => t[1]) : []
|
||||||
const setActiveTab = tab => navigate(`/notes/${tab}`)
|
const setActiveTab = tab => navigate(`/notes/${tab}`)
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
<script>
|
<script>
|
||||||
import {fly} from 'svelte/transition'
|
import {fly} from 'svelte/transition'
|
||||||
import {find, identity, whereEq, reject} from 'ramda'
|
|
||||||
import {fuzzy} from "src/util/misc"
|
import {fuzzy} from "src/util/misc"
|
||||||
import Input from "src/partials/Input.svelte"
|
import Input from "src/partials/Input.svelte"
|
||||||
import {dispatch} from "src/state/dispatch"
|
import {modal} from "src/state/app"
|
||||||
import {modal, relays, knownRelays} from "src/state/app"
|
import relay from 'src/relay'
|
||||||
|
|
||||||
let q = ""
|
let q = ""
|
||||||
let search
|
let search
|
||||||
let data
|
|
||||||
|
|
||||||
$: data = reject(r => $relays.includes(r.url), $knownRelays || [])
|
const relays = relay.pool.relays
|
||||||
$: search = fuzzy(data, {keys: ["name", "description", "url"]})
|
const knownRelays = relay.lq(() => relay.db.relays.toArray())
|
||||||
|
|
||||||
const join = url => dispatch("relay/join", url)
|
$: search = fuzzy($knownRelays, {keys: ["name", "description", "url"]})
|
||||||
const leave = url => dispatch("relay/leave", url)
|
|
||||||
|
const join = url => relay.pool.addRelay(url)
|
||||||
|
const leave = url => relay.pool.removeRelay(url)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex justify-center py-8 px-4" in:fly={{y: 20}}>
|
<div class="flex justify-center py-8 px-4" in:fly={{y: 20}}>
|
||||||
@ -30,27 +30,29 @@
|
|||||||
<i slot="before" class="fa-solid fa-search" />
|
<i slot="before" class="fa-solid fa-search" />
|
||||||
</Input>
|
</Input>
|
||||||
<div class="flex flex-col gap-6 overflow-auto flex-grow -mx-6 px-6">
|
<div class="flex flex-col gap-6 overflow-auto flex-grow -mx-6 px-6">
|
||||||
{#each $relays.map(url => find(whereEq({url}), $knownRelays)).filter(identity) as relay}
|
{#each ($knownRelays || []) as r}
|
||||||
|
{#if $relays.includes(r.url)}
|
||||||
<div class="flex gap-2 justify-between">
|
<div class="flex gap-2 justify-between">
|
||||||
<div>
|
<div>
|
||||||
<strong>{relay.name || relay.url}</strong>
|
<strong>{r.name || r.url}</strong>
|
||||||
<p class="text-light">{relay.description || ''}</p>
|
<p class="text-light">{r.description || ''}</p>
|
||||||
</div>
|
</div>
|
||||||
<a class="underline cursor-pointer" on:click={() => leave(relay.url)}>
|
<a class="underline cursor-pointer" on:click={() => leave(r.url)}>
|
||||||
Leave
|
Leave
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
{#if $relays.length > 0}
|
{#if ($knownRelays || []).length > 0}
|
||||||
<div class="pt-2 mb-2 border-b border-solid border-medium" />
|
<div class="pt-2 mb-2 border-b border-solid border-medium" />
|
||||||
{/if}
|
{/if}
|
||||||
{#each search(q).slice(0, 10) as relay}
|
{#each (search(q) || []).slice(0, 10) as r}
|
||||||
<div class="flex gap-2 justify-between">
|
<div class="flex gap-2 justify-between">
|
||||||
<div>
|
<div>
|
||||||
<strong>{relay.name || relay.url}</strong>
|
<strong>{r.name || r.url}</strong>
|
||||||
<p class="text-light">{relay.description || ''}</p>
|
<p class="text-light">{r.description || ''}</p>
|
||||||
</div>
|
</div>
|
||||||
<a class="underline cursor-pointer" on:click={() => join(relay.url)}>
|
<a class="underline cursor-pointer" on:click={() => join(r.url)}>
|
||||||
Join
|
Join
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import {uniqBy, prop} from 'ramda'
|
|
||||||
import {writable, get} from 'svelte/store'
|
import {writable, get} from 'svelte/store'
|
||||||
import {navigate} from "svelte-routing"
|
import {navigate} from "svelte-routing"
|
||||||
import {globalHistory} from "svelte-routing/src/history"
|
import {globalHistory} from "svelte-routing/src/history"
|
||||||
@ -32,46 +31,6 @@ userLq.subscribe(person => {
|
|||||||
user.update($user => $user ? ({...$user, ...person}) : null)
|
user.update($user => $user ? ({...$user, ...person}) : null)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Keep track of known relays
|
|
||||||
|
|
||||||
export const knownRelays = writable((getLocalJson("coracle/knownRelays") || [
|
|
||||||
{url: "wss://nostr.zebedee.cloud"},
|
|
||||||
{url: "wss://nostr-pub.wellorder.net"},
|
|
||||||
{url: "wss://nostr.rocks"},
|
|
||||||
{url: "wss://nostr-pub.semisol.dev"},
|
|
||||||
{url: "wss://nostr.drss.io"},
|
|
||||||
{url: "wss://relay.damus.io"},
|
|
||||||
{url: "wss://nostr.openchain.fr"},
|
|
||||||
{url: "wss://nostr.delo.software"},
|
|
||||||
{url: "wss://relay.nostr.info"},
|
|
||||||
{url: "wss://nostr.ono.re"},
|
|
||||||
{url: "wss://relay.grunch.dev"},
|
|
||||||
{url: "wss://nostr.sandwich.farm"},
|
|
||||||
{url: "wss://relay.nostr.ch"},
|
|
||||||
{url: "wss://nostr-relay.wlvs.space"},
|
|
||||||
]).filter(x => x.url))
|
|
||||||
|
|
||||||
knownRelays.subscribe($knownRelays => {
|
|
||||||
setLocalJson("coracle/knownRelays", $knownRelays)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const registerRelay = async url => {
|
|
||||||
let json
|
|
||||||
try {
|
|
||||||
const res = await fetch(url.replace(/^ws/, 'http'), {
|
|
||||||
headers: {
|
|
||||||
Accept: 'application/nostr_json',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
json = await res.json()
|
|
||||||
} catch (e) {
|
|
||||||
json = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
knownRelays.update($xs => uniqBy(prop('url'), $xs.concat({...json, url})))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep track of which relays we're subscribed to
|
// Keep track of which relays we're subscribed to
|
||||||
|
|
||||||
export const relays = writable(getLocalJson("coracle/relays") || [])
|
export const relays = writable(getLocalJson("coracle/relays") || [])
|
||||||
@ -139,3 +98,40 @@ export const alerts = writable({
|
|||||||
alerts.subscribe($alerts => {
|
alerts.subscribe($alerts => {
|
||||||
setLocalJson("coracle/alerts", $alerts)
|
setLocalJson("coracle/alerts", $alerts)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Relays
|
||||||
|
|
||||||
|
const defaultRelays = [
|
||||||
|
"wss://nostr.zebedee.cloud",
|
||||||
|
"wss://nostr-pub.wellorder.net",
|
||||||
|
"wss://relay.damus.io",
|
||||||
|
"wss://relay.grunch.dev",
|
||||||
|
"wss://nostr.sandwich.farm",
|
||||||
|
"wss://relay.nostr.ch",
|
||||||
|
"wss://nostr-relay.wlvs.space",
|
||||||
|
]
|
||||||
|
|
||||||
|
export const registerRelay = async url => {
|
||||||
|
const {dufflepudUrl} = get(settings)
|
||||||
|
|
||||||
|
let json
|
||||||
|
try {
|
||||||
|
const res = await fetch(dufflepudUrl + '/relay/info', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({url}),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
json = await res.json()
|
||||||
|
} catch (e) {
|
||||||
|
json = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
relay.db.relays.put({...json, url})
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const url of defaultRelays) {
|
||||||
|
registerRelay(url)
|
||||||
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import {identity, isNil, uniqBy, last, without} from 'ramda'
|
import {identity, isNil, uniqBy, last} from 'ramda'
|
||||||
import {get} from 'svelte/store'
|
|
||||||
import {first, defmulti} from "hurdak/lib/hurdak"
|
import {first, defmulti} from "hurdak/lib/hurdak"
|
||||||
import relay from 'src/relay'
|
import relay from 'src/relay'
|
||||||
import {relays} from 'src/state/app'
|
|
||||||
|
|
||||||
// Commands are processed in two layers:
|
// Commands are processed in two layers:
|
||||||
// - App-oriented commands are created via dispatch
|
// - App-oriented commands are created via dispatch
|
||||||
@ -12,7 +10,10 @@ import {relays} from 'src/state/app'
|
|||||||
export const dispatch = defmulti("dispatch", identity)
|
export const dispatch = defmulti("dispatch", identity)
|
||||||
|
|
||||||
dispatch.addMethod("user/init", (topic, pubkey) => {
|
dispatch.addMethod("user/init", (topic, pubkey) => {
|
||||||
return relay.pool.syncUserInfo({pubkey})
|
// Hardcode one to get them started
|
||||||
|
relay.pool.addRelay("wss://nostr.zebedee.cloud")
|
||||||
|
|
||||||
|
return relay.pool.syncPersonInfo({pubkey})
|
||||||
})
|
})
|
||||||
|
|
||||||
dispatch.addMethod("user/update", async (topic, updates) => {
|
dispatch.addMethod("user/update", async (topic, updates) => {
|
||||||
@ -27,14 +28,6 @@ dispatch.addMethod("user/muffle", async (topic, muffle) => {
|
|||||||
await relay.pool.publishEvent(makeEvent(12165, '', muffle))
|
await relay.pool.publishEvent(makeEvent(12165, '', muffle))
|
||||||
})
|
})
|
||||||
|
|
||||||
dispatch.addMethod("relay/join", async (topic, url) => {
|
|
||||||
relays.update(r => r.concat(url))
|
|
||||||
})
|
|
||||||
|
|
||||||
dispatch.addMethod("relay/leave", (topic, url) => {
|
|
||||||
relays.update(r => without([url], r))
|
|
||||||
})
|
|
||||||
|
|
||||||
dispatch.addMethod("room/create", async (topic, room) => {
|
dispatch.addMethod("room/create", async (topic, room) => {
|
||||||
const event = makeEvent(40, JSON.stringify(room))
|
const event = makeEvent(40, JSON.stringify(room))
|
||||||
|
|
||||||
@ -104,7 +97,7 @@ export const copyTags = (e, newTags = []) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const t = (type, content, marker) => {
|
export const t = (type, content, marker) => {
|
||||||
const tag = [type, content, first(get(relays))]
|
const tag = [type, content, first(Object.keys(relay.pool.relays))]
|
||||||
|
|
||||||
if (!isNil(marker)) {
|
if (!isNil(marker)) {
|
||||||
tag.push(marker)
|
tag.push(marker)
|
||||||
|
@ -64,7 +64,7 @@ export const createScroller = loadMore => {
|
|||||||
await loadMore()
|
await loadMore()
|
||||||
}
|
}
|
||||||
|
|
||||||
await sleep(100)
|
await sleep(1000)
|
||||||
|
|
||||||
if (!done) {
|
if (!done) {
|
||||||
requestAnimationFrame(check)
|
requestAnimationFrame(check)
|
||||||
|
@ -1,26 +1,35 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import {onDestroy} from 'svelte'
|
||||||
import {fly} from 'svelte/transition'
|
import {fly} from 'svelte/transition'
|
||||||
import {propEq} from 'ramda'
|
import {uniqBy, identity, prop} from 'ramda'
|
||||||
|
import {timedelta} from 'src/util/misc'
|
||||||
import Note from "src/views/Note.svelte"
|
import Note from "src/views/Note.svelte"
|
||||||
import {findReply} from 'src/util/nostr'
|
import {findReply} from 'src/util/nostr'
|
||||||
import relay from 'src/relay'
|
import relay from 'src/relay'
|
||||||
|
|
||||||
export let author
|
export let author
|
||||||
|
|
||||||
const notes = relay.lq(async () => {
|
const filter = {kinds: [7], authors: [author]}
|
||||||
const reactions = await relay.db.events
|
const delta = timedelta(1, 'days')
|
||||||
.where('pubkey').equals(author).filter(propEq('kind', 7)).toArray()
|
|
||||||
|
|
||||||
return Promise.all(reactions.map(r => relay.findNote(findReply(r))))
|
let notes
|
||||||
|
|
||||||
|
onDestroy(relay.scroller(filter, delta, async chunk => {
|
||||||
|
notes = relay.lq(async () => {
|
||||||
|
const notes = await Promise.all(chunk.map(r => relay.findNote(findReply(r))))
|
||||||
|
|
||||||
|
return uniqBy(prop('id'), notes.filter(identity))
|
||||||
})
|
})
|
||||||
|
}))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $notes}
|
{#if $notes}
|
||||||
<ul class="py-4 flex flex-col gap-2 max-w-xl m-auto">
|
<ul class="py-4 flex flex-col gap-2 max-w-xl m-auto">
|
||||||
{#each $notes as n (n.id)}
|
{#each $notes as n (n.id)}
|
||||||
<li><Note interactive noReply note={n} depth={1} /></li>
|
<li><Note note={n} depth={1} /></li>
|
||||||
{:else}
|
{:else}
|
||||||
<li class="p-20 text-center" in:fly={{y: 20}}>No notes found.</li>
|
<li class="p-20 text-center" in:fly={{y: 20}}>No notes found.</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
const values = {
|
const values = {
|
||||||
// Scale up to integers for each choice we have
|
// Scale up to integers for each choice we have
|
||||||
muffle: switcher(Math.round(getMuffleValue($modal.user) * 3), muffleOptions),
|
muffle: switcher(Math.round(getMuffleValue($modal.person) * 3), muffleOptions),
|
||||||
}
|
}
|
||||||
|
|
||||||
const save = async e => {
|
const save = async e => {
|
||||||
@ -21,8 +21,8 @@
|
|||||||
// Scale back down to a decimal based on string value
|
// Scale back down to a decimal based on string value
|
||||||
const muffleValue = muffleOptions.indexOf(values.muffle) / 3
|
const muffleValue = muffleOptions.indexOf(values.muffle) / 3
|
||||||
const muffle = $user.muffle
|
const muffle = $user.muffle
|
||||||
.filter(x => x[1] !== $modal.user.pubkey)
|
.filter(x => x[1] !== $modal.person.pubkey)
|
||||||
.concat([t("p", $modal.user.pubkey, muffleValue.toString())])
|
.concat([t("p", $modal.person.pubkey, muffleValue.toString())])
|
||||||
.filter(x => last(x) !== "1")
|
.filter(x => last(x) !== "1")
|
||||||
|
|
||||||
dispatch('user/muffle', muffle)
|
dispatch('user/muffle', muffle)
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ul class="py-8 flex flex-col gap-2 max-w-xl m-auto">
|
<ul class="py-8 flex flex-col gap-2 max-w-xl m-auto">
|
||||||
{#each results as e (e.id)}
|
{#each results.slice(0, 50) as e (e.id)}
|
||||||
<li in:fly={{y: 20}}>
|
<li in:fly={{y: 20}}>
|
||||||
<Note interactive note={e} />
|
<Note interactive note={e} />
|
||||||
</li>
|
</li>
|
||||||
|
@ -6,37 +6,29 @@
|
|||||||
|
|
||||||
export let q
|
export let q
|
||||||
|
|
||||||
let results = []
|
let search
|
||||||
|
|
||||||
const search = relay.lq(async () => {
|
const people = relay.lq(() => relay.db.people.toArray())
|
||||||
return fuzzy(await relay.db.people.toArray(), {keys: ["name", "about", "pubkey"]})
|
|
||||||
})
|
|
||||||
|
|
||||||
$: {
|
$: search = fuzzy($people || [], {keys: ["name", "about", "pubkey"]})
|
||||||
if ($search) {
|
|
||||||
Promise.all(
|
|
||||||
$search(q).map(n => relay.findNote(n.id))
|
|
||||||
).then(notes => {
|
|
||||||
results = notes
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#if search}
|
||||||
<ul class="py-8 flex flex-col gap-2 max-w-xl m-auto">
|
<ul class="py-8 flex flex-col gap-2 max-w-xl m-auto">
|
||||||
{#each results as e (e.pubkey)}
|
{#each search(q) as p (p.pubkey)}
|
||||||
{#if e.pubkey !== $user.pubkey}
|
{#if p.pubkey !== $user.pubkey}
|
||||||
<li in:fly={{y: 20}}>
|
<li in:fly={{y: 20}}>
|
||||||
<a href="/people/{e.pubkey}/notes" class="flex gap-4 my-4">
|
<a href="/people/{p.pubkey}/notes" class="flex gap-4 my-4">
|
||||||
<div
|
<div
|
||||||
class="overflow-hidden w-12 h-12 rounded-full bg-cover bg-center shrink-0 border border-solid border-white"
|
class="overflow-hidden w-12 h-12 rounded-full bg-cover bg-center shrink-0 border border-solid border-white"
|
||||||
style="background-image: url({e.picture})" />
|
style="background-image: url({p.picture})" />
|
||||||
<div class="flex-grow">
|
<div class="flex-grow">
|
||||||
<h1 class="text-2xl">{e.name || e.pubkey.slice(0, 8)}</h1>
|
<h1 class="text-2xl">{p.name || p.pubkey.slice(0, 8)}</h1>
|
||||||
<p>{e.about || ''}</p>
|
<p>{p.about || ''}</p>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<li>
|
<li>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
{/if}
|
||||||
|
Loading…
Reference in New Issue
Block a user