@netless/window-manager 1.0.13-test.2 → 1.0.13-test.20
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.
- package/dist/index.d.ts +33 -1
- package/dist/index.js +14 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +552 -28
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/AppListener.ts +1 -20
- package/src/AppManager.ts +29 -4
- package/src/AttributesDelegate.ts +7 -5
- package/src/ContainerResizeObserver.ts +15 -4
- package/src/InternalEmitter.ts +1 -0
- package/src/Utils/Common.ts +0 -1
- package/src/Utils/Reactive.ts +2 -2
- package/src/Utils/RoomHacker.ts +18 -1
- package/src/Utils/log.ts +37 -0
- package/src/View/MainView.ts +124 -12
- package/src/index.ts +451 -3
package/src/index.ts
CHANGED
|
@@ -199,6 +199,25 @@ export type MountParams = {
|
|
|
199
199
|
useBoxesStatus?: boolean;
|
|
200
200
|
};
|
|
201
201
|
|
|
202
|
+
type DiagnosticColorChannels = {
|
|
203
|
+
raw: string;
|
|
204
|
+
r?: number;
|
|
205
|
+
g?: number;
|
|
206
|
+
b?: number;
|
|
207
|
+
a?: number;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
type DiagnosticRect = {
|
|
211
|
+
x: number;
|
|
212
|
+
y: number;
|
|
213
|
+
width: number;
|
|
214
|
+
height: number;
|
|
215
|
+
top: number;
|
|
216
|
+
right: number;
|
|
217
|
+
bottom: number;
|
|
218
|
+
left: number;
|
|
219
|
+
};
|
|
220
|
+
|
|
202
221
|
export const reconnectRefresher = new ReconnectRefresher({ emitter: internalEmitter });
|
|
203
222
|
export class WindowManager
|
|
204
223
|
extends InvisiblePlugin<WindowMangerAttributes, any>
|
|
@@ -253,6 +272,7 @@ export class WindowManager
|
|
|
253
272
|
super(context);
|
|
254
273
|
WindowManager.displayer = context.displayer;
|
|
255
274
|
(window as any).NETLESS_DEPS = __APP_DEPENDENCIES__;
|
|
275
|
+
this.emitter.on('mainViewScenePathChange', this.onMainViewScenePathChangeHandler)
|
|
256
276
|
}
|
|
257
277
|
|
|
258
278
|
public static onCreate(manager: WindowManager) {
|
|
@@ -386,10 +406,438 @@ export class WindowManager
|
|
|
386
406
|
console.warn("[WindowManager]: indexedDB open failed");
|
|
387
407
|
console.log(error);
|
|
388
408
|
}
|
|
389
|
-
|
|
409
|
+
manager.emitter.on('mainViewScenePathChange', manager.onMainViewScenePathChangeHandler)
|
|
390
410
|
return manager;
|
|
391
411
|
}
|
|
392
412
|
|
|
413
|
+
public onMainViewScenePathChangeHandler = (scenePath: string) => {
|
|
414
|
+
const mainViewElement = this.mainView.divElement;
|
|
415
|
+
this.logMainViewVisibilityDiagnostics("onMainViewScenePathChange", scenePath, mainViewElement);
|
|
416
|
+
if (mainViewElement) {
|
|
417
|
+
const backgroundImage = mainViewElement.querySelector('.background img');
|
|
418
|
+
if (backgroundImage) {
|
|
419
|
+
const backgroundImageRect = backgroundImage?.getBoundingClientRect();
|
|
420
|
+
const backgroundImageCSS = window.getComputedStyle(backgroundImage);
|
|
421
|
+
const backgroundImageVisible = backgroundImageRect?.width > 0 && backgroundImageRect?.height > 0 && backgroundImageCSS.display !== 'none';
|
|
422
|
+
const camera = this.mainView.camera;
|
|
423
|
+
console.log("[window-manager] backgroundImageVisible:" + backgroundImageVisible + " camera:" + JSON.stringify(camera));
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
console.log("[window-manager] onMainViewScenePathChange scenePath:" + scenePath + ' backgroundImageVisible is not found');
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
console.log("[window-manager] onMainViewScenePathChange scenePath:" + scenePath + ' mainViewElement is not found');
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
public logMainViewVisibilityDiagnostics(
|
|
433
|
+
tag: string,
|
|
434
|
+
scenePath?: string,
|
|
435
|
+
mainViewElement?: HTMLDivElement | null
|
|
436
|
+
): void {
|
|
437
|
+
const element = mainViewElement ?? this.mainView?.divElement;
|
|
438
|
+
const label = scenePath ? `${tag}:${scenePath}` : tag;
|
|
439
|
+
const payload = this.collectMainViewVisibilityDiagnostics(element, scenePath);
|
|
440
|
+
this.emitMainViewVisibilityDiagnostic(label, payload.summary);
|
|
441
|
+
if (payload.details) {
|
|
442
|
+
this.emitMainViewVisibilityDiagnostic(`${label}:details`, payload.details);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
private emitMainViewVisibilityDiagnostic(tag: string, payload: unknown): void {
|
|
447
|
+
const content = `[window-manager][visibility][${tag}] ${JSON.stringify(payload)}`;
|
|
448
|
+
// console.log(content);
|
|
449
|
+
this._roomLogger?.info(content);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
private collectMainViewVisibilityDiagnostics(
|
|
453
|
+
mainViewElement: HTMLDivElement | null | undefined,
|
|
454
|
+
scenePath?: string
|
|
455
|
+
): {
|
|
456
|
+
summary: Record<string, any>;
|
|
457
|
+
details: Record<string, any> | null;
|
|
458
|
+
} {
|
|
459
|
+
const element = mainViewElement ?? null;
|
|
460
|
+
const backgroundImage = element?.querySelector(".background img") as HTMLImageElement | null;
|
|
461
|
+
const elementDiagnostic = element ? this.collectElementDiagnostic(element) : null;
|
|
462
|
+
const chainDiagnostics = element ? this.collectElementChainDiagnostics(element) : [];
|
|
463
|
+
const elementRect = element?.getBoundingClientRect?.() ?? null;
|
|
464
|
+
const centerPoint = elementRect
|
|
465
|
+
? {
|
|
466
|
+
x: elementRect.left + elementRect.width / 2,
|
|
467
|
+
y: elementRect.top + elementRect.height / 2,
|
|
468
|
+
}
|
|
469
|
+
: undefined;
|
|
470
|
+
const topElement =
|
|
471
|
+
centerPoint &&
|
|
472
|
+
Number.isFinite(centerPoint.x) &&
|
|
473
|
+
Number.isFinite(centerPoint.y)
|
|
474
|
+
? document.elementFromPoint(centerPoint.x, centerPoint.y)
|
|
475
|
+
: null;
|
|
476
|
+
const overlayStack =
|
|
477
|
+
centerPoint &&
|
|
478
|
+
Number.isFinite(centerPoint.x) &&
|
|
479
|
+
Number.isFinite(centerPoint.y) &&
|
|
480
|
+
document.elementsFromPoint
|
|
481
|
+
? document
|
|
482
|
+
.elementsFromPoint(centerPoint.x, centerPoint.y)
|
|
483
|
+
.slice(0, 10)
|
|
484
|
+
.map(item => this.describeElement(item))
|
|
485
|
+
.filter((item): item is string => item !== null)
|
|
486
|
+
: [];
|
|
487
|
+
const topElementDiagnostic = topElement ? this.collectElementDiagnostic(topElement) : null;
|
|
488
|
+
const backgroundImageDiagnostic = backgroundImage
|
|
489
|
+
? this.collectImageDiagnostic(backgroundImage)
|
|
490
|
+
: null;
|
|
491
|
+
const blockers: string[] = [];
|
|
492
|
+
const warnings: string[] = [];
|
|
493
|
+
const suspiciousAncestors: Array<Record<string, any>> = [];
|
|
494
|
+
const mainViewBlockers: string[] = [];
|
|
495
|
+
const mainViewWarnings: string[] = [];
|
|
496
|
+
|
|
497
|
+
if (!element) {
|
|
498
|
+
blockers.push("mainViewElement.missing");
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
if (document.hidden || document.visibilityState === "hidden") {
|
|
502
|
+
blockers.push("document.hidden");
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
if (elementDiagnostic) {
|
|
506
|
+
this.appendRenderImpactIssues(
|
|
507
|
+
"mainViewElement",
|
|
508
|
+
elementDiagnostic,
|
|
509
|
+
mainViewBlockers,
|
|
510
|
+
mainViewWarnings
|
|
511
|
+
);
|
|
512
|
+
blockers.push(...mainViewBlockers);
|
|
513
|
+
warnings.push(...mainViewWarnings);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
chainDiagnostics.slice(1).forEach((diagnostic, index) => {
|
|
517
|
+
const ancestorBlockers: string[] = [];
|
|
518
|
+
const ancestorWarnings: string[] = [];
|
|
519
|
+
this.appendRenderImpactIssues(
|
|
520
|
+
`ancestor[${index + 1}]`,
|
|
521
|
+
diagnostic,
|
|
522
|
+
ancestorBlockers,
|
|
523
|
+
ancestorWarnings
|
|
524
|
+
);
|
|
525
|
+
if (ancestorBlockers.length > 0 || ancestorWarnings.length > 0) {
|
|
526
|
+
blockers.push(...ancestorBlockers);
|
|
527
|
+
warnings.push(...ancestorWarnings);
|
|
528
|
+
suspiciousAncestors.push(this.pickRenderRelevantFields(diagnostic));
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
let backgroundImageStatus: Record<string, any> | null = null;
|
|
533
|
+
const backgroundImageBlockers: string[] = [];
|
|
534
|
+
const backgroundImageWarnings: string[] = [];
|
|
535
|
+
if (backgroundImageDiagnostic) {
|
|
536
|
+
backgroundImageStatus = this.pickBackgroundImageStatus(backgroundImageDiagnostic);
|
|
537
|
+
this.appendRenderImpactIssues(
|
|
538
|
+
"backgroundImage",
|
|
539
|
+
backgroundImageDiagnostic,
|
|
540
|
+
backgroundImageBlockers,
|
|
541
|
+
backgroundImageWarnings
|
|
542
|
+
);
|
|
543
|
+
blockers.push(...backgroundImageBlockers);
|
|
544
|
+
warnings.push(...backgroundImageWarnings);
|
|
545
|
+
if (backgroundImageDiagnostic.complete === false) {
|
|
546
|
+
warnings.push("backgroundImage.loading");
|
|
547
|
+
} else if (backgroundImageDiagnostic.naturalWidth === 0) {
|
|
548
|
+
warnings.push("backgroundImage.empty");
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
let topElementSummary: Record<string, any> | null = null;
|
|
553
|
+
if (topElementDiagnostic) {
|
|
554
|
+
const coveredByOutsideElement = Boolean(
|
|
555
|
+
element && topElement && topElement !== element && !element.contains(topElement)
|
|
556
|
+
);
|
|
557
|
+
topElementSummary = {
|
|
558
|
+
node: topElementDiagnostic.node,
|
|
559
|
+
coveredByOutsideElement,
|
|
560
|
+
};
|
|
561
|
+
if (coveredByOutsideElement) {
|
|
562
|
+
warnings.push(`center.coveredBy:${topElementDiagnostic.node}`);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
const summary: Record<string, any> = {
|
|
567
|
+
scenePath: scenePath || null,
|
|
568
|
+
timestamp: new Date().toISOString(),
|
|
569
|
+
status:
|
|
570
|
+
blockers.length > 0
|
|
571
|
+
? "blocked"
|
|
572
|
+
: warnings.length > 0
|
|
573
|
+
? "uncertain"
|
|
574
|
+
: "likely-renderable",
|
|
575
|
+
canRender: blockers.length === 0,
|
|
576
|
+
blockers,
|
|
577
|
+
warnings,
|
|
578
|
+
};
|
|
579
|
+
if (
|
|
580
|
+
backgroundImageStatus &&
|
|
581
|
+
backgroundImageDiagnostic &&
|
|
582
|
+
(backgroundImageDiagnostic.complete === false ||
|
|
583
|
+
backgroundImageDiagnostic.naturalWidth === 0)
|
|
584
|
+
) {
|
|
585
|
+
summary.backgroundImage = backgroundImageStatus;
|
|
586
|
+
}
|
|
587
|
+
if (topElementSummary?.coveredByOutsideElement) {
|
|
588
|
+
summary.coveringElement = topElementSummary.node;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
const shouldEmitDetails =
|
|
592
|
+
blockers.length > 0 ||
|
|
593
|
+
warnings.some(
|
|
594
|
+
warning =>
|
|
595
|
+
warning !== "backgroundImage.loading" &&
|
|
596
|
+
warning !== "backgroundImage.empty"
|
|
597
|
+
);
|
|
598
|
+
const details: Record<string, any> = {};
|
|
599
|
+
if ((mainViewBlockers.length > 0 || mainViewWarnings.length > 0) && elementDiagnostic) {
|
|
600
|
+
details.mainViewElement = this.pickRenderRelevantFields(elementDiagnostic);
|
|
601
|
+
}
|
|
602
|
+
if (
|
|
603
|
+
suspiciousAncestors.length > 0
|
|
604
|
+
) {
|
|
605
|
+
details.suspiciousAncestors = suspiciousAncestors;
|
|
606
|
+
}
|
|
607
|
+
if (
|
|
608
|
+
backgroundImageDiagnostic &&
|
|
609
|
+
(backgroundImageBlockers.length > 0 ||
|
|
610
|
+
backgroundImageWarnings.length > 0 ||
|
|
611
|
+
backgroundImageDiagnostic.complete === false ||
|
|
612
|
+
backgroundImageDiagnostic.naturalWidth === 0)
|
|
613
|
+
) {
|
|
614
|
+
details.backgroundImage = {
|
|
615
|
+
...this.pickRenderRelevantFields(backgroundImageDiagnostic),
|
|
616
|
+
loadState: backgroundImageStatus,
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
if (topElementSummary?.coveredByOutsideElement && topElementDiagnostic) {
|
|
620
|
+
details.topElementAtCenter = {
|
|
621
|
+
...this.pickRenderRelevantFields(topElementDiagnostic),
|
|
622
|
+
overlayStack,
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
return {
|
|
627
|
+
summary,
|
|
628
|
+
details: shouldEmitDetails && Object.keys(details).length > 0 ? details : null,
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
private collectElementChainDiagnostics(element: Element): Array<Record<string, any>> {
|
|
633
|
+
const chain: Array<Record<string, any>> = [];
|
|
634
|
+
let current: Element | null = element;
|
|
635
|
+
while (current) {
|
|
636
|
+
const diagnostic = this.collectElementDiagnostic(current);
|
|
637
|
+
if (diagnostic) {
|
|
638
|
+
chain.push(diagnostic);
|
|
639
|
+
}
|
|
640
|
+
current = current.parentElement;
|
|
641
|
+
}
|
|
642
|
+
return chain;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
private collectImageDiagnostic(image: HTMLImageElement): Record<string, any> {
|
|
646
|
+
const diagnostic = this.collectElementDiagnostic(image);
|
|
647
|
+
return {
|
|
648
|
+
...diagnostic,
|
|
649
|
+
currentSrc: image.currentSrc,
|
|
650
|
+
src: image.getAttribute("src"),
|
|
651
|
+
complete: image.complete,
|
|
652
|
+
naturalWidth: image.naturalWidth,
|
|
653
|
+
naturalHeight: image.naturalHeight,
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
private appendRenderImpactIssues(
|
|
658
|
+
label: string,
|
|
659
|
+
diagnostic: Record<string, any>,
|
|
660
|
+
blockers: string[],
|
|
661
|
+
warnings: string[]
|
|
662
|
+
): void {
|
|
663
|
+
const opacity = Number.parseFloat(diagnostic.opacity || "1");
|
|
664
|
+
if (diagnostic.hiddenAttribute) {
|
|
665
|
+
blockers.push(`${label}.hiddenAttribute`);
|
|
666
|
+
}
|
|
667
|
+
if (diagnostic.display === "none") {
|
|
668
|
+
blockers.push(`${label}.display:none`);
|
|
669
|
+
}
|
|
670
|
+
if (diagnostic.visibility === "hidden" || diagnostic.visibility === "collapse") {
|
|
671
|
+
blockers.push(`${label}.visibility:${diagnostic.visibility}`);
|
|
672
|
+
}
|
|
673
|
+
if (Number.isFinite(opacity) && opacity <= 0.01) {
|
|
674
|
+
blockers.push(`${label}.opacity:${diagnostic.opacity}`);
|
|
675
|
+
}
|
|
676
|
+
if (diagnostic.contentVisibility === "hidden") {
|
|
677
|
+
blockers.push(`${label}.contentVisibility:hidden`);
|
|
678
|
+
}
|
|
679
|
+
if (diagnostic.transform !== "none") {
|
|
680
|
+
warnings.push(`${label}.transform`);
|
|
681
|
+
}
|
|
682
|
+
if (diagnostic.filter !== "none") {
|
|
683
|
+
warnings.push(`${label}.filter`);
|
|
684
|
+
}
|
|
685
|
+
if (diagnostic.backdropFilter !== "none") {
|
|
686
|
+
warnings.push(`${label}.backdropFilter`);
|
|
687
|
+
}
|
|
688
|
+
if (diagnostic.clipPath !== "none") {
|
|
689
|
+
warnings.push(`${label}.clipPath`);
|
|
690
|
+
}
|
|
691
|
+
if (diagnostic.maskImage !== "none") {
|
|
692
|
+
warnings.push(`${label}.maskImage`);
|
|
693
|
+
}
|
|
694
|
+
if (diagnostic.mixBlendMode !== "normal") {
|
|
695
|
+
warnings.push(`${label}.mixBlendMode:${diagnostic.mixBlendMode}`);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
private pickRenderRelevantFields(diagnostic: Record<string, any>): Record<string, any> {
|
|
700
|
+
const result: Record<string, any> = {
|
|
701
|
+
node: diagnostic.node,
|
|
702
|
+
display: diagnostic.display,
|
|
703
|
+
visibility: diagnostic.visibility,
|
|
704
|
+
opacity: diagnostic.opacity,
|
|
705
|
+
hiddenAttribute: diagnostic.hiddenAttribute,
|
|
706
|
+
contentVisibility: diagnostic.contentVisibility,
|
|
707
|
+
backgroundColor: diagnostic.backgroundColor,
|
|
708
|
+
backgroundAlpha: diagnostic.backgroundColorChannels?.a ?? null,
|
|
709
|
+
color: diagnostic.color,
|
|
710
|
+
colorAlpha: diagnostic.colorChannels?.a ?? null,
|
|
711
|
+
textFillColor: diagnostic.textFillColor,
|
|
712
|
+
textFillAlpha: diagnostic.textFillColorChannels?.a ?? null,
|
|
713
|
+
};
|
|
714
|
+
if (diagnostic.transform !== "none") {
|
|
715
|
+
result.transform = diagnostic.transform;
|
|
716
|
+
}
|
|
717
|
+
if (diagnostic.filter !== "none") {
|
|
718
|
+
result.filter = diagnostic.filter;
|
|
719
|
+
}
|
|
720
|
+
if (diagnostic.backdropFilter !== "none") {
|
|
721
|
+
result.backdropFilter = diagnostic.backdropFilter;
|
|
722
|
+
}
|
|
723
|
+
if (diagnostic.mixBlendMode !== "normal") {
|
|
724
|
+
result.mixBlendMode = diagnostic.mixBlendMode;
|
|
725
|
+
}
|
|
726
|
+
if (diagnostic.clipPath !== "none") {
|
|
727
|
+
result.clipPath = diagnostic.clipPath;
|
|
728
|
+
}
|
|
729
|
+
if (diagnostic.maskImage !== "none") {
|
|
730
|
+
result.maskImage = diagnostic.maskImage;
|
|
731
|
+
}
|
|
732
|
+
if (diagnostic.overflow !== "visible") {
|
|
733
|
+
result.overflow = diagnostic.overflow;
|
|
734
|
+
}
|
|
735
|
+
if (diagnostic.zIndex !== "auto") {
|
|
736
|
+
result.zIndex = diagnostic.zIndex;
|
|
737
|
+
}
|
|
738
|
+
return result;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
private pickBackgroundImageStatus(diagnostic: Record<string, any>): Record<string, any> {
|
|
742
|
+
return {
|
|
743
|
+
found: true,
|
|
744
|
+
complete: diagnostic.complete,
|
|
745
|
+
currentSrc: diagnostic.currentSrc || diagnostic.src || "",
|
|
746
|
+
naturalWidth: diagnostic.naturalWidth,
|
|
747
|
+
naturalHeight: diagnostic.naturalHeight,
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
private collectElementDiagnostic(element: Element | null): Record<string, any> | null {
|
|
752
|
+
if (!element) {
|
|
753
|
+
return null;
|
|
754
|
+
}
|
|
755
|
+
const style = window.getComputedStyle(element);
|
|
756
|
+
const htmlElement = element as HTMLElement;
|
|
757
|
+
return {
|
|
758
|
+
node: this.describeElement(element),
|
|
759
|
+
isConnected: element.isConnected,
|
|
760
|
+
hiddenAttribute: htmlElement.hidden,
|
|
761
|
+
ariaHidden: htmlElement.getAttribute("aria-hidden"),
|
|
762
|
+
opacity: style.opacity,
|
|
763
|
+
alpha: style.opacity,
|
|
764
|
+
display: style.display,
|
|
765
|
+
visibility: style.visibility,
|
|
766
|
+
backgroundColor: style.backgroundColor,
|
|
767
|
+
backgroundColorChannels: this.parseColorChannels(style.backgroundColor),
|
|
768
|
+
color: style.color,
|
|
769
|
+
colorChannels: this.parseColorChannels(style.color),
|
|
770
|
+
textFillColor: style.getPropertyValue("-webkit-text-fill-color"),
|
|
771
|
+
textFillColorChannels: this.parseColorChannels(
|
|
772
|
+
style.getPropertyValue("-webkit-text-fill-color")
|
|
773
|
+
),
|
|
774
|
+
filter: style.filter,
|
|
775
|
+
backdropFilter: style.getPropertyValue("backdrop-filter"),
|
|
776
|
+
mixBlendMode: style.mixBlendMode,
|
|
777
|
+
transform: style.transform,
|
|
778
|
+
contentVisibility: style.getPropertyValue("content-visibility"),
|
|
779
|
+
clipPath: style.clipPath,
|
|
780
|
+
maskImage:
|
|
781
|
+
style.getPropertyValue("mask-image") ||
|
|
782
|
+
style.getPropertyValue("-webkit-mask-image"),
|
|
783
|
+
overflow: style.overflow,
|
|
784
|
+
zIndex: style.zIndex,
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
private describeElement(element: Element | null): string | null {
|
|
789
|
+
if (!element) {
|
|
790
|
+
return null;
|
|
791
|
+
}
|
|
792
|
+
const tagName = element.tagName.toLowerCase();
|
|
793
|
+
const id = element.id ? `#${element.id}` : "";
|
|
794
|
+
const className =
|
|
795
|
+
typeof (element as HTMLElement).className === "string" &&
|
|
796
|
+
(element as HTMLElement).className.trim()
|
|
797
|
+
? `.${(element as HTMLElement).className.trim().replace(/\s+/g, ".")}`
|
|
798
|
+
: "";
|
|
799
|
+
return `${tagName}${id}${className}`;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
private serializeRect(rect?: DOMRect | null): DiagnosticRect | null {
|
|
803
|
+
if (!rect) {
|
|
804
|
+
return null;
|
|
805
|
+
}
|
|
806
|
+
return {
|
|
807
|
+
x: rect.x,
|
|
808
|
+
y: rect.y,
|
|
809
|
+
width: rect.width,
|
|
810
|
+
height: rect.height,
|
|
811
|
+
top: rect.top,
|
|
812
|
+
right: rect.right,
|
|
813
|
+
bottom: rect.bottom,
|
|
814
|
+
left: rect.left,
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
private parseColorChannels(value?: string | null): DiagnosticColorChannels {
|
|
819
|
+
const raw = value?.trim() || "";
|
|
820
|
+
if (!raw) {
|
|
821
|
+
return { raw };
|
|
822
|
+
}
|
|
823
|
+
if (raw === "transparent") {
|
|
824
|
+
return { raw, r: 0, g: 0, b: 0, a: 0 };
|
|
825
|
+
}
|
|
826
|
+
const matches = raw.match(/^rgba?\((.+)\)$/i);
|
|
827
|
+
if (!matches) {
|
|
828
|
+
return { raw };
|
|
829
|
+
}
|
|
830
|
+
const parts = matches[1].split(",").map(part => part.trim());
|
|
831
|
+
const [r, g, b, a] = parts.map(part => Number(part));
|
|
832
|
+
return {
|
|
833
|
+
raw,
|
|
834
|
+
r: Number.isFinite(r) ? r : undefined,
|
|
835
|
+
g: Number.isFinite(g) ? g : undefined,
|
|
836
|
+
b: Number.isFinite(b) ? b : undefined,
|
|
837
|
+
a: Number.isFinite(a) ? a : raw.startsWith("rgb(") ? 1 : undefined,
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
|
|
393
841
|
private static initManager(room: Room): Promise<WindowManager | undefined> {
|
|
394
842
|
return createInvisiblePlugin(room);
|
|
395
843
|
}
|
|
@@ -462,6 +910,7 @@ export class WindowManager
|
|
|
462
910
|
this.appManager.setBoxManager(boxManager);
|
|
463
911
|
}
|
|
464
912
|
this.bindMainView(mainViewElement, params.disableCameraTransform);
|
|
913
|
+
this.logMainViewVisibilityDiagnostics("bindContainer.afterBindMainView");
|
|
465
914
|
if (WindowManager.wrapper) {
|
|
466
915
|
this.cursorManager?.setupWrapper(WindowManager.wrapper);
|
|
467
916
|
}
|
|
@@ -1011,7 +1460,6 @@ export class WindowManager
|
|
|
1011
1460
|
const mainViewCamera = { ...this.mainView.camera };
|
|
1012
1461
|
if (isEqual({ ...mainViewCamera, ...pureCamera }, mainViewCamera)) return;
|
|
1013
1462
|
this.mainView.moveCamera(camera);
|
|
1014
|
-
// this.appManager?.dispatchInternalEvent(Events.MoveCamera, camera);
|
|
1015
1463
|
setTimeout(() => {
|
|
1016
1464
|
this.appManager?.mainViewProxy.setCameraAndSize();
|
|
1017
1465
|
}, 500);
|
|
@@ -1024,7 +1472,6 @@ export class WindowManager
|
|
|
1024
1472
|
}>
|
|
1025
1473
|
): void {
|
|
1026
1474
|
this.mainView.moveCameraToContain(rectangle);
|
|
1027
|
-
// this.appManager?.dispatchInternalEvent(Events.MoveCameraToContain, rectangle);
|
|
1028
1475
|
setTimeout(() => {
|
|
1029
1476
|
this.appManager?.mainViewProxy.setCameraAndSize();
|
|
1030
1477
|
}, 500);
|
|
@@ -1059,6 +1506,7 @@ export class WindowManager
|
|
|
1059
1506
|
WindowManager.playground.parentNode?.removeChild(WindowManager.playground);
|
|
1060
1507
|
}
|
|
1061
1508
|
WindowManager.params = undefined;
|
|
1509
|
+
this.emitter.off('mainViewScenePathChange', this.onMainViewScenePathChangeHandler);
|
|
1062
1510
|
this._iframeBridge?.destroy();
|
|
1063
1511
|
this._iframeBridge = undefined;
|
|
1064
1512
|
log("Destroyed");
|