web/composer: send thread message when replying in thread

This commit is contained in:
Tulir Asokan 2024-10-22 19:53:10 +03:00
parent 014c8c07a8
commit c4266fbc22
5 changed files with 49 additions and 8 deletions

View file

@ -41,7 +41,7 @@ func (h *HiClient) handleJSONCommand(ctx context.Context, req *JSONCommand) (any
})
case "send_message":
return unmarshalAndCall(req.Data, func(params *sendMessageParams) (*database.Event, error) {
return h.SendMessage(ctx, params.RoomID, params.BaseContent, params.Text, params.ReplyTo, params.Mentions)
return h.SendMessage(ctx, params.RoomID, params.BaseContent, params.Text, params.RelatesTo, params.Mentions)
})
case "send_event":
return unmarshalAndCall(req.Data, func(params *sendEventParams) (*database.Event, error) {
@ -122,7 +122,7 @@ type sendMessageParams struct {
RoomID id.RoomID `json:"room_id"`
BaseContent *event.MessageEventContent `json:"base_content"`
Text string `json:"text"`
ReplyTo id.EventID `json:"reply_to"`
RelatesTo *event.RelatesTo `json:"relates_to"`
Mentions *event.Mentions `json:"mentions"`
}

View file

@ -32,7 +32,14 @@ var (
rainbowWithHTML = goldmark.New(format.Extensions, format.HTMLOptions, goldmark.WithExtensions(rainbow.Extension))
)
func (h *HiClient) SendMessage(ctx context.Context, roomID id.RoomID, base *event.MessageEventContent, text string, replyTo id.EventID, mentions *event.Mentions) (*database.Event, error) {
func (h *HiClient) SendMessage(
ctx context.Context,
roomID id.RoomID,
base *event.MessageEventContent,
text string,
relatesTo *event.RelatesTo,
mentions *event.Mentions,
) (*database.Event, error) {
var content event.MessageEventContent
if strings.HasPrefix(text, "/rainbow ") {
text = strings.TrimPrefix(text, "/rainbow ")
@ -66,8 +73,16 @@ func (h *HiClient) SendMessage(ctx context.Context, roomID id.RoomID, base *even
}
}
}
if replyTo != "" {
content.RelatesTo = (&event.RelatesTo{}).SetReplyTo(replyTo)
if relatesTo != nil {
if relatesTo.Type == event.RelReplace {
contentCopy := content
content = event.MessageEventContent{
NewContent: &contentCopy,
RelatesTo: relatesTo,
}
} else {
content.RelatesTo = relatesTo
}
}
return h.Send(ctx, roomID, event.EventMessage, &content)
}

View file

@ -27,6 +27,7 @@ import type {
RPCEvent,
RawDBEvent,
ReceiptType,
RelatesTo,
ResolveAliasResponse,
RoomAlias,
RoomID,
@ -50,7 +51,7 @@ export interface SendMessageParams {
base_content?: MessageEventContent
text: string
media_path?: string
reply_to?: EventID
relates_to?: RelatesTo
mentions?: Mentions
}

View file

@ -74,12 +74,24 @@ export interface Mentions {
room: boolean
}
export interface RelatesTo {
rel_type?: RelationType
event_id?: EventID
key?: string
is_falling_back?: boolean
"m.in_reply_to"?: {
event_id?: EventID
}
}
export interface BaseMessageEventContent {
msgtype: string
body: string
formatted_body?: string
format?: "org.matrix.custom.html"
"m.mentions"?: Mentions
"m.relates_to"?: RelatesTo
}
export interface TextMessageEventContent extends BaseMessageEventContent {

View file

@ -16,7 +16,7 @@
import React, { use, useCallback, useEffect, useLayoutEffect, useReducer, useRef, useState } from "react"
import { ScaleLoader } from "react-spinners"
import { RoomStateStore, useRoomEvent } from "@/api/statestore"
import type { EventID, MediaMessageEventContent, Mentions, RoomID } from "@/api/types"
import type { EventID, MediaMessageEventContent, Mentions, RelatesTo, RoomID } from "@/api/types"
import useEvent from "@/util/useEvent.ts"
import { ClientContext } from "../ClientContext.ts"
import { ReplyBody } from "../timeline/ReplyBody.tsx"
@ -90,14 +90,27 @@ const MessageComposer = ({ room, scrollToBottomRef, setReplyToRef }: MessageComp
user_ids: [],
room: false,
}
let relates_to: RelatesTo | undefined = undefined
if (replyToEvt) {
mentions.user_ids.push(replyToEvt.sender)
relates_to = {
"m.in_reply_to": {
event_id: replyToEvt.event_id,
},
}
if (replyToEvt.content["m.relates_to"]?.rel_type === "m.thread"
&& typeof replyToEvt.content["m.relates_to"]?.event_id === "string") {
relates_to.rel_type = "m.thread"
relates_to.event_id = replyToEvt.content["m.relates_to"].event_id
// TODO set this to true if replying to the last event in a thread?
relates_to.is_falling_back = false
}
}
client.sendMessage({
room_id: room.roomID,
base_content: state.media ?? undefined,
text: state.text,
reply_to: replyToEvt?.event_id,
relates_to,
mentions,
}).catch(err => window.alert("Failed to send message: " + err))
})