mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-30 00:41:12 +00:00
Rename user > person
This commit is contained in:
parent
447c112d21
commit
1d4b4a73d8
@ -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
|
||||||
|
@ -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
10
src/partials/Badge.svelte
Normal 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>
|
@ -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>
|
|
@ -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}`)
|
||||||
},
|
},
|
||||||
|
@ -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)) {
|
||||||
pool.fetchEvents([
|
promises.push(p)
|
||||||
{kinds: [1, 5, 7], '#e': ids},
|
}
|
||||||
{kinds: [1, 5], ids},
|
}
|
||||||
]),
|
|
||||||
])
|
if (ids.length > 0) {
|
||||||
|
promises.push(
|
||||||
|
pool.fetchEvents([
|
||||||
|
{kinds: [1, 5, 7], '#e': 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})
|
||||||
|
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
|
@ -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">
|
||||||
|
@ -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})
|
||||||
|
@ -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'}
|
||||||
|
@ -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}
|
@ -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!")
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -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))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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">
|
||||||
|
@ -16,49 +16,44 @@
|
|||||||
|
|
||||||
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 notes = await relay.filterEvents({...filter, since}).reverse().sortBy('created_at')
|
||||||
|
const ancestorIds = concat(notes.map(findRoot), notes.map(findReply)).filter(identity)
|
||||||
|
const ancestors = await relay.filterEvents({kinds: [1], ids: ancestorIds}).toArray()
|
||||||
|
|
||||||
|
const allNotes = uniqBy(prop('id'), notes.concat(ancestors))
|
||||||
|
const notesById = createMap('id', allNotes)
|
||||||
|
const notesByRoot = groupBy(
|
||||||
|
n => {
|
||||||
|
const rootId = findRoot(n)
|
||||||
|
const parentId = findReply(n)
|
||||||
|
|
||||||
|
// Actually dereference the notes in case we weren't able to retrieve them
|
||||||
|
if (notesById[rootId]) {
|
||||||
|
return rootId
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notesById[parentId]) {
|
||||||
|
return parentId
|
||||||
|
}
|
||||||
|
|
||||||
|
return n.id
|
||||||
|
},
|
||||||
|
allNotes
|
||||||
|
)
|
||||||
|
|
||||||
|
return await Promise.all(Object.keys(notesByRoot).map(relay.findNote))
|
||||||
})
|
})
|
||||||
|
|
||||||
const createNotesObservable = () => {
|
onDestroy(unsub)
|
||||||
notes = relay.lq(async () => {
|
|
||||||
const notes = await relay.filterEvents({...filter, since}).reverse().sortBy('created_at')
|
|
||||||
const ancestorIds = concat(notes.map(findRoot), notes.map(findReply)).filter(identity)
|
|
||||||
const ancestors = await relay.filterEvents({kinds: [1], ids: ancestorIds}).toArray()
|
|
||||||
|
|
||||||
const allNotes = uniqBy(prop('id'), notes.concat(ancestors))
|
|
||||||
const notesById = createMap('id', allNotes)
|
|
||||||
const notesByRoot = groupBy(
|
|
||||||
n => {
|
|
||||||
const rootId = findRoot(n)
|
|
||||||
const parentId = findReply(n)
|
|
||||||
|
|
||||||
// Actually dereference the notes in case we weren't able to retrieve them
|
|
||||||
if (notesById[rootId]) {
|
|
||||||
return rootId
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notesById[parentId]) {
|
|
||||||
return parentId
|
|
||||||
}
|
|
||||||
|
|
||||||
return n.id
|
|
||||||
},
|
|
||||||
allNotes
|
|
||||||
)
|
|
||||||
|
|
||||||
return await Promise.all(Object.keys(notesByRoot).map(relay.findNote))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onDestroy(done)
|
|
||||||
</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">
|
||||||
|
@ -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">
|
@ -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})" />
|
||||||
|
Loading…
Reference in New Issue
Block a user