@@ -5,7 +5,7 @@ import { css } from '@emotion/react';
5
5
import isEmpty from 'lodash-es/isEmpty.js' ;
6
6
import { useObservable , useSubscription } from 'observable-hooks' ;
7
7
import type { KeyboardEventHandler , ReactNode } from 'react' ;
8
- import { useCallback , useEffect , useRef , useState } from 'react' ;
8
+ import { useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
9
9
import * as rxjs from 'rxjs' ;
10
10
import { v4 as uuid } from 'uuid' ;
11
11
import { getExperienceMindState } from '../../common/game/get-experience-mindstate.js' ;
@@ -347,167 +347,173 @@ const GridPage: React.FC = (): ReactNode => {
347
347
const [ gridWidthRef , { width : gridWidth } ] = useMeasure < HTMLDivElement > ( ) ;
348
348
const gridHeight = windowSize . height - bottomBarSize . height - 40 ;
349
349
350
- // TODO define a default config set
351
- // TODO allow users to customize the set and add/remove items
352
- // TODO IPC handler to get/save the user's config set
353
- const configGridItems : Array < GridItemConfig > = [ ] ;
350
+ const contentGridItems = useMemo < Array < GridItemContent > > ( ( ) => {
351
+ // TODO define a default config set
352
+ // TODO allow users to customize the set and add/remove items
353
+ // TODO IPC handler to get/save the user's config set
354
+ const configGridItems : Array < GridItemConfig > = [ ] ;
354
355
355
- configGridItems . push ( {
356
- gameItemInfo : getGameItemInfo ( GameItemId . ROOM ) ,
357
- whenVisibleStreamToItemIds : [ GameItemId . ROOM ] ,
358
- whenHiddenStreamToItemIds : [ ] ,
359
- } ) ;
356
+ configGridItems . push ( {
357
+ gameItemInfo : getGameItemInfo ( GameItemId . ROOM ) ,
358
+ whenVisibleStreamToItemIds : [ GameItemId . ROOM ] ,
359
+ whenHiddenStreamToItemIds : [ ] ,
360
+ } ) ;
360
361
361
- configGridItems . push ( {
362
- gameItemInfo : getGameItemInfo ( GameItemId . EXPERIENCE ) ,
363
- whenVisibleStreamToItemIds : [ GameItemId . EXPERIENCE ] ,
364
- whenHiddenStreamToItemIds : [ ] ,
365
- } ) ;
362
+ configGridItems . push ( {
363
+ gameItemInfo : getGameItemInfo ( GameItemId . EXPERIENCE ) ,
364
+ whenVisibleStreamToItemIds : [ GameItemId . EXPERIENCE ] ,
365
+ whenHiddenStreamToItemIds : [ ] ,
366
+ } ) ;
366
367
367
- configGridItems . push ( {
368
- gameItemInfo : getGameItemInfo ( GameItemId . MAIN ) ,
369
- whenVisibleStreamToItemIds : [ GameItemId . MAIN ] ,
370
- whenHiddenStreamToItemIds : [ ] ,
371
- } ) ;
368
+ configGridItems . push ( {
369
+ gameItemInfo : getGameItemInfo ( GameItemId . MAIN ) ,
370
+ whenVisibleStreamToItemIds : [ GameItemId . MAIN ] ,
371
+ whenHiddenStreamToItemIds : [ ] ,
372
+ } ) ;
372
373
373
- configGridItems . push ( {
374
- gameItemInfo : getGameItemInfo ( GameItemId . SPELLS ) ,
375
- whenVisibleStreamToItemIds : [ GameItemId . SPELLS ] ,
376
- whenHiddenStreamToItemIds : [ ] ,
377
- } ) ;
374
+ configGridItems . push ( {
375
+ gameItemInfo : getGameItemInfo ( GameItemId . SPELLS ) ,
376
+ whenVisibleStreamToItemIds : [ GameItemId . SPELLS ] ,
377
+ whenHiddenStreamToItemIds : [ ] ,
378
+ } ) ;
378
379
379
- const configItemsMap : Record < string , GridItemConfig > = { } ;
380
- const configItemIds : Array < string > = [ ] ;
381
- configGridItems . forEach ( ( configItem ) => {
382
- const itemId = configItem . gameItemInfo . itemId ;
383
- configItemsMap [ itemId ] = configItem ;
384
- configItemIds . push ( itemId ) ;
385
- } ) ;
380
+ const configItemsMap : Record < string , GridItemConfig > = { } ;
381
+ const configItemIds : Array < string > = [ ] ;
382
+ configGridItems . forEach ( ( configItem ) => {
383
+ const itemId = configItem . gameItemInfo . itemId ;
384
+ configItemsMap [ itemId ] = configItem ;
385
+ configItemIds . push ( itemId ) ;
386
+ } ) ;
386
387
387
- // TODO define a default layout
388
- // TODO IPC handler to get/save a layout
389
- // TODO allow user to assign layouts to characters
390
- let layoutGridItems = new Array < GridItemInfo > ( ) ;
391
-
392
- layoutGridItems . push ( {
393
- itemId : 'room' ,
394
- itemTitle : 'Room' ,
395
- isFocused : false ,
396
- layout : {
397
- x : 0 ,
398
- y : 0 ,
399
- width : 828 ,
400
- height : 200 ,
401
- } ,
402
- } ) ;
388
+ // TODO define a default layout
389
+ // TODO IPC handler to get/save a layout
390
+ // TODO allow user to assign layouts to characters
391
+ let layoutGridItems = new Array < GridItemInfo > ( ) ;
392
+
393
+ layoutGridItems . push ( {
394
+ itemId : 'room' ,
395
+ itemTitle : 'Room' ,
396
+ isFocused : false ,
397
+ layout : {
398
+ x : 0 ,
399
+ y : 0 ,
400
+ width : 828 ,
401
+ height : 200 ,
402
+ } ,
403
+ } ) ;
403
404
404
- layoutGridItems . push ( {
405
- itemId : 'experience' ,
406
- itemTitle : 'Experience' ,
407
- isFocused : false ,
408
- layout : {
409
- x : 828 ,
410
- y : 0 ,
411
- width : 306 ,
412
- height : 392 ,
413
- } ,
414
- } ) ;
405
+ layoutGridItems . push ( {
406
+ itemId : 'experience' ,
407
+ itemTitle : 'Experience' ,
408
+ isFocused : false ,
409
+ layout : {
410
+ x : 828 ,
411
+ y : 0 ,
412
+ width : 306 ,
413
+ height : 392 ,
414
+ } ,
415
+ } ) ;
415
416
416
- layoutGridItems . push ( {
417
- itemId : 'spells' ,
418
- itemTitle : 'Spells' ,
419
- isFocused : false ,
420
- layout : {
421
- x : 828 ,
422
- y : 390 ,
423
- width : 306 ,
424
- height : 310 ,
425
- } ,
426
- } ) ;
417
+ layoutGridItems . push ( {
418
+ itemId : 'spells' ,
419
+ itemTitle : 'Spells' ,
420
+ isFocused : false ,
421
+ layout : {
422
+ x : 828 ,
423
+ y : 390 ,
424
+ width : 306 ,
425
+ height : 310 ,
426
+ } ,
427
+ } ) ;
427
428
428
- layoutGridItems . push ( {
429
- itemId : 'main' ,
430
- itemTitle : 'Main' ,
431
- isFocused : true ,
432
- layout : {
433
- x : 0 ,
434
- y : 200 ,
435
- width : 828 ,
436
- height : 500 ,
437
- } ,
438
- } ) ;
429
+ layoutGridItems . push ( {
430
+ itemId : 'main' ,
431
+ itemTitle : 'Main' ,
432
+ isFocused : true ,
433
+ layout : {
434
+ x : 0 ,
435
+ y : 200 ,
436
+ width : 828 ,
437
+ height : 500 ,
438
+ } ,
439
+ } ) ;
439
440
440
- // Drop any items that no longer have a matching config item.
441
- layoutGridItems = layoutGridItems . filter ( ( layoutItem ) => {
442
- return configItemIds . includes ( layoutItem . itemId ) ;
443
- } ) ;
441
+ // Drop any items that no longer have a matching config item.
442
+ layoutGridItems = layoutGridItems . filter ( ( layoutItem ) => {
443
+ return configItemIds . includes ( layoutItem . itemId ) ;
444
+ } ) ;
444
445
445
- const layoutItemsMap : Record < string , GridItemInfo > = { } ;
446
- const layoutItemIds : Array < string > = [ ] ;
447
- layoutGridItems . forEach ( ( layoutItem ) => {
448
- const itemId = layoutItem . itemId ;
449
- layoutItemsMap [ itemId ] = layoutItem ;
450
- layoutItemIds . push ( itemId ) ;
451
- } ) ;
446
+ const layoutItemsMap : Record < string , GridItemInfo > = { } ;
447
+ const layoutItemIds : Array < string > = [ ] ;
448
+ layoutGridItems . forEach ( ( layoutItem ) => {
449
+ const itemId = layoutItem . itemId ;
450
+ layoutItemsMap [ itemId ] = layoutItem ;
451
+ layoutItemIds . push ( itemId ) ;
452
+ } ) ;
452
453
453
- // Map of item ids to the item ids that should stream to it.
454
- // The key is the item id that should receive the stream(s).
455
- // The values are the items redirecting their stream to the key item.
456
- const itemStreamMapping : Record < string , Array < string > > = { } ;
457
-
458
- // If layout includes the config item then stream to its visible items.
459
- // If layout does not include the config item then stream to its hidden items.
460
- configGridItems . forEach ( ( configItem ) => {
461
- const itemId = configItem . gameItemInfo . itemId ;
462
-
463
- const streamToItemIds = layoutItemsMap [ itemId ]
464
- ? configItem . whenVisibleStreamToItemIds
465
- : configItem . whenHiddenStreamToItemIds ;
466
-
467
- // TODO rename this method and move it out the for-each loop
468
- // If an item is hidden and redirects elsewhere, follow the chain
469
- // until we find an item that is visible to truly redirect to.
470
- // This is necessary because the layout may not include all items.
471
- const funcX = ( streamToItemIds : Array < string > , itemId : string ) => {
472
- streamToItemIds . forEach ( ( streamToItemId ) => {
473
- if ( layoutItemsMap [ streamToItemId ] ) {
474
- // We're in luck. We found a visible item to stream to.
475
- itemStreamMapping [ streamToItemId ] ||= [ ] ;
476
- itemStreamMapping [ streamToItemId ] . push ( itemId ) ;
477
- } else {
478
- // Well, where the hidden item wanted to redirect to
479
- // also is hidden so we need to keep looking for a visible item.
480
- funcX (
481
- configItemsMap [ streamToItemId ] . whenHiddenStreamToItemIds ,
482
- itemId
483
- ) ;
484
- }
485
- } ) ;
486
- } ;
454
+ // Map of item ids to the item ids that should stream to it.
455
+ // The key is the item id that should receive the stream(s).
456
+ // The values are the items redirecting their stream to the key item.
457
+ const itemStreamMapping : Record < string , Array < string > > = { } ;
458
+
459
+ // If layout includes the config item then stream to its visible items.
460
+ // If layout does not include the config item then stream to its hidden items.
461
+ configGridItems . forEach ( ( configItem ) => {
462
+ const itemId = configItem . gameItemInfo . itemId ;
463
+
464
+ const streamToItemIds = layoutItemsMap [ itemId ]
465
+ ? configItem . whenVisibleStreamToItemIds
466
+ : configItem . whenHiddenStreamToItemIds ;
467
+
468
+ // TODO rename this method and move it out the for-each loop
469
+ // If an item is hidden and redirects elsewhere, follow the chain
470
+ // until we find an item that is visible to truly redirect to.
471
+ // This is necessary because the layout may not include all items.
472
+ const funcX = ( streamToItemIds : Array < string > , itemId : string ) => {
473
+ streamToItemIds . forEach ( ( streamToItemId ) => {
474
+ if ( layoutItemsMap [ streamToItemId ] ) {
475
+ // We're in luck. We found a visible item to stream to.
476
+ itemStreamMapping [ streamToItemId ] ||= [ ] ;
477
+ itemStreamMapping [ streamToItemId ] . push ( itemId ) ;
478
+ } else {
479
+ // Well, where the hidden item wanted to redirect to
480
+ // also is hidden so we need to keep looking for a visible item.
481
+ funcX (
482
+ configItemsMap [ streamToItemId ] . whenHiddenStreamToItemIds ,
483
+ itemId
484
+ ) ;
485
+ }
486
+ } ) ;
487
+ } ;
487
488
488
- funcX ( streamToItemIds , itemId ) ;
489
- } ) ;
489
+ funcX ( streamToItemIds , itemId ) ;
490
+ } ) ;
490
491
491
- const contentGridItems : Array < GridItemContent > = [ ] ;
492
-
493
- layoutGridItems . forEach ( ( layoutItem ) => {
494
- const configItem = configItemsMap [ layoutItem . itemId ] ;
495
-
496
- contentGridItems . push ( {
497
- itemId : layoutItem . itemId ,
498
- itemTitle : configItem . gameItemInfo . itemTitle ?? layoutItem . itemTitle ,
499
- isFocused : layoutItem . isFocused ,
500
- layout : layoutItem . layout ,
501
- content : (
502
- < GameStream
503
- gameStreamIds = { itemStreamMapping [ layoutItem . itemId ] . map ( ( itemId ) => {
504
- return configItemsMap [ itemId ] . gameItemInfo . streamId ;
505
- } ) }
506
- stream$ = { gameLogLineSubject$ }
507
- />
508
- ) ,
492
+ const contentGridItems : Array < GridItemContent > = [ ] ;
493
+
494
+ layoutGridItems . forEach ( ( layoutItem ) => {
495
+ const configItem = configItemsMap [ layoutItem . itemId ] ;
496
+
497
+ contentGridItems . push ( {
498
+ itemId : layoutItem . itemId ,
499
+ itemTitle : configItem . gameItemInfo . itemTitle ?? layoutItem . itemTitle ,
500
+ isFocused : layoutItem . isFocused ,
501
+ layout : layoutItem . layout ,
502
+ content : (
503
+ < GameStream
504
+ gameStreamIds = { itemStreamMapping [ layoutItem . itemId ] . map (
505
+ ( itemId ) => {
506
+ return configItemsMap [ itemId ] . gameItemInfo . streamId ;
507
+ }
508
+ ) }
509
+ stream$ = { gameLogLineSubject$ }
510
+ />
511
+ ) ,
512
+ } ) ;
509
513
} ) ;
510
- } ) ;
514
+
515
+ return contentGridItems ;
516
+ } , [ gameLogLineSubject$ ] ) ;
511
517
512
518
return (
513
519
< EuiPageTemplate
0 commit comments