@noya-app/noya-multiplayer-react 0.1.62 → 0.1.64
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 +20 -0
- package/dist/index.bundle.js +50 -17
- package/dist/index.d.mts +87 -24
- package/dist/index.d.ts +87 -24
- package/dist/index.js +2556 -708
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2523 -692
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/NoyaStateContext.tsx +248 -28
- package/src/__tests__/serialize.test.ts +126 -0
- package/src/ai.ts +2 -0
- package/src/index.ts +1 -0
- package/src/inspector/ColoredDot.tsx +17 -0
- package/src/inspector/ObjectRootLabel.tsx +48 -0
- package/src/inspector/StateInspector.tsx +266 -741
- package/src/inspector/StateInspectorArrow.tsx +28 -0
- package/src/inspector/StateInspectorButton.tsx +45 -0
- package/src/inspector/StateInspectorDisclosureSection.tsx +97 -0
- package/src/inspector/StateInspectorRow.tsx +57 -0
- package/src/inspector/StateInspectorTitleLabel.tsx +13 -0
- package/src/inspector/StateInspectorToggleButton.tsx +82 -0
- package/src/inspector/inspectorTheme.ts +21 -0
- package/src/inspector/sections/ActivityEventsSection.tsx +136 -0
- package/src/inspector/sections/EventsSection.tsx +89 -0
- package/src/inspector/sections/HistorySection.tsx +236 -0
- package/src/inspector/serialization.ts +202 -0
- package/src/inspector/utils.ts +60 -0
- package/src/inspector/zip/TinyZip.ts +464 -0
- package/src/inspector/zip/crc32.ts +16 -0
- package/src/inspector/zip/struct.ts +117 -0
- package/src/noyaApp.ts +3 -2
- package/src/useObservable.ts +2 -0
|
@@ -1,246 +1,39 @@
|
|
|
1
|
+
/* eslint-disable no-restricted-globals */
|
|
1
2
|
"use client";
|
|
2
3
|
|
|
3
4
|
import { Input, OutputTransform } from "@noya-app/noya-schemas";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
5
|
+
import { Base64, uuid } from "@noya-app/noya-utils";
|
|
6
|
+
import { downloadBlob, memoGeneric } from "@noya-app/react-utils";
|
|
7
|
+
import { NoyaManager } from "@noya-app/state-manager";
|
|
6
8
|
import React, {
|
|
7
9
|
CSSProperties,
|
|
8
10
|
ComponentPropsWithoutRef,
|
|
9
|
-
|
|
11
|
+
useCallback,
|
|
10
12
|
useEffect,
|
|
11
13
|
useLayoutEffect,
|
|
12
14
|
} from "react";
|
|
13
|
-
import {
|
|
14
|
-
ObjectInspector,
|
|
15
|
-
ObjectLabel,
|
|
16
|
-
ObjectName,
|
|
17
|
-
ObjectPreview,
|
|
18
|
-
chromeDark,
|
|
19
|
-
chromeLight,
|
|
20
|
-
} from "react-inspector";
|
|
15
|
+
import { ObjectInspector } from "react-inspector";
|
|
21
16
|
import { useManagedHistory } from "../hooks";
|
|
22
17
|
import { useObservable } from "../useObservable";
|
|
18
|
+
import { ColoredDot } from "./ColoredDot";
|
|
19
|
+
import {
|
|
20
|
+
getStateInspectorBorderColor,
|
|
21
|
+
getStateInspectorTheme,
|
|
22
|
+
} from "./inspectorTheme";
|
|
23
|
+
import { ActivityEventsSection } from "./sections/ActivityEventsSection";
|
|
24
|
+
import { EventsSection } from "./sections/EventsSection";
|
|
25
|
+
import { HistorySection } from "./sections/HistorySection";
|
|
26
|
+
import { exportAll, importAll } from "./serialization";
|
|
27
|
+
import { StateInspectorButton } from "./StateInspectorButton";
|
|
28
|
+
import {
|
|
29
|
+
StateInspectorDisclosureRowInner,
|
|
30
|
+
StateInspectorDisclosureSection,
|
|
31
|
+
} from "./StateInspectorDisclosureSection";
|
|
32
|
+
import { StateInspectorRow } from "./StateInspectorRow";
|
|
33
|
+
import { StateInspectorTitleLabel } from "./StateInspectorTitleLabel";
|
|
34
|
+
import { StateInspectorToggleButton } from "./StateInspectorToggleButton";
|
|
23
35
|
import { useLocalStorageState } from "./useLocalStorageState";
|
|
24
|
-
|
|
25
|
-
const lightTheme = {
|
|
26
|
-
...chromeLight,
|
|
27
|
-
BASE_BACKGROUND_COLOR: "transparent",
|
|
28
|
-
OBJECT_NAME_COLOR: "rgba(0,0,0,0.7)",
|
|
29
|
-
} as any;
|
|
30
|
-
|
|
31
|
-
const darkTheme = {
|
|
32
|
-
...chromeDark,
|
|
33
|
-
BASE_BACKGROUND_COLOR: "transparent",
|
|
34
|
-
OBJECT_NAME_COLOR: "rgba(255,255,255,0.7)",
|
|
35
|
-
} as any;
|
|
36
|
-
|
|
37
|
-
const styles = {
|
|
38
|
-
sectionInner: {
|
|
39
|
-
flex: "1 1 0",
|
|
40
|
-
overflowY: "auto",
|
|
41
|
-
overflowX: "hidden",
|
|
42
|
-
display: "flex",
|
|
43
|
-
flexDirection: "column",
|
|
44
|
-
},
|
|
45
|
-
} as const;
|
|
46
|
-
|
|
47
|
-
function ToggleButton({
|
|
48
|
-
showInspector,
|
|
49
|
-
setShowInspector,
|
|
50
|
-
theme,
|
|
51
|
-
anchor,
|
|
52
|
-
}: {
|
|
53
|
-
showInspector: boolean;
|
|
54
|
-
setShowInspector: (value: boolean) => void;
|
|
55
|
-
theme: typeof chromeLight;
|
|
56
|
-
anchor: StateInspectorAnchor;
|
|
57
|
-
}) {
|
|
58
|
-
const isRightAnchor = anchor === "right";
|
|
59
|
-
|
|
60
|
-
const rightIcon = (
|
|
61
|
-
<svg
|
|
62
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
63
|
-
fill="none"
|
|
64
|
-
viewBox="0 0 24 24"
|
|
65
|
-
strokeWidth={1.5}
|
|
66
|
-
stroke="currentColor"
|
|
67
|
-
className="size-6"
|
|
68
|
-
>
|
|
69
|
-
<path
|
|
70
|
-
strokeLinecap="round"
|
|
71
|
-
strokeLinejoin="round"
|
|
72
|
-
d="m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5"
|
|
73
|
-
/>
|
|
74
|
-
</svg>
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
const leftIcon = (
|
|
78
|
-
<svg
|
|
79
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
80
|
-
fill="none"
|
|
81
|
-
viewBox="0 0 24 24"
|
|
82
|
-
strokeWidth={1.5}
|
|
83
|
-
stroke="currentColor"
|
|
84
|
-
className="size-6"
|
|
85
|
-
>
|
|
86
|
-
<path
|
|
87
|
-
strokeLinecap="round"
|
|
88
|
-
strokeLinejoin="round"
|
|
89
|
-
d="m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5"
|
|
90
|
-
/>
|
|
91
|
-
</svg>
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
return (
|
|
95
|
-
<span
|
|
96
|
-
role="button"
|
|
97
|
-
style={{
|
|
98
|
-
flex: "0",
|
|
99
|
-
appearance: "none",
|
|
100
|
-
color: theme.BASE_COLOR,
|
|
101
|
-
border: "none",
|
|
102
|
-
fontSize: "12px",
|
|
103
|
-
whiteSpace: "nowrap",
|
|
104
|
-
display: "inline-flex",
|
|
105
|
-
alignItems: "center",
|
|
106
|
-
justifyContent: "center",
|
|
107
|
-
padding: "2px 0",
|
|
108
|
-
}}
|
|
109
|
-
onClick={(event) => {
|
|
110
|
-
event.stopPropagation();
|
|
111
|
-
|
|
112
|
-
setShowInspector(!showInspector);
|
|
113
|
-
}}
|
|
114
|
-
>
|
|
115
|
-
{showInspector ? (
|
|
116
|
-
"Hide Inspector"
|
|
117
|
-
) : (
|
|
118
|
-
<span style={{ width: "12px", height: "12px" }}>
|
|
119
|
-
{isRightAnchor ? rightIcon : leftIcon}
|
|
120
|
-
</span>
|
|
121
|
-
)}
|
|
122
|
-
</span>
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function DisclosureSection({
|
|
127
|
-
open,
|
|
128
|
-
setOpen,
|
|
129
|
-
title,
|
|
130
|
-
right,
|
|
131
|
-
children,
|
|
132
|
-
colorScheme,
|
|
133
|
-
isFirst,
|
|
134
|
-
style,
|
|
135
|
-
}: {
|
|
136
|
-
open: boolean;
|
|
137
|
-
setOpen?: (value: boolean) => void;
|
|
138
|
-
title: React.ReactNode;
|
|
139
|
-
right?: React.ReactNode;
|
|
140
|
-
children: React.ReactNode;
|
|
141
|
-
colorScheme: "light" | "dark";
|
|
142
|
-
isFirst?: boolean;
|
|
143
|
-
style?: CSSProperties;
|
|
144
|
-
}) {
|
|
145
|
-
const theme = colorScheme === "light" ? lightTheme : darkTheme;
|
|
146
|
-
|
|
147
|
-
const borderColor =
|
|
148
|
-
colorScheme === "light" ? "rgba(0,0,0,0.1)" : "rgba(255,255,255,0.1)";
|
|
149
|
-
|
|
150
|
-
return (
|
|
151
|
-
<div
|
|
152
|
-
style={{
|
|
153
|
-
flex: open ? "1 1 0" : "0",
|
|
154
|
-
display: "flex",
|
|
155
|
-
flexDirection: "column",
|
|
156
|
-
...style,
|
|
157
|
-
}}
|
|
158
|
-
>
|
|
159
|
-
<div
|
|
160
|
-
onClick={() => setOpen?.(!open)}
|
|
161
|
-
style={{
|
|
162
|
-
cursor: "default",
|
|
163
|
-
fontSize: "12px",
|
|
164
|
-
padding: "4px 10px",
|
|
165
|
-
display: "flex",
|
|
166
|
-
alignItems: "center",
|
|
167
|
-
...(!isFirst && { borderTop: `1px solid ${borderColor}` }),
|
|
168
|
-
...(open && { borderBottom: `1px solid ${borderColor}` }),
|
|
169
|
-
}}
|
|
170
|
-
>
|
|
171
|
-
{setOpen && (
|
|
172
|
-
<Arrow
|
|
173
|
-
expanded={open}
|
|
174
|
-
style={{
|
|
175
|
-
fontSize: theme.ARROW_FONT_SIZE,
|
|
176
|
-
marginRight: theme.ARROW_MARGIN_RIGHT + 1,
|
|
177
|
-
color: theme.ARROW_COLOR,
|
|
178
|
-
}}
|
|
179
|
-
/>
|
|
180
|
-
)}
|
|
181
|
-
<span style={{ flex: "1 1 0", userSelect: "none" }}>{title}</span>
|
|
182
|
-
{right}
|
|
183
|
-
</div>
|
|
184
|
-
{open && children}
|
|
185
|
-
</div>
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
function InspectorRow({
|
|
190
|
-
children,
|
|
191
|
-
colorScheme,
|
|
192
|
-
selected,
|
|
193
|
-
style,
|
|
194
|
-
variant,
|
|
195
|
-
}: {
|
|
196
|
-
children: React.ReactNode;
|
|
197
|
-
colorScheme: "light" | "dark";
|
|
198
|
-
selected?: boolean;
|
|
199
|
-
style?: CSSProperties;
|
|
200
|
-
variant?: "up" | "down";
|
|
201
|
-
}) {
|
|
202
|
-
const solidBorderColor =
|
|
203
|
-
colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
|
|
204
|
-
|
|
205
|
-
return (
|
|
206
|
-
<div
|
|
207
|
-
style={{
|
|
208
|
-
borderBottom: `1px solid ${solidBorderColor}`,
|
|
209
|
-
fontSize: "12px",
|
|
210
|
-
fontFamily: "Menlo, monospace",
|
|
211
|
-
padding: "2px 12px 1px",
|
|
212
|
-
display: "flex",
|
|
213
|
-
alignItems: "center",
|
|
214
|
-
background:
|
|
215
|
-
variant === "up"
|
|
216
|
-
? "rgba(0,255,0,0.1)"
|
|
217
|
-
: variant === "down"
|
|
218
|
-
? "transparent"
|
|
219
|
-
: selected
|
|
220
|
-
? "rgb(59 130 246 / 15%)"
|
|
221
|
-
: undefined,
|
|
222
|
-
// background:
|
|
223
|
-
// colorScheme === "light"
|
|
224
|
-
// ? "rgba(0,0,0,0.05)"
|
|
225
|
-
// : "rgba(255,255,255,0.05)",
|
|
226
|
-
...style,
|
|
227
|
-
}}
|
|
228
|
-
>
|
|
229
|
-
<span
|
|
230
|
-
style={{
|
|
231
|
-
fontFamily: "Menlo, monospace",
|
|
232
|
-
fontSize: "11px",
|
|
233
|
-
borderRadius: 4,
|
|
234
|
-
display: "inline-block",
|
|
235
|
-
}}
|
|
236
|
-
>
|
|
237
|
-
{children}
|
|
238
|
-
</span>
|
|
239
|
-
</div>
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const HISTORY_ELEMENT_PREFIX = "noya-multiplayer-history-";
|
|
36
|
+
import { ellipsis, uploadFile } from "./utils";
|
|
244
37
|
|
|
245
38
|
export type StateInspectorAnchor =
|
|
246
39
|
| "left"
|
|
@@ -278,6 +71,8 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
278
71
|
connectionEventManager,
|
|
279
72
|
taskManager,
|
|
280
73
|
ioManager,
|
|
74
|
+
resourceManager,
|
|
75
|
+
activityEventsManager,
|
|
281
76
|
} = noyaManager;
|
|
282
77
|
|
|
283
78
|
const [didMount, setDidMount] = React.useState(false);
|
|
@@ -290,7 +85,7 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
290
85
|
}, []);
|
|
291
86
|
|
|
292
87
|
const eventsContainerRef = React.useRef<HTMLDivElement>(null);
|
|
293
|
-
const
|
|
88
|
+
const activityEventsContainerRef = React.useRef<HTMLDivElement>(null);
|
|
294
89
|
|
|
295
90
|
const [showInspector, setShowInspector] = useLocalStorageState(
|
|
296
91
|
"noya-multiplayer-react-show-inspector",
|
|
@@ -324,6 +119,10 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
324
119
|
"noya-multiplayer-react-show-assets",
|
|
325
120
|
false
|
|
326
121
|
);
|
|
122
|
+
const [showResources, setShowResources] = useLocalStorageState(
|
|
123
|
+
"noya-multiplayer-react-show-resources",
|
|
124
|
+
false
|
|
125
|
+
);
|
|
327
126
|
const [showSecrets, setShowSecrets] = useLocalStorageState(
|
|
328
127
|
"noya-multiplayer-react-show-secrets",
|
|
329
128
|
false
|
|
@@ -336,9 +135,12 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
336
135
|
"noya-multiplayer-react-show-output-transforms",
|
|
337
136
|
false
|
|
338
137
|
);
|
|
138
|
+
const [showActivityEvents, setShowActivityEvents] = useLocalStorageState(
|
|
139
|
+
"noya-multiplayer-react-show-activity-events",
|
|
140
|
+
false
|
|
141
|
+
);
|
|
339
142
|
|
|
340
143
|
const connectionEvents = useObservable(connectionEventManager.events$);
|
|
341
|
-
|
|
342
144
|
useEffect(() => {
|
|
343
145
|
if (eventsContainerRef.current) {
|
|
344
146
|
eventsContainerRef.current.scrollTop =
|
|
@@ -352,6 +154,8 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
352
154
|
const ephemeral = useObservable(ephemeralUserDataManager.data$);
|
|
353
155
|
const historySnapshot = useManagedHistory(multiplayerStateManager.sm);
|
|
354
156
|
const assets = useObservable(assetManager.assets$);
|
|
157
|
+
const resources = useObservable(resourceManager.resources$);
|
|
158
|
+
const resourcesInitialized = useObservable(resourceManager.isInitialized$);
|
|
355
159
|
const assetsInitialized = useObservable(assetManager.isInitialized$);
|
|
356
160
|
const secrets = useObservable(secretManager.secrets$);
|
|
357
161
|
const secretsInitialized = useObservable(secretManager.isInitialized$);
|
|
@@ -362,35 +166,8 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
362
166
|
const outputTransformsInitialized = useObservable(
|
|
363
167
|
ioManager.outputTransformsInitialized$
|
|
364
168
|
);
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
if (historyContainerRef.current) {
|
|
368
|
-
historyContainerRef.current.scrollTop =
|
|
369
|
-
historyContainerRef.current.scrollHeight;
|
|
370
|
-
}
|
|
371
|
-
}, [historySnapshot]);
|
|
372
|
-
|
|
373
|
-
// If history index changes, scroll to the new history entry into view
|
|
374
|
-
useEffect(() => {
|
|
375
|
-
if (!historyContainerRef.current) return;
|
|
376
|
-
|
|
377
|
-
const historyEntry = historyContainerRef.current.querySelector(
|
|
378
|
-
`#${HISTORY_ELEMENT_PREFIX}${historySnapshot.historyIndex}`
|
|
379
|
-
);
|
|
380
|
-
|
|
381
|
-
if (historyEntry) {
|
|
382
|
-
historyEntry.scrollIntoView({
|
|
383
|
-
block: "nearest",
|
|
384
|
-
inline: "nearest",
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
|
-
}, [historySnapshot.historyIndex]);
|
|
388
|
-
|
|
389
|
-
const theme = colorScheme === "light" ? lightTheme : darkTheme;
|
|
390
|
-
// const borderColor =
|
|
391
|
-
// colorScheme === "light" ? "rgba(0,0,0,0.1)" : "rgba(255,255,255,0.1)";
|
|
392
|
-
const solidBorderColor =
|
|
393
|
-
colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
|
|
169
|
+
const theme = getStateInspectorTheme(colorScheme);
|
|
170
|
+
const solidBorderColor = getStateInspectorBorderColor(colorScheme);
|
|
394
171
|
|
|
395
172
|
const baseStyle: CSSProperties = {
|
|
396
173
|
position: "fixed",
|
|
@@ -413,6 +190,25 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
413
190
|
lineHeight: "13px",
|
|
414
191
|
};
|
|
415
192
|
|
|
193
|
+
const handleExportAll = useCallback(async () => {
|
|
194
|
+
const buffer = await exportAll(noyaManager);
|
|
195
|
+
|
|
196
|
+
downloadBlob(new Blob([buffer]), "state.zip");
|
|
197
|
+
}, [noyaManager]);
|
|
198
|
+
|
|
199
|
+
const handleImportAll = useCallback(async () => {
|
|
200
|
+
const file = await uploadFile();
|
|
201
|
+
const buffer = await file.arrayBuffer();
|
|
202
|
+
|
|
203
|
+
importAll(buffer, noyaManager, {
|
|
204
|
+
shouldAllowSchemaChange: () => {
|
|
205
|
+
return confirm(
|
|
206
|
+
`The imported state uses a different schema than the schema this app expects. Do you want to continue?`
|
|
207
|
+
);
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
}, [noyaManager]);
|
|
211
|
+
|
|
416
212
|
if (!didMount) return null;
|
|
417
213
|
|
|
418
214
|
if (!showInspector) {
|
|
@@ -429,7 +225,7 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
429
225
|
}}
|
|
430
226
|
onClick={() => setShowInspector(true)}
|
|
431
227
|
>
|
|
432
|
-
<
|
|
228
|
+
<StateInspectorToggleButton
|
|
433
229
|
showInspector={showInspector}
|
|
434
230
|
setShowInspector={setShowInspector}
|
|
435
231
|
theme={theme}
|
|
@@ -447,7 +243,7 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
447
243
|
...props.style,
|
|
448
244
|
}}
|
|
449
245
|
>
|
|
450
|
-
<
|
|
246
|
+
<StateInspectorDisclosureSection
|
|
451
247
|
isFirst
|
|
452
248
|
open={showUsers}
|
|
453
249
|
setOpen={setShowUsers}
|
|
@@ -458,7 +254,7 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
458
254
|
maxHeight: "200px",
|
|
459
255
|
}}
|
|
460
256
|
right={
|
|
461
|
-
<
|
|
257
|
+
<StateInspectorToggleButton
|
|
462
258
|
showInspector={showInspector}
|
|
463
259
|
setShowInspector={setShowInspector}
|
|
464
260
|
theme={theme}
|
|
@@ -466,9 +262,9 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
466
262
|
/>
|
|
467
263
|
}
|
|
468
264
|
>
|
|
469
|
-
<
|
|
265
|
+
<StateInspectorDisclosureRowInner style={{ flex: "0 0 auto" }}>
|
|
470
266
|
{connectedUsers?.map((user) => (
|
|
471
|
-
<
|
|
267
|
+
<StateInspectorRow
|
|
472
268
|
key={user.id}
|
|
473
269
|
colorScheme={colorScheme}
|
|
474
270
|
variant={user.id === userId ? "up" : undefined}
|
|
@@ -490,7 +286,7 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
490
286
|
/>
|
|
491
287
|
)}
|
|
492
288
|
{user.name} ({ellipsis(user.id.toString(), 8, "middle")})
|
|
493
|
-
</
|
|
289
|
+
</StateInspectorRow>
|
|
494
290
|
))}
|
|
495
291
|
{!connectedUsers && (
|
|
496
292
|
<div
|
|
@@ -505,16 +301,16 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
505
301
|
<span>No connected users</span>
|
|
506
302
|
</div>
|
|
507
303
|
)}
|
|
508
|
-
</
|
|
509
|
-
</
|
|
510
|
-
<
|
|
304
|
+
</StateInspectorDisclosureRowInner>
|
|
305
|
+
</StateInspectorDisclosureSection>
|
|
306
|
+
<StateInspectorDisclosureSection
|
|
511
307
|
title={
|
|
512
|
-
<
|
|
308
|
+
<StateInspectorTitleLabel>
|
|
513
309
|
Data
|
|
514
310
|
<ColoredDot
|
|
515
311
|
type={multipeerStateInitialized ? "success" : "error"}
|
|
516
312
|
/>
|
|
517
|
-
</
|
|
313
|
+
</StateInspectorTitleLabel>
|
|
518
314
|
}
|
|
519
315
|
colorScheme={colorScheme}
|
|
520
316
|
setOpen={setShowData}
|
|
@@ -523,10 +319,16 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
523
319
|
<span
|
|
524
320
|
style={{
|
|
525
321
|
display: "flex",
|
|
526
|
-
gap: "
|
|
322
|
+
gap: "12px",
|
|
527
323
|
}}
|
|
528
324
|
>
|
|
529
|
-
<
|
|
325
|
+
<StateInspectorButton theme={theme} onClick={handleImportAll}>
|
|
326
|
+
Import
|
|
327
|
+
</StateInspectorButton>
|
|
328
|
+
<StateInspectorButton theme={theme} onClick={handleExportAll}>
|
|
329
|
+
Export
|
|
330
|
+
</StateInspectorButton>
|
|
331
|
+
<StateInspectorButton
|
|
530
332
|
// disabled={!historySnapshot.canUndo}
|
|
531
333
|
theme={theme}
|
|
532
334
|
onClick={() => {
|
|
@@ -534,207 +336,63 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
534
336
|
}}
|
|
535
337
|
>
|
|
536
338
|
Reset
|
|
537
|
-
</
|
|
339
|
+
</StateInspectorButton>
|
|
538
340
|
</span>
|
|
539
341
|
}
|
|
540
342
|
>
|
|
541
|
-
<
|
|
542
|
-
<
|
|
343
|
+
<StateInspectorDisclosureRowInner>
|
|
344
|
+
<StateInspectorRow colorScheme={colorScheme}>
|
|
543
345
|
<ObjectInspector
|
|
544
346
|
name={multiplayerStateManager.schema ? "state" : undefined}
|
|
545
347
|
data={state}
|
|
546
348
|
theme={theme}
|
|
547
349
|
/>
|
|
548
|
-
</
|
|
350
|
+
</StateInspectorRow>
|
|
549
351
|
{multiplayerStateManager.schema && (
|
|
550
|
-
<
|
|
352
|
+
<StateInspectorRow colorScheme={colorScheme}>
|
|
551
353
|
<ObjectInspector
|
|
552
354
|
name="schema"
|
|
553
355
|
data={multiplayerStateManager.schema}
|
|
554
356
|
theme={theme}
|
|
555
357
|
/>
|
|
556
|
-
</
|
|
358
|
+
</StateInspectorRow>
|
|
557
359
|
)}
|
|
558
|
-
</
|
|
559
|
-
</
|
|
560
|
-
<
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
title="History"
|
|
360
|
+
</StateInspectorDisclosureRowInner>
|
|
361
|
+
</StateInspectorDisclosureSection>
|
|
362
|
+
<HistorySection
|
|
363
|
+
showHistory={showHistory}
|
|
364
|
+
setShowHistory={setShowHistory}
|
|
564
365
|
colorScheme={colorScheme}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
gap: "4px",
|
|
570
|
-
}}
|
|
571
|
-
>
|
|
572
|
-
<SmallButton
|
|
573
|
-
disabled={!historySnapshot.canUndo}
|
|
574
|
-
theme={theme}
|
|
575
|
-
onClick={() => {
|
|
576
|
-
multiplayerStateManager.undo();
|
|
577
|
-
}}
|
|
578
|
-
>
|
|
579
|
-
<span style={{ width: "12px", height: "12px" }}>
|
|
580
|
-
<svg
|
|
581
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
582
|
-
width="1em"
|
|
583
|
-
height="1em"
|
|
584
|
-
viewBox="0 0 20 20"
|
|
585
|
-
>
|
|
586
|
-
<path
|
|
587
|
-
fill="currentColor"
|
|
588
|
-
d="M12 5H7V2L1 6l6 4V7h5c2.2 0 4 1.8 4 4s-1.8 4-4 4H7v2h5c3.3 0 6-2.7 6-6s-2.7-6-6-6"
|
|
589
|
-
/>
|
|
590
|
-
</svg>
|
|
591
|
-
</span>
|
|
592
|
-
</SmallButton>
|
|
593
|
-
<SmallButton
|
|
594
|
-
disabled={!historySnapshot.canRedo}
|
|
595
|
-
theme={theme}
|
|
596
|
-
onClick={() => {
|
|
597
|
-
multiplayerStateManager.redo();
|
|
598
|
-
}}
|
|
599
|
-
>
|
|
600
|
-
<span style={{ width: "12px", height: "12px" }}>
|
|
601
|
-
<svg
|
|
602
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
603
|
-
width="1em"
|
|
604
|
-
height="1em"
|
|
605
|
-
viewBox="0 0 20 20"
|
|
606
|
-
>
|
|
607
|
-
<path
|
|
608
|
-
fill="currentColor"
|
|
609
|
-
d="M8 5h5V2l6 4l-6 4V7H8c-2.2 0-4 1.8-4 4s1.8 4 4 4h5v2H8c-3.3 0-6-2.7-6-6s2.7-6 6-6"
|
|
610
|
-
/>
|
|
611
|
-
</svg>
|
|
612
|
-
</span>
|
|
613
|
-
</SmallButton>
|
|
614
|
-
</span>
|
|
615
|
-
}
|
|
616
|
-
>
|
|
617
|
-
<div ref={historyContainerRef} style={styles.sectionInner}>
|
|
618
|
-
<div
|
|
619
|
-
id={`${HISTORY_ELEMENT_PREFIX}0`}
|
|
620
|
-
style={{
|
|
621
|
-
borderBottom: `1px solid ${solidBorderColor}`,
|
|
622
|
-
fontSize: "12px",
|
|
623
|
-
fontFamily: "Menlo, monospace",
|
|
624
|
-
padding: "2px 12px 1px",
|
|
625
|
-
display: "flex",
|
|
626
|
-
alignItems: "center",
|
|
627
|
-
background:
|
|
628
|
-
historySnapshot.historyIndex === 0
|
|
629
|
-
? "rgb(59 130 246 / 15%)"
|
|
630
|
-
: undefined,
|
|
631
|
-
}}
|
|
632
|
-
>
|
|
633
|
-
<span
|
|
634
|
-
style={{
|
|
635
|
-
fontFamily: "Menlo, monospace",
|
|
636
|
-
fontSize: "11px",
|
|
637
|
-
borderRadius: 4,
|
|
638
|
-
display: "inline-block",
|
|
639
|
-
}}
|
|
640
|
-
>
|
|
641
|
-
Initial state
|
|
642
|
-
</span>
|
|
643
|
-
</div>
|
|
644
|
-
{historySnapshot.history.map((entry, index) => (
|
|
645
|
-
<div
|
|
646
|
-
id={`${HISTORY_ELEMENT_PREFIX}${index + 1}`}
|
|
647
|
-
key={index}
|
|
648
|
-
style={{
|
|
649
|
-
padding: "0px 12px 1px",
|
|
650
|
-
borderBottom: `1px solid ${solidBorderColor}`,
|
|
651
|
-
background:
|
|
652
|
-
index + 1 === historySnapshot.historyIndex
|
|
653
|
-
? "rgb(59 130 246 / 15%)"
|
|
654
|
-
: undefined,
|
|
655
|
-
}}
|
|
656
|
-
>
|
|
657
|
-
{"name" in entry.metadata &&
|
|
658
|
-
typeof entry.metadata.name === "string" && (
|
|
659
|
-
<pre
|
|
660
|
-
style={{
|
|
661
|
-
fontSize: "11px",
|
|
662
|
-
display: "flex",
|
|
663
|
-
flexWrap: "wrap",
|
|
664
|
-
margin: 0,
|
|
665
|
-
}}
|
|
666
|
-
>
|
|
667
|
-
{entry.metadata.name}
|
|
668
|
-
</pre>
|
|
669
|
-
)}
|
|
670
|
-
{entry.redoPatches?.map((patch, j) => (
|
|
671
|
-
<pre
|
|
672
|
-
key={j}
|
|
673
|
-
style={{
|
|
674
|
-
fontSize: "11px",
|
|
675
|
-
display: "flex",
|
|
676
|
-
flexWrap: "wrap",
|
|
677
|
-
margin: 0,
|
|
678
|
-
}}
|
|
679
|
-
>
|
|
680
|
-
{patch.op === "add" && (
|
|
681
|
-
<>
|
|
682
|
-
<span style={{ fontStyle: "italic" }}>
|
|
683
|
-
{pathToString(patch.path)}
|
|
684
|
-
</span>
|
|
685
|
-
{" = "}
|
|
686
|
-
<ObjectInspector data={patch.value} theme={theme} />
|
|
687
|
-
</>
|
|
688
|
-
)}
|
|
689
|
-
{patch.op === "replace" && (
|
|
690
|
-
<>
|
|
691
|
-
<span style={{ fontStyle: "italic" }}>
|
|
692
|
-
{pathToString(patch.path)}
|
|
693
|
-
</span>
|
|
694
|
-
{" = "}
|
|
695
|
-
<ObjectInspector data={patch.value} theme={theme} />
|
|
696
|
-
</>
|
|
697
|
-
)}
|
|
698
|
-
{patch.op === "remove" && (
|
|
699
|
-
<>
|
|
700
|
-
<span style={{ color: theme.OBJECT_VALUE_STRING_COLOR }}>
|
|
701
|
-
delete{" "}
|
|
702
|
-
</span>
|
|
703
|
-
<span style={{ fontStyle: "italic" }}>
|
|
704
|
-
{pathToString(patch.path)}
|
|
705
|
-
</span>
|
|
706
|
-
</>
|
|
707
|
-
)}
|
|
708
|
-
{patch.op === "move" && (
|
|
709
|
-
<>
|
|
710
|
-
<span style={{ fontStyle: "italic" }}>
|
|
711
|
-
{pathToString(patch.from!)}
|
|
712
|
-
</span>
|
|
713
|
-
{" -> "}
|
|
714
|
-
<span style={{ fontStyle: "italic" }}>
|
|
715
|
-
{pathToString(patch.path)}
|
|
716
|
-
</span>
|
|
717
|
-
</>
|
|
718
|
-
)}
|
|
719
|
-
</pre>
|
|
720
|
-
))}
|
|
721
|
-
</div>
|
|
722
|
-
))}
|
|
723
|
-
</div>
|
|
724
|
-
</DisclosureSection>
|
|
725
|
-
<DisclosureSection
|
|
366
|
+
historySnapshot={historySnapshot}
|
|
367
|
+
multiplayerStateManager={multiplayerStateManager}
|
|
368
|
+
/>
|
|
369
|
+
<StateInspectorDisclosureSection
|
|
726
370
|
open={showAssets}
|
|
727
371
|
setOpen={setShowAssets}
|
|
728
372
|
title={
|
|
729
|
-
<
|
|
730
|
-
Assets
|
|
373
|
+
<StateInspectorTitleLabel>
|
|
374
|
+
Assets ({assets.length})
|
|
731
375
|
<ColoredDot type={assetsInitialized ? "success" : "error"} />
|
|
732
|
-
</
|
|
376
|
+
</StateInspectorTitleLabel>
|
|
733
377
|
}
|
|
734
378
|
colorScheme={colorScheme}
|
|
735
379
|
right={
|
|
736
380
|
<span style={{ display: "flex", gap: "10px" }}>
|
|
737
|
-
<
|
|
381
|
+
<StateInspectorButton
|
|
382
|
+
theme={theme}
|
|
383
|
+
onClick={async () => {
|
|
384
|
+
const ok = confirm(
|
|
385
|
+
"Are you sure you want to delete all assets?"
|
|
386
|
+
);
|
|
387
|
+
if (!ok) return;
|
|
388
|
+
await Promise.all(
|
|
389
|
+
assets.map((asset) => assetManager.delete(asset.id))
|
|
390
|
+
);
|
|
391
|
+
}}
|
|
392
|
+
>
|
|
393
|
+
Delete all
|
|
394
|
+
</StateInspectorButton>
|
|
395
|
+
<StateInspectorButton
|
|
738
396
|
theme={theme}
|
|
739
397
|
onClick={() => {
|
|
740
398
|
console.info(
|
|
@@ -745,8 +403,8 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
745
403
|
}}
|
|
746
404
|
>
|
|
747
405
|
Reload
|
|
748
|
-
</
|
|
749
|
-
<
|
|
406
|
+
</StateInspectorButton>
|
|
407
|
+
<StateInspectorButton
|
|
750
408
|
theme={theme}
|
|
751
409
|
onClick={() => {
|
|
752
410
|
// get file input
|
|
@@ -767,36 +425,129 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
767
425
|
}}
|
|
768
426
|
>
|
|
769
427
|
Upload
|
|
770
|
-
</
|
|
428
|
+
</StateInspectorButton>
|
|
771
429
|
</span>
|
|
772
430
|
}
|
|
773
431
|
>
|
|
774
|
-
<
|
|
432
|
+
<StateInspectorDisclosureRowInner>
|
|
775
433
|
{assets.map((asset) => (
|
|
776
|
-
<
|
|
434
|
+
<StateInspectorRow key={asset.id} colorScheme={colorScheme}>
|
|
777
435
|
<ObjectInspector name={asset.id} data={asset} theme={theme} />
|
|
778
|
-
<
|
|
436
|
+
<StateInspectorButton
|
|
779
437
|
theme={theme}
|
|
780
438
|
onClick={() => assetManager.delete(asset.id)}
|
|
781
439
|
>
|
|
782
440
|
Delete
|
|
783
|
-
</
|
|
784
|
-
</
|
|
441
|
+
</StateInspectorButton>
|
|
442
|
+
</StateInspectorRow>
|
|
443
|
+
))}
|
|
444
|
+
</StateInspectorDisclosureRowInner>
|
|
445
|
+
</StateInspectorDisclosureSection>
|
|
446
|
+
<StateInspectorDisclosureSection
|
|
447
|
+
title={
|
|
448
|
+
<StateInspectorTitleLabel>
|
|
449
|
+
Resources ({resources.length})
|
|
450
|
+
<ColoredDot type={resourcesInitialized ? "success" : "error"} />
|
|
451
|
+
</StateInspectorTitleLabel>
|
|
452
|
+
}
|
|
453
|
+
colorScheme={colorScheme}
|
|
454
|
+
open={showResources}
|
|
455
|
+
setOpen={setShowResources}
|
|
456
|
+
right={
|
|
457
|
+
<span style={{ display: "flex", gap: "10px" }}>
|
|
458
|
+
<StateInspectorButton
|
|
459
|
+
theme={theme}
|
|
460
|
+
onClick={async () => {
|
|
461
|
+
const ok = confirm(
|
|
462
|
+
"Are you sure you want to delete all resources?"
|
|
463
|
+
);
|
|
464
|
+
if (!ok) return;
|
|
465
|
+
await Promise.all(
|
|
466
|
+
resources.map((resource) =>
|
|
467
|
+
resourceManager.deleteResource({ id: resource.id })
|
|
468
|
+
)
|
|
469
|
+
);
|
|
470
|
+
}}
|
|
471
|
+
>
|
|
472
|
+
Delete all
|
|
473
|
+
</StateInspectorButton>
|
|
474
|
+
<StateInspectorButton
|
|
475
|
+
theme={theme}
|
|
476
|
+
onClick={async () => {
|
|
477
|
+
const path = prompt("Enter directory path") || uuid();
|
|
478
|
+
await resourceManager.createResource({
|
|
479
|
+
type: "directory",
|
|
480
|
+
path,
|
|
481
|
+
});
|
|
482
|
+
}}
|
|
483
|
+
>
|
|
484
|
+
Create Directory
|
|
485
|
+
</StateInspectorButton>
|
|
486
|
+
<StateInspectorButton
|
|
487
|
+
theme={theme}
|
|
488
|
+
onClick={async () => {
|
|
489
|
+
const file = await uploadFile();
|
|
490
|
+
|
|
491
|
+
resourceManager.createResource({
|
|
492
|
+
type: "asset",
|
|
493
|
+
path: file.name || uuid(),
|
|
494
|
+
asset: {
|
|
495
|
+
content: Base64.encode(await file.arrayBuffer()),
|
|
496
|
+
contentType: file.type,
|
|
497
|
+
encoding: "base64",
|
|
498
|
+
},
|
|
499
|
+
});
|
|
500
|
+
}}
|
|
501
|
+
>
|
|
502
|
+
Create Asset
|
|
503
|
+
</StateInspectorButton>
|
|
504
|
+
</span>
|
|
505
|
+
}
|
|
506
|
+
>
|
|
507
|
+
<StateInspectorDisclosureRowInner>
|
|
508
|
+
{resources?.map((resource) => (
|
|
509
|
+
<StateInspectorRow key={resource.id} colorScheme={colorScheme}>
|
|
510
|
+
<ObjectInspector
|
|
511
|
+
name={resource.path}
|
|
512
|
+
data={resource}
|
|
513
|
+
theme={theme}
|
|
514
|
+
/>
|
|
515
|
+
<div style={{ display: "flex", gap: "4px" }}>
|
|
516
|
+
<StateInspectorButton
|
|
517
|
+
theme={theme}
|
|
518
|
+
onClick={() =>
|
|
519
|
+
resourceManager.deleteResource({ id: resource.id })
|
|
520
|
+
}
|
|
521
|
+
>
|
|
522
|
+
Delete
|
|
523
|
+
</StateInspectorButton>
|
|
524
|
+
<StateInspectorButton
|
|
525
|
+
theme={theme}
|
|
526
|
+
onClick={() => {
|
|
527
|
+
const path = prompt("Enter new path", resource.path);
|
|
528
|
+
if (!path) return;
|
|
529
|
+
resourceManager.updateResource({ id: resource.id, path });
|
|
530
|
+
}}
|
|
531
|
+
>
|
|
532
|
+
Rename
|
|
533
|
+
</StateInspectorButton>
|
|
534
|
+
</div>
|
|
535
|
+
</StateInspectorRow>
|
|
785
536
|
))}
|
|
786
|
-
</
|
|
787
|
-
</
|
|
788
|
-
<
|
|
537
|
+
</StateInspectorDisclosureRowInner>
|
|
538
|
+
</StateInspectorDisclosureSection>
|
|
539
|
+
<StateInspectorDisclosureSection
|
|
789
540
|
title={
|
|
790
|
-
<
|
|
541
|
+
<StateInspectorTitleLabel>
|
|
791
542
|
Secrets
|
|
792
543
|
<ColoredDot type={secretsInitialized ? "success" : "error"} />
|
|
793
|
-
</
|
|
544
|
+
</StateInspectorTitleLabel>
|
|
794
545
|
}
|
|
795
546
|
colorScheme={colorScheme}
|
|
796
547
|
open={showSecrets}
|
|
797
548
|
setOpen={setShowSecrets}
|
|
798
549
|
right={
|
|
799
|
-
<
|
|
550
|
+
<StateInspectorButton
|
|
800
551
|
theme={theme}
|
|
801
552
|
onClick={() => {
|
|
802
553
|
const name = prompt("Enter secret name");
|
|
@@ -807,39 +558,39 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
807
558
|
}}
|
|
808
559
|
>
|
|
809
560
|
Create
|
|
810
|
-
</
|
|
561
|
+
</StateInspectorButton>
|
|
811
562
|
}
|
|
812
563
|
>
|
|
813
|
-
<
|
|
564
|
+
<StateInspectorDisclosureRowInner>
|
|
814
565
|
{secrets.map((secret) => (
|
|
815
|
-
<
|
|
566
|
+
<StateInspectorRow key={secret.id} colorScheme={colorScheme}>
|
|
816
567
|
<ObjectInspector data={secret} theme={theme} />
|
|
817
|
-
<
|
|
568
|
+
<StateInspectorButton
|
|
818
569
|
theme={theme}
|
|
819
570
|
onClick={() => secretManager.deleteSecret(secret.id)}
|
|
820
571
|
>
|
|
821
572
|
Delete
|
|
822
|
-
</
|
|
823
|
-
</
|
|
573
|
+
</StateInspectorButton>
|
|
574
|
+
</StateInspectorRow>
|
|
824
575
|
))}
|
|
825
|
-
</
|
|
826
|
-
</
|
|
827
|
-
<
|
|
576
|
+
</StateInspectorDisclosureRowInner>
|
|
577
|
+
</StateInspectorDisclosureSection>{" "}
|
|
578
|
+
<StateInspectorDisclosureSection
|
|
828
579
|
open={showInputs}
|
|
829
580
|
setOpen={setShowInputs}
|
|
830
581
|
title={
|
|
831
|
-
<
|
|
582
|
+
<StateInspectorTitleLabel>
|
|
832
583
|
Inputs
|
|
833
584
|
<ColoredDot type={inputsInitialized ? "success" : "error"} />
|
|
834
|
-
</
|
|
585
|
+
</StateInspectorTitleLabel>
|
|
835
586
|
}
|
|
836
587
|
colorScheme={colorScheme}
|
|
837
588
|
>
|
|
838
|
-
<
|
|
589
|
+
<StateInspectorDisclosureRowInner>
|
|
839
590
|
{inputs?.map((input: Input) => (
|
|
840
|
-
<
|
|
591
|
+
<StateInspectorRow key={input.id} colorScheme={colorScheme}>
|
|
841
592
|
<ObjectInspector data={input} theme={theme} />
|
|
842
|
-
</
|
|
593
|
+
</StateInspectorRow>
|
|
843
594
|
))}
|
|
844
595
|
{!inputs?.length && (
|
|
845
596
|
<div
|
|
@@ -854,26 +605,26 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
854
605
|
<span>No inputs</span>
|
|
855
606
|
</div>
|
|
856
607
|
)}
|
|
857
|
-
</
|
|
858
|
-
</
|
|
859
|
-
<
|
|
608
|
+
</StateInspectorDisclosureRowInner>
|
|
609
|
+
</StateInspectorDisclosureSection>
|
|
610
|
+
<StateInspectorDisclosureSection
|
|
860
611
|
open={showOutputTransforms}
|
|
861
612
|
setOpen={setShowOutputTransforms}
|
|
862
613
|
title={
|
|
863
|
-
<
|
|
614
|
+
<StateInspectorTitleLabel>
|
|
864
615
|
Output Transforms
|
|
865
616
|
<ColoredDot
|
|
866
617
|
type={outputTransformsInitialized ? "success" : "error"}
|
|
867
618
|
/>
|
|
868
|
-
</
|
|
619
|
+
</StateInspectorTitleLabel>
|
|
869
620
|
}
|
|
870
621
|
colorScheme={colorScheme}
|
|
871
622
|
>
|
|
872
|
-
<
|
|
623
|
+
<StateInspectorDisclosureRowInner>
|
|
873
624
|
{outputTransforms?.map((transform: OutputTransform) => (
|
|
874
|
-
<
|
|
625
|
+
<StateInspectorRow key={transform.id} colorScheme={colorScheme}>
|
|
875
626
|
<ObjectInspector data={transform} theme={theme} />
|
|
876
|
-
</
|
|
627
|
+
</StateInspectorRow>
|
|
877
628
|
))}
|
|
878
629
|
{!outputTransforms?.length && (
|
|
879
630
|
<div
|
|
@@ -888,17 +639,17 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
888
639
|
<span>No output transforms</span>
|
|
889
640
|
</div>
|
|
890
641
|
)}
|
|
891
|
-
</
|
|
892
|
-
</
|
|
893
|
-
<
|
|
642
|
+
</StateInspectorDisclosureRowInner>
|
|
643
|
+
</StateInspectorDisclosureSection>
|
|
644
|
+
<StateInspectorDisclosureSection
|
|
894
645
|
title="Tasks"
|
|
895
646
|
colorScheme={colorScheme}
|
|
896
647
|
open={showTasks}
|
|
897
648
|
setOpen={setShowTasks}
|
|
898
649
|
>
|
|
899
|
-
<
|
|
650
|
+
<StateInspectorDisclosureRowInner>
|
|
900
651
|
{tasks?.map((task) => (
|
|
901
|
-
<
|
|
652
|
+
<StateInspectorRow
|
|
902
653
|
key={task.id}
|
|
903
654
|
colorScheme={colorScheme}
|
|
904
655
|
style={{
|
|
@@ -915,269 +666,43 @@ export const StateInspector = memoGeneric(function StateInspector<
|
|
|
915
666
|
data={task.payload}
|
|
916
667
|
theme={theme}
|
|
917
668
|
/>
|
|
918
|
-
</
|
|
669
|
+
</StateInspectorRow>
|
|
919
670
|
))}
|
|
920
|
-
</
|
|
921
|
-
</
|
|
922
|
-
<
|
|
671
|
+
</StateInspectorDisclosureRowInner>
|
|
672
|
+
</StateInspectorDisclosureSection>
|
|
673
|
+
<StateInspectorDisclosureSection
|
|
923
674
|
open={showEphemeral}
|
|
924
675
|
setOpen={setShowEphemeral}
|
|
925
676
|
title="Ephemeral User Data"
|
|
926
677
|
colorScheme={colorScheme}
|
|
927
678
|
>
|
|
928
|
-
<
|
|
679
|
+
<StateInspectorDisclosureRowInner>
|
|
929
680
|
{Object.entries(ephemeral).map(([key, value]) => (
|
|
930
|
-
<
|
|
681
|
+
<StateInspectorRow key={key} colorScheme={colorScheme}>
|
|
931
682
|
<ObjectInspector
|
|
932
683
|
name={key}
|
|
933
684
|
data={value}
|
|
934
685
|
theme={theme}
|
|
935
686
|
expandLevel={10}
|
|
936
687
|
/>
|
|
937
|
-
</
|
|
688
|
+
</StateInspectorRow>
|
|
938
689
|
))}
|
|
939
|
-
</
|
|
940
|
-
</
|
|
941
|
-
<
|
|
942
|
-
open={showEvents}
|
|
943
|
-
setOpen={setShowEvents}
|
|
944
|
-
title="Events"
|
|
690
|
+
</StateInspectorDisclosureRowInner>
|
|
691
|
+
</StateInspectorDisclosureSection>
|
|
692
|
+
<ActivityEventsSection
|
|
945
693
|
colorScheme={colorScheme}
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
key={index}
|
|
959
|
-
colorScheme={colorScheme}
|
|
960
|
-
variant={event.type === "send" ? "up" : "down"}
|
|
961
|
-
style={{
|
|
962
|
-
padding: "0px 12px 1px",
|
|
963
|
-
}}
|
|
964
|
-
>
|
|
965
|
-
<ObjectInspector
|
|
966
|
-
data={event.type === "error" ? event.error : event.message}
|
|
967
|
-
theme={theme}
|
|
968
|
-
nodeRenderer={({
|
|
969
|
-
depth,
|
|
970
|
-
name,
|
|
971
|
-
data,
|
|
972
|
-
isNonenumerable,
|
|
973
|
-
}: any) => {
|
|
974
|
-
const direction = event.type === "send" ? "up" : "down";
|
|
975
|
-
|
|
976
|
-
return depth === 0 ? (
|
|
977
|
-
<ObjectRootLabel direction={direction} data={data} />
|
|
978
|
-
) : (
|
|
979
|
-
<ObjectLabel
|
|
980
|
-
direction={direction}
|
|
981
|
-
name={name}
|
|
982
|
-
data={data}
|
|
983
|
-
isNonenumerable={isNonenumerable}
|
|
984
|
-
/>
|
|
985
|
-
);
|
|
986
|
-
}}
|
|
987
|
-
/>
|
|
988
|
-
</InspectorRow>
|
|
989
|
-
)
|
|
990
|
-
)}
|
|
991
|
-
{!connectionEvents && (
|
|
992
|
-
<div
|
|
993
|
-
style={{
|
|
994
|
-
padding: "12px",
|
|
995
|
-
fontSize: "12px",
|
|
996
|
-
display: "flex",
|
|
997
|
-
flexDirection: "column",
|
|
998
|
-
gap: "4px",
|
|
999
|
-
}}
|
|
1000
|
-
>
|
|
1001
|
-
<span>No recorded events</span>
|
|
1002
|
-
</div>
|
|
1003
|
-
)}
|
|
1004
|
-
</div>
|
|
1005
|
-
</DisclosureSection>
|
|
694
|
+
activityEventsContainerRef={activityEventsContainerRef}
|
|
695
|
+
showEvents={showActivityEvents}
|
|
696
|
+
setShowEvents={setShowActivityEvents}
|
|
697
|
+
activityEventsManager={activityEventsManager}
|
|
698
|
+
/>
|
|
699
|
+
<EventsSection<S>
|
|
700
|
+
connectionEvents={connectionEvents}
|
|
701
|
+
colorScheme={colorScheme}
|
|
702
|
+
eventsContainerRef={eventsContainerRef}
|
|
703
|
+
showEvents={showEvents}
|
|
704
|
+
setShowEvents={setShowEvents}
|
|
705
|
+
/>
|
|
1006
706
|
</div>
|
|
1007
707
|
);
|
|
1008
708
|
});
|
|
1009
|
-
|
|
1010
|
-
type MessageDirection = "up" | "down";
|
|
1011
|
-
|
|
1012
|
-
const ObjectRootLabel: FC<{
|
|
1013
|
-
name?: string;
|
|
1014
|
-
data: any;
|
|
1015
|
-
direction?: MessageDirection;
|
|
1016
|
-
}> = ({ name, data, direction }) => {
|
|
1017
|
-
if (typeof name === "string") {
|
|
1018
|
-
return (
|
|
1019
|
-
<span>
|
|
1020
|
-
<ObjectName name={name} />
|
|
1021
|
-
<span>: </span>
|
|
1022
|
-
<ObjectPreview data={data} />
|
|
1023
|
-
</span>
|
|
1024
|
-
);
|
|
1025
|
-
}
|
|
1026
|
-
if (direction === "up" || direction === "down") {
|
|
1027
|
-
const arrow = direction === "up" ? "↑" : "↓";
|
|
1028
|
-
|
|
1029
|
-
return (
|
|
1030
|
-
<span>
|
|
1031
|
-
<span
|
|
1032
|
-
style={{
|
|
1033
|
-
background:
|
|
1034
|
-
direction === "up" ? "rgba(0,255,0,0.2)" : "rgba(255,0,0,0.2)",
|
|
1035
|
-
// color: "white",
|
|
1036
|
-
width: 12,
|
|
1037
|
-
height: 12,
|
|
1038
|
-
borderRadius: 2,
|
|
1039
|
-
display: "inline-flex",
|
|
1040
|
-
justifyContent: "center",
|
|
1041
|
-
alignItems: "center",
|
|
1042
|
-
marginRight: 4,
|
|
1043
|
-
lineHeight: "12px",
|
|
1044
|
-
}}
|
|
1045
|
-
>
|
|
1046
|
-
{arrow}
|
|
1047
|
-
</span>
|
|
1048
|
-
<ObjectPreview data={data} />
|
|
1049
|
-
</span>
|
|
1050
|
-
);
|
|
1051
|
-
} else {
|
|
1052
|
-
return <ObjectPreview data={data} />;
|
|
1053
|
-
}
|
|
1054
|
-
};
|
|
1055
|
-
|
|
1056
|
-
// Rotates ▶️ or ▼ based on expanded state
|
|
1057
|
-
function Arrow({
|
|
1058
|
-
expanded,
|
|
1059
|
-
onClick,
|
|
1060
|
-
style,
|
|
1061
|
-
}: {
|
|
1062
|
-
expanded: boolean;
|
|
1063
|
-
onClick?: () => void;
|
|
1064
|
-
style?: CSSProperties;
|
|
1065
|
-
}) {
|
|
1066
|
-
return (
|
|
1067
|
-
<span
|
|
1068
|
-
role="button"
|
|
1069
|
-
onClick={onClick}
|
|
1070
|
-
style={{
|
|
1071
|
-
display: "inline-block",
|
|
1072
|
-
textAlign: "center",
|
|
1073
|
-
transform: expanded ? "rotate(0deg)" : "rotate(-90deg)",
|
|
1074
|
-
fontFamily: "Menlo, monospace",
|
|
1075
|
-
...style,
|
|
1076
|
-
}}
|
|
1077
|
-
>
|
|
1078
|
-
{"▼"}
|
|
1079
|
-
</span>
|
|
1080
|
-
);
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
function pathToString(extendedPath: ExtendedPathKey[]) {
|
|
1084
|
-
return extendedPath
|
|
1085
|
-
.map((key) =>
|
|
1086
|
-
typeof key === "object"
|
|
1087
|
-
? `:${ellipsis(key.id.toString(), 8, "middle")}`
|
|
1088
|
-
: key
|
|
1089
|
-
)
|
|
1090
|
-
.map((key, index) =>
|
|
1091
|
-
index === 0 || (typeof key === "string" && key.startsWith(":"))
|
|
1092
|
-
? key
|
|
1093
|
-
: `.${key}`
|
|
1094
|
-
)
|
|
1095
|
-
.join("");
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
type EllipsisPosition = "start" | "middle" | "end";
|
|
1099
|
-
|
|
1100
|
-
function ellipsis(
|
|
1101
|
-
str: string,
|
|
1102
|
-
maxLength: number,
|
|
1103
|
-
position: EllipsisPosition = "end"
|
|
1104
|
-
) {
|
|
1105
|
-
if (str.length <= maxLength) return str;
|
|
1106
|
-
|
|
1107
|
-
switch (position) {
|
|
1108
|
-
case "start":
|
|
1109
|
-
return `…${str.slice(str.length - maxLength)}`;
|
|
1110
|
-
case "middle":
|
|
1111
|
-
const halfLength = Math.floor(maxLength / 2);
|
|
1112
|
-
return `${str.slice(0, halfLength)}…${str.slice(str.length - halfLength)}`;
|
|
1113
|
-
case "end":
|
|
1114
|
-
return `${str.slice(0, maxLength)}…`;
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
function SmallButton({
|
|
1119
|
-
children,
|
|
1120
|
-
onClick,
|
|
1121
|
-
style,
|
|
1122
|
-
theme,
|
|
1123
|
-
disabled,
|
|
1124
|
-
}: {
|
|
1125
|
-
children: React.ReactNode;
|
|
1126
|
-
onClick: () => void;
|
|
1127
|
-
style?: CSSProperties;
|
|
1128
|
-
theme: typeof chromeLight;
|
|
1129
|
-
disabled?: boolean;
|
|
1130
|
-
}) {
|
|
1131
|
-
return (
|
|
1132
|
-
<button
|
|
1133
|
-
type="button"
|
|
1134
|
-
disabled={disabled}
|
|
1135
|
-
onClick={(event) => {
|
|
1136
|
-
event.stopPropagation();
|
|
1137
|
-
onClick();
|
|
1138
|
-
}}
|
|
1139
|
-
style={{
|
|
1140
|
-
flex: "0",
|
|
1141
|
-
appearance: "none",
|
|
1142
|
-
background: "none",
|
|
1143
|
-
color: theme.BASE_COLOR,
|
|
1144
|
-
opacity: disabled ? 0.25 : 1,
|
|
1145
|
-
border: "none",
|
|
1146
|
-
fontSize: "12px",
|
|
1147
|
-
whiteSpace: "nowrap",
|
|
1148
|
-
display: "inline-flex",
|
|
1149
|
-
alignItems: "center",
|
|
1150
|
-
justifyContent: "center",
|
|
1151
|
-
padding: "0",
|
|
1152
|
-
cursor: "pointer",
|
|
1153
|
-
...style,
|
|
1154
|
-
}}
|
|
1155
|
-
>
|
|
1156
|
-
{children}
|
|
1157
|
-
</button>
|
|
1158
|
-
);
|
|
1159
|
-
}
|
|
1160
|
-
|
|
1161
|
-
function ColoredDot({ type }: { type: "success" | "error" }) {
|
|
1162
|
-
return (
|
|
1163
|
-
<span
|
|
1164
|
-
style={{
|
|
1165
|
-
display: "inline-block",
|
|
1166
|
-
width: 6,
|
|
1167
|
-
height: 6,
|
|
1168
|
-
background:
|
|
1169
|
-
type === "success" ? "rgba(0,200,0,0.8)" : "rgba(200,0,0,0.8)",
|
|
1170
|
-
borderRadius: "50%",
|
|
1171
|
-
verticalAlign: "middle",
|
|
1172
|
-
}}
|
|
1173
|
-
/>
|
|
1174
|
-
);
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
function TitleLabel({ children }: { children: React.ReactNode }) {
|
|
1178
|
-
return (
|
|
1179
|
-
<span style={{ display: "flex", alignItems: "center", gap: "4px" }}>
|
|
1180
|
-
{children}
|
|
1181
|
-
</span>
|
|
1182
|
-
);
|
|
1183
|
-
}
|