@@ -233,6 +233,11 @@ export interface IRoomState {
233
233
liveTimeline ?: EventTimeline ;
234
234
narrow : boolean ;
235
235
msc3946ProcessDynamicPredecessor : boolean ;
236
+ /**
237
+ * Whether the room is encrypted or not.
238
+ * If null, we are still determining the encryption status.
239
+ */
240
+ isRoomEncrypted : boolean | null ;
236
241
237
242
canAskToJoin : boolean ;
238
243
promptAskToJoin : boolean ;
@@ -417,6 +422,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
417
422
canAskToJoin : this . askToJoinEnabled ,
418
423
promptAskToJoin : false ,
419
424
viewRoomOpts : { buttons : [ ] } ,
425
+ isRoomEncrypted : false ,
420
426
} ;
421
427
}
422
428
@@ -847,7 +853,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
847
853
return isManuallyShown && widgets . length > 0 ;
848
854
}
849
855
850
- public componentDidMount ( ) : void {
856
+ public async componentDidMount ( ) : Promise < void > {
851
857
this . unmounted = false ;
852
858
853
859
this . dispatcherRef = defaultDispatcher . register ( this . onAction ) ;
@@ -914,6 +920,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
914
920
const callState = call ?. state ;
915
921
this . setState ( {
916
922
callState,
923
+ isRoomEncrypted : await this . getIsRoomEncrypted ( ) ,
917
924
} ) ;
918
925
919
926
this . context . legacyCallHandler . on ( LegacyCallHandlerEvent . CallState , this . onCallState ) ;
@@ -1377,6 +1384,13 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
1377
1384
return room ?. currentState . getStateEvents ( EventType . RoomTombstone , "" ) ?? undefined ;
1378
1385
}
1379
1386
1387
+ private async getIsRoomEncrypted ( roomId = this . state . roomId ) : Promise < boolean > {
1388
+ const crypto = this . context . client ?. getCrypto ( ) ;
1389
+ if ( ! crypto || ! roomId ) return false ;
1390
+
1391
+ return await crypto . isEncryptionEnabledInRoom ( roomId ) ;
1392
+ }
1393
+
1380
1394
private async calculateRecommendedVersion ( room : Room ) : Promise < void > {
1381
1395
const upgradeRecommendation = await room . getRecommendedVersion ( ) ;
1382
1396
if ( this . unmounted ) return ;
@@ -1411,7 +1425,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
1411
1425
1412
1426
private updatePreviewUrlVisibility ( { roomId } : Room ) : void {
1413
1427
// URL Previews in E2EE rooms can be a privacy leak so use a different setting which is per-room explicit
1414
- const key = this . context . client ?. isRoomEncrypted ( roomId ) ? "urlPreviewsEnabled_e2ee" : "urlPreviewsEnabled" ;
1428
+ const key = this . state . isRoomEncrypted ? "urlPreviewsEnabled_e2ee" : "urlPreviewsEnabled" ;
1415
1429
this . setState ( {
1416
1430
showUrlPreview : SettingsStore . getValue ( key , roomId ) ,
1417
1431
} ) ;
@@ -1456,7 +1470,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
1456
1470
} ;
1457
1471
1458
1472
private async updateE2EStatus ( room : Room ) : Promise < void > {
1459
- if ( ! this . context . client ?. isRoomEncrypted ( room . roomId ) ) return ;
1473
+ if ( ! this . context . client || ! this . state . isRoomEncrypted ) return ;
1460
1474
1461
1475
// If crypto is not currently enabled, we aren't tracking devices at all,
1462
1476
// so we don't know what the answer is. Let's error on the safe side and show
@@ -1480,15 +1494,19 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
1480
1494
}
1481
1495
} ;
1482
1496
1483
- private onRoomStateEvents = ( ev : MatrixEvent , state : RoomState ) : void => {
1497
+ private onRoomStateEvents = async ( ev : MatrixEvent , state : RoomState ) : Promise < void > => {
1484
1498
// ignore if we don't have a room yet
1485
1499
if ( ! this . state . room || this . state . room . roomId !== state . roomId ) return ;
1486
1500
1487
1501
switch ( ev . getType ( ) ) {
1488
1502
case EventType . RoomTombstone :
1489
1503
this . setState ( { tombstone : this . getRoomTombstone ( ) } ) ;
1490
1504
break ;
1491
-
1505
+ case EventType . RoomEncryption :
1506
+ this . setState ( { isRoomEncrypted : await this . getIsRoomEncrypted ( ) } , ( ) => {
1507
+ if ( this . state . room ) this . updatePreviewUrlVisibility ( this . state . room ) ;
1508
+ } ) ;
1509
+ break ;
1492
1510
default :
1493
1511
this . updatePermissions ( this . state . room ) ;
1494
1512
}
@@ -2026,7 +2044,9 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
2026
2044
} ;
2027
2045
2028
2046
public render ( ) : ReactNode {
2029
- if ( ! this . context . client ) return null ;
2047
+ const { isRoomEncrypted } = this . state ;
2048
+ const isRoomEncryptionLoading = isRoomEncrypted === null ;
2049
+ if ( ! this . context . client || isRoomEncryptionLoading ) return null ;
2030
2050
2031
2051
if ( this . state . room instanceof LocalRoom ) {
2032
2052
if ( this . state . room . state === LocalRoomState . CREATING ) {
@@ -2247,7 +2267,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
2247
2267
searchInfo = { this . state . search }
2248
2268
onCancelClick = { this . onCancelSearchClick }
2249
2269
onSearchScopeChange = { this . onSearchScopeChange }
2250
- isRoomEncrypted = { this . context . client . isRoomEncrypted ( this . state . room . roomId ) }
2270
+ isRoomEncrypted = { isRoomEncrypted }
2251
2271
/>
2252
2272
) ;
2253
2273
} else if ( showRoomUpgradeBar ) {
0 commit comments