feat: add room mentions and clickable room/relay refs

This commit is contained in:
2026-04-04 16:48:29 +05:30
parent 9311cab3b2
commit bf2dfdc2d0
11 changed files with 595 additions and 3 deletions
+61 -2
View File
@@ -14,12 +14,20 @@ import {
getWotGraph,
} from "@welshman/app"
import type {FileAttributes} from "@welshman/editor"
import {Editor, MentionSuggestion, WelshmanExtension, editorProps} from "@welshman/editor"
import {
Editor,
MentionSuggestion,
TippySuggestion,
WelshmanExtension,
editorProps,
} from "@welshman/editor"
import {escapeHtml} from "@lib/html"
import {makeMentionNodeView} from "@app/editor/MentionNodeView"
import ProfileSuggestion from "@app/editor/ProfileSuggestion.svelte"
import {RoomReferenceExtension} from "@app/editor/RoomReferenceExtension"
import RoomSuggestion from "@app/editor/RoomSuggestion.svelte"
import {uploadFile} from "@app/core/commands"
import {deriveSpaceMembers} from "@app/core/state"
import {deriveSpaceMembers, splitRoomId, userSpaceUrls, roomsByUrl} from "@app/core/state"
import {pushToast} from "@app/util/toast"
export const makeEditor = async ({
@@ -82,12 +90,40 @@ export const makeEditor = async ({
},
)
const roomReferenceSearch = derived(
[throttled(800, userSpaceUrls), throttled(800, roomsByUrl)],
([$userSpaceUrls, $roomsByUrl]) => {
const options: Array<{id: string; name: string; h: string; url: string}> = []
for (const roomUrl of $userSpaceUrls) {
for (const room of $roomsByUrl.get(roomUrl) || []) {
options.push({
id: room.id,
name: room.name || "",
h: room.h,
url: roomUrl,
})
}
}
return createSearch(options, {
getValue: item => item.id,
fuseOptions: {
keys: ["name", "h", "url"],
threshold: 0.3,
shouldSort: false,
},
})
},
)
return new Editor({
content: escapeHtml(content),
autofocus,
editorProps,
element: document.createElement("div"),
extensions: [
RoomReferenceExtension,
WelshmanExtension.configure({
submit,
extensions: {
@@ -129,6 +165,29 @@ export const makeEditor = async ({
mount(ProfileSuggestion, {target, props: {value, url}})
return target
},
}),
TippySuggestion({
char: "~",
name: "roomref",
editor: (this as any).editor,
search: (term: string) => get(roomReferenceSearch).searchValues(term),
updateSignal: roomReferenceSearch,
select: (id: string, props) => {
const [roomUrl, h] = splitRoomId(id)
if (!roomUrl || !h) {
return
}
return props.command({url: roomUrl, h})
},
createSuggestion: (value: string) => {
const target = document.createElement("div")
mount(RoomSuggestion, {target, props: {value}})
return target
},
}),