1
1
import type { IRoom , IMessage , IUser } from '@rocket.chat/core-typings' ;
2
+ import { UserStatus } from '@rocket.chat/core-typings' ;
2
3
import { Random } from '@rocket.chat/random' ;
3
4
import EJSON from 'ejson' ;
4
5
import { Meteor } from 'meteor/meteor' ;
@@ -7,6 +8,7 @@ import { Tracker } from 'meteor/tracker';
7
8
8
9
import GenericModal from '../../../client/components/GenericModal' ;
9
10
import { imperativeModal } from '../../../client/lib/imperativeModal' ;
11
+ import type { UserPresence } from '../../../client/lib/presence' ;
10
12
import { Presence } from '../../../client/lib/presence' ;
11
13
import { dispatchToastMessage } from '../../../client/lib/toast' ;
12
14
import { getUidDirectMessage } from '../../../client/lib/utils/getUidDirectMessage' ;
@@ -47,13 +49,16 @@ export class OTRRoom implements IOTRRoom {
47
49
48
50
private isFirstOTR : boolean ;
49
51
52
+ private onPresenceEventHook : ( event : UserPresence | undefined ) => void ;
53
+
50
54
protected constructor ( uid : IUser [ '_id' ] , rid : IRoom [ '_id' ] , peerId : IUser [ '_id' ] ) {
51
55
this . _userId = uid ;
52
56
this . _roomId = rid ;
53
57
this . _keyPair = null ;
54
58
this . _sessionKey = null ;
55
59
this . peerId = peerId ;
56
60
this . isFirstOTR = true ;
61
+ this . onPresenceEventHook = this . onPresenceEvent . bind ( this ) ;
57
62
}
58
63
59
64
public static create ( uid : IUser [ '_id' ] , rid : IRoom [ '_id' ] ) : OTRRoom | undefined {
@@ -110,6 +115,35 @@ export class OTRRoom implements IOTRRoom {
110
115
}
111
116
}
112
117
118
+ onPresenceEvent ( event : UserPresence | undefined ) : void {
119
+ if ( ! event ) {
120
+ return ;
121
+ }
122
+ if ( event . status !== UserStatus . OFFLINE ) {
123
+ return ;
124
+ }
125
+ console . warn ( `OTR Room ${ this . _roomId } ended because ${ this . peerId } went offline` ) ;
126
+ this . end ( ) ;
127
+
128
+ imperativeModal . open ( {
129
+ component : GenericModal ,
130
+ props : {
131
+ variant : 'warning' ,
132
+ title : t ( 'OTR' ) ,
133
+ children : t ( 'OTR_Session_ended_other_user_went_offline' , { username : event . username } ) ,
134
+ confirmText : t ( 'Ok' ) ,
135
+ onClose : imperativeModal . close ,
136
+ onConfirm : imperativeModal . close ,
137
+ } ,
138
+ } ) ;
139
+ }
140
+
141
+ // Starts listening to other user's status changes and end OTR if any of the Users goes offline
142
+ // this should be called in 2 places: on acknowledge (meaning user accepted OTR) or on establish (meaning user initiated OTR)
143
+ listenToUserStatus ( ) : void {
144
+ Presence . listen ( this . peerId , this . onPresenceEventHook ) ;
145
+ }
146
+
113
147
acknowledge ( ) : void {
114
148
void sdk . rest . post ( '/v1/statistics.telemetry' , { params : [ { eventName : 'otrStats' , timestamp : Date . now ( ) , rid : this . _roomId } ] } ) ;
115
149
@@ -137,10 +171,19 @@ export class OTRRoom implements IOTRRoom {
137
171
] ) ;
138
172
}
139
173
174
+ softReset ( ) : void {
175
+ this . isFirstOTR = true ;
176
+ this . setState ( OtrRoomState . NOT_STARTED ) ;
177
+ this . _keyPair = null ;
178
+ this . _exportedPublicKey = { } ;
179
+ this . _sessionKey = null ;
180
+ }
181
+
140
182
end ( ) : void {
141
183
this . isFirstOTR = true ;
142
184
this . reset ( ) ;
143
185
this . setState ( OtrRoomState . NOT_STARTED ) ;
186
+ Presence . stop ( this . peerId , this . onPresenceEventHook ) ;
144
187
sdk . publish ( 'notify-user' , [
145
188
`${ this . peerId } /otr` ,
146
189
'end' ,
@@ -285,6 +328,7 @@ export class OTRRoom implements IOTRRoom {
285
328
setTimeout ( async ( ) => {
286
329
this . setState ( OtrRoomState . ESTABLISHED ) ;
287
330
this . acknowledge ( ) ;
331
+ this . listenToUserStatus ( ) ;
288
332
289
333
if ( data . refresh ) {
290
334
await sdk . rest . post ( '/v1/chat.otr' , {
@@ -362,6 +406,7 @@ export class OTRRoom implements IOTRRoom {
362
406
this . setState ( OtrRoomState . ESTABLISHED ) ;
363
407
364
408
if ( this . isFirstOTR ) {
409
+ this . listenToUserStatus ( ) ;
365
410
await sdk . rest . post ( '/v1/chat.otr' , {
366
411
roomId : this . _roomId ,
367
412
type : otrSystemMessages . USER_JOINED_OTR ,
0 commit comments