mirror of
https://github.com/tulir/gomuks.git
synced 2025-04-19 18:13:41 -05:00
web/timeline: mark thread replies
This commit is contained in:
parent
c4266fbc22
commit
082e5642aa
4 changed files with 24 additions and 7 deletions
|
@ -255,7 +255,12 @@ const MessageComposer = ({ room, scrollToBottomRef, setReplyToRef }: MessageComp
|
||||||
setState={setState}
|
setState={setState}
|
||||||
setAutocomplete={setAutocomplete}
|
setAutocomplete={setAutocomplete}
|
||||||
/></div>}
|
/></div>}
|
||||||
{replyToEvt && <ReplyBody room={room} event={replyToEvt} onClose={closeReply}/>}
|
{replyToEvt && <ReplyBody
|
||||||
|
room={room}
|
||||||
|
event={replyToEvt}
|
||||||
|
onClose={closeReply}
|
||||||
|
isThread={replyToEvt.content["m.relates_to"]?.rel_type === "m.thread"}
|
||||||
|
/>}
|
||||||
{loadingMedia && <div className="composer-media"><ScaleLoader/></div>}
|
{loadingMedia && <div className="composer-media"><ScaleLoader/></div>}
|
||||||
{state.media && <ComposerMedia content={state.media} clearMedia={clearMedia}/>}
|
{state.media && <ComposerMedia content={state.media} clearMedia={clearMedia}/>}
|
||||||
<div className="input-area">
|
<div className="input-area">
|
||||||
|
|
|
@ -27,6 +27,12 @@ blockquote.reply-body {
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.thread > div.reply-sender > span.event-sender::after {
|
||||||
|
content: " (thread)";
|
||||||
|
font-size: .75rem;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
> div.reply-sender {
|
> div.reply-sender {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -25,15 +25,17 @@ import "./ReplyBody.css"
|
||||||
interface ReplyBodyProps {
|
interface ReplyBodyProps {
|
||||||
room: RoomStateStore
|
room: RoomStateStore
|
||||||
event: MemDBEvent
|
event: MemDBEvent
|
||||||
|
isThread: boolean
|
||||||
onClose?: (evt: React.MouseEvent) => void
|
onClose?: (evt: React.MouseEvent) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ReplyIDBodyProps {
|
interface ReplyIDBodyProps {
|
||||||
room: RoomStateStore
|
room: RoomStateStore
|
||||||
eventID: EventID
|
eventID: EventID
|
||||||
|
isThread: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ReplyIDBody = ({ room, eventID }: ReplyIDBodyProps) => {
|
export const ReplyIDBody = ({ room, eventID, isThread }: ReplyIDBodyProps) => {
|
||||||
const event = useRoomEvent(room, eventID)
|
const event = useRoomEvent(room, eventID)
|
||||||
if (!event) {
|
if (!event) {
|
||||||
// This caches whether the event is requested or not, so it doesn't need to be wrapped in an effect.
|
// This caches whether the event is requested or not, so it doesn't need to be wrapped in an effect.
|
||||||
|
@ -42,7 +44,7 @@ export const ReplyIDBody = ({ room, eventID }: ReplyIDBodyProps) => {
|
||||||
Reply to unknown event<br/><code>{eventID}</code>
|
Reply to unknown event<br/><code>{eventID}</code>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
}
|
}
|
||||||
return <ReplyBody room={room} event={event}/>
|
return <ReplyBody room={room} event={event} isThread={isThread}/>
|
||||||
}
|
}
|
||||||
|
|
||||||
const onClickReply = (evt: React.MouseEvent) => {
|
const onClickReply = (evt: React.MouseEvent) => {
|
||||||
|
@ -62,13 +64,13 @@ const onClickReply = (evt: React.MouseEvent) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ReplyBody = ({ room, event, onClose }: ReplyBodyProps) => {
|
export const ReplyBody = ({ room, event, onClose, isThread }: ReplyBodyProps) => {
|
||||||
const memberEvt = useRoomState(room, "m.room.member", event.sender)
|
const memberEvt = useRoomState(room, "m.room.member", event.sender)
|
||||||
const memberEvtContent = memberEvt?.content as MemberEventContent | undefined
|
const memberEvtContent = memberEvt?.content as MemberEventContent | undefined
|
||||||
const BodyType = getBodyType(event, true)
|
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" : ""} ${isThread ? "thread" : ""}`}
|
||||||
onClick={onClickReply}
|
onClick={onClickReply}
|
||||||
>
|
>
|
||||||
<div className="reply-sender">
|
<div className="reply-sender">
|
||||||
|
|
|
@ -92,7 +92,7 @@ const TimelineEvent = ({ room, evt, prevEvt, setReplyToRef }: TimelineEventProps
|
||||||
const fullTime = fullTimeFormatter.format(eventTS)
|
const fullTime = fullTimeFormatter.format(eventTS)
|
||||||
const shortTime = formatShortTime(eventTS)
|
const shortTime = formatShortTime(eventTS)
|
||||||
const editTime = editEventTS ? `Edited at ${fullTimeFormatter.format(editEventTS)}` : null
|
const editTime = editEventTS ? `Edited at ${fullTimeFormatter.format(editEventTS)}` : null
|
||||||
const replyTo = (evt.orig_content ?? evt.content)["m.relates_to"]?.["m.in_reply_to"]?.event_id
|
const replyTo = evt.content["m.relates_to"]?.["m.in_reply_to"]?.event_id
|
||||||
const mainEvent = <div data-event-id={evt.event_id} className={wrapperClassNames.join(" ")}>
|
const mainEvent = <div data-event-id={evt.event_id} className={wrapperClassNames.join(" ")}>
|
||||||
<div className="sender-avatar" title={evt.sender}>
|
<div className="sender-avatar" title={evt.sender}>
|
||||||
<img
|
<img
|
||||||
|
@ -114,7 +114,11 @@ const TimelineEvent = ({ room, evt, prevEvt, setReplyToRef }: TimelineEventProps
|
||||||
<span className="event-time" title={editTime ? `${fullTime} - ${editTime}` : fullTime}>{shortTime}</span>
|
<span className="event-time" title={editTime ? `${fullTime} - ${editTime}` : fullTime}>{shortTime}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="event-content">
|
<div className="event-content">
|
||||||
{isEventID(replyTo) && BodyType !== HiddenEvent ? <ReplyIDBody room={room} eventID={replyTo}/> : null}
|
{isEventID(replyTo) && BodyType !== HiddenEvent ? <ReplyIDBody
|
||||||
|
room={room}
|
||||||
|
eventID={replyTo}
|
||||||
|
isThread={evt.content["m.relates_to"]?.rel_type === "m.thread"}
|
||||||
|
/> : null}
|
||||||
<ContentErrorBoundary>
|
<ContentErrorBoundary>
|
||||||
<BodyType room={room} sender={memberEvt} event={evt}/>
|
<BodyType room={room} sender={memberEvt} event={evt}/>
|
||||||
</ContentErrorBoundary>
|
</ContentErrorBoundary>
|
||||||
|
|
Loading…
Add table
Reference in a new issue