Strictify `components/structures/Thread*` (#10478)

* Strictify `components/structures/Thread*`

* Fix ThreadView event Id
pull/28217/head
Michael Weimann 2023-03-30 10:44:28 +02:00 committed by GitHub
parent beb8861df6
commit 052c7e6d27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 11 deletions

View File

@ -127,7 +127,7 @@ export const ThreadPanelHeader: React.FC<{
PosthogTrackers.trackInteraction("WebRightPanelThreadPanelFilterDropdown", ev); PosthogTrackers.trackInteraction("WebRightPanelThreadPanelFilterDropdown", ev);
}} }}
> >
{`${_t("Show:")} ${value.label}`} {`${_t("Show:")} ${value?.label}`}
</ContextMenuButton> </ContextMenuButton>
{contextMenu} {contextMenu}
</> </>
@ -197,8 +197,8 @@ const EmptyThread: React.FC<EmptyThreadIProps> = ({ hasThreads, filterOption, sh
const ThreadPanel: React.FC<IProps> = ({ roomId, onClose, permalinkCreator }) => { const ThreadPanel: React.FC<IProps> = ({ roomId, onClose, permalinkCreator }) => {
const mxClient = useContext(MatrixClientContext); const mxClient = useContext(MatrixClientContext);
const roomContext = useContext(RoomContext); const roomContext = useContext(RoomContext);
const timelinePanel = useRef<TimelinePanel>(); const timelinePanel = useRef<TimelinePanel | null>(null);
const card = useRef<HTMLDivElement>(); const card = useRef<HTMLDivElement | null>(null);
const [filterOption, setFilterOption] = useState<ThreadFilterType>(ThreadFilterType.All); const [filterOption, setFilterOption] = useState<ThreadFilterType>(ThreadFilterType.All);
const [room, setRoom] = useState<Room | null>(null); const [room, setRoom] = useState<Room | null>(null);
@ -220,7 +220,7 @@ const ThreadPanel: React.FC<IProps> = ({ roomId, onClose, permalinkCreator }) =>
useEffect(() => { useEffect(() => {
if (timelineSet && !Thread.hasServerSideSupport) { if (timelineSet && !Thread.hasServerSideSupport) {
timelinePanel.current.refreshTimeline(); timelinePanel.current?.refreshTimeline();
} }
}, [timelineSet, timelinePanel]); }, [timelineSet, timelinePanel]);
@ -246,7 +246,7 @@ const ThreadPanel: React.FC<IProps> = ({ roomId, onClose, permalinkCreator }) =>
withoutScrollContainer={true} withoutScrollContainer={true}
ref={card} ref={card}
> >
<Measured sensor={card.current} onMeasurement={setNarrow} /> {card.current && <Measured sensor={card.current} onMeasurement={setNarrow} />}
{timelineSet ? ( {timelineSet ? (
<TimelinePanel <TimelinePanel
key={filterOption + ":" + (timelineSet.getFilter()?.filterId ?? roomId)} key={filterOption + ":" + (timelineSet.getFilter()?.filterId ?? roomId)}

View File

@ -79,15 +79,19 @@ export default class ThreadView extends React.Component<IProps, IState> {
public static contextType = RoomContext; public static contextType = RoomContext;
public context!: React.ContextType<typeof RoomContext>; public context!: React.ContextType<typeof RoomContext>;
private dispatcherRef: string; private dispatcherRef: string | null = null;
private readonly layoutWatcherRef: string; private readonly layoutWatcherRef: string;
private timelinePanel = createRef<TimelinePanel>(); private timelinePanel = createRef<TimelinePanel>();
private card = createRef<HTMLDivElement>(); private card = createRef<HTMLDivElement>();
// Set by setEventId in ctor.
private eventId!: string;
public constructor(props: IProps) { public constructor(props: IProps) {
super(props); 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.setupThreadListeners(thread);
this.state = { this.state = {
@ -108,10 +112,18 @@ export default class ThreadView extends React.Component<IProps, IState> {
if (this.state.thread) { if (this.state.thread) {
this.postThreadUpdate(this.state.thread); this.postThreadUpdate(this.state.thread);
} }
this.setupThread(this.props.mxEvent); this.setupThread(this.props.mxEvent);
this.dispatcherRef = dis.register(this.onAction); this.dispatcherRef = dis.register(this.onAction);
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId()); 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); room.on(ThreadEvent.New, this.onNewThread);
} }
@ -119,7 +131,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
if (this.dispatcherRef) dis.unregister(this.dispatcherRef); if (this.dispatcherRef) dis.unregister(this.dispatcherRef);
const roomId = this.props.mxEvent.getRoomId(); const roomId = this.props.mxEvent.getRoomId();
const room = MatrixClientPeg.get().getRoom(roomId); const room = MatrixClientPeg.get().getRoom(roomId);
room.removeListener(ThreadEvent.New, this.onNewThread); room?.removeListener(ThreadEvent.New, this.onNewThread);
SettingsStore.unwatchSetting(this.layoutWatcherRef); SettingsStore.unwatchSetting(this.layoutWatcherRef);
const hasRoomChanged = SdkContextClass.instance.roomViewStore.getRoomId() !== roomId; const hasRoomChanged = SdkContextClass.instance.roomViewStore.getRoomId() !== roomId;
@ -139,6 +151,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
public componentDidUpdate(prevProps: IProps): void { public componentDidUpdate(prevProps: IProps): void {
if (prevProps.mxEvent !== this.props.mxEvent) { if (prevProps.mxEvent !== this.props.mxEvent) {
this.setEventId(this.props.mxEvent);
this.setupThread(this.props.mxEvent); this.setupThread(this.props.mxEvent);
} }
@ -147,6 +160,14 @@ export default class ThreadView extends React.Component<IProps, IState> {
} }
} }
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 => { private onAction = (payload: ActionPayload): void => {
if (payload.phase == RightPanelPhases.ThreadView && payload.event) { if (payload.phase == RightPanelPhases.ThreadView && payload.event) {
this.setupThread(payload.event); this.setupThread(payload.event);
@ -193,10 +214,15 @@ export default class ThreadView extends React.Component<IProps, IState> {
}; };
private setupThread = (mxEv: MatrixEvent): void => { 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) { if (!thread) {
thread = this.props.room.createThread(mxEv.getId(), mxEv, [mxEv], true); thread = this.props.room.createThread(eventId, mxEv, [mxEv], true);
} }
this.updateThread(thread); this.updateThread(thread);
}; };
@ -420,7 +446,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
PosthogTrackers.trackInteraction("WebThreadViewBackButton", ev); PosthogTrackers.trackInteraction("WebThreadViewBackButton", ev);
}} }}
> >
<Measured sensor={this.card.current} onMeasurement={this.onMeasurement} /> {this.card.current && <Measured sensor={this.card.current} onMeasurement={this.onMeasurement} />}
<div className="mx_ThreadView_timelinePanelWrapper">{timeline}</div> <div className="mx_ThreadView_timelinePanelWrapper">{timeline}</div>
{ContentMessages.sharedInstance().getCurrentUploads(threadRelation).length > 0 && ( {ContentMessages.sharedInstance().getCurrentUploads(threadRelation).length > 0 && (