Rename user > person

This commit is contained in:
Jonathan Staab 2022-12-17 13:22:09 -08:00
parent 447c112d21
commit 1d4b4a73d8
20 changed files with 137 additions and 135 deletions

View File

@ -40,7 +40,6 @@ 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
- [ ] Rename users/accounts to people
- [ ] Move relays to db - [ ] Move relays to db
- [ ] Make user a livequery instead of a store - [ ] Make user a livequery instead of a store
- [ ] Figure out if multiple relays congest response times because we wait for all eose - [ ] Figure out if multiple relays congest response times because we wait for all eose

View File

@ -16,6 +16,7 @@
import relay from 'src/relay' import relay from 'src/relay'
import Anchor from 'src/partials/Anchor.svelte' import Anchor from 'src/partials/Anchor.svelte'
import NoteDetail from "src/views/NoteDetail.svelte" import NoteDetail from "src/views/NoteDetail.svelte"
import PersonSettings from "src/views/PersonSettings.svelte"
import NotFound from "src/routes/NotFound.svelte" import NotFound from "src/routes/NotFound.svelte"
import Search from "src/routes/Search.svelte" import Search from "src/routes/Search.svelte"
import Alerts from "src/routes/Alerts.svelte" import Alerts from "src/routes/Alerts.svelte"
@ -26,8 +27,7 @@
import Keys from "src/routes/Keys.svelte" import Keys from "src/routes/Keys.svelte"
import RelayList from "src/routes/RelayList.svelte" import RelayList from "src/routes/RelayList.svelte"
import AddRelay from "src/routes/AddRelay.svelte" import AddRelay from "src/routes/AddRelay.svelte"
import UserDetail from "src/routes/UserDetail.svelte" import Person from "src/routes/Person.svelte"
import UserAdvanced from "src/routes/UserAdvanced.svelte"
import NoteCreate from "src/routes/NoteCreate.svelte" import NoteCreate from "src/routes/NoteCreate.svelte"
export let url = "" export let url = ""
@ -97,9 +97,9 @@
<Route path="/search/:type" component={Search} /> <Route path="/search/:type" component={Search} />
<Route path="/notes/:activeTab" component={Notes} /> <Route path="/notes/:activeTab" component={Notes} />
<Route path="/notes/new" component={NoteCreate} /> <Route path="/notes/new" component={NoteCreate} />
<Route path="/users/:pubkey/:activeTab" let:params> <Route path="/people/:pubkey/:activeTab" let:params>
{#key params.pubkey} {#key params.pubkey}
<UserDetail {...params} /> <Person {...params} />
{/key} {/key}
</Route> </Route>
<Route path="/keys" component={Keys} /> <Route path="/keys" component={Keys} />
@ -117,7 +117,7 @@
> >
{#if $user} {#if $user}
<li> <li>
<a href={`/users/${$user.pubkey}/notes`} class="flex gap-2 px-4 py-2 pb-6 items-center"> <a href={`/people/${$user.pubkey}/notes`} class="flex gap-2 px-4 py-2 pb-6 items-center">
<div <div
class="overflow-hidden w-6 h-6 rounded-full bg-cover bg-center shrink-0 border border-solid border-white" class="overflow-hidden w-6 h-6 rounded-full bg-cover bg-center shrink-0 border border-solid border-white"
style="background-image: url({$user.picture})" /> style="background-image: url({$user.picture})" />
@ -201,8 +201,8 @@
{/key} {/key}
{:else if $modal.form === 'relay'} {:else if $modal.form === 'relay'}
<AddRelay /> <AddRelay />
{:else if $modal.form === 'user/advanced'} {:else if $modal.form === 'person/settings'}
<UserAdvanced /> <PersonSettings />
{/if} {/if}
</dialog> </dialog>
</div> </div>

10
src/partials/Badge.svelte Normal file
View File

@ -0,0 +1,10 @@
<script>
export let person
</script>
<a href={`/people/${person.pubkey}/notes`} class="flex gap-2 items-center relative z-10">
<div
class="overflow-hidden w-4 h-4 rounded-full bg-cover bg-center shrink-0 border border-solid border-white"
style="background-image: url({person.picture})" />
<span class="text-lg font-bold">{person.name || person.pubkey.slice(0, 8)}</span>
</a>

View File

@ -1,10 +0,0 @@
<script>
export let user
</script>
<a href={`/users/${user.pubkey}/notes`} class="flex gap-2 items-center relative z-10">
<div
class="overflow-hidden w-4 h-4 rounded-full bg-cover bg-center shrink-0 border border-solid border-white"
style="background-image: url({user.picture})" />
<span class="text-lg font-bold">{user.name || user.pubkey.slice(0, 8)}</span>
</a>

View File

@ -8,7 +8,7 @@ export const db = new Dexie('coracle/relay')
db.version(3).stores({ db.version(3).stores({
events: '++id, pubkey, created_at, kind, content, reply, root', events: '++id, pubkey, created_at, kind, content, reply, root',
users: '++pubkey, name, about', people: '++pubkey, name, about',
tags: '++key, event, value', tags: '++key, event, value',
}) })
@ -18,7 +18,7 @@ window.db = db
db.events.process = async events => { db.events.process = async events => {
// Only persist ones we care about, the rest can be // Only persist ones we care about, the rest can be
// ephemeral and used to update users etc // ephemeral and used to update people etc
const eventsByKind = groupBy(prop('kind'), ensurePlural(events)) const eventsByKind = groupBy(prop('kind'), ensurePlural(events))
const notesAndReactions = flatten(Object.values(pick([1, 7], eventsByKind))) const notesAndReactions = flatten(Object.values(pick([1, 7], eventsByKind)))
const profileUpdates = flatten(Object.values(pick([0, 3, 12165], eventsByKind))) const profileUpdates = flatten(Object.values(pick([0, 3, 12165], eventsByKind)))
@ -56,16 +56,16 @@ db.events.process = async events => {
db.tags.where('event').anyOf(eventIds).delete() db.tags.where('event').anyOf(eventIds).delete()
} }
// Update our users // Update our people
for (const event of profileUpdates) { for (const event of profileUpdates) {
const {pubkey, kind, content, tags} = event const {pubkey, kind, content, tags} = event
const user = await db.users.where('pubkey').equals(pubkey).first() const person = await db.people.where('pubkey').equals(pubkey).first()
const putUser = data => db.users.put({...user, ...data, pubkey, updated_at: now()}) const putPerson = data => db.people.put({...person, ...data, pubkey, updated_at: now()})
await switcherFn(kind, { await switcherFn(kind, {
0: () => putUser(JSON.parse(content)), 0: () => putPerson(JSON.parse(content)),
3: () => putUser({petnames: tags}), 3: () => putPerson({petnames: tags}),
12165: () => putUser({muffle: tags}), 12165: () => putPerson({muffle: tags}),
default: () => { default: () => {
console.log(`Received unsupported event type ${event.kind}`) console.log(`Received unsupported event type ${event.kind}`)
}, },

View File

@ -17,25 +17,35 @@ const lq = f => liveQuery(async () => {
}) })
const ensurePerson = async ({pubkey}) => { const ensurePerson = async ({pubkey}) => {
const user = await db.users.where('pubkey').equals(pubkey).first() const person = await db.people.where('pubkey').equals(pubkey).first()
// Throttle updates for users // Throttle updates for people
if (!user || user.updated_at < now() - timedelta(1, 'hours')) { if (!person || person.updated_at < now() - timedelta(1, 'hours')) {
await pool.syncUserInfo({pubkey, ...user}) await pool.syncPersonInfo({pubkey, ...person})
} }
} }
const ensureContext = async events => { const ensureContext = async events => {
const ids = events.flatMap(e => filterTags({tag: "e"}, e).concat(e.id)) const promises = []
const people = uniq(pluck('pubkey', events)).map(objOf('pubkey')) const people = uniq(pluck('pubkey', events)).map(objOf('pubkey'))
const ids = events.flatMap(e => filterTags({tag: "e"}, e).concat(e.id))
await Promise.all([ if (people.length > 0) {
people.map(ensurePerson), for (const p of people.map(ensurePerson)) {
promises.push(p)
}
}
if (ids.length > 0) {
promises.push(
pool.fetchEvents([ pool.fetchEvents([
{kinds: [1, 5, 7], '#e': ids}, {kinds: [1, 5, 7], '#e': ids},
{kinds: [1, 5], ids}, {kinds: [1, 5], ids},
]),
]) ])
)
}
await Promise.all(promises)
} }
const prefilterEvents = filter => { const prefilterEvents = filter => {
@ -111,15 +121,15 @@ const findNote = async (id, giveUp = false) => {
return findNote(id, true) return findNote(id, true)
} }
const [replies, reactions, user, html] = await Promise.all([ const [replies, reactions, person, html] = await Promise.all([
children.clone().filter(e => e.kind === 1).toArray(), children.clone().filter(e => e.kind === 1).toArray(),
children.clone().filter(e => e.kind === 7).toArray(), children.clone().filter(e => e.kind === 7).toArray(),
db.users.get(note.pubkey), db.people.get(note.pubkey),
renderNote(note, {showEntire: false}), renderNote(note, {showEntire: false}),
]) ])
return { return {
...note, reactions, user, html, ...note, reactions, person, html,
replies: await Promise.all(replies.map(r => findNote(r.id))), replies: await Promise.all(replies.map(r => findNote(r.id))),
} }
} }
@ -127,8 +137,8 @@ const findNote = async (id, giveUp = false) => {
const renderNote = async (note, {showEntire = false}) => { const renderNote = async (note, {showEntire = false}) => {
const shouldEllipsize = note.content.length > 500 && !showEntire const shouldEllipsize = note.content.length > 500 && !showEntire
const content = shouldEllipsize ? ellipsize(note.content, 500) : note.content const content = shouldEllipsize ? ellipsize(note.content, 500) : note.content
const accounts = await db.users.where('pubkey').anyOf(filterTags({tag: "p"}, note)).toArray() const people = await db.people.where('pubkey').anyOf(filterTags({tag: "p"}, note)).toArray()
const accountsByPubkey = createMap('pubkey', accounts) const peopleByPubkey = createMap('pubkey', people)
return escapeHtml(content) return escapeHtml(content)
.replace(/\n/g, '<br />') .replace(/\n/g, '<br />')
@ -141,15 +151,15 @@ const renderNote = async (note, {showEntire = false}) => {
} }
const pubkey = note.tags[parseInt(i)][1] const pubkey = note.tags[parseInt(i)][1]
const user = accountsByPubkey[pubkey] const person = peopleByPubkey[pubkey]
const name = user?.name || pubkey.slice(0, 8) const name = person?.name || pubkey.slice(0, 8)
return `@<a href="/users/${pubkey}/notes" class="underline">${name}</a>` return `@<a href="/people/${pubkey}/notes" class="underline">${name}</a>`
}) })
} }
const filterAlerts = async (user, filter) => { const filterAlerts = async (person, filter) => {
const tags = db.tags.where('value').equals(user.pubkey) const tags = db.tags.where('value').equals(person.pubkey)
const ids = pluck('event', await tags.toArray()) const ids = pluck('event', await tags.toArray())
const events = await filterEvents({...filter, kinds: [1, 7], ids}) const events = await filterEvents({...filter, kinds: [1, 7], ids})

View File

@ -118,21 +118,19 @@ const loadEvents = async filter => {
return events return events
} }
const syncUserInfo = async user => { const syncPersonInfo = async person => {
const [events] = await Promise.all([ const [events] = await Promise.all([
// Get profile info events // Get profile info events
req({kinds: [0, 3, 12165], authors: [user.pubkey]}), req({kinds: [0, 3, 12165], authors: [person.pubkey]}),
// Make sure we have something in the database // Make sure we have something in the database
db.users.put({muffle: [], petnames: [], updated_at: 0, ...user}), db.people.put({muffle: [], petnames: [], updated_at: 0, ...person}),
]) ])
// Process the events to flesh out the user // Process the events to flesh out the person
await db.events.process(events) await db.events.process(events)
// Return our user for convenience // Return our person for convenience
const person = await db.users.where('pubkey').equals(user.pubkey).first() return await db.people.where('pubkey').equals(person.pubkey).first()
return person
} }
const fetchEvents = async filter => { const fetchEvents = async filter => {
@ -142,15 +140,15 @@ const fetchEvents = async filter => {
let syncSub = null let syncSub = null
let syncChan = new Channel('sync') let syncChan = new Channel('sync')
const sync = async user => { const sync = async person => {
if (syncSub) { if (syncSub) {
(await syncSub).unsub() (await syncSub).unsub()
} }
if (!user) return if (!person) return
// Get user info right away // Get person info right away
const {petnames, pubkey} = await syncUserInfo(user) const {petnames, pubkey} = await syncPersonInfo(person)
// Don't grab nothing, but don't grab everything either // Don't grab nothing, but don't grab everything either
const since = Math.max( const since = Math.max(
@ -163,7 +161,7 @@ const sync = async user => {
setLocalJson('pool/lastSync', now()) setLocalJson('pool/lastSync', now())
// Populate recent activity in network so the user has something to look at right away // Populate recent activity in network so the person has something to look at right away
syncSub = syncChan.sub( syncSub = syncChan.sub(
[{since, authors: getTagValues(petnames).concat(pubkey)}, [{since, authors: getTagValues(petnames).concat(pubkey)},
{since, '#p': [pubkey]}], {since, '#p': [pubkey]}],
@ -173,5 +171,5 @@ const sync = async user => {
export default { export default {
getPubkey, addRelay, removeRelay, setPrivateKey, setPublicKey, getPubkey, addRelay, removeRelay, setPrivateKey, setPublicKey,
publishEvent, loadEvents, syncUserInfo, fetchEvents, sync, publishEvent, loadEvents, syncPersonInfo, fetchEvents, sync,
} }

View File

@ -5,7 +5,7 @@
import {ellipsize} from 'hurdak/src/core' import {ellipsize} from 'hurdak/src/core'
import relay from 'src/relay' import relay from 'src/relay'
import {alerts, modal, user} from 'src/state/app' import {alerts, modal, user} from 'src/state/app'
import UserBadge from "src/partials/UserBadge.svelte" import Badge from "src/partials/Badge.svelte"
import Note from 'src/views/Note.svelte' import Note from 'src/views/Note.svelte'
const events = relay.lq(async () => { const events = relay.lq(async () => {
@ -32,7 +32,7 @@
border border-solid border-black hover:border-medium hover:bg-dark" border border-solid border-black hover:border-medium hover:bg-dark"
on:click={() => modal.set({note: e.parent})}> on:click={() => modal.set({note: e.parent})}>
<div class="flex gap-2 items-center"> <div class="flex gap-2 items-center">
<UserBadge user={e.user} /> <Badge person={e.person} />
<span>liked your note.</span> <span>liked your note.</span>
</div> </div>
<div class="ml-6 text-light"> <div class="ml-6 text-light">

View File

@ -33,7 +33,7 @@
const logIn = async ({privkey, pubkey}) => { const logIn = async ({privkey, pubkey}) => {
console.log(1) console.log(1)
const person = await dispatch("account/init", pubkey) const person = await dispatch("user/init", pubkey)
console.log(person) console.log(person)
user.set({...person, pubkey, privkey}) user.set({...person, pubkey, privkey})

View File

@ -25,7 +25,7 @@
{#if activeTab === 'follows' && authors.length === 0} {#if activeTab === 'follows' && authors.length === 0}
<div class="flex w-full justify-center items-center py-16"> <div class="flex w-full justify-center items-center py-16">
<div class="text-center max-w-md"> <div class="text-center max-w-md">
You haven't yet followed anyone. Visit a user's profile to follow them. You haven't yet followed anyone. Visit a person's profile to follow them.
</div> </div>
</div> </div>
{:else if activeTab === 'follows'} {:else if activeTab === 'follows'}

View File

@ -8,7 +8,7 @@
import Notes from "src/views/Notes.svelte" import Notes from "src/views/Notes.svelte"
import Likes from "src/views/Likes.svelte" import Likes from "src/views/Likes.svelte"
import {t, dispatch} from 'src/state/dispatch' import {t, dispatch} from 'src/state/dispatch'
import {modal, user as currentUser} from "src/state/app" import {modal, user} from "src/state/app"
import relay from 'src/relay' import relay from 'src/relay'
export let pubkey export let pubkey
@ -16,32 +16,32 @@
relay.ensurePerson({pubkey}) relay.ensurePerson({pubkey})
const user = relay.lq(() => relay.db.users.get(pubkey)) const person = relay.lq(() => relay.db.people.get(pubkey))
let following = $currentUser && find(t => t[1] === pubkey, $currentUser.petnames) let following = $user && find(t => t[1] === pubkey, $user.petnames)
const setActiveTab = tab => navigate(`/users/${pubkey}/${tab}`) const setActiveTab = tab => navigate(`/people/${pubkey}/${tab}`)
const follow = () => { const follow = () => {
const petnames = $currentUser.petnames const petnames = $user.petnames
.concat([t("p", pubkey, $user?.name)]) .concat([t("p", pubkey, $person?.name)])
dispatch('account/petnames', petnames) dispatch('user/petnames', petnames)
following = true following = true
} }
const unfollow = () => { const unfollow = () => {
const petnames = $currentUser.petnames const petnames = $user.petnames
.filter(([_, pubkey]) => pubkey !== pubkey) .filter(([_, pubkey]) => pubkey !== pubkey)
dispatch('account/petnames', petnames) dispatch('user/petnames', petnames)
following = false following = false
} }
const openAdvanced = () => { const openAdvanced = () => {
modal.set({form: 'user/advanced', user: $user || {pubkey}}) modal.set({form: 'person/settings', person: $person || {pubkey}})
} }
</script> </script>
@ -50,18 +50,18 @@
<div class="flex gap-4"> <div class="flex gap-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({$user?.picture})" /> style="background-image: url({$person?.picture})" />
<div class="flex-grow"> <div class="flex-grow">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<h1 class="text-2xl">{$user?.name || pubkey.slice(0, 8)}</h1> <h1 class="text-2xl">{$person?.name || pubkey.slice(0, 8)}</h1>
{#if $currentUser && $currentUser.pubkey !== pubkey} {#if $user && $user.pubkey !== pubkey}
<i class="fa-solid fa-sliders cursor-pointer" on:click={openAdvanced} /> <i class="fa-solid fa-sliders cursor-pointer" on:click={openAdvanced} />
{/if} {/if}
</div> </div>
<p>{$user?.about || ''}</p> <p>{$person?.about || ''}</p>
</div> </div>
<div class="whitespace-nowrap"> <div class="whitespace-nowrap">
{#if $currentUser?.pubkey === pubkey} {#if $user?.pubkey === pubkey}
<a href="/profile" class="cursor-pointer text-sm"> <a href="/profile" class="cursor-pointer text-sm">
<i class="fa-solid fa-edit" /> Edit <i class="fa-solid fa-edit" /> Edit
</a> </a>
@ -85,11 +85,11 @@
{:else if activeTab === 'likes'} {:else if activeTab === 'likes'}
<Likes author={pubkey} /> <Likes author={pubkey} />
{:else if activeTab === 'network'} {:else if activeTab === 'network'}
{#if $user} {#if $person}
<Notes shouldMuffle filter={{kinds: [1], authors: $user.petnames.map(t => t[1])}} /> <Notes shouldMuffle filter={{kinds: [1], authors: $person.petnames.map(t => t[1])}} />
{:else} {:else}
<div class="py-16 max-w-xl m-auto flex justify-center"> <div class="py-16 max-w-xl m-auto flex justify-center">
Unable to show network for this user. Unable to show network for this person.
</div> </div>
{/if} {/if}
{/if} {/if}

View File

@ -38,9 +38,9 @@
const submit = async event => { const submit = async event => {
event.preventDefault() event.preventDefault()
await dispatch("account/update", values) await dispatch("user/update", values)
navigate(`/users/${$user.pubkey}/profile`) navigate(`/people/${$user.pubkey}/profile`)
toast.show("info", "Your profile has been updated!") toast.show("info", "Your profile has been updated!")
} }

View File

@ -24,7 +24,7 @@ const userLq = relay.lq(() => {
const $user = get(user) const $user = get(user)
if ($user) { if ($user) {
return relay.db.users.where('pubkey').equals($user?.pubkey).first() return relay.db.people.where('pubkey').equals($user?.pubkey).first()
} }
}) })

View File

@ -11,19 +11,19 @@ import {relays} from 'src/state/app'
export const dispatch = defmulti("dispatch", identity) export const dispatch = defmulti("dispatch", identity)
dispatch.addMethod("account/init", (topic, pubkey) => { dispatch.addMethod("user/init", (topic, pubkey) => {
return relay.pool.syncUserInfo({pubkey}) return relay.pool.syncUserInfo({pubkey})
}) })
dispatch.addMethod("account/update", async (topic, updates) => { dispatch.addMethod("user/update", async (topic, updates) => {
await relay.pool.publishEvent(makeEvent(0, JSON.stringify(updates))) await relay.pool.publishEvent(makeEvent(0, JSON.stringify(updates)))
}) })
dispatch.addMethod("account/petnames", async (topic, petnames) => { dispatch.addMethod("user/petnames", async (topic, petnames) => {
await relay.pool.publishEvent(makeEvent(3, '', petnames)) await relay.pool.publishEvent(makeEvent(3, '', petnames))
}) })
dispatch.addMethod("account/muffle", async (topic, muffle) => { dispatch.addMethod("user/muffle", async (topic, muffle) => {
await relay.pool.publishEvent(makeEvent(12165, '', muffle)) await relay.pool.publishEvent(makeEvent(12165, '', muffle))
}) })

View File

@ -60,7 +60,7 @@ export const createScroller = loadMore => {
const {scrollY, innerHeight} = window const {scrollY, innerHeight} = window
const {scrollHeight} = document.body const {scrollHeight} = document.body
if (scrollY + innerHeight + 600 > scrollHeight) { if (scrollY + innerHeight + 2000 > scrollHeight) {
await loadMore() await loadMore()
} }

View File

@ -47,12 +47,12 @@ export const filterMatches = (filter, e) => {
)) ))
} }
export const getMuffleValue = user => { export const getMuffleValue = person => {
if (!user) { if (!person) {
return 1 return 1
} }
const tag = find(t => t[1] === user.pubkey, user.muffle) const tag = find(t => t[1] === person.pubkey, person.muffle)
if (!tag) { if (!tag) {
return 1 return 1

View File

@ -10,7 +10,7 @@
import {dispatch} from "src/state/dispatch" import {dispatch} from "src/state/dispatch"
import {settings, user, modal} from "src/state/app" import {settings, user, modal} from "src/state/app"
import {formatTimestamp} from 'src/util/misc' import {formatTimestamp} from 'src/util/misc'
import UserBadge from "src/partials/UserBadge.svelte" import Badge from "src/partials/Badge.svelte"
import Card from "src/partials/Card.svelte" import Card from "src/partials/Card.svelte"
export let note export let note
@ -94,7 +94,7 @@
<Card on:click={onClick} {interactive} {invertColors}> <Card on:click={onClick} {interactive} {invertColors}>
<div class="flex gap-4 items-center justify-between"> <div class="flex gap-4 items-center justify-between">
<UserBadge user={{...note.user, pubkey: note.pubkey}} /> <Badge person={{...note.person, pubkey: note.pubkey}} />
<p class="text-sm text-light">{formatTimestamp(note.created_at)}</p> <p class="text-sm text-light">{formatTimestamp(note.created_at)}</p>
</div> </div>
<div class="ml-6 flex flex-col gap-2"> <div class="ml-6 flex flex-col gap-2">

View File

@ -16,19 +16,15 @@
let since = now() - delta, until = now(), notes let since = now() - delta, until = now(), notes
const done = createScroller(async () => { const unsub = createScroller(async () => {
since -= delta since -= delta
until -= delta until -= delta
// Load our events, but don't wait for them because we probably have them in dexie
await relay.ensureContext( await relay.ensureContext(
await relay.pool.loadEvents({...filter, since, until}) await relay.pool.loadEvents({...filter, since, until})
) )
createNotesObservable()
})
const createNotesObservable = () => {
notes = relay.lq(async () => {
const notes = await relay.filterEvents({...filter, since}).reverse().sortBy('created_at') const notes = await relay.filterEvents({...filter, since}).reverse().sortBy('created_at')
const ancestorIds = concat(notes.map(findRoot), notes.map(findReply)).filter(identity) const ancestorIds = concat(notes.map(findRoot), notes.map(findReply)).filter(identity)
const ancestors = await relay.filterEvents({kinds: [1], ids: ancestorIds}).toArray() const ancestors = await relay.filterEvents({kinds: [1], ids: ancestorIds}).toArray()
@ -56,9 +52,8 @@
return await Promise.all(Object.keys(notesByRoot).map(relay.findNote)) return await Promise.all(Object.keys(notesByRoot).map(relay.findNote))
}) })
}
onDestroy(done) onDestroy(unsub)
</script> </script>
<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">

View File

@ -25,7 +25,7 @@
.concat([t("p", $modal.user.pubkey, muffleValue.toString())]) .concat([t("p", $modal.user.pubkey, muffleValue.toString())])
.filter(x => last(x) !== "1") .filter(x => last(x) !== "1")
dispatch('account/muffle', muffle) dispatch('user/muffle', muffle)
modal.set(null) modal.set(null)
} }
@ -35,7 +35,7 @@
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<h1 class="text-3xl">Advanced Follow</h1> <h1 class="text-3xl">Advanced Follow</h1>
<p> <p>
Fine grained controls for interacting with other users. Fine grained controls for interacting with other people.
</p> </p>
</div> </div>
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">

View File

@ -9,7 +9,7 @@
let results = [] let results = []
const search = relay.lq(async () => { const search = relay.lq(async () => {
return fuzzy(await relay.db.users.toArray(), {keys: ["name", "about", "pubkey"]}) return fuzzy(await relay.db.people.toArray(), {keys: ["name", "about", "pubkey"]})
}) })
$: { $: {
@ -27,7 +27,7 @@
{#each results as e (e.pubkey)} {#each results as e (e.pubkey)}
{#if e.pubkey !== $user.pubkey} {#if e.pubkey !== $user.pubkey}
<li in:fly={{y: 20}}> <li in:fly={{y: 20}}>
<a href="/users/{e.pubkey}/notes" class="flex gap-4 my-4"> <a href="/people/{e.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({e.picture})" />