From 052c7e6d27bbb81df130f1d223cf6f9e5b5a1182 Mon Sep 17 00:00:00 2001 From: Michael Weimann Date: Thu, 30 Mar 2023 10:44:28 +0200 Subject: [PATCH] Strictify `components/structures/Thread*` (#10478) * Strictify `components/structures/Thread*` * Fix ThreadView event Id --- src/components/structures/ThreadPanel.tsx | 10 +++--- src/components/structures/ThreadView.tsx | 38 +++++++++++++++++++---- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/components/structures/ThreadPanel.tsx b/src/components/structures/ThreadPanel.tsx index ef97bd71c8..cbff5392e8 100644 --- a/src/components/structures/ThreadPanel.tsx +++ b/src/components/structures/ThreadPanel.tsx @@ -127,7 +127,7 @@ export const ThreadPanelHeader: React.FC<{ PosthogTrackers.trackInteraction("WebRightPanelThreadPanelFilterDropdown", ev); }} > - {`${_t("Show:")} ${value.label}`} + {`${_t("Show:")} ${value?.label}`} {contextMenu} @@ -197,8 +197,8 @@ const EmptyThread: React.FC = ({ hasThreads, filterOption, sh const ThreadPanel: React.FC = ({ roomId, onClose, permalinkCreator }) => { const mxClient = useContext(MatrixClientContext); const roomContext = useContext(RoomContext); - const timelinePanel = useRef(); - const card = useRef(); + const timelinePanel = useRef(null); + const card = useRef(null); const [filterOption, setFilterOption] = useState(ThreadFilterType.All); const [room, setRoom] = useState(null); @@ -220,7 +220,7 @@ const ThreadPanel: React.FC = ({ roomId, onClose, permalinkCreator }) => useEffect(() => { if (timelineSet && !Thread.hasServerSideSupport) { - timelinePanel.current.refreshTimeline(); + timelinePanel.current?.refreshTimeline(); } }, [timelineSet, timelinePanel]); @@ -246,7 +246,7 @@ const ThreadPanel: React.FC = ({ roomId, onClose, permalinkCreator }) => withoutScrollContainer={true} ref={card} > - + {card.current && } {timelineSet ? ( { public static contextType = RoomContext; public context!: React.ContextType; - private dispatcherRef: string; + private dispatcherRef: string | null = null; private readonly layoutWatcherRef: string; private timelinePanel = createRef(); private card = createRef(); + // Set by setEventId in ctor. + private eventId!: string; + public constructor(props: IProps) { super(props); - const thread = this.props.room.getThread(this.props.mxEvent.getId()); + this.setEventId(this.props.mxEvent); + const thread = this.props.room.getThread(this.eventId) ?? undefined; this.setupThreadListeners(thread); this.state = { @@ -108,10 +112,18 @@ export default class ThreadView extends React.Component { if (this.state.thread) { this.postThreadUpdate(this.state.thread); } + this.setupThread(this.props.mxEvent); this.dispatcherRef = dis.register(this.onAction); const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId()); + + if (!room) { + throw new Error( + `Unable to find room ${this.props.mxEvent.getRoomId()} for thread ${this.props.mxEvent.getId()}`, + ); + } + room.on(ThreadEvent.New, this.onNewThread); } @@ -119,7 +131,7 @@ export default class ThreadView extends React.Component { if (this.dispatcherRef) dis.unregister(this.dispatcherRef); const roomId = this.props.mxEvent.getRoomId(); const room = MatrixClientPeg.get().getRoom(roomId); - room.removeListener(ThreadEvent.New, this.onNewThread); + room?.removeListener(ThreadEvent.New, this.onNewThread); SettingsStore.unwatchSetting(this.layoutWatcherRef); const hasRoomChanged = SdkContextClass.instance.roomViewStore.getRoomId() !== roomId; @@ -139,6 +151,7 @@ export default class ThreadView extends React.Component { public componentDidUpdate(prevProps: IProps): void { if (prevProps.mxEvent !== this.props.mxEvent) { + this.setEventId(this.props.mxEvent); this.setupThread(this.props.mxEvent); } @@ -147,6 +160,14 @@ export default class ThreadView extends React.Component { } } + private setEventId(event: MatrixEvent): void { + if (!event.getId()) { + throw new Error("Got thread event without id"); + } + + this.eventId = event.getId()!; + } + private onAction = (payload: ActionPayload): void => { if (payload.phase == RightPanelPhases.ThreadView && payload.event) { this.setupThread(payload.event); @@ -193,10 +214,15 @@ export default class ThreadView extends React.Component { }; private setupThread = (mxEv: MatrixEvent): void => { - let thread = this.props.room.getThread(mxEv.getId()); + /** presence of event Id has been ensured by {@link setEventId} */ + const eventId = mxEv.getId()!; + + let thread = this.props.room.getThread(eventId); + if (!thread) { - thread = this.props.room.createThread(mxEv.getId(), mxEv, [mxEv], true); + thread = this.props.room.createThread(eventId, mxEv, [mxEv], true); } + this.updateThread(thread); }; @@ -420,7 +446,7 @@ export default class ThreadView extends React.Component { PosthogTrackers.trackInteraction("WebThreadViewBackButton", ev); }} > - + {this.card.current && }
{timeline}
{ContentMessages.sharedInstance().getCurrentUploads(threadRelation).length > 0 && (