@netless/telebox-insider 0.3.0-beta.1 → 0.3.0-beta.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,6 +30,7 @@ import {
30
30
  ValEnhancedResult,
31
31
  withValueEnhancer,
32
32
  } from "value-enhancer";
33
+ import { AppMenu } from "../AppMenu";
33
34
 
34
35
  export * from "./typings";
35
36
  export * from "./constants";
@@ -47,8 +48,20 @@ type ValConfig = {
47
48
  export interface TeleBoxManager extends ValEnhancedResult<ValConfig> {}
48
49
 
49
50
  export class TeleBoxManager {
50
- private boxesStatus$: Map<string, TeleBoxState>;
51
- private lastNotMinimizedBoxesStatus$: Map<string, NotMinimizedBoxState>;
51
+ protected boxesStatus$: Map<string, TeleBoxState>;
52
+ protected lastNotMinimizedBoxesStatus$: Map<string, NotMinimizedBoxState>;
53
+ protected appMenu: AppMenu | undefined;
54
+ protected useBoxesStatus: boolean;
55
+ protected effectBoxesStatusTimer?: {
56
+ skipUpdate: boolean;
57
+ timer: number | undefined;
58
+ resolve?: (skipUpdate: boolean) => void;
59
+ }
60
+ protected effectLastNotMinimizedBoxStatusTimer?: {
61
+ skipUpdate: boolean;
62
+ timer: number | undefined;
63
+ resolve?: (skipUpdate: boolean) => void;
64
+ }
52
65
 
53
66
  public constructor({
54
67
  root = document.body,
@@ -65,8 +78,10 @@ export class TeleBoxManager {
65
78
  collector,
66
79
  namespace = "telebox",
67
80
  readonly = false,
81
+ useBoxesStatus = false,
68
82
  }: TeleBoxManagerConfig = {}) {
69
83
  this._sideEffect = new SideEffectManager();
84
+ this.useBoxesStatus = useBoxesStatus;
70
85
  const { combine, createVal } = createSideEffectBinder(this._sideEffect);
71
86
 
72
87
  this.root = root;
@@ -75,12 +90,17 @@ export class TeleBoxManager {
75
90
  this.boxes$ = createVal<TeleBox[]>([]);
76
91
  this.topBox$ = this.boxes$.derive((boxes) => {
77
92
  if (boxes.length > 0) {
78
- const topBox = boxes.reduce((topBox, box) => {
93
+ let currentTopBox: TeleBox | undefined = undefined;
94
+ const topBox = boxes.reduce((topBox, box) => {
79
95
  if (box.boxStatus && box.boxStatus === TELE_BOX_STATE.Minimized) {
80
96
  return topBox;
81
97
  }
98
+ if (!topBox) {
99
+ topBox = box;
100
+ return topBox;
101
+ }
82
102
  return topBox.zIndex > box.zIndex ? topBox : box;
83
- });
103
+ }, currentTopBox as (TeleBox | undefined));
84
104
  return topBox;
85
105
  }
86
106
  return;
@@ -181,7 +201,7 @@ export class TeleBoxManager {
181
201
  new TeleBoxCollector({
182
202
  visible: minimized,
183
203
  readonly: readonly,
184
- namespace,
204
+ namespace
185
205
  }).mount(root)
186
206
  );
187
207
  collector$.subscribe((collector) => {
@@ -189,20 +209,20 @@ export class TeleBoxManager {
189
209
  collector.setVisible(minimized$.value);
190
210
  collector.setReadonly(readonly$.value);
191
211
  collector.setDarkMode(this._darkMode$.value);
212
+ if (this.useBoxesStatus && this.appMenu) {
213
+ this.appMenu.setContainer(collector.$appMenuContainer);
214
+ }
192
215
  this._sideEffect.add(() => {
216
+ collector.getBoxesStatus = () => {
217
+ return this.boxesStatus$;
218
+ };
193
219
  collector.onClick = () => {
194
220
  if (!readonly$.value) {
195
- if (this.hasMinimizedBox()) {
196
- this.getAllMinimizedBoxes().forEach((box) => {
197
- const lastNotMinimizedBoxStatus = box.lastNotMinimizedBoxStatus;
198
- if (lastNotMinimizedBoxStatus) {
199
- this.setBoxStatus(box.id, lastNotMinimizedBoxStatus);
200
- } else {
201
- this.setBoxStatus(box.id, TELE_BOX_STATE.Normal);
202
- }
203
- });
221
+ if (!this.useBoxesStatus) {
222
+ minimized$.setValue(false);
223
+ } else if (this.useBoxesStatus && this.appMenu) {
224
+ this.appMenu.containerClickHandler();
204
225
  }
205
- minimized$.setValue(false);
206
226
  }
207
227
  };
208
228
  return () => collector.destroy();
@@ -232,6 +252,14 @@ export class TeleBoxManager {
232
252
  return;
233
253
  };
234
254
 
255
+ this._setCollectorRect = (collectorRect: TeleBoxRect | undefined) => {
256
+ if (collector$.value?.$collector) {
257
+ collectorRect$.setValue(collectorRect);
258
+ } else if (import.meta.env.DEV) {
259
+ console.warn("No collector for minimized boxes.");
260
+ }
261
+ };
262
+
235
263
  const collectorRect$ = createVal(
236
264
  minimized$.value ? this._calcCollectorRect() : void 0
237
265
  );
@@ -245,11 +273,7 @@ export class TeleBoxManager {
245
273
  collector$.value?.setVisible(minimized);
246
274
 
247
275
  if (minimized) {
248
- if (collector$.value?.$collector) {
249
- collectorRect$.setValue(this._calcCollectorRect());
250
- } else if (import.meta.env.DEV) {
251
- console.warn("No collector for minimized boxes.");
252
- }
276
+ this._setCollectorRect(this._calcCollectorRect());
253
277
  }
254
278
 
255
279
  this.boxes.forEach((box) =>
@@ -285,10 +309,27 @@ export class TeleBoxManager {
285
309
  if (id) {
286
310
  const box = this.getBox(id);
287
311
  if (box) {
288
- this.focusBox(box);
289
- if ((box.boxStatus && box.boxStatus !== TELE_BOX_STATE.Maximized) || !box.boxStatus) {
312
+ if (!this.useBoxesStatus) {
290
313
  this.makeBoxTop(box);
291
- }
314
+ } else {
315
+ if (box.boxStatus && box.boxStatus === TELE_BOX_STATE.Normal) {
316
+ const maxNormalBoxZIndex = this.getMaxNormalBoxZIndex();
317
+ if (maxNormalBoxZIndex > box.zIndex) {
318
+ this.setBox(box, {
319
+ zIndex: maxNormalBoxZIndex + 1
320
+ }, false);
321
+ }
322
+ } else if(box.boxStatus && box.boxStatus === TELE_BOX_STATE.Maximized){
323
+ const maxMaximizedBoxZIndex = this.getMaxMaximizedBoxZIndex();
324
+ if (maxMaximizedBoxZIndex > box.zIndex) {
325
+ this.setBox(box, {
326
+ zIndex: maxMaximizedBoxZIndex + 1
327
+ }, false);
328
+ }
329
+ this.makeMaximizedTopBoxFocus();
330
+ }
331
+ }
332
+ this.focusBox(box);
292
333
  return;
293
334
  }
294
335
  }
@@ -315,31 +356,85 @@ export class TeleBoxManager {
315
356
  state: state$.value,
316
357
  boxes: this.boxes$.value,
317
358
  containerRect: containerRect$.value,
318
- boxesStatus: this.boxesStatus$,
359
+ getBoxesStatus: () => {
360
+ return this.boxesStatus$;
361
+ },
319
362
  onEvent: (event): void => {
320
363
  switch (event.type) {
321
364
  case TELE_BOX_DELEGATE_EVENT.Maximize: {
322
- if (this.hasBoxesStatus() && this.maxTitleBar.focusedBox?.id) {
323
- this.setBoxStatus(this.maxTitleBar.focusedBox.id, TELE_BOX_STATE.Normal);
324
- this.makeMaximizedTopBoxFocus();
365
+ if (this.hasBoxesStatus()) {
366
+ let targetBox = this.maxTitleBar.focusedBox;
367
+ if (!targetBox) {
368
+ targetBox = this.getMaximizedTopBox();
369
+ }
370
+ if (targetBox?.id) {
371
+ const box = this.getBox(targetBox.id);
372
+ if (box) {
373
+ this.setBox(box, {
374
+ status: TELE_BOX_STATE.Normal,
375
+ zIndex: this.getMaxNormalBoxZIndex() + 1
376
+ }, false, ()=>{
377
+ this.makeMaximizedTopBoxFocus();
378
+ });
379
+ }
380
+ }
325
381
  } else {
326
382
  maximized$.setValue(!maximized$.value);
327
383
  }
328
384
  break;
329
385
  }
330
386
  case TELE_BOX_DELEGATE_EVENT.Minimize: {
331
- if (this.hasBoxesStatus() && this.maxTitleBar.focusedBox?.id) {
332
- this.setBoxStatus(this.maxTitleBar.focusedBox.id, TELE_BOX_STATE.Minimized);
333
- this.makeMaximizedTopBoxFocus();
387
+ if (this.hasBoxesStatus()) {
388
+ let targetBox = this.maxTitleBar.focusedBox;
389
+ if (!targetBox) {
390
+ targetBox = this.getMaximizedTopBox();
391
+ }
392
+ if(targetBox?.id){
393
+ const box = this.getBox(targetBox.id);
394
+ if (box) {
395
+ let isFocusChanged = false;
396
+ if (box.focus) {
397
+ this.blurBox(box);
398
+ isFocusChanged = true;
399
+ }
400
+ this.setBox(box, {
401
+ status: TELE_BOX_STATE.Minimized,
402
+ zIndex: -1
403
+ }, false);
404
+ if (isFocusChanged) {
405
+ this.focusTopBox();
406
+ } else {
407
+ this.makeMaximizedTopBoxFocus();
408
+ }
409
+ }
410
+ }
334
411
  } else {
335
412
  minimized$.setValue(true);
336
413
  }
337
414
  break;
338
415
  }
339
416
  case TELE_BOX_EVENT.Close: {
340
- if (this.hasBoxesStatus() && this.maxTitleBar.focusedBox?.id) {
341
- this.remove(this.maxTitleBar.focusedBox.id);
342
- this.makeMaximizedTopBoxFocus();
417
+ if (this.hasBoxesStatus()) {
418
+ let targetBox = this.maxTitleBar.focusedBox;
419
+ if (!targetBox) {
420
+ targetBox = this.getMaximizedTopBox();
421
+ }
422
+ if (targetBox?.id) {
423
+ const box = this.getBox(targetBox.id);
424
+ if (box) {
425
+ let isFocusChanged = false;
426
+ if (box.focus) {
427
+ this.blurBox(box);
428
+ isFocusChanged = true;
429
+ }
430
+ this.remove(box, false);
431
+ if (isFocusChanged) {
432
+ this.focusTopBox();
433
+ } else {
434
+ this.makeMaximizedTopBoxFocus();
435
+ }
436
+ }
437
+ }
343
438
  } else {
344
439
  this.removeTopBox();
345
440
  this.focusTopBox();
@@ -378,6 +473,10 @@ export class TeleBoxManager {
378
473
  this._state$ = state$;
379
474
 
380
475
  this.root.appendChild(this.maxTitleBar.render());
476
+
477
+ if (useBoxesStatus) {
478
+ this.appMenu = this.createMinimizedAppMenu();
479
+ }
381
480
  }
382
481
 
383
482
  public get boxes(): ReadonlyArray<TeleBox> {
@@ -400,6 +499,8 @@ export class TeleBoxManager {
400
499
 
401
500
  public _calcCollectorRect: () => TeleBoxRect | undefined;
402
501
 
502
+ public _setCollectorRect: (collectorRect: TeleBoxRect | undefined) => void;
503
+
403
504
  public get darkMode(): boolean {
404
505
  return this._darkMode$.value;
405
506
  }
@@ -433,93 +534,293 @@ export class TeleBoxManager {
433
534
  }
434
535
 
435
536
  public setBoxStatus(boxId: string, boxStatus?: TeleBoxState, skipUpdate = false): void {
436
- const boxesStatus = this.boxesStatus$;
437
537
  if (boxStatus) {
438
- const oldBoxStatus = boxesStatus.get(boxId);
439
- boxesStatus.set(boxId, boxStatus);
538
+ const oldBoxStatus = this.boxesStatus$.get(boxId);
539
+ this.boxesStatus$.set(boxId, boxStatus);
440
540
  if (boxStatus === TELE_BOX_STATE.Minimized && oldBoxStatus !== TELE_BOX_STATE.Minimized) {
441
541
  this.setLastNotMinimizedBoxStatus(boxId, oldBoxStatus, skipUpdate);
442
542
  } else if (oldBoxStatus === TELE_BOX_STATE.Minimized && boxStatus !== TELE_BOX_STATE.Minimized) {
443
543
  this.setLastNotMinimizedBoxStatus(boxId, undefined, skipUpdate);
444
544
  }
445
545
  } else {
446
- boxesStatus.delete(boxId);
546
+ this.boxesStatus$.delete(boxId);
447
547
  this.setLastNotMinimizedBoxStatus(boxId, undefined, skipUpdate);
448
548
  }
449
- this.setBoxesStatus(boxesStatus, skipUpdate);
450
549
  if (!skipUpdate) {
451
550
  this.events.emit(TELE_BOX_MANAGER_EVENT.BoxStatus, { id: boxId, boxStatus});
452
551
  }
453
552
  }
454
553
 
455
- private setBoxesStatus(boxesStatus: Map<string, TeleBoxState>, skipUpdate = false): void {
456
- let topBox:TeleBox | undefined;
457
- const topBoxId = this.topBox?.id;
458
- let hasMinimizedBox = false;
554
+ public getBoxStatus(boxId: string): TeleBoxState | undefined {
555
+ return this.boxesStatus$.get(boxId);
556
+ }
557
+
558
+ public get boxesStatus(): ReadonlyMap<string, TeleBoxState> {
559
+ return this.boxesStatus$;
560
+ }
561
+
562
+ public get lastNotMinimizedBoxesStatus(): ReadonlyMap<string, NotMinimizedBoxState> {
563
+ return this.lastNotMinimizedBoxesStatus$;
564
+ }
565
+
566
+ public setBoxesStatus(boxesStatus: Map<string, TeleBoxState>, skipUpdate = false) {
567
+ this.boxesStatus$ = boxesStatus;
568
+ this.effectBoxesStatusChange(skipUpdate);
569
+ }
570
+
571
+ public getBoxesStatus(): Map<string, TeleBoxState> {
572
+ return this.boxesStatus$;
573
+ }
574
+
575
+ protected effectBoxStatusChange(){
576
+ if (!this.useBoxesStatus) {
577
+ return;
578
+ }
579
+ if(this.collector){
580
+ this.collector.updateBoxesStatus();
581
+ if(this.hasMinimizedBox()){
582
+ this._setCollectorRect(this._calcCollectorRect());
583
+ }
584
+ }
585
+ if (this.appMenu) {
586
+ this.appMenu.appMenuChange();
587
+ }
588
+ if (this.maxTitleBar) {
589
+ this.maxTitleBar.updateBoxesStatus();
590
+ }
591
+ }
592
+
593
+ protected effectBoxesStatusTimerFunc(skipUpdate: boolean){
594
+ if (!this.useBoxesStatus) {
595
+ return;
596
+ }
597
+ let newTopBox:TeleBox | undefined;
598
+ const curTopBox = this.topBox;
459
599
  this.boxes.forEach((box) => {
460
- const boxStatus = boxesStatus.get(box.id);
600
+ const boxStatus = this.boxesStatus$.get(box.id);
461
601
  if (boxStatus) {
462
- if (boxStatus !== TELE_BOX_STATE.Minimized && box.zIndex > (topBox?.zIndex ?? 0)) {
463
- topBox = box;
602
+ if (boxStatus !== TELE_BOX_STATE.Minimized && box.zIndex > (newTopBox?.zIndex ?? 0)) {
603
+ newTopBox = box;
464
604
  }
465
605
  box.setBoxStatus(boxStatus, skipUpdate);
466
- if (boxStatus === TELE_BOX_STATE.Minimized) {
467
- hasMinimizedBox = true;
468
- }
469
606
  }
470
607
  });
471
- if (hasMinimizedBox) {
472
- this.collector?.setVisible(true);
473
- if (this.collector?.$collector) {
474
- this.setCollectorRect(this._calcCollectorRect());
475
- } else if (import.meta.env.DEV) {
476
- console.warn("No collector for minimized boxes.");
608
+ this.effectBoxStatusChange();
609
+ if (newTopBox && curTopBox !== newTopBox) {
610
+ this.topBox$.setValue(newTopBox);
611
+ }
612
+ if (!newTopBox && curTopBox) {
613
+ this.topBox$.setValue(undefined);
614
+ }
615
+ }
616
+
617
+ public async effectBoxesStatusChange(skipUpdate = false): Promise<void> {
618
+ if (!this.useBoxesStatus) {
619
+ if (this.effectBoxesStatusTimer && this.effectBoxesStatusTimer.timer) {
620
+ clearTimeout(this.effectBoxesStatusTimer.timer);
621
+ if (this.effectBoxesStatusTimer.resolve) {
622
+ this.effectBoxesStatusTimer.resolve(!!this.effectBoxesStatusTimer?.skipUpdate);
623
+ }
477
624
  }
478
- } else {
479
- this.collector?.setVisible(false);
625
+ this.effectBoxesStatusTimer=undefined;
626
+ return;
480
627
  }
481
- if (topBox && topBoxId !== topBox.id) {
482
- this.makeBoxTop(topBox, skipUpdate);
483
- this.focusTopBox();
484
- this.topBox$.setValue(topBox);
628
+ if (this.effectBoxesStatusTimer && this.effectBoxesStatusTimer.timer) {
629
+ if (this.effectBoxesStatusTimer.skipUpdate !== skipUpdate) {
630
+ clearTimeout(this.effectBoxesStatusTimer.timer);
631
+ if (this.effectBoxesStatusTimer.resolve) {
632
+ this.effectBoxesStatusTimer.resolve(!!this.effectBoxesStatusTimer?.skipUpdate);
633
+ }
634
+ this.effectBoxesStatusTimer.skipUpdate = skipUpdate;
635
+ } else {
636
+ return;
637
+ }
485
638
  }
486
- if (this.maxTitleBar) {
487
- this.maxTitleBar.setBoxesStatus(boxesStatus);
639
+ if (!this.effectBoxesStatusTimer) {
640
+ this.effectBoxesStatusTimer = {
641
+ skipUpdate,
642
+ timer: undefined,
643
+ resolve: undefined,
644
+ } as {
645
+ skipUpdate: boolean;
646
+ timer: number | undefined;
647
+ }
648
+ }
649
+ if (this.effectBoxesStatusTimer) {
650
+ const _skipUpdate = await new Promise<boolean>((resolve)=>{
651
+ this.effectBoxesStatusTimer!.resolve = resolve;
652
+ this.effectBoxesStatusTimer!.timer = setTimeout(()=>{
653
+ if (this.effectBoxesStatusTimer && this.effectBoxesStatusTimer.resolve) {
654
+ this.effectBoxesStatusTimer.resolve(this.effectBoxesStatusTimer!.skipUpdate);
655
+ }
656
+ }, 100) as unknown as number;
657
+ })
658
+ this.effectBoxesStatusTimerFunc(_skipUpdate)
659
+ this.effectBoxesStatusTimer = undefined;
488
660
  }
489
661
  }
490
662
 
491
663
  public hasBoxesStatus(): boolean {
664
+ if (!this.useBoxesStatus) {
665
+ return false;
666
+ }
492
667
  return this.boxesStatus$.size > 0;
493
668
  }
494
669
 
495
670
  public hasMinimizedBox(): boolean {
671
+ if (!this.useBoxesStatus) {
672
+ return false;
673
+ }
496
674
  return this.boxes.some((box) => box.boxStatus && box.boxStatus === TELE_BOX_STATE.Minimized);
497
675
  }
498
676
 
677
+ public getMinimizedBoxesStatus(): Map<string, TELE_BOX_STATE.Minimized> {
678
+ const minimizedBoxes = new Map<string, TELE_BOX_STATE.Minimized>();
679
+ this.boxesStatus$.forEach((boxStatus, boxId) => {
680
+ if (boxStatus === TELE_BOX_STATE.Minimized) {
681
+ minimizedBoxes.set(boxId, boxStatus as TELE_BOX_STATE.Minimized);
682
+ }
683
+ });
684
+ return minimizedBoxes;
685
+ }
686
+
687
+ public getNotMinimizedBoxesStatus(): Map<string, NotMinimizedBoxState> {
688
+ const notMinimizedBoxes = new Map<string, NotMinimizedBoxState>();
689
+ this.boxesStatus$.forEach((boxStatus, boxId) => {
690
+ if (boxStatus !== TELE_BOX_STATE.Minimized) {
691
+ notMinimizedBoxes.set(boxId, boxStatus as NotMinimizedBoxState);
692
+ }
693
+ });
694
+ return notMinimizedBoxes;
695
+ }
696
+
697
+ public getAllMaximizedBoxesStatus(): Map<string, TELE_BOX_STATE.Maximized> {
698
+ const maximizedBoxes = new Map<string, TELE_BOX_STATE.Maximized>();
699
+ this.boxesStatus$.forEach((boxStatus, boxId) => {
700
+ if (boxStatus === TELE_BOX_STATE.Maximized) {
701
+ maximizedBoxes.set(boxId, boxStatus as TELE_BOX_STATE.Maximized);
702
+ }
703
+ });
704
+ return maximizedBoxes;
705
+ }
706
+
707
+ public getAllNormalBoxesStatus(): Map<string, TELE_BOX_STATE.Normal> {
708
+ const normalBoxes = new Map<string, TELE_BOX_STATE.Normal>();
709
+ this.boxesStatus$.forEach((boxStatus, boxId) => {
710
+ if (boxStatus === TELE_BOX_STATE.Normal) {
711
+ normalBoxes.set(boxId, boxStatus as TELE_BOX_STATE.Normal);
712
+ }
713
+ });
714
+ return normalBoxes;
715
+ }
716
+
717
+ public getLastNotMinimizedBoxStatus(boxId: string): NotMinimizedBoxState | undefined {
718
+ return this.lastNotMinimizedBoxesStatus$.get(boxId);
719
+ }
720
+
499
721
  public setLastNotMinimizedBoxStatus(boxId: string, lastNotMinimizedBoxStatus?: NotMinimizedBoxState, skipUpdate = false): void {
500
- const boxesStatus = this.lastNotMinimizedBoxesStatus$;
501
722
  if (lastNotMinimizedBoxStatus) {
502
- boxesStatus.set(boxId, lastNotMinimizedBoxStatus);
723
+ this.lastNotMinimizedBoxesStatus$.set(boxId, lastNotMinimizedBoxStatus);
503
724
  } else {
504
- boxesStatus.delete(boxId);
725
+ this.lastNotMinimizedBoxesStatus$.delete(boxId);
505
726
  }
506
- this.setLastNotMinimizedBoxesStatus(boxesStatus, skipUpdate);
507
727
  if (!skipUpdate) {
508
728
  this.events.emit(TELE_BOX_MANAGER_EVENT.LastNotMinimizedBoxStatus, { id: boxId, boxStatus:lastNotMinimizedBoxStatus});
509
729
  }
510
730
  }
511
731
 
512
- private setLastNotMinimizedBoxesStatus(lastNotMinimizedBoxesStatus: Map<string, NotMinimizedBoxState>, skipUpdate = false): void {
732
+ public setLastNotMinimizedBoxesStatus(lastNotMinimizedBoxesStatus: Map<string, NotMinimizedBoxState>, skipUpdate = false): void {
733
+ this.lastNotMinimizedBoxesStatus$ = lastNotMinimizedBoxesStatus;
734
+ this.effectLastNotMinimizedBoxStatusChange(skipUpdate);
735
+ }
736
+
737
+ protected async effectLastNotMinimizedBoxStatusChange(skipUpdate = false): Promise<void> {
738
+ if (!this.useBoxesStatus) {
739
+ if (this.effectLastNotMinimizedBoxStatusTimer && this.effectLastNotMinimizedBoxStatusTimer.timer) {
740
+ clearTimeout(this.effectLastNotMinimizedBoxStatusTimer.timer);
741
+ if (this.effectLastNotMinimizedBoxStatusTimer.resolve) {
742
+ this.effectLastNotMinimizedBoxStatusTimer.resolve(!!this.effectLastNotMinimizedBoxStatusTimer?.skipUpdate);
743
+ }
744
+ }
745
+ this.effectLastNotMinimizedBoxStatusTimer=undefined;
746
+ return;
747
+ }
748
+ if (this.effectLastNotMinimizedBoxStatusTimer && this.effectLastNotMinimizedBoxStatusTimer.timer) {
749
+ clearTimeout(this.effectLastNotMinimizedBoxStatusTimer.timer);
750
+ if (this.effectLastNotMinimizedBoxStatusTimer.skipUpdate !== skipUpdate) {
751
+ // this.effectLastNotMinimizedBoxStatusFunc(this.effectLastNotMinimizedBoxStatusTimer.skipUpdate)
752
+ if (this.effectLastNotMinimizedBoxStatusTimer.resolve) {
753
+ this.effectLastNotMinimizedBoxStatusTimer.resolve(!!this.effectLastNotMinimizedBoxStatusTimer?.skipUpdate);
754
+ }
755
+ this.effectLastNotMinimizedBoxStatusTimer.skipUpdate = skipUpdate;
756
+ } else {
757
+ return;
758
+ }
759
+ }
760
+ if (!this.effectLastNotMinimizedBoxStatusTimer) {
761
+ this.effectLastNotMinimizedBoxStatusTimer = {
762
+ skipUpdate,
763
+ timer: undefined,
764
+ resolve: undefined,
765
+ } as {
766
+ skipUpdate: boolean;
767
+ timer: number | undefined;
768
+ }
769
+ }
770
+ if (this.effectLastNotMinimizedBoxStatusTimer) {
771
+ const _skipUpdate = await new Promise<boolean>((resolve)=>{
772
+ this.effectLastNotMinimizedBoxStatusTimer!.resolve = resolve;
773
+ this.effectLastNotMinimizedBoxStatusTimer!.timer = setTimeout(()=>{
774
+ if (this.effectLastNotMinimizedBoxStatusTimer && this.effectLastNotMinimizedBoxStatusTimer.resolve) {
775
+ this.effectLastNotMinimizedBoxStatusTimer.resolve(this.effectLastNotMinimizedBoxStatusTimer!.skipUpdate);
776
+ }
777
+ }, 100) as unknown as number;
778
+ })
779
+ this.effectLastNotMinimizedBoxStatusFunc(_skipUpdate)
780
+ this.effectLastNotMinimizedBoxStatusTimer = undefined;
781
+ }
782
+ }
783
+
784
+ protected effectLastNotMinimizedBoxStatusFunc(skipUpdate = false){
785
+ if (!this.useBoxesStatus) {
786
+ return;
787
+ }
513
788
  this.boxes.forEach((box) => {
514
- const boxStatus = lastNotMinimizedBoxesStatus.get(box.id);
515
- if (boxStatus) {
789
+ const boxStatus = this.lastNotMinimizedBoxesStatus$.get(box.id);
790
+ if(boxStatus){
516
791
  box.setLastNotMinimizedBoxStatus(boxStatus, skipUpdate);
517
792
  }
518
793
  });
519
794
  }
520
795
 
521
- private getAllMinimizedBoxes(): ReadonlyArray<TeleBox> {
522
- return this.boxes.filter((box) => box.boxStatus && box.boxStatus === TELE_BOX_STATE.Minimized);
796
+ protected getUnabledBoxesStatusZIndex(): number {
797
+ return this.topBox ? this.topBox.zIndex : 99;
798
+ }
799
+
800
+ /** Maximized box zIndex range: 100-299 */
801
+ public getMaxMaximizedBoxZIndex(): number {
802
+ if (!this.useBoxesStatus) {
803
+ return this.getUnabledBoxesStatusZIndex();
804
+ }
805
+ return this.boxes.reduce((maxZIndex, box) => {
806
+ if (box.boxStatus && box.boxStatus === TELE_BOX_STATE.Maximized) {
807
+ return Math.max(maxZIndex, box.zIndex);
808
+ }
809
+ return maxZIndex;
810
+ }, 99);
811
+ }
812
+
813
+ /** normal box zIndex range: 300-499 */
814
+ public getMaxNormalBoxZIndex(): number {
815
+ if (!this.useBoxesStatus) {
816
+ return this.getUnabledBoxesStatusZIndex();
817
+ }
818
+ return this.boxes.reduce((maxZIndex, box) => {
819
+ if (box.boxStatus && box.boxStatus === TELE_BOX_STATE.Normal) {
820
+ return Math.max(maxZIndex, box.zIndex);
821
+ }
822
+ return maxZIndex;
823
+ }, 299);
523
824
  }
524
825
 
525
826
  public create(
@@ -527,7 +828,7 @@ export class TeleBoxManager {
527
828
  smartPosition = true
528
829
  ): ReadonlyTeleBox {
529
830
  const box = new TeleBox({
530
- zIndex: this.topBox ? this.topBox.zIndex + 1 : 100,
831
+ zIndex: this.getMaxNormalBoxZIndex() + 1,
531
832
  ...(smartPosition ? this.smartPosition(config) : config),
532
833
  darkMode: this.darkMode,
533
834
  prefersColorScheme: this.prefersColorScheme,
@@ -542,6 +843,15 @@ export class TeleBoxManager {
542
843
 
543
844
  box.mount(this.root);
544
845
 
846
+ this.boxes$.setValue([...this.boxes, box]);
847
+
848
+ if (box.boxStatus && this.useBoxesStatus) {
849
+ this.setBox(box, {
850
+ status: box.boxStatus,
851
+ lastNotMinimizedBoxStatus: box._lastNotMinimizedBoxStatus$.value
852
+ }, true);
853
+ }
854
+
545
855
  if (box.focus) {
546
856
  this.focusBox(box);
547
857
  if (smartPosition) {
@@ -549,45 +859,50 @@ export class TeleBoxManager {
549
859
  }
550
860
  }
551
861
 
552
- this.boxes$.setValue([...this.boxes, box]);
553
-
554
- if (box.boxStatus) {
555
- this.setBoxStatus(box.id, box.boxStatus, true);
556
- }
557
-
558
- if (box._lastNotMinimizedBoxStatus$.value) {
559
- this.setLastNotMinimizedBoxStatus(box.id, box._lastNotMinimizedBoxStatus$.value, true);
560
- }
561
-
562
862
  box._delegateEvents.on(TELE_BOX_DELEGATE_EVENT.Maximize, () => {
563
- if (box.boxStatus) {
863
+ if (this.useBoxesStatus && box.boxStatus) {
564
864
  if (box.boxStatus === TELE_BOX_STATE.Maximized) {
565
- this.setBoxStatus(box.id, TELE_BOX_STATE.Normal);
865
+ this.setBox(box.id, {
866
+ status: TELE_BOX_STATE.Normal,
867
+ zIndex: this.getMaxNormalBoxZIndex() + 1
868
+ }, false);
566
869
  } else {
567
- this.boxes.forEach((box) => {
870
+ // 所有normal box都最大化
871
+ [...this.boxes].filter((box) => box.boxStatus === TELE_BOX_STATE.Normal).sort((a, b) => a.zIndex - b.zIndex).forEach((box) => {
568
872
  if (box.boxStatus === TELE_BOX_STATE.Normal) {
569
- this.setBoxStatus(box.id, TELE_BOX_STATE.Maximized);
873
+ this.setBox(box.id, {
874
+ status: TELE_BOX_STATE.Maximized,
875
+ zIndex: this.getMaxMaximizedBoxZIndex() + 1
876
+ }, false);
570
877
  }
571
878
  });
879
+ this.makeMaximizedTopBoxFocus();
572
880
  }
573
- this.makeMaximizedTopBoxFocus();
574
881
  } else {
575
882
  this.setMaximized(!this.maximized);
576
883
  }
577
884
 
578
885
  });
579
886
  box._delegateEvents.on(TELE_BOX_DELEGATE_EVENT.Minimize, () => {
580
- if (box.boxStatus) {
581
- const oldBoxStatus = box.boxStatus;
582
- this.setBoxStatus(box.id, TELE_BOX_STATE.Minimized);
583
- if (oldBoxStatus === TELE_BOX_STATE.Maximized) {
584
- this.makeMaximizedTopBoxFocus();
887
+ if (box.boxStatus && this.useBoxesStatus) {
888
+ if(box.focus) {
889
+ this.blurBox(box);
585
890
  }
891
+ this.setBox(box, {
892
+ status: TELE_BOX_STATE.Minimized,
893
+ zIndex: -1
894
+ }, false, ()=>{
895
+ this.focusTopBox();
896
+ });
897
+
586
898
  } else{
587
899
  this.setMinimized(true);
588
900
  }
589
901
  });
590
902
  box._delegateEvents.on(TELE_BOX_DELEGATE_EVENT.Close, () => {
903
+ if (this.useBoxesStatus && box.focus) {
904
+ this.blurBox(box);
905
+ }
591
906
  this.remove(box);
592
907
  this.focusTopBox();
593
908
  });
@@ -618,12 +933,17 @@ export class TeleBoxManager {
618
933
  });
619
934
  box._zIndex$.reaction((_, __, skipUpdate) => {
620
935
  if (this.boxes.length > 0) {
936
+ let currentTopBox: TeleBox | undefined = undefined;
621
937
  const topBox = this.boxes.reduce((topBox, box) => {
622
938
  if (box.boxStatus && box.boxStatus === TELE_BOX_STATE.Minimized) {
623
939
  return topBox;
624
940
  }
941
+ if (!topBox) {
942
+ topBox = box;
943
+ return topBox;
944
+ }
625
945
  return topBox.zIndex > box.zIndex ? topBox : box;
626
- });
946
+ }, currentTopBox as (TeleBox | undefined));
627
947
  this.topBox$.setValue(topBox);
628
948
  }
629
949
  if (!skipUpdate) {
@@ -669,21 +989,48 @@ export class TeleBoxManager {
669
989
  });
670
990
  }
671
991
 
992
+ public setBox(boxOrID: string | TeleBox, options: {
993
+ status?: TeleBoxState;
994
+ lastNotMinimizedBoxStatus?: NotMinimizedBoxState;
995
+ zIndex?: number;
996
+ }, skipUpdate = false, effectFunc?: () => void){
997
+ const box = this.getBox(boxOrID)
998
+ if (box) {
999
+ const {status, zIndex, lastNotMinimizedBoxStatus} = options;
1000
+ if (status) {
1001
+ this.setBoxStatus(box.id, status, skipUpdate);
1002
+ box.setBoxStatus(status, skipUpdate);
1003
+ this.effectBoxStatusChange();
1004
+ }
1005
+ if (zIndex) {
1006
+ box.setZIndex(zIndex, skipUpdate);
1007
+ }
1008
+ if (lastNotMinimizedBoxStatus) {
1009
+ this.setLastNotMinimizedBoxStatus(box.id, lastNotMinimizedBoxStatus, skipUpdate);
1010
+ box.setLastNotMinimizedBoxStatus(lastNotMinimizedBoxStatus, skipUpdate);
1011
+ }
1012
+ effectFunc && effectFunc();
1013
+ }
1014
+ }
1015
+
672
1016
  public remove(
673
1017
  boxOrID: string | TeleBox,
674
- skipUpdate = false
1018
+ skipUpdate = false,
1019
+ effectFunc?: () => void
675
1020
  ): ReadonlyTeleBox | undefined {
676
1021
  const box = this.getBox(boxOrID);
677
- if (box) {
678
- this.setBoxStatus(box.id, undefined, skipUpdate);
679
- this.setLastNotMinimizedBoxStatus(box.id, undefined, skipUpdate);
680
- }
681
1022
  const index = this.getBoxIndex(boxOrID);
682
1023
  if (index >= 0) {
683
1024
  const boxes = this.boxes.slice();
684
1025
  const deletedBoxes = boxes.splice(index, 1);
685
1026
  this.boxes$.setValue(boxes);
686
1027
  deletedBoxes.forEach((box) => box.destroy());
1028
+ if (box && this.useBoxesStatus) {
1029
+ this.setBoxStatus(box.id, undefined, skipUpdate);
1030
+ this.setLastNotMinimizedBoxStatus(box.id, undefined, skipUpdate);
1031
+ this.effectBoxStatusChange();
1032
+ effectFunc && effectFunc();
1033
+ }
687
1034
  if (!skipUpdate) {
688
1035
  if (this.boxes.length <= 0) {
689
1036
  this.setMaximized(false);
@@ -756,10 +1103,10 @@ export class TeleBoxManager {
756
1103
  this.blurBox(box, skipUpdate);
757
1104
  }
758
1105
  });
759
- if (this.maxTitleBar.hasMaximizedBoxInStatus()) {
760
- this.makeMaximizedBoxFocus(targetBox);
761
- } else {
1106
+ if (!this.useBoxesStatus) {
762
1107
  this.maxTitleBar.focusBox(targetBox);
1108
+ } else if (this.useBoxesStatus && this.maxTitleBar.hasMaximizedBoxInStatus()) {
1109
+ this.makeMaximizedTopBoxFocus();
763
1110
  }
764
1111
  }
765
1112
  }
@@ -780,11 +1127,7 @@ export class TeleBoxManager {
780
1127
  }
781
1128
  }
782
1129
  if (this.maxTitleBar.focusedBox === targetBox) {
783
- if (this.maxTitleBar.hasMaximizedBoxInStatus()) {
784
- this.makeMaximizedTopBoxFocus();
785
- } else {
786
- this.maxTitleBar.focusBox();
787
- }
1130
+ this.maxTitleBar.focusBox();
788
1131
  }
789
1132
  }
790
1133
  }
@@ -799,11 +1142,7 @@ export class TeleBoxManager {
799
1142
  }
800
1143
  });
801
1144
  if (this.maxTitleBar.focusedBox) {
802
- if (this.maxTitleBar.hasMaximizedBoxInStatus()) {
803
- this.makeMaximizedBoxBlur();
804
- } else {
805
- this.maxTitleBar.focusBox();
806
- }
1145
+ this.maxTitleBar.focusBox();
807
1146
  }
808
1147
  }
809
1148
 
@@ -811,6 +1150,7 @@ export class TeleBoxManager {
811
1150
 
812
1151
  protected boxes$: Val<TeleBox[]>;
813
1152
  protected topBox$: Val<TeleBox | undefined>;
1153
+ // protected maximizedTopBox$: Val<MaxTitleBarTeleBox | undefined>;
814
1154
 
815
1155
  protected teleBoxMatcher(
816
1156
  config: TeleBoxManagerQueryConfig
@@ -872,11 +1212,11 @@ export class TeleBoxManager {
872
1212
  if (config.footer != null) {
873
1213
  box.mountFooter(config.footer);
874
1214
  }
875
- if (config.boxStatus) {
876
- this.setBoxStatus(box.id, config.boxStatus, skipUpdate);
877
- }
878
- if (config.lastNotMinimizedBoxStatus) {
879
- this.setLastNotMinimizedBoxStatus(box.id, config.lastNotMinimizedBoxStatus, skipUpdate);
1215
+ if (this.useBoxesStatus && (config.boxStatus || config.lastNotMinimizedBoxStatus)) {
1216
+ this.setBox(box, {
1217
+ status: config.boxStatus,
1218
+ lastNotMinimizedBoxStatus: config.lastNotMinimizedBoxStatus
1219
+ }, skipUpdate);
880
1220
  }
881
1221
  }
882
1222
 
@@ -888,13 +1228,17 @@ export class TeleBoxManager {
888
1228
  let vx = 20;
889
1229
  if (this.topBox) {
890
1230
  vx = this.topBox.intrinsicX * this.containerRect.width + 20;
891
-
892
1231
  if (
893
1232
  vx >
894
1233
  this.containerRect.width - width * this.containerRect.width
895
1234
  ) {
896
1235
  vx = 20;
897
1236
  }
1237
+ } else if (this.hasMinimizedBox()) {
1238
+ // 如果都最小化,则获取lastNotMinimizedBoxesStatus中normal box的最大x
1239
+ vx = [...this.boxes].filter((box) => box.boxStatus && box.boxStatus === TELE_BOX_STATE.Minimized && box.lastNotMinimizedBoxStatus && box.lastNotMinimizedBoxStatus === TELE_BOX_STATE.Normal).reduce((maxX, box) => {
1240
+ return Math.max(maxX, box.intrinsicX * this.containerRect.width + 20);
1241
+ }, vx);
898
1242
  }
899
1243
  x = vx / this.containerRect.width;
900
1244
  }
@@ -912,6 +1256,11 @@ export class TeleBoxManager {
912
1256
  ) {
913
1257
  vy = 20;
914
1258
  }
1259
+ } else if (this.hasMinimizedBox()) {
1260
+ // 如果都最小化,则获取lastNotMinimizedBoxesStatus中normal box的最大y
1261
+ vy = [...this.boxes].filter((box) => box.boxStatus && box.boxStatus === TELE_BOX_STATE.Minimized && box.lastNotMinimizedBoxStatus && box.lastNotMinimizedBoxStatus === TELE_BOX_STATE.Normal).reduce((maxY, box) => {
1262
+ return Math.max(maxY, box.intrinsicY * this.containerRect.height + 20);
1263
+ }, vy);
915
1264
  }
916
1265
 
917
1266
  y = vy / this.containerRect.height;
@@ -921,17 +1270,19 @@ export class TeleBoxManager {
921
1270
  }
922
1271
 
923
1272
  protected makeBoxTop(box: TeleBox, skipUpdate = false): void {
924
- if (this.topBox) {
1273
+ if (!this.useBoxesStatus && this.topBox) {
925
1274
  if (box !== this.topBox) {
926
- const currentBoxZIndex = box.zIndex;
927
- const addZIndex = this.topBox.zIndex + 1 - box.zIndex;
928
1275
  box.setZIndex(this.topBox.zIndex + 1, skipUpdate);
929
- this.makeTopBoxEffect(box.id, addZIndex, currentBoxZIndex, skipUpdate);
930
1276
  }
1277
+ } else if (this.useBoxesStatus) {
1278
+ // todo
931
1279
  }
932
1280
  }
933
1281
 
934
- protected makeMaximizedTopBoxFocus(): void {
1282
+ protected getMaximizedTopBox(): MaxTitleBarTeleBox | undefined {
1283
+ if (!this.useBoxesStatus) {
1284
+ return undefined;
1285
+ }
935
1286
  let maximizedBox: MaxTitleBarTeleBox | undefined;
936
1287
  if (this.maxTitleBar.hasMaximizedBoxInStatus()) {
937
1288
  maximizedBox = this.maxTitleBar.MaximizedBoxes.reduce((topBox, currentBox) => {
@@ -939,49 +1290,17 @@ export class TeleBoxManager {
939
1290
  return currentBox;
940
1291
  }
941
1292
  return topBox.zIndex > currentBox.zIndex ? topBox : currentBox;
942
- });
943
- if (maximizedBox) {
944
- this.maxTitleBar.focusBox(maximizedBox);
945
- }
946
- }
947
- }
948
-
949
- private makeTopBoxEffect(boxId: string, addZIndex: number, currentZIndex: number, skipUpdate = false): void {
950
- if (this.hasBoxesStatus() && this.hasMinimizedBox()) {
951
- this.boxes.forEach((b) => {
952
- if (b.boxStatus && b.id !== boxId && b.zIndex >= currentZIndex) {
953
- b.setZIndex(b.zIndex + addZIndex, skipUpdate);
954
- }
955
- });
1293
+ }, );
956
1294
  }
1295
+ return maximizedBox;
957
1296
  }
958
1297
 
959
- protected makeMaximizedBoxFocus(maximizedBox: MaxTitleBarTeleBox, skipUpdate = false): void {
960
- if (this.maxTitleBar.hasMaximizedBoxInStatus() && this.maxTitleBar.MaximizedBoxes.find((box) => box.id === maximizedBox.id)) {
961
- const currentZIndex = maximizedBox.zIndex;
962
- const currentMaximizedTopBox = this.maxTitleBar.MaximizedBoxes.reduce((topBox, box) => {
963
- if (!topBox) {
964
- return box;
965
- }
966
- return topBox.zIndex > box.zIndex ? topBox : box;
967
- });
968
- if (currentMaximizedTopBox !== maximizedBox) {
969
- const addZIndex = currentMaximizedTopBox.zIndex - currentZIndex + 1;
970
- this.boxes.forEach((box) => {
971
- if (this.maxTitleBar.MaximizedBoxes.find((b) => b.id === box.id && b.id !== maximizedBox.id)) {
972
- return;
973
- }
974
- if (box.zIndex >= currentZIndex) {
975
- box.setZIndex(box.zIndex + addZIndex, skipUpdate);
976
- }
977
- });
978
- }
979
- this.maxTitleBar.focusBox(maximizedBox);
1298
+ protected makeMaximizedTopBoxFocus(): void {
1299
+ if (!this.useBoxesStatus) {
1300
+ return;
980
1301
  }
981
- }
982
-
983
- protected makeMaximizedBoxBlur(): void {
984
- this.maxTitleBar.focusBox();
1302
+ const maximizedBox: MaxTitleBarTeleBox | undefined = this.getMaximizedTopBox();
1303
+ this.maxTitleBar.focusBox(maximizedBox);
985
1304
  }
986
1305
 
987
1306
  protected getBoxIndex(boxOrID: TeleBox | string): number {
@@ -990,9 +1309,23 @@ export class TeleBoxManager {
990
1309
  : this.boxes.findIndex((box) => box === boxOrID);
991
1310
  }
992
1311
 
993
- protected getBox(boxOrID: TeleBox | string): TeleBox | undefined {
1312
+ public getBox(boxOrID: TeleBox | string): TeleBox | undefined {
994
1313
  return typeof boxOrID === "string"
995
1314
  ? this.boxes.find((box) => box.id === boxOrID)
996
1315
  : boxOrID;
997
1316
  }
1317
+
1318
+ public createMinimizedAppMenu():AppMenu | undefined {
1319
+ if (this.collector?.$appMenuContainer) {
1320
+ return new AppMenu({
1321
+ manager: this,
1322
+ container: this.collector?.$appMenuContainer,
1323
+ theme: this.prefersColorScheme ? 'dark' : 'light',
1324
+ getBoxesStatus: () => {
1325
+ return this.boxesStatus$;
1326
+ }
1327
+ });
1328
+ }
1329
+ return;
1330
+ }
998
1331
  }