diff --git a/web/src/api/types/mxtypes.ts b/web/src/api/types/mxtypes.ts
index 9e8fc8d..469d5f9 100644
--- a/web/src/api/types/mxtypes.ts
+++ b/web/src/api/types/mxtypes.ts
@@ -62,3 +62,43 @@ export interface MemberEventContent {
avatar_url?: ContentURI
reason?: string
}
+
+export interface BaseMessageEventContent {
+ msgtype: string
+ body: string
+ formatted_body?: string
+ format?: "org.matrix.custom.html"
+}
+
+export interface TextMessageEventContent extends BaseMessageEventContent {
+ msgtype: "m.text" | "m.notice" | "m.emote"
+}
+
+export interface MediaMessageEventContent extends BaseMessageEventContent {
+ msgtype: "m.image" | "m.file" | "m.audio" | "m.video"
+ filename?: string
+ url?: ContentURI
+ file?: {
+ url: ContentURI
+ k: string
+ v: "v2"
+ ext: true
+ alg: "A256CTR"
+ key_ops: string[]
+ kty: "oct"
+ }
+ info?: {
+ mimetype?: string
+ size?: number
+ w?: number
+ h?: number
+ duration?: number
+ }
+}
+
+export interface LocationMessageEventContent extends BaseMessageEventContent {
+ msgtype: "m.location"
+ geo_uri: string
+}
+
+export type MessageEventContent = TextMessageEventContent | MediaMessageEventContent | LocationMessageEventContent
diff --git a/web/src/ui/timeline/ReplyBody.css b/web/src/ui/timeline/ReplyBody.css
new file mode 100644
index 0000000..7c11623
--- /dev/null
+++ b/web/src/ui/timeline/ReplyBody.css
@@ -0,0 +1,33 @@
+blockquote.reply-body {
+ margin: 0;
+ border-left: 2px solid #aaa;
+ padding: .25rem .5rem;
+
+ &:hover {
+ border-color: black;
+
+ > div.message-text {
+ color: black;
+ }
+ }
+
+ > div.message-text {
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ color: #666;
+
+ }
+
+ > div.reply-sender {
+ display: flex;
+ align-items: center;
+
+ > div.sender-avatar {
+ width: 1rem;
+ height: 1rem;
+ margin-right: .25rem;
+ }
+ }
+}
diff --git a/web/src/ui/timeline/ReplyBody.tsx b/web/src/ui/timeline/ReplyBody.tsx
new file mode 100644
index 0000000..4588b8a
--- /dev/null
+++ b/web/src/ui/timeline/ReplyBody.tsx
@@ -0,0 +1,52 @@
+// gomuks - A Matrix client written in Go.
+// Copyright (C) 2024 Tulir Asokan
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see
+ Reply to {eventID} ++ } + const memberEvt = room.getStateEvent("m.room.member", evt.sender) + const memberEvtContent = memberEvt?.content as MemberEventContent | undefined + return
++} + +export default ReplyBody diff --git a/web/src/ui/timeline/TimelineEvent.css b/web/src/ui/timeline/TimelineEvent.css index 259b58c..e543506 100644 --- a/web/src/ui/timeline/TimelineEvent.css +++ b/web/src/ui/timeline/TimelineEvent.css @@ -93,16 +93,8 @@ div.timeline-event { margin-top: 0; > div.sender-avatar { - margin-top: 0; width: 1.5rem; height: 1.5rem; - display: flex; - align-items: center; - - > img { - width: 1rem; - height: 1rem; - } } > div.event-sender-and-time { @@ -115,6 +107,17 @@ div.timeline-event { } } +div.hidden-event > div.sender-avatar, blockquote.reply-body > div.reply-sender > div.sender-avatar { + margin-top: 0; + display: flex; + align-items: center; + + > img { + width: 1rem; + height: 1rem; + } +} + div.date-separator { display: flex; align-items: center; @@ -146,6 +149,10 @@ div.redacted-body, div.decryption-pending-body { } } +div.plaintext-body { + white-space: pre-wrap; +} + div.html-body { overflow: hidden; img[data-mx-emoticon] { diff --git a/web/src/ui/timeline/TimelineEvent.tsx b/web/src/ui/timeline/TimelineEvent.tsx index dcf6d6e..0d23a6c 100644 --- a/web/src/ui/timeline/TimelineEvent.tsx +++ b/web/src/ui/timeline/TimelineEvent.tsx @@ -18,9 +18,10 @@ import { getAvatarURL } from "../../api/media.ts" import { RoomStateStore } from "../../api/statestore.ts" import { MemDBEvent, MemberEventContent } from "../../api/types" import { ClientContext } from "../ClientContext.ts" +import ReplyBody from "./ReplyBody.tsx" import EncryptedBody from "./content/EncryptedBody.tsx" import HiddenEvent from "./content/HiddenEvent.tsx" -import MessageBody from "./content/MessageBody.tsx" +import { MediaMessageBody, TextMessageBody, UnknownMessageBody } from "./content/MessageBody.tsx" import RedactedBody from "./content/RedactedBody.tsx" import { EventContentProps } from "./content/props.ts" import ErrorIcon from "../../icons/error.svg?react" @@ -44,7 +45,22 @@ function getBodyType(evt: MemDBEvent): React.FunctionComponent++++ {memberEvtContent?.displayname ?? evt.sender} ++
+
{`{ "type": "${event.type}", "content": { "msgtype": "${content.msgtype}" } }`}
+ return {`{ "type": "${event.type}", "content": { "msgtype": "${content.msgtype}" } }`}
+}