diff --git a/src/app/components/ProfileBadges.svelte b/src/app/components/ProfileBadges.svelte
index 45cac751..13a96b0e 100644
--- a/src/app/components/ProfileBadges.svelte
+++ b/src/app/components/ProfileBadges.svelte
@@ -1,11 +1,11 @@
- {#if $events.length > 0}
+ {#if $latest}
{/if}
{#if $spaceUrls.length > 0}
diff --git a/src/app/repository.ts b/src/app/repository.ts
index 8c2ef850..35ea1202 100644
--- a/src/app/repository.ts
+++ b/src/app/repository.ts
@@ -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>()
+
+const latestSubscribers = new Map) => void>>()
+
+let latestUnsubscriber: Maybe
+
+const readLatest = (pubkey: string) =>
+ first(sortEventsDesc(app.get().repository.query([{authors: [pubkey]}])))
+
+export const deriveLatestEvent = (pubkey: string) =>
+ readable>(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()
+
+ 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
+ }
+ }
+ }
+ })