Add deriveLatestEvent for ProfileBadges
This commit is contained in:
parent
3bf3927896
commit
8cb89f362c
2 changed files with 83 additions and 19 deletions
|
|
@ -1,11 +1,11 @@
|
|||
<script lang="ts">
|
||||
import {onMount} from "svelte"
|
||||
import {formatTimestampRelative} from "@welshman/lib"
|
||||
import {NOTE, ROOMS, COMMENT, MESSAGE, outbox} from "@welshman/util"
|
||||
import {NOTE, COMMENT, MESSAGE} from "@welshman/util"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import ProfileSpaces from "@app/components/ProfileSpaces.svelte"
|
||||
import {network, relayLists, roomLists, router} from "@app/core"
|
||||
import {deriveEvents} from "@app/repository"
|
||||
import {network, roomLists} from "@app/core"
|
||||
import {deriveLatestEvent} from "@app/repository"
|
||||
import {goToEvent} from "@app/routes"
|
||||
import {pushModal} from "@app/modal"
|
||||
|
||||
|
|
@ -16,31 +16,23 @@
|
|||
|
||||
const {pubkey, url}: Props = $props()
|
||||
|
||||
const events = deriveEvents([{authors: [pubkey], limit: 1}])
|
||||
const latest = deriveLatestEvent(pubkey)
|
||||
|
||||
const spaceUrls = $roomLists.urls(pubkey).$
|
||||
|
||||
const viewEvent = () => goToEvent($events[0]!)
|
||||
const viewEvent = () => goToEvent($latest!)
|
||||
|
||||
const openSpaces = () => pushModal(ProfileSpaces, {pubkey, url})
|
||||
|
||||
onMount(async () => {
|
||||
await $relayLists.load(pubkey)
|
||||
|
||||
$network.load({
|
||||
filters: [
|
||||
{authors: [pubkey], kinds: [ROOMS]},
|
||||
{authors: [pubkey], limit: 1, kinds: [NOTE, COMMENT, MESSAGE]},
|
||||
],
|
||||
relays: await $router.resolver.relays([outbox(pubkey)]),
|
||||
})
|
||||
onMount(() => {
|
||||
$network.loadUsingOutbox(pubkey, {limit: 1, kinds: [NOTE, COMMENT, MESSAGE]})
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{#if $events.length > 0}
|
||||
{#if $latest}
|
||||
<Button onclick={viewEvent} class="badge badge-neutral">
|
||||
Last active {formatTimestampRelative($events[0].created_at)}
|
||||
Last active {formatTimestampRelative($latest.created_at)}
|
||||
</Button>
|
||||
{/if}
|
||||
{#if $spaceUrls.length > 0}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import {derived} from "svelte/store"
|
||||
import {filter, spec} from "@welshman/lib"
|
||||
import {derived, readable} from "svelte/store"
|
||||
import type {Unsubscriber} from "svelte/store"
|
||||
import {filter, first, on, spec} from "@welshman/lib"
|
||||
import type {Maybe} from "@welshman/lib"
|
||||
import {sortEventsDesc} from "@welshman/util"
|
||||
import type {Filter, TrustedEvent} from "@welshman/util"
|
||||
import * as store from "@welshman/store"
|
||||
import {Network, Relays} from "@welshman/app"
|
||||
|
|
@ -61,3 +64,72 @@ export const deriveRelaySignedEvents = (url: string, filters: Filter[] = [{}]) =
|
|||
[fromApp($app => $app.use(Relays).one(url)), deriveEventsForUrl(url, filters)],
|
||||
([$relay, $events]) => filter(spec({pubkey: $relay?.self}), $events as TrustedEvent[]),
|
||||
)
|
||||
|
||||
// The most recent event held from one author.
|
||||
|
||||
const latestByPubkey = new Map<string, Maybe<TrustedEvent>>()
|
||||
|
||||
const latestSubscribers = new Map<string, Set<(event: Maybe<TrustedEvent>) => void>>()
|
||||
|
||||
let latestUnsubscriber: Maybe<Unsubscriber>
|
||||
|
||||
const readLatest = (pubkey: string) =>
|
||||
first(sortEventsDesc(app.get().repository.query([{authors: [pubkey]}])))
|
||||
|
||||
export const deriveLatestEvent = (pubkey: string) =>
|
||||
readable<Maybe<TrustedEvent>>(undefined, set => {
|
||||
let subscribers = latestSubscribers.get(pubkey)
|
||||
|
||||
if (!subscribers) {
|
||||
subscribers = new Set()
|
||||
latestSubscribers.set(pubkey, subscribers)
|
||||
latestByPubkey.set(pubkey, readLatest(pubkey))
|
||||
}
|
||||
|
||||
subscribers.add(set)
|
||||
set(latestByPubkey.get(pubkey))
|
||||
|
||||
latestUnsubscriber ??= on(app.get().repository, "update", ({added, removed}) => {
|
||||
const touched = new Set<string>()
|
||||
|
||||
for (const event of added) {
|
||||
if (latestSubscribers.has(event.pubkey)) {
|
||||
const current = latestByPubkey.get(event.pubkey)
|
||||
|
||||
if (!current || event.created_at > current.created_at) {
|
||||
latestByPubkey.set(event.pubkey, event)
|
||||
touched.add(event.pubkey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A removal can take the very event a row is showing, so that author has to be looked up
|
||||
// again rather than just dropped
|
||||
for (const [author, event] of latestByPubkey) {
|
||||
if (event && removed.has(event.id)) {
|
||||
latestByPubkey.set(author, readLatest(author))
|
||||
touched.add(author)
|
||||
}
|
||||
}
|
||||
|
||||
for (const author of touched) {
|
||||
for (const subscriber of latestSubscribers.get(author) || []) {
|
||||
subscriber(latestByPubkey.get(author))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return () => {
|
||||
subscribers.delete(set)
|
||||
|
||||
if (subscribers.size === 0) {
|
||||
latestSubscribers.delete(pubkey)
|
||||
latestByPubkey.delete(pubkey)
|
||||
|
||||
if (latestSubscribers.size === 0) {
|
||||
latestUnsubscriber?.()
|
||||
latestUnsubscriber = undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue