Bump welshman, use new message kind

This commit is contained in:
Jon Staab 2026-09-14 16:34:45 -07:00
parent 75451b71e3
commit 7dffabd9d9
5 changed files with 49 additions and 54 deletions

View file

@ -88,16 +88,16 @@
"@types/throttle-debounce": "^5.0.2", "@types/throttle-debounce": "^5.0.2",
"@vite-pwa/assets-generator": "^1.0.2", "@vite-pwa/assets-generator": "^1.0.2",
"@vite-pwa/sveltekit": "^1.1.0", "@vite-pwa/sveltekit": "^1.1.0",
"@welshman/app": "^0.10.7", "@welshman/app": "^0.10.8",
"@welshman/content": "^0.10.7", "@welshman/content": "^0.10.8",
"@welshman/domain": "^0.10.7", "@welshman/domain": "^0.10.8",
"@welshman/editor": "^0.10.7", "@welshman/editor": "^0.10.8",
"@welshman/feeds": "^0.10.7", "@welshman/feeds": "^0.10.8",
"@welshman/lib": "^0.10.7", "@welshman/lib": "^0.10.8",
"@welshman/net": "^0.10.7", "@welshman/net": "^0.10.8",
"@welshman/signer": "^0.10.7", "@welshman/signer": "^0.10.8",
"@welshman/store": "^0.10.7", "@welshman/store": "^0.10.8",
"@welshman/util": "^0.10.7", "@welshman/util": "^0.10.8",
"cheerio": "^1.2.0", "cheerio": "^1.2.0",
"compressorjs-next": "^1.1.2", "compressorjs-next": "^1.1.2",
"dompurify": "^3.4.13", "dompurify": "^3.4.13",

Binary file not shown.

View file

@ -9,7 +9,8 @@
import {now, ifLet, ago, MINUTE} from "@welshman/lib" import {now, ifLet, ago, MINUTE} from "@welshman/lib"
import type {Maybe} from "@welshman/lib" import type {Maybe} from "@welshman/lib"
import type {TrustedEvent, EventContent} from "@welshman/util" import type {TrustedEvent, EventContent} from "@welshman/util"
import {makeEvent, MESSAGE, RELAY_ADD_MEMBER, ROOM_ADD_MEMBER} from "@welshman/util" import {relay, stamp, MESSAGE, RELAY_ADD_MEMBER, ROOM_ADD_MEMBER} from "@welshman/util"
import {Message} from "@welshman/domain"
import {MembershipStatus} from "@welshman/app" import {MembershipStatus} from "@welshman/app"
import AltArrowDown from "@assets/icons/alt-arrow-down.svg?dataurl" import AltArrowDown from "@assets/icons/alt-arrow-down.svg?dataurl"
import ClockCircle from "@assets/icons/clock-circle.svg?dataurl" import ClockCircle from "@assets/icons/clock-circle.svg?dataurl"
@ -32,11 +33,10 @@
import ThunkToast from "@app/components/ThunkToast.svelte" import ThunkToast from "@app/components/ThunkToast.svelte"
import VideoCallContent from "@app/components/VideoCallContent.svelte" import VideoCallContent from "@app/components/VideoCallContent.svelte"
import CallControlBar from "@app/components/CallControlBar.svelte" import CallControlBar from "@app/components/CallControlBar.svelte"
import {deletes, relays, rooms, thunks, user} from "@app/core" import {deletes, relays, rooms, thunks, user, writer} from "@app/core"
import {joinRoom, leaveRoom} from "@app/access" import {joinRoom, leaveRoom} from "@app/access"
import {CallState, callTargetRoom, callState, VideoCallLayout, videoCallLayout} from "@app/call" import {CallState, callTargetRoom, callState, VideoCallLayout, videoCallLayout} from "@app/call"
import { import {
PROTECTED,
RoomType, RoomType,
deriveUserRoomMembershipStatus, deriveUserRoomMembershipStatus,
getRoomType, getRoomType,
@ -177,27 +177,15 @@
} }
try { try {
if (h) {
tags.push(["h", h])
}
const protect = await shouldProtect const protect = await shouldProtect
if (protect) {
tags.push(PROTECTED)
}
let template: EventContent & {created_at?: number} = {content, tags}
if (eventToEdit) { if (eventToEdit) {
// Don't do anything if message hasn't changed // Don't do anything if message hasn't changed
if (eventToEdit.content === content) { if (eventToEdit.content === content) {
return return
} }
// Delete previous message, to be republished with same timestamp // Delete the previous message, to be republished below with the same timestamp
template.created_at = eventToEdit.created_at
const command = await $deletes.deleteEvent($state.snapshot(eventToEdit), w => const command = await $deletes.deleteEvent($state.snapshot(eventToEdit), w =>
w.setProtected(protect), w.setProtected(protect),
) )
@ -205,17 +193,30 @@
command.publishToRelays([url]) command.publishToRelays([url])
} }
// A share is a quote rather than a reply, so it goes in the content directly and
// setParent prepends the reply's own reference ahead of it.
if (sharedEvent) { if (sharedEvent) {
template = await prependParent(sharedEvent, template, url) ;({content, tags} = await prependParent(sharedEvent, {content, tags}, url))
}
const eventWriter = writer(Message)
.setContent(content)
.addTags(...tags)
.setProtected(protect)
if (h) {
eventWriter.setRoom(url, h)
} else {
eventWriter.forceRoutes(relay(url))
} }
if (parent) { if (parent) {
template = await prependParent(parent, template, url) eventWriter.setParent(parent)
} }
const thunk = $thunks.publish({ const thunk = $thunks.publish({
relays: [url], relays: [url],
event: makeEvent(MESSAGE, template), event: stamp(await eventWriter.renderTemplate(), eventToEdit?.created_at),
delay: $userSettingsValues.send_delay, delay: $userSettingsValues.send_delay,
}) })

View file

@ -1,24 +1,17 @@
<script lang="ts"> <script lang="ts">
import cx from "classnames" import cx from "classnames"
import {readable} from "svelte/store" import {readable} from "svelte/store"
import { import {now, uniq, displayList, formatTimestampAsTime, formatTimestampAsDate} from "@welshman/lib"
gte,
now,
uniq,
displayList,
formatTimestampAsTime,
formatTimestampAsDate,
} from "@welshman/lib"
import type {TrustedEvent, EventContent} from "@welshman/util" import type {TrustedEvent, EventContent} from "@welshman/util"
import { import {
MESSAGE, MESSAGE,
THREAD, THREAD,
getCommentFiltersForParent, getCommentFiltersForParent,
getIdOrAddress, getIdOrAddress,
matchTag,
tagSpec, tagSpec,
tagValue, tagValue,
} from "@welshman/util" } from "@welshman/util"
import {getContentQuote} from "@welshman/domain"
import {isMobile} from "@lib/html" import {isMobile} from "@lib/html"
import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl" import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl"
import Pen from "@assets/icons/pen.svg?dataurl" import Pen from "@assets/icons/pen.svg?dataurl"
@ -74,11 +67,10 @@
const thunk = $derived($thunks.merge($thunksByEventId.get(event.id) ?? noThunks)) const thunk = $derived($thunks.merge($thunksByEventId.get(event.id) ?? noThunks))
const colorValue = colorFor(event.pubkey) const colorValue = colorFor(event.pubkey)
const qTag = matchTag(tagSpec("q"), event.tags) // A message that is nothing but a reference renders as the event it quotes.
const isQuoteOnly = Boolean( const isQuoteOnly = event.content.trim().split(/\s/).length === 1
gte(qTag?.length, 2) && event.content.trim().match(/^nostr:n(event|addr)1\w+\s*$/), const quote = isQuoteOnly ? getContentQuote(event.content) : undefined
) const innerEvent = quote ? deriveEvent(quote.value, [url]) : readable(undefined)
const innerEvent = isQuoteOnly ? deriveEvent(qTag![1], [url]) : readable(undefined)
const innerComments = $derived( const innerComments = $derived(
$innerEvent ? deriveEventsForUrl(url, getCommentFiltersForParent([$innerEvent])) : readable([]), $innerEvent ? deriveEventsForUrl(url, getCommentFiltersForParent([$innerEvent])) : readable([]),
) )

View file

@ -2,8 +2,9 @@ import * as nip19 from "nostr-tools/nip19"
import {derived, get} from "svelte/store" import {derived, get} from "svelte/store"
import {formatTimestampAsDate, int, sortBy, uniq, MINUTE} from "@welshman/lib" import {formatTimestampAsDate, int, sortBy, uniq, MINUTE} from "@welshman/lib"
import type {Maybe} from "@welshman/lib" import type {Maybe} from "@welshman/lib"
import {MESSAGE, makeEvent, outbox, seen, toNostrURI} from "@welshman/util" import {outbox, relay, seen, toNostrURI} from "@welshman/util"
import type {EventContent, TrustedEvent} from "@welshman/util" import type {EventContent, TrustedEvent} from "@welshman/util"
import {Message} from "@welshman/domain"
import {MembershipStatus, RoomLists, makeRoomKey, createSearch, publish} from "@welshman/app" import {MembershipStatus, RoomLists, makeRoomKey, createSearch, publish} from "@welshman/app"
import type {Room, RoomMeta} from "@welshman/app" import type {Room, RoomMeta} from "@welshman/app"
import { import {
@ -16,6 +17,7 @@ import {
thunks, thunks,
relays, relays,
user, user,
writer,
} from "@app/core" } from "@app/core"
import {deriveUserIsSpaceAdmin} from "@app/management" import {deriveUserIsSpaceAdmin} from "@app/management"
import {makeRoomPath} from "@app/routes" import {makeRoomPath} from "@app/routes"
@ -83,7 +85,7 @@ export const prependParent = async (
const resolver = router.get().resolver const resolver = router.get().resolver
const relays = url ? [url] : await resolver.relays([seen(parent)]) const relays = url ? [url] : await resolver.relays([seen(parent)])
const hint = url ?? (await resolver.relay([outbox(parent.pubkey)])) ?? "" const hint = url ?? (await resolver.relay([outbox(parent.pubkey)])) ?? ""
const nevent = nip19.neventEncode({...parent, relays}) const nevent = nip19.neventEncode({id: parent.id, author: parent.pubkey, relays})
content = toNostrURI(nevent) + "\n\n" + content content = toNostrURI(nevent) + "\n\n" + content
tags = [...tags, ["q", parent.id, hint, parent.pubkey], ["p", parent.pubkey, hint]] tags = [...tags, ["q", parent.id, hint, parent.pubkey], ["p", parent.pubkey, hint]]
@ -105,19 +107,19 @@ export const publishRoomQuote = async ({
protect: boolean protect: boolean
delay?: number delay?: number
}) => { }) => {
const tags: string[][] = [] const eventWriter = writer(Message).setParent(parent).setProtected(protect)
if (h) { if (h) {
tags.push([ROOM, h]) eventWriter.setRoom(url, h)
} else {
eventWriter.forceRoutes(relay(url))
} }
if (protect) { return thunks.get().publish({
tags.push(PROTECTED) relays: [url],
} event: await eventWriter.renderTemplate(),
delay,
const event = makeEvent(MESSAGE, await prependParent(parent, {content: "", tags}, url)) })
return thunks.get().publish({relays: [url], event, delay})
} }
// User // User