From b552b07c74073b2aeb90b6e60cce219449dbc8f1 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Tue, 12 Nov 2024 17:01:00 +0200 Subject: [PATCH] web/timeline: insert mention when clicking name --- web/src/ui/composer/MessageComposer.tsx | 4 ++++ web/src/ui/roomview/roomcontext.ts | 11 +++++++++++ web/src/ui/timeline/TimelineEvent.css | 2 ++ web/src/ui/timeline/TimelineEvent.tsx | 6 +++++- 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/web/src/ui/composer/MessageComposer.tsx b/web/src/ui/composer/MessageComposer.tsx index 323fbed..48ff98a 100644 --- a/web/src/ui/composer/MessageComposer.tsx +++ b/web/src/ui/composer/MessageComposer.tsx @@ -90,6 +90,10 @@ const MessageComposer = () => { const textRows = useRef(1) const typingSentAt = useRef(0) const replyToEvt = useRoomEvent(room, state.replyTo) + roomCtx.insertText = useCallback((text: string) => { + textInput.current?.focus() + document.execCommand("insertText", false, text) + }, []) roomCtx.setReplyTo = useCallback((evt: EventID | null) => { setState({ replyTo: evt }) textInput.current?.focus() diff --git a/web/src/ui/roomview/roomcontext.ts b/web/src/ui/roomview/roomcontext.ts index 0fa7557..13c49e9 100644 --- a/web/src/ui/roomview/roomcontext.ts +++ b/web/src/ui/roomview/roomcontext.ts @@ -17,6 +17,7 @@ import { RefObject, createContext, createRef, use } from "react" import { RoomStateStore } from "@/api/statestore" import { EventID, EventRowID, MemDBEvent } from "@/api/types" import { NonNullCachedEventDispatcher } from "@/util/eventdispatcher.ts" +import { escapeMarkdown } from "@/util/markdown.ts" const noop = (name: string) => () => { console.warn(`${name} called before initialization`) @@ -26,6 +27,7 @@ export class RoomContextData { public timelineBottomRef: RefObject = createRef() public setReplyTo: (eventID: EventID | null) => void = noop("setReplyTo") public setEditing: (evt: MemDBEvent | null) => void = noop("setEditing") + public insertText: (text: string) => void = noop("insertText") public isEditing = new NonNullCachedEventDispatcher(false) public ownMessages: EventRowID[] = [] public scrolledToBottom = true @@ -37,6 +39,15 @@ export class RoomContextData { this.timelineBottomRef.current?.scrollIntoView() } } + + appendMentionToComposer = (evt: React.MouseEvent) => { + const targetUser = evt.currentTarget.getAttribute("data-target-user") + if (!targetUser) { + return + } + const targetUserName = evt.currentTarget.innerText + this.insertText(`[${escapeMarkdown(targetUserName)}](https://matrix.to/#/${encodeURIComponent(targetUser)}) `) + } } export const RoomContext = createContext(undefined) diff --git a/web/src/ui/timeline/TimelineEvent.css b/web/src/ui/timeline/TimelineEvent.css index b16cefb..821f229 100644 --- a/web/src/ui/timeline/TimelineEvent.css +++ b/web/src/ui/timeline/TimelineEvent.css @@ -52,6 +52,8 @@ div.timeline-event { > span.event-sender { font-weight: bold; + user-select: none; + cursor: var(--clickable-cursor); } > span.event-time, > span.event-edited { diff --git a/web/src/ui/timeline/TimelineEvent.tsx b/web/src/ui/timeline/TimelineEvent.tsx index 73bc985..810c8bd 100644 --- a/web/src/ui/timeline/TimelineEvent.tsx +++ b/web/src/ui/timeline/TimelineEvent.tsx @@ -120,7 +120,11 @@ const TimelineEvent = ({ evt, prevEvt, disableMenu }: TimelineEventProps) => { /> } {!eventTimeOnly ?
- + {memberEvtContent?.displayname || evt.sender} {shortTime}