mirror of
https://github.com/tulir/gomuks.git
synced 2025-04-20 10:33:41 -05:00
web/timeline: fix rendering replies to non-message events
This commit is contained in:
parent
d73cf4d863
commit
e1c937849e
3 changed files with 58 additions and 46 deletions
|
@ -18,7 +18,7 @@ import { getAvatarURL } from "@/api/media.ts"
|
||||||
import { RoomStateStore, useRoomEvent } from "@/api/statestore"
|
import { RoomStateStore, useRoomEvent } from "@/api/statestore"
|
||||||
import type { EventID, MemDBEvent, MemberEventContent } from "@/api/types"
|
import type { EventID, MemDBEvent, MemberEventContent } from "@/api/types"
|
||||||
import { ClientContext } from "../ClientContext.ts"
|
import { ClientContext } from "../ClientContext.ts"
|
||||||
import { TextMessageBody } from "./content/MessageBody.tsx"
|
import getBodyType from "./content/getBodyType.ts"
|
||||||
import CloseButton from "@/icons/close.svg?react"
|
import CloseButton from "@/icons/close.svg?react"
|
||||||
import "./ReplyBody.css"
|
import "./ReplyBody.css"
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ const onClickReply = (evt: React.MouseEvent) => {
|
||||||
export const ReplyBody = ({ room, event, onClose }: ReplyBodyProps) => {
|
export const ReplyBody = ({ room, event, onClose }: ReplyBodyProps) => {
|
||||||
const memberEvt = room.getStateEvent("m.room.member", event.sender)
|
const memberEvt = room.getStateEvent("m.room.member", event.sender)
|
||||||
const memberEvtContent = memberEvt?.content as MemberEventContent | undefined
|
const memberEvtContent = memberEvt?.content as MemberEventContent | undefined
|
||||||
|
const BodyType = getBodyType(event, true)
|
||||||
return <blockquote
|
return <blockquote
|
||||||
data-reply-to={event.event_id}
|
data-reply-to={event.event_id}
|
||||||
className={`reply-body ${onClose ? "composer" : ""}`}
|
className={`reply-body ${onClose ? "composer" : ""}`}
|
||||||
|
@ -82,6 +83,6 @@ export const ReplyBody = ({ room, event, onClose }: ReplyBodyProps) => {
|
||||||
<span className="event-sender">{memberEvtContent?.displayname || event.sender}</span>
|
<span className="event-sender">{memberEvtContent?.displayname || event.sender}</span>
|
||||||
{onClose && <button className="close-reply" onClick={onClose}><CloseButton/></button>}
|
{onClose && <button className="close-reply" onClick={onClose}><CloseButton/></button>}
|
||||||
</div>
|
</div>
|
||||||
<TextMessageBody room={room} event={event}/>
|
<BodyType room={room} event={event}/>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,9 @@ import { isEventID } from "@/util/validation.ts"
|
||||||
import { ClientContext } from "../ClientContext.ts"
|
import { ClientContext } from "../ClientContext.ts"
|
||||||
import { LightboxContext } from "../Lightbox.tsx"
|
import { LightboxContext } from "../Lightbox.tsx"
|
||||||
import { ReplyIDBody } from "./ReplyBody.tsx"
|
import { ReplyIDBody } from "./ReplyBody.tsx"
|
||||||
import EncryptedBody from "./content/EncryptedBody.tsx"
|
|
||||||
import HiddenEvent from "./content/HiddenEvent.tsx"
|
import HiddenEvent from "./content/HiddenEvent.tsx"
|
||||||
import MemberBody from "./content/MemberBody.tsx"
|
import MemberBody from "./content/MemberBody.tsx"
|
||||||
import { MediaMessageBody, TextMessageBody, UnknownMessageBody } from "./content/MessageBody.tsx"
|
import getBodyType from "./content/getBodyType.ts"
|
||||||
import RedactedBody from "./content/RedactedBody.tsx"
|
|
||||||
import { EventContentProps } from "./content/props.ts"
|
import { EventContentProps } from "./content/props.ts"
|
||||||
import ErrorIcon from "../../icons/error.svg?react"
|
import ErrorIcon from "../../icons/error.svg?react"
|
||||||
import PendingIcon from "../../icons/pending.svg?react"
|
import PendingIcon from "../../icons/pending.svg?react"
|
||||||
|
@ -39,47 +37,6 @@ export interface TimelineEventProps {
|
||||||
setReplyToRef: React.RefObject<(evt: EventID | null) => void>
|
setReplyToRef: React.RefObject<(evt: EventID | null) => void>
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBodyType(evt: MemDBEvent): React.FunctionComponent<EventContentProps> {
|
|
||||||
if (evt.relation_type === "m.replace") {
|
|
||||||
return HiddenEvent
|
|
||||||
}
|
|
||||||
switch (evt.type) {
|
|
||||||
case "m.room.message":
|
|
||||||
if (evt.redacted_by) {
|
|
||||||
return RedactedBody
|
|
||||||
}
|
|
||||||
switch (evt.content.msgtype) {
|
|
||||||
case "m.text":
|
|
||||||
case "m.notice":
|
|
||||||
case "m.emote":
|
|
||||||
return TextMessageBody
|
|
||||||
case "m.image":
|
|
||||||
case "m.video":
|
|
||||||
case "m.audio":
|
|
||||||
case "m.file":
|
|
||||||
return MediaMessageBody
|
|
||||||
case "m.location":
|
|
||||||
// return LocationMessageBody
|
|
||||||
// fallthrough
|
|
||||||
default:
|
|
||||||
return UnknownMessageBody
|
|
||||||
}
|
|
||||||
case "m.sticker":
|
|
||||||
if (evt.redacted_by) {
|
|
||||||
return RedactedBody
|
|
||||||
}
|
|
||||||
return MediaMessageBody
|
|
||||||
case "m.room.encrypted":
|
|
||||||
if (evt.redacted_by) {
|
|
||||||
return RedactedBody
|
|
||||||
}
|
|
||||||
return EncryptedBody
|
|
||||||
case "m.room.member":
|
|
||||||
return MemberBody
|
|
||||||
}
|
|
||||||
return HiddenEvent
|
|
||||||
}
|
|
||||||
|
|
||||||
const fullTimeFormatter = new Intl.DateTimeFormat("en-GB", { dateStyle: "full", timeStyle: "medium" })
|
const fullTimeFormatter = new Intl.DateTimeFormat("en-GB", { dateStyle: "full", timeStyle: "medium" })
|
||||||
const dateFormatter = new Intl.DateTimeFormat("en-GB", { dateStyle: "full" })
|
const dateFormatter = new Intl.DateTimeFormat("en-GB", { dateStyle: "full" })
|
||||||
const formatShortTime = (time: Date) =>
|
const formatShortTime = (time: Date) =>
|
||||||
|
|
54
web/src/ui/timeline/content/getBodyType.ts
Normal file
54
web/src/ui/timeline/content/getBodyType.ts
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import React from "react"
|
||||||
|
import { MemDBEvent } from "@/api/types"
|
||||||
|
import EncryptedBody from "./EncryptedBody.tsx"
|
||||||
|
import HiddenEvent from "./HiddenEvent.tsx"
|
||||||
|
import MemberBody from "./MemberBody.tsx"
|
||||||
|
import { MediaMessageBody, TextMessageBody, UnknownMessageBody } from "./MessageBody.tsx"
|
||||||
|
import RedactedBody from "./RedactedBody.tsx"
|
||||||
|
import { EventContentProps } from "./props.ts"
|
||||||
|
|
||||||
|
export default function getBodyType(evt: MemDBEvent, forReply = false): React.FunctionComponent<EventContentProps> {
|
||||||
|
if (evt.relation_type === "m.replace") {
|
||||||
|
return HiddenEvent
|
||||||
|
}
|
||||||
|
switch (evt.type) {
|
||||||
|
case "m.room.message":
|
||||||
|
if (evt.redacted_by) {
|
||||||
|
return RedactedBody
|
||||||
|
}
|
||||||
|
switch (evt.content.msgtype) {
|
||||||
|
case "m.text":
|
||||||
|
case "m.notice":
|
||||||
|
case "m.emote":
|
||||||
|
return TextMessageBody
|
||||||
|
case "m.image":
|
||||||
|
case "m.video":
|
||||||
|
case "m.audio":
|
||||||
|
case "m.file":
|
||||||
|
if (forReply) {
|
||||||
|
return TextMessageBody
|
||||||
|
}
|
||||||
|
return MediaMessageBody
|
||||||
|
case "m.location":
|
||||||
|
// return LocationMessageBody
|
||||||
|
// fallthrough
|
||||||
|
default:
|
||||||
|
return UnknownMessageBody
|
||||||
|
}
|
||||||
|
case "m.sticker":
|
||||||
|
if (evt.redacted_by) {
|
||||||
|
return RedactedBody
|
||||||
|
} else if (forReply) {
|
||||||
|
return TextMessageBody
|
||||||
|
}
|
||||||
|
return MediaMessageBody
|
||||||
|
case "m.room.encrypted":
|
||||||
|
if (evt.redacted_by) {
|
||||||
|
return RedactedBody
|
||||||
|
}
|
||||||
|
return EncryptedBody
|
||||||
|
case "m.room.member":
|
||||||
|
return MemberBody
|
||||||
|
}
|
||||||
|
return HiddenEvent
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue