@noya-app/noya-multiplayer-react 0.1.69 → 0.1.71
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/.turbo/turbo-build.log +11 -11
- package/CHANGELOG.md +15 -0
- package/dist/index.bundle.js +30 -20
- package/dist/index.d.mts +18 -9
- package/dist/index.d.ts +18 -9
- package/dist/index.js +58 -35
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +68 -45
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/NoyaStateContext.tsx +8 -8
- package/src/__tests__/noyaApp.test.ts +28 -0
- package/src/components/UserPointersOverlay.tsx +4 -4
- package/src/hooks.ts +3 -2
- package/src/inspector/StateInspector.tsx +239 -224
- package/src/inspector/StateInspectorRow.tsx +3 -1
- package/src/inspector/useStateInspector.tsx +8 -3
- package/src/noyaApp.ts +17 -3
- package/src/singleton.tsx +14 -0
|
@@ -44,6 +44,7 @@ export type StateInspectorAnchor =
|
|
|
44
44
|
export type StateInspectorOptions = {
|
|
45
45
|
colorScheme?: "light" | "dark";
|
|
46
46
|
anchor?: StateInspectorAnchor;
|
|
47
|
+
advanced?: boolean;
|
|
47
48
|
};
|
|
48
49
|
|
|
49
50
|
export const StateInspector = memoGeneric(function StateInspector<
|
|
@@ -56,6 +57,7 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
56
57
|
colorScheme = "light",
|
|
57
58
|
anchor = "right",
|
|
58
59
|
unstyled = false,
|
|
60
|
+
advanced = false,
|
|
59
61
|
...props
|
|
60
62
|
}: {
|
|
61
63
|
noyaManager: NoyaManager<S, M, E, MenuT>;
|
|
@@ -65,7 +67,7 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
65
67
|
const {
|
|
66
68
|
multiplayerStateManager,
|
|
67
69
|
assetManager,
|
|
68
|
-
|
|
70
|
+
userManager,
|
|
69
71
|
secretManager,
|
|
70
72
|
ephemeralUserDataManager,
|
|
71
73
|
connectionEventManager,
|
|
@@ -159,8 +161,8 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
159
161
|
const assetsInitialized = useObservable(assetManager.isInitialized$);
|
|
160
162
|
const secrets = useObservable(secretManager.secrets$);
|
|
161
163
|
const secretsInitialized = useObservable(secretManager.isInitialized$);
|
|
162
|
-
const connectedUsers = useObservable(
|
|
163
|
-
const userId = useObservable(
|
|
164
|
+
const connectedUsers = useObservable(userManager.connectedUsers$);
|
|
165
|
+
const userId = useObservable(userManager.currentUserId$);
|
|
164
166
|
const state = useObservable(multiplayerStateManager.optimisticState$);
|
|
165
167
|
const inputsInitialized = useObservable(ioManager.inputsInitialized$);
|
|
166
168
|
const outputTransformsInitialized = useObservable(
|
|
@@ -263,11 +265,12 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
263
265
|
}
|
|
264
266
|
>
|
|
265
267
|
<StateInspectorDisclosureRowInner style={{ flex: "0 0 auto" }}>
|
|
266
|
-
{connectedUsers?.map((user) => (
|
|
268
|
+
{connectedUsers?.map((user, index, array) => (
|
|
267
269
|
<StateInspectorRow
|
|
268
270
|
key={user.id}
|
|
269
271
|
colorScheme={colorScheme}
|
|
270
272
|
variant={user.id === userId ? "up" : undefined}
|
|
273
|
+
bordered={index !== array.length - 1}
|
|
271
274
|
>
|
|
272
275
|
{user.image && (
|
|
273
276
|
<img
|
|
@@ -447,231 +450,241 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
447
450
|
))}
|
|
448
451
|
</StateInspectorDisclosureRowInner>
|
|
449
452
|
</StateInspectorDisclosureSection>
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
<
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
453
|
+
{advanced && (
|
|
454
|
+
<StateInspectorDisclosureSection
|
|
455
|
+
title={
|
|
456
|
+
<StateInspectorTitleLabel>
|
|
457
|
+
Resources ({resources.length})
|
|
458
|
+
<ColoredDot type={resourcesInitialized ? "success" : "error"} />
|
|
459
|
+
</StateInspectorTitleLabel>
|
|
460
|
+
}
|
|
461
|
+
colorScheme={colorScheme}
|
|
462
|
+
open={showResources}
|
|
463
|
+
setOpen={setShowResources}
|
|
464
|
+
right={
|
|
465
|
+
<span style={{ display: "flex", gap: "10px" }}>
|
|
466
|
+
<StateInspectorButton
|
|
467
|
+
theme={theme}
|
|
468
|
+
onClick={async () => {
|
|
469
|
+
const ok = confirm(
|
|
470
|
+
"Are you sure you want to delete all resources?"
|
|
471
|
+
);
|
|
472
|
+
if (!ok) return;
|
|
473
|
+
await resourceManager.deleteResource(
|
|
474
|
+
resources.map((resource) => ({ id: resource.id }))
|
|
475
|
+
);
|
|
476
|
+
}}
|
|
477
|
+
>
|
|
478
|
+
Delete all
|
|
479
|
+
</StateInspectorButton>
|
|
480
|
+
<StateInspectorButton
|
|
481
|
+
theme={theme}
|
|
482
|
+
onClick={async () => {
|
|
483
|
+
const path = prompt("Enter directory path") || uuid();
|
|
484
|
+
await resourceManager.createResource({
|
|
485
|
+
type: "directory",
|
|
486
|
+
path,
|
|
487
|
+
});
|
|
488
|
+
}}
|
|
489
|
+
>
|
|
490
|
+
Create Directory
|
|
491
|
+
</StateInspectorButton>
|
|
492
|
+
<StateInspectorButton
|
|
493
|
+
theme={theme}
|
|
494
|
+
onClick={async () => {
|
|
495
|
+
const file = await uploadFile();
|
|
496
|
+
|
|
497
|
+
resourceManager.createResource({
|
|
498
|
+
type: "asset",
|
|
499
|
+
path: file.name || uuid(),
|
|
500
|
+
asset: {
|
|
501
|
+
content: Base64.encode(await file.arrayBuffer()),
|
|
502
|
+
contentType: file.type,
|
|
503
|
+
encoding: "base64",
|
|
504
|
+
},
|
|
505
|
+
});
|
|
506
|
+
}}
|
|
507
|
+
>
|
|
508
|
+
Create Asset
|
|
509
|
+
</StateInspectorButton>
|
|
510
|
+
</span>
|
|
511
|
+
}
|
|
512
|
+
>
|
|
513
|
+
<StateInspectorDisclosureRowInner>
|
|
514
|
+
{resources?.map((resource) => (
|
|
515
|
+
<StateInspectorRow key={resource.id} colorScheme={colorScheme}>
|
|
516
|
+
<ObjectInspector
|
|
517
|
+
name={resource.path}
|
|
518
|
+
data={resource}
|
|
519
|
+
theme={theme}
|
|
520
|
+
/>
|
|
521
|
+
<div style={{ display: "flex", gap: "4px" }}>
|
|
522
|
+
<StateInspectorButton
|
|
523
|
+
theme={theme}
|
|
524
|
+
onClick={() =>
|
|
525
|
+
resourceManager.deleteResource({ id: resource.id })
|
|
526
|
+
}
|
|
527
|
+
>
|
|
528
|
+
Delete
|
|
529
|
+
</StateInspectorButton>
|
|
530
|
+
<StateInspectorButton
|
|
531
|
+
theme={theme}
|
|
532
|
+
onClick={() => {
|
|
533
|
+
const path = prompt("Enter new path", resource.path);
|
|
534
|
+
if (!path) return;
|
|
535
|
+
resourceManager.updateResource({ id: resource.id, path });
|
|
536
|
+
}}
|
|
537
|
+
>
|
|
538
|
+
Rename
|
|
539
|
+
</StateInspectorButton>
|
|
540
|
+
</div>
|
|
541
|
+
</StateInspectorRow>
|
|
542
|
+
))}
|
|
543
|
+
</StateInspectorDisclosureRowInner>
|
|
544
|
+
</StateInspectorDisclosureSection>
|
|
545
|
+
)}
|
|
546
|
+
{advanced && (
|
|
547
|
+
<StateInspectorDisclosureSection
|
|
548
|
+
title={
|
|
549
|
+
<StateInspectorTitleLabel>
|
|
550
|
+
Secrets
|
|
551
|
+
<ColoredDot type={secretsInitialized ? "success" : "error"} />
|
|
552
|
+
</StateInspectorTitleLabel>
|
|
553
|
+
}
|
|
554
|
+
colorScheme={colorScheme}
|
|
555
|
+
open={showSecrets}
|
|
556
|
+
setOpen={setShowSecrets}
|
|
557
|
+
right={
|
|
488
558
|
<StateInspectorButton
|
|
489
559
|
theme={theme}
|
|
490
|
-
onClick={
|
|
491
|
-
const
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
asset: {
|
|
497
|
-
content: Base64.encode(await file.arrayBuffer()),
|
|
498
|
-
contentType: file.type,
|
|
499
|
-
encoding: "base64",
|
|
500
|
-
},
|
|
501
|
-
});
|
|
560
|
+
onClick={() => {
|
|
561
|
+
const name = prompt("Enter secret name");
|
|
562
|
+
if (!name) return;
|
|
563
|
+
const value = prompt("Enter secret value");
|
|
564
|
+
if (!value) return;
|
|
565
|
+
secretManager.createSecret(null, name, value);
|
|
502
566
|
}}
|
|
503
567
|
>
|
|
504
|
-
Create
|
|
568
|
+
Create
|
|
505
569
|
</StateInspectorButton>
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
<ObjectInspector
|
|
513
|
-
name={resource.path}
|
|
514
|
-
data={resource}
|
|
515
|
-
theme={theme}
|
|
516
|
-
/>
|
|
517
|
-
<div style={{ display: "flex", gap: "4px" }}>
|
|
570
|
+
}
|
|
571
|
+
>
|
|
572
|
+
<StateInspectorDisclosureRowInner>
|
|
573
|
+
{secrets.map((secret) => (
|
|
574
|
+
<StateInspectorRow key={secret.id} colorScheme={colorScheme}>
|
|
575
|
+
<ObjectInspector data={secret} theme={theme} />
|
|
518
576
|
<StateInspectorButton
|
|
519
577
|
theme={theme}
|
|
520
|
-
onClick={() =>
|
|
521
|
-
resourceManager.deleteResource({ id: resource.id })
|
|
522
|
-
}
|
|
578
|
+
onClick={() => secretManager.deleteSecret(secret.id)}
|
|
523
579
|
>
|
|
524
580
|
Delete
|
|
525
581
|
</StateInspectorButton>
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
<
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
if (!value) return;
|
|
559
|
-
secretManager.createSecret(null, name, value);
|
|
560
|
-
}}
|
|
561
|
-
>
|
|
562
|
-
Create
|
|
563
|
-
</StateInspectorButton>
|
|
564
|
-
}
|
|
565
|
-
>
|
|
566
|
-
<StateInspectorDisclosureRowInner>
|
|
567
|
-
{secrets.map((secret) => (
|
|
568
|
-
<StateInspectorRow key={secret.id} colorScheme={colorScheme}>
|
|
569
|
-
<ObjectInspector data={secret} theme={theme} />
|
|
570
|
-
<StateInspectorButton
|
|
571
|
-
theme={theme}
|
|
572
|
-
onClick={() => secretManager.deleteSecret(secret.id)}
|
|
582
|
+
</StateInspectorRow>
|
|
583
|
+
))}
|
|
584
|
+
</StateInspectorDisclosureRowInner>
|
|
585
|
+
</StateInspectorDisclosureSection>
|
|
586
|
+
)}
|
|
587
|
+
{advanced && (
|
|
588
|
+
<StateInspectorDisclosureSection
|
|
589
|
+
open={showInputs}
|
|
590
|
+
setOpen={setShowInputs}
|
|
591
|
+
title={
|
|
592
|
+
<StateInspectorTitleLabel>
|
|
593
|
+
Inputs
|
|
594
|
+
<ColoredDot type={inputsInitialized ? "success" : "error"} />
|
|
595
|
+
</StateInspectorTitleLabel>
|
|
596
|
+
}
|
|
597
|
+
colorScheme={colorScheme}
|
|
598
|
+
>
|
|
599
|
+
<StateInspectorDisclosureRowInner>
|
|
600
|
+
{inputs?.map((input: Input) => (
|
|
601
|
+
<StateInspectorRow key={input.id} colorScheme={colorScheme}>
|
|
602
|
+
<ObjectInspector data={input} theme={theme} />
|
|
603
|
+
</StateInspectorRow>
|
|
604
|
+
))}
|
|
605
|
+
{!inputs?.length && (
|
|
606
|
+
<div
|
|
607
|
+
style={{
|
|
608
|
+
padding: "12px",
|
|
609
|
+
fontSize: "12px",
|
|
610
|
+
display: "flex",
|
|
611
|
+
flexDirection: "column",
|
|
612
|
+
gap: "4px",
|
|
613
|
+
}}
|
|
573
614
|
>
|
|
574
|
-
|
|
575
|
-
</
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
</
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
colorScheme={colorScheme}
|
|
590
|
-
>
|
|
591
|
-
<StateInspectorDisclosureRowInner>
|
|
592
|
-
{inputs?.map((input: Input) => (
|
|
593
|
-
<StateInspectorRow key={input.id} colorScheme={colorScheme}>
|
|
594
|
-
<ObjectInspector data={input} theme={theme} />
|
|
595
|
-
</StateInspectorRow>
|
|
596
|
-
))}
|
|
597
|
-
{!inputs?.length && (
|
|
598
|
-
<div
|
|
599
|
-
style={{
|
|
600
|
-
padding: "12px",
|
|
601
|
-
fontSize: "12px",
|
|
602
|
-
display: "flex",
|
|
603
|
-
flexDirection: "column",
|
|
604
|
-
gap: "4px",
|
|
605
|
-
}}
|
|
606
|
-
>
|
|
607
|
-
<span>No inputs</span>
|
|
608
|
-
</div>
|
|
609
|
-
)}
|
|
610
|
-
</StateInspectorDisclosureRowInner>
|
|
611
|
-
</StateInspectorDisclosureSection>
|
|
612
|
-
<StateInspectorDisclosureSection
|
|
613
|
-
open={showOutputTransforms}
|
|
614
|
-
setOpen={setShowOutputTransforms}
|
|
615
|
-
title={
|
|
616
|
-
<StateInspectorTitleLabel>
|
|
617
|
-
Output Transforms
|
|
618
|
-
<ColoredDot
|
|
619
|
-
type={outputTransformsInitialized ? "success" : "error"}
|
|
620
|
-
/>
|
|
621
|
-
</StateInspectorTitleLabel>
|
|
622
|
-
}
|
|
623
|
-
colorScheme={colorScheme}
|
|
624
|
-
>
|
|
625
|
-
<StateInspectorDisclosureRowInner>
|
|
626
|
-
{outputTransforms?.map((transform: OutputTransform) => (
|
|
627
|
-
<StateInspectorRow key={transform.id} colorScheme={colorScheme}>
|
|
628
|
-
<ObjectInspector data={transform} theme={theme} />
|
|
629
|
-
</StateInspectorRow>
|
|
630
|
-
))}
|
|
631
|
-
{!outputTransforms?.length && (
|
|
632
|
-
<div
|
|
633
|
-
style={{
|
|
634
|
-
padding: "12px",
|
|
635
|
-
fontSize: "12px",
|
|
636
|
-
display: "flex",
|
|
637
|
-
flexDirection: "column",
|
|
638
|
-
gap: "4px",
|
|
639
|
-
}}
|
|
640
|
-
>
|
|
641
|
-
<span>No output transforms</span>
|
|
642
|
-
</div>
|
|
643
|
-
)}
|
|
644
|
-
</StateInspectorDisclosureRowInner>
|
|
645
|
-
</StateInspectorDisclosureSection>
|
|
646
|
-
<StateInspectorDisclosureSection
|
|
647
|
-
title="Tasks"
|
|
648
|
-
colorScheme={colorScheme}
|
|
649
|
-
open={showTasks}
|
|
650
|
-
setOpen={setShowTasks}
|
|
651
|
-
>
|
|
652
|
-
<StateInspectorDisclosureRowInner>
|
|
653
|
-
{tasks?.map((task) => (
|
|
654
|
-
<StateInspectorRow
|
|
655
|
-
key={task.id}
|
|
656
|
-
colorScheme={colorScheme}
|
|
657
|
-
style={{
|
|
658
|
-
backgroundColor:
|
|
659
|
-
task.status === "done"
|
|
660
|
-
? "rgba(0,255,0,0.2)"
|
|
661
|
-
: task.status === "error"
|
|
662
|
-
? "rgba(255,0,0,0.2)"
|
|
663
|
-
: undefined,
|
|
664
|
-
}}
|
|
665
|
-
>
|
|
666
|
-
<ObjectInspector
|
|
667
|
-
name={task.name}
|
|
668
|
-
data={task.payload}
|
|
669
|
-
theme={theme}
|
|
615
|
+
<span>No inputs</span>
|
|
616
|
+
</div>
|
|
617
|
+
)}
|
|
618
|
+
</StateInspectorDisclosureRowInner>
|
|
619
|
+
</StateInspectorDisclosureSection>
|
|
620
|
+
)}
|
|
621
|
+
{advanced && (
|
|
622
|
+
<StateInspectorDisclosureSection
|
|
623
|
+
open={showOutputTransforms}
|
|
624
|
+
setOpen={setShowOutputTransforms}
|
|
625
|
+
title={
|
|
626
|
+
<StateInspectorTitleLabel>
|
|
627
|
+
Output Transforms
|
|
628
|
+
<ColoredDot
|
|
629
|
+
type={outputTransformsInitialized ? "success" : "error"}
|
|
670
630
|
/>
|
|
671
|
-
</
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
631
|
+
</StateInspectorTitleLabel>
|
|
632
|
+
}
|
|
633
|
+
colorScheme={colorScheme}
|
|
634
|
+
>
|
|
635
|
+
<StateInspectorDisclosureRowInner>
|
|
636
|
+
{outputTransforms?.map((transform: OutputTransform) => (
|
|
637
|
+
<StateInspectorRow key={transform.id} colorScheme={colorScheme}>
|
|
638
|
+
<ObjectInspector data={transform} theme={theme} />
|
|
639
|
+
</StateInspectorRow>
|
|
640
|
+
))}
|
|
641
|
+
{!outputTransforms?.length && (
|
|
642
|
+
<div
|
|
643
|
+
style={{
|
|
644
|
+
padding: "12px",
|
|
645
|
+
fontSize: "12px",
|
|
646
|
+
display: "flex",
|
|
647
|
+
flexDirection: "column",
|
|
648
|
+
gap: "4px",
|
|
649
|
+
}}
|
|
650
|
+
>
|
|
651
|
+
<span>No output transforms</span>
|
|
652
|
+
</div>
|
|
653
|
+
)}
|
|
654
|
+
</StateInspectorDisclosureRowInner>
|
|
655
|
+
</StateInspectorDisclosureSection>
|
|
656
|
+
)}
|
|
657
|
+
{advanced && (
|
|
658
|
+
<StateInspectorDisclosureSection
|
|
659
|
+
title="Tasks"
|
|
660
|
+
colorScheme={colorScheme}
|
|
661
|
+
open={showTasks}
|
|
662
|
+
setOpen={setShowTasks}
|
|
663
|
+
>
|
|
664
|
+
<StateInspectorDisclosureRowInner>
|
|
665
|
+
{tasks?.map((task) => (
|
|
666
|
+
<StateInspectorRow
|
|
667
|
+
key={task.id}
|
|
668
|
+
colorScheme={colorScheme}
|
|
669
|
+
style={{
|
|
670
|
+
backgroundColor:
|
|
671
|
+
task.status === "done"
|
|
672
|
+
? "rgba(0,255,0,0.2)"
|
|
673
|
+
: task.status === "error"
|
|
674
|
+
? "rgba(255,0,0,0.2)"
|
|
675
|
+
: undefined,
|
|
676
|
+
}}
|
|
677
|
+
>
|
|
678
|
+
<ObjectInspector
|
|
679
|
+
name={task.name}
|
|
680
|
+
data={task.payload}
|
|
681
|
+
theme={theme}
|
|
682
|
+
/>
|
|
683
|
+
</StateInspectorRow>
|
|
684
|
+
))}
|
|
685
|
+
</StateInspectorDisclosureRowInner>
|
|
686
|
+
</StateInspectorDisclosureSection>
|
|
687
|
+
)}
|
|
675
688
|
<StateInspectorDisclosureSection
|
|
676
689
|
open={showEphemeral}
|
|
677
690
|
setOpen={setShowEphemeral}
|
|
@@ -691,13 +704,15 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
691
704
|
))}
|
|
692
705
|
</StateInspectorDisclosureRowInner>
|
|
693
706
|
</StateInspectorDisclosureSection>
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
707
|
+
{advanced && (
|
|
708
|
+
<ActivityEventsSection
|
|
709
|
+
colorScheme={colorScheme}
|
|
710
|
+
activityEventsContainerRef={activityEventsContainerRef}
|
|
711
|
+
showEvents={showActivityEvents}
|
|
712
|
+
setShowEvents={setShowActivityEvents}
|
|
713
|
+
activityEventsManager={activityEventsManager}
|
|
714
|
+
/>
|
|
715
|
+
)}
|
|
701
716
|
<EventsSection<S>
|
|
702
717
|
connectionEvents={connectionEvents}
|
|
703
718
|
colorScheme={colorScheme}
|
|
@@ -8,12 +8,14 @@ export function StateInspectorRow({
|
|
|
8
8
|
selected,
|
|
9
9
|
style,
|
|
10
10
|
variant,
|
|
11
|
+
bordered = true,
|
|
11
12
|
}: {
|
|
12
13
|
children: React.ReactNode;
|
|
13
14
|
colorScheme: "light" | "dark";
|
|
14
15
|
selected?: boolean;
|
|
15
16
|
style?: CSSProperties;
|
|
16
17
|
variant?: "up" | "down";
|
|
18
|
+
bordered?: boolean;
|
|
17
19
|
}) {
|
|
18
20
|
const solidBorderColor =
|
|
19
21
|
colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
|
|
@@ -21,7 +23,7 @@ export function StateInspectorRow({
|
|
|
21
23
|
return (
|
|
22
24
|
<div
|
|
23
25
|
style={{
|
|
24
|
-
borderBottom: `1px solid ${solidBorderColor}
|
|
26
|
+
borderBottom: bordered ? `1px solid ${solidBorderColor}` : undefined,
|
|
25
27
|
fontSize: "12px",
|
|
26
28
|
fontFamily: "Menlo, monospace",
|
|
27
29
|
padding: "2px 12px 1px",
|
|
@@ -38,12 +38,16 @@ export function useStateInspector<
|
|
|
38
38
|
>({
|
|
39
39
|
noyaManager,
|
|
40
40
|
disabled = false,
|
|
41
|
+
advanced = false,
|
|
41
42
|
colorScheme,
|
|
42
43
|
anchor,
|
|
43
44
|
}: {
|
|
44
45
|
noyaManager: NoyaManager<S, M, E, MenuT>;
|
|
45
|
-
disabled
|
|
46
|
-
|
|
46
|
+
disabled?: boolean;
|
|
47
|
+
advanced?: boolean;
|
|
48
|
+
colorScheme?: ComponentProps<typeof StateInspector>["colorScheme"];
|
|
49
|
+
anchor?: ComponentProps<typeof StateInspector>["anchor"];
|
|
50
|
+
}) {
|
|
47
51
|
const [root, setRoot] = React.useState<Root | null>(null);
|
|
48
52
|
|
|
49
53
|
useIsomorphicLayoutEffect(() => {
|
|
@@ -64,7 +68,8 @@ export function useStateInspector<
|
|
|
64
68
|
colorScheme={colorScheme}
|
|
65
69
|
anchor={anchor}
|
|
66
70
|
noyaManager={noyaManager}
|
|
71
|
+
advanced={advanced}
|
|
67
72
|
/>
|
|
68
73
|
);
|
|
69
|
-
}, [noyaManager, anchor, colorScheme, root]);
|
|
74
|
+
}, [noyaManager, anchor, colorScheme, root, advanced]);
|
|
70
75
|
}
|
package/src/noyaApp.ts
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
TypeGuard,
|
|
15
15
|
webSocketSync,
|
|
16
16
|
} from "@noya-app/state-manager";
|
|
17
|
-
import { useMemo, useState } from "react";
|
|
17
|
+
import { useEffect, useMemo, useState } from "react";
|
|
18
18
|
import { useBindNoyaManager, UseMultiplayerStateOptions } from "./hooks";
|
|
19
19
|
import { StateInspectorOptions } from "./inspector/StateInspector";
|
|
20
20
|
|
|
@@ -28,6 +28,8 @@ export type AppData<State> = {
|
|
|
28
28
|
viewType: AppViewType;
|
|
29
29
|
initialState: State;
|
|
30
30
|
inspector: boolean | StateInspectorOptions;
|
|
31
|
+
userId?: string;
|
|
32
|
+
isDemo: boolean;
|
|
31
33
|
};
|
|
32
34
|
|
|
33
35
|
export function createDefaultAppData<State>(
|
|
@@ -38,6 +40,7 @@ export function createDefaultAppData<State>(
|
|
|
38
40
|
viewType: "editable",
|
|
39
41
|
initialState,
|
|
40
42
|
inspector: false,
|
|
43
|
+
isDemo: false,
|
|
41
44
|
};
|
|
42
45
|
}
|
|
43
46
|
|
|
@@ -93,6 +96,7 @@ export function getAppData<State>(
|
|
|
93
96
|
}
|
|
94
97
|
|
|
95
98
|
appData.initialState = enforceSchema(appData.initialState, schema) as State;
|
|
99
|
+
appData.isDemo = appData.isDemo ?? false;
|
|
96
100
|
|
|
97
101
|
return appData as AppData<State>;
|
|
98
102
|
}
|
|
@@ -138,6 +142,7 @@ export type UseNoyaStateResult<
|
|
|
138
142
|
ReturnType<typeof useBindNoyaManager<S, M, E, MenuT>>[2] & {
|
|
139
143
|
theme: AppTheme;
|
|
140
144
|
viewType: AppViewType;
|
|
145
|
+
isDemo: boolean;
|
|
141
146
|
},
|
|
142
147
|
];
|
|
143
148
|
|
|
@@ -192,6 +197,8 @@ export function useNoyaStateInternal<
|
|
|
192
197
|
initialState: noyaAppInitialState,
|
|
193
198
|
theme,
|
|
194
199
|
viewType,
|
|
200
|
+
userId,
|
|
201
|
+
isDemo,
|
|
195
202
|
},
|
|
196
203
|
] = useState(() => {
|
|
197
204
|
return getAppData(initialState, options?.schema, {
|
|
@@ -211,6 +218,13 @@ export function useNoyaStateInternal<
|
|
|
211
218
|
() => new NoyaManager<S, M, E, MenuT>(noyaAppInitialState as S, options)
|
|
212
219
|
);
|
|
213
220
|
|
|
221
|
+
useEffect(() => {
|
|
222
|
+
if (!userId) return;
|
|
223
|
+
|
|
224
|
+
noyaManager.ephemeralUserDataManager.setCurrentUserId(userId);
|
|
225
|
+
noyaManager.userManager.setCurrentUserId(userId);
|
|
226
|
+
}, [noyaManager, userId]);
|
|
227
|
+
|
|
214
228
|
const result = useBindNoyaManager<S, M, E, MenuT>(noyaManager, {
|
|
215
229
|
inspector: options?.inspector ?? inspector,
|
|
216
230
|
sync: options?.sync ?? sync,
|
|
@@ -219,8 +233,8 @@ export function useNoyaStateInternal<
|
|
|
219
233
|
const [, , extras] = result;
|
|
220
234
|
|
|
221
235
|
const mergedExtras = useMemo(() => {
|
|
222
|
-
return { ...extras, theme, viewType } as const;
|
|
223
|
-
}, [extras, theme, viewType]);
|
|
236
|
+
return { ...extras, theme, viewType, isDemo } as const;
|
|
237
|
+
}, [extras, theme, viewType, isDemo]);
|
|
224
238
|
|
|
225
239
|
return [result[0], result[1], mergedExtras] as UseNoyaStateResult<
|
|
226
240
|
O["schema"] extends TSchema ? Static<O["schema"]> : S,
|