From 42fcb9ce851a20f39242a3975ca604856faae2ea Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Wed, 23 Oct 2024 10:49:43 +0200 Subject: [PATCH 1/6] Replace `MatrixClient.isRoomEncrypted` by `MatrixClient.CryptoApi.isEncryptionEnabledInRoom` in FilePanel --- src/components/structures/FilePanel.tsx | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/components/structures/FilePanel.tsx b/src/components/structures/FilePanel.tsx index 74a91d8cbc5..5d754f0e4d8 100644 --- a/src/components/structures/FilePanel.tsx +++ b/src/components/structures/FilePanel.tsx @@ -44,6 +44,7 @@ interface IProps { interface IState { timelineSet: EventTimelineSet | null; narrow: boolean; + isRoomEncrypted: boolean; } /* @@ -62,6 +63,7 @@ class FilePanel extends React.Component { public state: IState = { timelineSet: null, narrow: false, + isRoomEncrypted: false, }; private onRoomTimeline = ( @@ -113,7 +115,12 @@ class FilePanel extends React.Component { await this.updateTimelineSet(this.props.roomId); - if (!client.isRoomEncrypted(this.props.roomId)) return; + const isRoomEncrypted = Boolean(await client.getCrypto()?.isEncryptionEnabledInRoom(this.props.roomId)); + this.setState({ + isRoomEncrypted, + }); + + if (!isRoomEncrypted) return; // The timelineSets filter makes sure that encrypted events that contain // URLs never get added to the timeline, even if they are live events. @@ -131,9 +138,7 @@ class FilePanel extends React.Component { public componentWillUnmount(): void { const client = MatrixClientPeg.get(); - if (client === null) return; - - if (!client.isRoomEncrypted(this.props.roomId)) return; + if (client === null || !this.state.isRoomEncrypted) return; if (EventIndexPeg.get() !== null) { client.removeListener(RoomEvent.Timeline, this.onRoomTimeline); @@ -173,7 +178,7 @@ class FilePanel extends React.Component { // the event index to fulfill the pagination request. Asking the server // to paginate won't ever work since the server can't correctly filter // out events containing URLs - if (room && client.isRoomEncrypted(roomId) && eventIndex !== null) { + if (room && this.state.isRoomEncrypted && eventIndex !== null) { return eventIndex.paginateTimelineWindow(room, timelineWindow, direction, limit); } else { return timelineWindow.paginate(direction, limit); @@ -206,7 +211,7 @@ class FilePanel extends React.Component { // event index to populate the timelineSet for us. This call // will add 10 events to the live timeline of the set. More can // be requested using pagination. - if (client.isRoomEncrypted(roomId) && eventIndex !== null) { + if (this.state.isRoomEncrypted && eventIndex !== null) { const timeline = timelineSet.getLiveTimeline(); await eventIndex.populateFileTimeline(timelineSet, timeline, room, 10); } @@ -265,7 +270,7 @@ class FilePanel extends React.Component { /> ); - const isRoomEncrypted = this.noRoom ? false : MatrixClientPeg.safeGet().isRoomEncrypted(this.props.roomId); + const isRoomEncrypted = this.noRoom ? false : this.state.isRoomEncrypted; if (this.state.timelineSet) { return ( From b718c092a77b3ac59e608ab9d4ce6d60ce642d39 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Wed, 23 Oct 2024 15:35:42 +0200 Subject: [PATCH 2/6] Display `SearchWarning` when `isRoomEncrypted` is loaded --- src/components/structures/FilePanel.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components/structures/FilePanel.tsx b/src/components/structures/FilePanel.tsx index 5d754f0e4d8..7ee0ab04eb7 100644 --- a/src/components/structures/FilePanel.tsx +++ b/src/components/structures/FilePanel.tsx @@ -44,7 +44,10 @@ interface IProps { interface IState { timelineSet: EventTimelineSet | null; narrow: boolean; - isRoomEncrypted: boolean; + /** + * Whether the room is encrypted or not. If null, the state is still being determined. + */ + isRoomEncrypted: boolean | null; } /* @@ -63,7 +66,7 @@ class FilePanel extends React.Component { public state: IState = { timelineSet: null, narrow: false, - isRoomEncrypted: false, + isRoomEncrypted: null, }; private onRoomTimeline = ( @@ -270,7 +273,8 @@ class FilePanel extends React.Component { /> ); - const isRoomEncrypted = this.noRoom ? false : this.state.isRoomEncrypted; + const isRoomEncryptedLoaded = this.state.isRoomEncrypted !== null; + const isRoomEncrypted = Boolean(this.noRoom ? false : this.state.isRoomEncrypted); if (this.state.timelineSet) { return ( @@ -291,7 +295,9 @@ class FilePanel extends React.Component { {this.card.current && ( )} - + {isRoomEncryptedLoaded && ( + + )} Date: Wed, 23 Oct 2024 15:57:46 +0200 Subject: [PATCH 3/6] Display timeline panel when room `isRoomEncrypted` is loaded --- src/components/structures/FilePanel.tsx | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/components/structures/FilePanel.tsx b/src/components/structures/FilePanel.tsx index 7ee0ab04eb7..54f8696370a 100644 --- a/src/components/structures/FilePanel.tsx +++ b/src/components/structures/FilePanel.tsx @@ -296,18 +296,20 @@ class FilePanel extends React.Component { )} {isRoomEncryptedLoaded && ( - + <> + + + )} - ); From 7507e3cb9a34ba9fa968330d648ace51a2b9667b Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Wed, 23 Oct 2024 16:10:33 +0200 Subject: [PATCH 4/6] Fix potential racy dangling listener --- src/components/structures/FilePanel.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/structures/FilePanel.tsx b/src/components/structures/FilePanel.tsx index 54f8696370a..8da686ab5d5 100644 --- a/src/components/structures/FilePanel.tsx +++ b/src/components/structures/FilePanel.tsx @@ -62,6 +62,8 @@ class FilePanel extends React.Component { private decryptingEvents = new Set(); public noRoom = false; private card = createRef(); + // This is used to track if the component is unmounting to avoid adding dangling listeners + private isUnloading = false; public state: IState = { timelineSet: null, @@ -133,13 +135,16 @@ class FilePanel extends React.Component { // We do this only for encrypted rooms and if an event index exists, // this could be made more general in the future or the filter logic // could be fixed. - if (EventIndexPeg.get() !== null) { + // + // `componentDidMount` is async and we need to be sure to not put this listener when the component is unmount before the mounting is done. + if (EventIndexPeg.get() !== null && this.isUnloading) { client.on(RoomEvent.Timeline, this.onRoomTimeline); client.on(MatrixEventEvent.Decrypted, this.onEventDecrypted); } } public componentWillUnmount(): void { + this.isUnloading = true; const client = MatrixClientPeg.get(); if (client === null || !this.state.isRoomEncrypted) return; From 3ccfd9bee1a27f70815c80fb16b1f8a99500e04f Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Wed, 23 Oct 2024 16:15:10 +0200 Subject: [PATCH 5/6] Move room encryption check earlier in mount --- src/components/structures/FilePanel.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/structures/FilePanel.tsx b/src/components/structures/FilePanel.tsx index 8da686ab5d5..b7c084c5249 100644 --- a/src/components/structures/FilePanel.tsx +++ b/src/components/structures/FilePanel.tsx @@ -117,15 +117,14 @@ class FilePanel extends React.Component { public async componentDidMount(): Promise { const client = MatrixClientPeg.safeGet(); - - await this.updateTimelineSet(this.props.roomId); - const isRoomEncrypted = Boolean(await client.getCrypto()?.isEncryptionEnabledInRoom(this.props.roomId)); this.setState({ isRoomEncrypted, }); - if (!isRoomEncrypted) return; + await this.updateTimelineSet(this.props.roomId); + + if (isRoomEncrypted) return; // The timelineSets filter makes sure that encrypted events that contain // URLs never get added to the timeline, even if they are live events. From 3797644dddf170554f84221d07bf79cf2bdcaa6a Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Wed, 23 Oct 2024 17:53:34 +0200 Subject: [PATCH 6/6] Fix didMount condition --- src/components/structures/FilePanel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/FilePanel.tsx b/src/components/structures/FilePanel.tsx index b7c084c5249..999d9292ee7 100644 --- a/src/components/structures/FilePanel.tsx +++ b/src/components/structures/FilePanel.tsx @@ -124,7 +124,7 @@ class FilePanel extends React.Component { await this.updateTimelineSet(this.props.roomId); - if (isRoomEncrypted) return; + if (!isRoomEncrypted) return; // The timelineSets filter makes sure that encrypted events that contain // URLs never get added to the timeline, even if they are live events.