From f130af4edd9bdc3e5d5d77f83ed605f0d99ed2a9 Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Fri, 25 Sep 2026 16:00:58 -0700 Subject: [PATCH] Find a comment's root through reader(Comment).root() instead of three hand-rolled K/A/E parsers --- src/app/feeds.ts | 29 +++++++++++++++++++++++------ src/app/notifications.ts | 8 +++++--- src/app/routes.ts | 25 ++++++++++++++----------- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/app/feeds.ts b/src/app/feeds.ts index 87d070ac..40b95f93 100644 --- a/src/app/feeds.ts +++ b/src/app/feeds.ts @@ -1,6 +1,18 @@ import {derived, get, readable, writable} from "svelte/store" import type {Readable} from "svelte/store" -import {batch, call, int, ms, now, on, sleep, uniqBy, MONTH, YEAR} from "@welshman/lib" +import { + batch, + call, + int, + ms, + now, + on, + removeUndefined, + sleep, + uniqBy, + MONTH, + YEAR, +} from "@welshman/lib" import { COMMENT, DELETE, @@ -17,7 +29,7 @@ import { matchFilters, tagValues, } from "@welshman/util" -import {TimeEvent} from "@welshman/domain" +import {Comment, TimeEvent} from "@welshman/domain" import type {Maybe} from "@welshman/lib" import type {Filter, TrustedEvent} from "@welshman/util" import {mergeRepositoryUpdates} from "@welshman/net" @@ -51,10 +63,15 @@ const mergeSorted = (left: T[], right: T[], compare: (a: T, b: T) => number) } // A NIP-22 comment points at its thread root with `E`/`A`, which is the scope a reply count wants. -const getTargets = ({kind, tags}: TrustedEvent) => - kind === COMMENT - ? [...tagValues(hexTags("E"), tags), ...tagValues(addressTags("A"), tags)] - : [...tagValues(hexTags("e"), tags), ...tagValues(addressTags("a"), tags)] +const getTargets = (event: TrustedEvent) => { + if (event.kind === COMMENT) { + const {id, address} = reader(Comment)(event).root() + + return removeUndefined([id, address]) + } + + return [...tagValues(hexTags("e"), event.tags), ...tagValues(addressTags("a"), event.tags)] +} // A related event may point at a replaceable one by either id or address, so both are keys const getKeys = (event: TrustedEvent) => diff --git a/src/app/notifications.ts b/src/app/notifications.ts index a36dc70f..722206d9 100644 --- a/src/app/notifications.ts +++ b/src/app/notifications.ts @@ -13,10 +13,11 @@ import { makeHttpAuth, makeHttpAuthHeader, } from "@welshman/util" +import {Comment} from "@welshman/domain" import {synced, throttled, withGetter} from "@welshman/store" import {Relays, RoomLists} from "@welshman/app" import {deriveEventsByIdByUrl} from "@app/repository" -import {app, fromApp} from "@app/core" +import {app, fromApp, reader} from "@app/core" import {makeRoomPath, makeSpaceChatPath, makeChatPath, makeContentPath} from "@app/routes" import {CONTENT_KINDS, makeCommentFilter} from "@app/content" import {getIsMuted, notificationSettings, userSettingsValues} from "@app/settings" @@ -185,8 +186,9 @@ const getContentTarget = (event: TrustedEvent) => { } if (event.kind === COMMENT) { - const kind = parseInt(tagValue(tagSpec("K"), event.tags) || "") - const idOrAddress = tagValue(tagSpec("A"), event.tags) || tagValue(tagSpec("E"), event.tags) + const root = reader(Comment)(event).root() + const kind = parseInt(root.kind || "") + const idOrAddress = root.address || root.id if (CONTENT_KINDS.includes(kind) && idOrAddress) { return {kind, idOrAddress} diff --git a/src/app/routes.ts b/src/app/routes.ts index d2db9ad5..29548a4a 100644 --- a/src/app/routes.ts +++ b/src/app/routes.ts @@ -5,6 +5,7 @@ import {identity, tryCatch} from "@welshman/lib" import type {TrustedEvent} from "@welshman/util" import { CLASSIFIED, + COMMENT, EVENT_TIME, LONG_FORM, MESSAGE, @@ -19,7 +20,8 @@ import { tagValue, tagValues, } from "@welshman/util" -import {app, messagingRelayLists, user} from "@app/core" +import {Comment} from "@welshman/domain" +import {app, messagingRelayLists, reader, user} from "@app/core" import {makeChatId} from "@app/chats" import {entityLink, PLATFORM_URL, PLATFORM_RELAYS} from "@app/env" import {decodeRelay, encodeRelay} from "@app/relays" @@ -219,19 +221,20 @@ export const makeEventPath = (event: TrustedEvent, urls: string[]) => { return path } - const parentKind = tagValue(tagSpec("K"), event.tags) - const parentIdOrAddress = - tagValue(tagSpec("A"), event.tags) ?? tagValue(tagSpec("E"), event.tags) + if (event.kind === COMMENT) { + const root = reader(Comment)(event).root() + const rootIdOrAddress = root.address ?? root.id - if (parentKind && parentIdOrAddress) { - if (parseInt(parentKind) === MESSAGE) { - return makeMessagePath(url, event) - } + if (root.kind && rootIdOrAddress) { + if (parseInt(root.kind) === MESSAGE) { + return makeMessagePath(url, event) + } - const parentPath = makeContentPath(url, parseInt(parentKind), parentIdOrAddress) + const rootPath = makeContentPath(url, parseInt(root.kind), rootIdOrAddress) - if (parentPath) { - return parentPath + if (rootPath) { + return rootPath + } } } }