From 2bfffab5663b382f64d5a2c6b7fb40b32ebd78c7 Mon Sep 17 00:00:00 2001 From: Timo <16718859+toger5@users.noreply.github.com> Date: Mon, 6 Dec 2021 12:29:37 +0100 Subject: [PATCH] Add edits and replies to the right panel timeline & prepare the timelineCard to share code with threads (#7262) Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: J. Ryan Stinnett --- src/components/structures/RightPanel.tsx | 6 +- .../views/right_panel/TimelineCard.tsx | 184 ++++++++++++++---- 2 files changed, 149 insertions(+), 41 deletions(-) diff --git a/src/components/structures/RightPanel.tsx b/src/components/structures/RightPanel.tsx index 6e17a19e0d..63084e589c 100644 --- a/src/components/structures/RightPanel.tsx +++ b/src/components/structures/RightPanel.tsx @@ -339,8 +339,12 @@ export default class RightPanel extends React.Component { if (!SettingsStore.getValue("feature_maximised_widgets")) break; panel = ; + onClose={this.onClose} + permalinkCreator={this.props.permalinkCreator} + e2eStatus={this.props.e2eStatus} + />; break; case RightPanelPhases.FilePanel: panel = ; diff --git a/src/components/views/right_panel/TimelineCard.tsx b/src/components/views/right_panel/TimelineCard.tsx index 940185c206..5bc875b8c6 100644 --- a/src/components/views/right_panel/TimelineCard.tsx +++ b/src/components/views/right_panel/TimelineCard.tsx @@ -15,7 +15,8 @@ limitations under the License. */ import React from 'react'; -import { MatrixEvent, Room } from 'matrix-js-sdk/src'; +import { EventSubscription } from "fbemitter"; +import { EventTimelineSet, IEventRelation, MatrixEvent, Room } from 'matrix-js-sdk/src'; import { Thread } from 'matrix-js-sdk/src/models/thread'; import BaseCard from "./BaseCard"; @@ -27,10 +28,16 @@ import { Layout } from '../../../settings/enums/Layout'; import TimelinePanel from '../../structures/TimelinePanel'; import { E2EStatus } from '../../../utils/ShieldUtils'; import EditorStateTransfer from '../../../utils/EditorStateTransfer'; -import RoomContext from '../../../contexts/RoomContext'; - +import RoomContext, { TimelineRenderingType } from '../../../contexts/RoomContext'; +import dis from '../../../dispatcher/dispatcher'; import { _t } from '../../../languageHandler'; import { replaceableComponent } from '../../../utils/replaceableComponent'; +import { ActionPayload } from '../../../dispatcher/payloads'; +import { Action } from '../../../dispatcher/actions'; +import RoomViewStore from '../../../stores/RoomViewStore'; +import ContentMessages from '../../../ContentMessages'; +import UploadBar from '../../structures/UploadBar'; +import SettingsStore from '../../../settings/SettingsStore'; interface IProps { room: Room; @@ -38,24 +45,103 @@ interface IProps { resizeNotifier: ResizeNotifier; permalinkCreator?: RoomPermalinkCreator; e2eStatus?: E2EStatus; - initialEvent?: MatrixEvent; - initialEventHighlighted?: boolean; + timelineSet?: EventTimelineSet; + timelineRenderingType?: TimelineRenderingType; + showComposer?: boolean; + composerRelation?: IEventRelation; } interface IState { thread?: Thread; editState?: EditorStateTransfer; replyToEvent?: MatrixEvent; + initialEventId?: string; + initialEventHighlighted?: boolean; + + // settings: + showReadReceipts?: boolean; } @replaceableComponent("structures.TimelineCard") export default class TimelineCard extends React.Component { static contextType = RoomContext; + private dispatcherRef: string; + private timelinePanelRef: React.RefObject = React.createRef(); + private roomStoreToken: EventSubscription; + private settingWatchers: string[]; + constructor(props: IProps) { super(props); - this.state = {}; + this.state = { + showReadReceipts: false, + }; + this.settingWatchers = []; } + public componentDidMount(): void { + this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); + this.dispatcherRef = dis.register(this.onAction); + } + + public componentWillUnmount(): void { + // Remove RoomStore listener + if (this.roomStoreToken) { + this.roomStoreToken.remove(); + } + dis.unregister(this.dispatcherRef); + for (const watcher of this.settingWatchers) { + SettingsStore.unwatchSetting(watcher); + } + } + + private onRoomViewStoreUpdate = async (initial?: boolean): Promise => { + const roomId = this.props.room.roomId; + const newState: Pick = { + // roomLoading: RoomViewStore.isRoomLoading(), + // roomLoadError: RoomViewStore.getRoomLoadError(), + + showReadReceipts: SettingsStore.getValue("showReadReceipts", roomId), + initialEventId: RoomViewStore.getInitialEventId(), + initialEventHighlighted: RoomViewStore.isInitialEventHighlighted(), + replyToEvent: RoomViewStore.getQuotingEvent(), + }; + + this.settingWatchers = this.settingWatchers.concat([ + SettingsStore.watchSetting("showReadReceipts", roomId, (...[,,, value]) => + this.setState({ showReadReceipts: value as boolean }), + ), + ]); + this.setState(newState); + }; + + private onAction = (payload: ActionPayload): void => { + switch (payload.action) { + case Action.EditEvent: + this.setState({ + editState: payload.event ? new EditorStateTransfer(payload.event) : null, + }, () => { + if (payload.event) { + this.timelinePanelRef.current?.scrollToEventIfNeeded(payload.event.getId()); + } + }); + break; + default: + break; + } + }; + + private onScroll = (): void => { + if (this.state.initialEventId && this.state.initialEventHighlighted) { + dis.dispatch({ + action: Action.ViewRoom, + room_id: this.props.room.roomId, + event_id: this.state.initialEventId, + highlighted: false, + replyingToEvent: this.state.replyToEvent, + }); + } + }; + private renderTimelineCardHeader = (): JSX.Element => { return
{ _t("Chat") } @@ -63,41 +149,59 @@ export default class TimelineCard extends React.Component { }; public render(): JSX.Element { - return ( - - + return ( + + + + ); } }