@noya-app/noya-multiplayer-react 0.1.63 → 0.1.65
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 +18 -0
- package/dist/index.bundle.js +19 -19
- package/dist/index.d.mts +33 -10
- package/dist/index.d.ts +33 -10
- package/dist/index.js +1410 -329
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1357 -283
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/NoyaStateContext.tsx +225 -19
- package/src/inspector/StateInspector.tsx +141 -20
- package/src/inspector/StateInspectorTitleLabel.tsx +13 -0
- package/src/inspector/sections/ActivityEventsSection.tsx +136 -0
- package/src/inspector/utils.ts +2 -2
- package/src/noyaApp.ts +1 -1
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { ActivityEventsManager, StreamFilter } from "@noya-app/state-manager";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import { ObjectInspector } from "react-inspector";
|
|
4
|
+
import { useActivityEventsForManager } from "../../NoyaStateContext";
|
|
5
|
+
import { getStateInspectorTheme } from "../inspectorTheme";
|
|
6
|
+
import { StateInspectorButton } from "../StateInspectorButton";
|
|
7
|
+
import {
|
|
8
|
+
StateInspectorDisclosureRowInner,
|
|
9
|
+
StateInspectorDisclosureSection,
|
|
10
|
+
} from "../StateInspectorDisclosureSection";
|
|
11
|
+
import { StateInspectorRow } from "../StateInspectorRow";
|
|
12
|
+
|
|
13
|
+
function isResourceStreamFilter(
|
|
14
|
+
streamFilter: StreamFilter
|
|
15
|
+
): streamFilter is { resourceId: string } {
|
|
16
|
+
return typeof streamFilter === "object" && "resourceId" in streamFilter;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function isResourceActivityEvent(
|
|
20
|
+
activityEvent: unknown
|
|
21
|
+
): activityEvent is { resourceId: string } {
|
|
22
|
+
return (
|
|
23
|
+
typeof activityEvent === "object" &&
|
|
24
|
+
activityEvent !== null &&
|
|
25
|
+
"type" in activityEvent &&
|
|
26
|
+
activityEvent.type === "resource" &&
|
|
27
|
+
"resourceId" in activityEvent &&
|
|
28
|
+
typeof activityEvent.resourceId === "string"
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function ActivityEventsSection({
|
|
33
|
+
showEvents,
|
|
34
|
+
setShowEvents,
|
|
35
|
+
colorScheme,
|
|
36
|
+
activityEventsContainerRef,
|
|
37
|
+
activityEventsManager,
|
|
38
|
+
}: {
|
|
39
|
+
showEvents: boolean;
|
|
40
|
+
setShowEvents: (value: boolean) => void;
|
|
41
|
+
colorScheme: "light" | "dark";
|
|
42
|
+
activityEventsContainerRef: React.RefObject<HTMLDivElement | null>;
|
|
43
|
+
activityEventsManager: ActivityEventsManager;
|
|
44
|
+
}) {
|
|
45
|
+
const [streamFilter, setStreamFilter] = useState<StreamFilter>("all");
|
|
46
|
+
const streamFilterType = isResourceStreamFilter(streamFilter)
|
|
47
|
+
? "resource"
|
|
48
|
+
: "all";
|
|
49
|
+
const theme = getStateInspectorTheme(colorScheme);
|
|
50
|
+
const activityEvents = useActivityEventsForManager(
|
|
51
|
+
showEvents ? streamFilter : undefined,
|
|
52
|
+
activityEventsManager
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<StateInspectorDisclosureSection
|
|
57
|
+
open={showEvents}
|
|
58
|
+
setOpen={setShowEvents}
|
|
59
|
+
title={`Activity Events`}
|
|
60
|
+
colorScheme={colorScheme}
|
|
61
|
+
>
|
|
62
|
+
<StateInspectorDisclosureRowInner ref={activityEventsContainerRef}>
|
|
63
|
+
<div style={{ padding: "4px 12px", display: "flex", gap: "4px" }}>
|
|
64
|
+
<select
|
|
65
|
+
name="streamFilterType"
|
|
66
|
+
value={streamFilterType}
|
|
67
|
+
style={{ flex: "0 0 auto", height: "19px" }}
|
|
68
|
+
onChange={(e) => {
|
|
69
|
+
const value = e.target.value as string;
|
|
70
|
+
if (value === "all") {
|
|
71
|
+
setStreamFilter("all");
|
|
72
|
+
} else {
|
|
73
|
+
setStreamFilter({ resourceId: "" });
|
|
74
|
+
}
|
|
75
|
+
}}
|
|
76
|
+
>
|
|
77
|
+
<option value="all">All</option>
|
|
78
|
+
<option value="resource">Resource</option>
|
|
79
|
+
</select>
|
|
80
|
+
{isResourceStreamFilter(streamFilter) && (
|
|
81
|
+
<input
|
|
82
|
+
name="resourceId"
|
|
83
|
+
type="text"
|
|
84
|
+
placeholder="Resource ID"
|
|
85
|
+
value={streamFilter.resourceId}
|
|
86
|
+
style={{
|
|
87
|
+
flex: "1 1 auto",
|
|
88
|
+
height: "19px",
|
|
89
|
+
padding: "0px 4px",
|
|
90
|
+
boxSizing: "border-box",
|
|
91
|
+
}}
|
|
92
|
+
onChange={(e) =>
|
|
93
|
+
setStreamFilter({ ...streamFilter, resourceId: e.target.value })
|
|
94
|
+
}
|
|
95
|
+
/>
|
|
96
|
+
)}
|
|
97
|
+
</div>
|
|
98
|
+
{activityEvents?.map((activityEvent, index) => (
|
|
99
|
+
<StateInspectorRow
|
|
100
|
+
key={index}
|
|
101
|
+
colorScheme={colorScheme}
|
|
102
|
+
style={{
|
|
103
|
+
padding: "0px 12px 1px",
|
|
104
|
+
}}
|
|
105
|
+
>
|
|
106
|
+
<ObjectInspector data={activityEvent} theme={theme} />
|
|
107
|
+
{streamFilterType === "all" &&
|
|
108
|
+
isResourceActivityEvent(activityEvent) && (
|
|
109
|
+
<StateInspectorButton
|
|
110
|
+
theme={theme}
|
|
111
|
+
onClick={() => {
|
|
112
|
+
setStreamFilter({ resourceId: activityEvent.resourceId });
|
|
113
|
+
}}
|
|
114
|
+
>
|
|
115
|
+
Watch this resource
|
|
116
|
+
</StateInspectorButton>
|
|
117
|
+
)}
|
|
118
|
+
</StateInspectorRow>
|
|
119
|
+
))}
|
|
120
|
+
{!activityEvents && (
|
|
121
|
+
<div
|
|
122
|
+
style={{
|
|
123
|
+
padding: "12px",
|
|
124
|
+
fontSize: "12px",
|
|
125
|
+
display: "flex",
|
|
126
|
+
flexDirection: "column",
|
|
127
|
+
gap: "4px",
|
|
128
|
+
}}
|
|
129
|
+
>
|
|
130
|
+
<span>No activity events</span>
|
|
131
|
+
</div>
|
|
132
|
+
)}
|
|
133
|
+
</StateInspectorDisclosureRowInner>
|
|
134
|
+
</StateInspectorDisclosureSection>
|
|
135
|
+
);
|
|
136
|
+
}
|
package/src/inspector/utils.ts
CHANGED
|
@@ -37,7 +37,7 @@ export function ellipsis(
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export function uploadFile() {
|
|
40
|
-
return new Promise<
|
|
40
|
+
return new Promise<File>((resolve, reject) => {
|
|
41
41
|
const input = document.createElement("input");
|
|
42
42
|
input.type = "file";
|
|
43
43
|
input.onchange = () => {
|
|
@@ -46,7 +46,7 @@ export function uploadFile() {
|
|
|
46
46
|
const reader = new FileReader();
|
|
47
47
|
reader.onload = () => {
|
|
48
48
|
const buffer = reader.result as ArrayBuffer;
|
|
49
|
-
const blob = new
|
|
49
|
+
const blob = new File([buffer], file.name, { type: file.type });
|
|
50
50
|
resolve(blob);
|
|
51
51
|
};
|
|
52
52
|
reader.onerror = () => {
|
package/src/noyaApp.ts
CHANGED
|
@@ -87,7 +87,7 @@ export function getAppData<State>(
|
|
|
87
87
|
parseAppDataParameter(options) ??
|
|
88
88
|
createDefaultAppData(resolvedInitialState);
|
|
89
89
|
|
|
90
|
-
if (options?.overrideExistingState) {
|
|
90
|
+
if (options?.overrideExistingState || appData.initialState === null) {
|
|
91
91
|
appData.initialState = resolvedInitialState;
|
|
92
92
|
}
|
|
93
93
|
|