@@ -35,6 +35,7 @@ import { EffectiveMembership, getEffectiveMembership, splitRoomsByMembership } f
35
35
import { OrderingAlgorithm } from "./list-ordering/OrderingAlgorithm" ;
36
36
import { getListAlgorithmInstance } from "./list-ordering" ;
37
37
import { VisibilityProvider } from "../filters/VisibilityProvider" ;
38
+ import VideoChannelStore , { VideoChannelEvent } from "../../VideoChannelStore" ;
38
39
39
40
/**
40
41
* Fired when the Algorithm has determined a list has been updated.
@@ -84,8 +85,14 @@ export class Algorithm extends EventEmitter {
84
85
*/
85
86
public updatesInhibited = false ;
86
87
87
- public constructor ( ) {
88
- super ( ) ;
88
+ public start ( ) {
89
+ VideoChannelStore . instance . on ( VideoChannelEvent . Connect , this . updateVideoRoom ) ;
90
+ VideoChannelStore . instance . on ( VideoChannelEvent . Disconnect , this . updateVideoRoom ) ;
91
+ }
92
+
93
+ public stop ( ) {
94
+ VideoChannelStore . instance . off ( VideoChannelEvent . Connect , this . updateVideoRoom ) ;
95
+ VideoChannelStore . instance . off ( VideoChannelEvent . Disconnect , this . updateVideoRoom ) ;
89
96
}
90
97
91
98
public get stickyRoom ( ) : Room {
@@ -108,6 +115,7 @@ export class Algorithm extends EventEmitter {
108
115
this . _cachedRooms = val ;
109
116
this . recalculateFilteredRooms ( ) ;
110
117
this . recalculateStickyRoom ( ) ;
118
+ this . recalculateVideoRoom ( ) ;
111
119
}
112
120
113
121
protected get cachedRooms ( ) : ITagMap {
@@ -145,6 +153,7 @@ export class Algorithm extends EventEmitter {
145
153
this . _cachedRooms [ tagId ] = algorithm . orderedRooms ;
146
154
this . recalculateFilteredRoomsForTag ( tagId ) ; // update filter to re-sort the list
147
155
this . recalculateStickyRoom ( tagId ) ; // update sticky room to make sure it appears if needed
156
+ this . recalculateVideoRoom ( tagId ) ;
148
157
}
149
158
150
159
public getListOrdering ( tagId : TagID ) : ListAlgorithm {
@@ -164,6 +173,7 @@ export class Algorithm extends EventEmitter {
164
173
this . _cachedRooms [ tagId ] = algorithm . orderedRooms ;
165
174
this . recalculateFilteredRoomsForTag ( tagId ) ; // update filter to re-sort the list
166
175
this . recalculateStickyRoom ( tagId ) ; // update sticky room to make sure it appears if needed
176
+ this . recalculateVideoRoom ( tagId ) ;
167
177
}
168
178
169
179
public addFilterCondition ( filterCondition : IFilterCondition ) : void {
@@ -311,12 +321,30 @@ export class Algorithm extends EventEmitter {
311
321
this . recalculateFilteredRoomsForTag ( tag ) ;
312
322
if ( lastStickyRoom && lastStickyRoom . tag !== tag ) this . recalculateFilteredRoomsForTag ( lastStickyRoom . tag ) ;
313
323
this . recalculateStickyRoom ( ) ;
324
+ this . recalculateVideoRoom ( tag ) ;
325
+ if ( lastStickyRoom && lastStickyRoom . tag !== tag ) this . recalculateVideoRoom ( lastStickyRoom . tag ) ;
314
326
315
327
// Finally, trigger an update
316
328
if ( this . updatesInhibited ) return ;
317
329
this . emit ( LIST_UPDATED_EVENT ) ;
318
330
}
319
331
332
+ /**
333
+ * Update the stickiness of video rooms.
334
+ */
335
+ public updateVideoRoom = ( ) => {
336
+ // In case we're unsticking a video room, sort it back into natural order
337
+ this . recalculateFilteredRooms ( ) ;
338
+ this . recalculateStickyRoom ( ) ;
339
+
340
+ this . recalculateVideoRoom ( ) ;
341
+
342
+ if ( this . updatesInhibited ) return ;
343
+ // This isn't in response to any particular RoomListStore update,
344
+ // so notify the store that it needs to force-update
345
+ this . emit ( LIST_UPDATED_EVENT , true ) ;
346
+ } ;
347
+
320
348
protected recalculateFilteredRooms ( ) {
321
349
if ( ! this . hasFilters ) {
322
350
return ;
@@ -374,6 +402,13 @@ export class Algorithm extends EventEmitter {
374
402
}
375
403
}
376
404
405
+ private initCachedStickyRooms ( ) {
406
+ this . _cachedStickyRooms = { } ;
407
+ for ( const tagId of Object . keys ( this . cachedRooms ) ) {
408
+ this . _cachedStickyRooms [ tagId ] = [ ...this . cachedRooms [ tagId ] ] ; // shallow clone
409
+ }
410
+ }
411
+
377
412
/**
378
413
* Recalculate the sticky room position. If this is being called in relation to
379
414
* a specific tag being updated, it should be given to this function to optimize
@@ -400,17 +435,13 @@ export class Algorithm extends EventEmitter {
400
435
}
401
436
402
437
if ( ! this . _cachedStickyRooms || ! updatedTag ) {
403
- const stickiedTagMap : ITagMap = { } ;
404
- for ( const tagId of Object . keys ( this . cachedRooms ) ) {
405
- stickiedTagMap [ tagId ] = this . cachedRooms [ tagId ] . map ( r => r ) ; // shallow clone
406
- }
407
- this . _cachedStickyRooms = stickiedTagMap ;
438
+ this . initCachedStickyRooms ( ) ;
408
439
}
409
440
410
441
if ( updatedTag ) {
411
442
// Update the tag indicated by the caller, if possible. This is mostly to ensure
412
443
// our cache is up to date.
413
- this . _cachedStickyRooms [ updatedTag ] = this . cachedRooms [ updatedTag ] . map ( r => r ) ; // shallow clone
444
+ this . _cachedStickyRooms [ updatedTag ] = [ ... this . cachedRooms [ updatedTag ] ] ; // shallow clone
414
445
}
415
446
416
447
// Now try to insert the sticky room, if we need to.
@@ -426,6 +457,46 @@ export class Algorithm extends EventEmitter {
426
457
this . emit ( LIST_UPDATED_EVENT ) ;
427
458
}
428
459
460
+ /**
461
+ * Recalculate the position of any video rooms. If this is being called in relation to
462
+ * a specific tag being updated, it should be given to this function to optimize
463
+ * the call.
464
+ *
465
+ * This expects to be called *after* the sticky rooms are updated, and sticks the
466
+ * currently connected video room to the top of its tag.
467
+ *
468
+ * @param updatedTag The tag that was updated, if possible.
469
+ */
470
+ protected recalculateVideoRoom ( updatedTag : TagID = null ) : void {
471
+ if ( ! updatedTag ) {
472
+ // Assume all tags need updating
473
+ // We're not modifying the map here, so can safely rely on the cached values
474
+ // rather than the explicitly sticky map.
475
+ for ( const tagId of Object . keys ( this . cachedRooms ) ) {
476
+ if ( ! tagId ) {
477
+ throw new Error ( "Unexpected recursion: falsy tag" ) ;
478
+ }
479
+ this . recalculateVideoRoom ( tagId ) ;
480
+ }
481
+ return ;
482
+ }
483
+
484
+ const videoRoomId = VideoChannelStore . instance . connected ? VideoChannelStore . instance . roomId : null ;
485
+
486
+ if ( videoRoomId ) {
487
+ // We operate directly on the sticky rooms map
488
+ if ( ! this . _cachedStickyRooms ) this . initCachedStickyRooms ( ) ;
489
+ const rooms = this . _cachedStickyRooms [ updatedTag ] ;
490
+ const videoRoomIdxInTag = rooms . findIndex ( r => r . roomId === videoRoomId ) ;
491
+ if ( videoRoomIdxInTag < 0 ) return ; // no-op
492
+
493
+ const videoRoom = rooms [ videoRoomIdxInTag ] ;
494
+ rooms . splice ( videoRoomIdxInTag , 1 ) ;
495
+ rooms . unshift ( videoRoom ) ;
496
+ this . _cachedStickyRooms [ updatedTag ] = rooms ; // re-set because references aren't always safe
497
+ }
498
+ }
499
+
429
500
/**
430
501
* Asks the Algorithm to regenerate all lists, using the tags given
431
502
* as reference for which lists to generate and which way to generate
@@ -706,6 +777,7 @@ export class Algorithm extends EventEmitter {
706
777
this . _cachedRooms [ rmTag ] = algorithm . orderedRooms ;
707
778
this . recalculateFilteredRoomsForTag ( rmTag ) ; // update filter to re-sort the list
708
779
this . recalculateStickyRoom ( rmTag ) ; // update sticky room to make sure it moves if needed
780
+ this . recalculateVideoRoom ( rmTag ) ;
709
781
}
710
782
for ( const addTag of diff . added ) {
711
783
const algorithm : OrderingAlgorithm = this . algorithms [ addTag ] ;
@@ -782,6 +854,7 @@ export class Algorithm extends EventEmitter {
782
854
// Flag that we've done something
783
855
this . recalculateFilteredRoomsForTag ( tag ) ; // update filter to re-sort the list
784
856
this . recalculateStickyRoom ( tag ) ; // update sticky room to make sure it appears if needed
857
+ this . recalculateVideoRoom ( tag ) ;
785
858
changed = true ;
786
859
}
787
860
0 commit comments