@rozenite/controls-plugin 1.11.0 → 1.13.0
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/CHANGELOG.md +22 -0
- package/README.md +33 -0
- package/dist/react-native/chunks/useRozeniteControlsPlugin.require.cjs +1 -1
- package/dist/react-native/chunks/useRozeniteControlsPlugin.require.js +320 -256
- package/dist/react-native/index.d.ts +5 -1
- package/dist/rozenite.json +1 -1
- package/package.json +8 -7
- package/react-native.d.ts +8 -4
- package/react-native.ts +2 -0
- package/src/react-native/__tests__/controlsRegistry.test.ts +92 -0
- package/src/react-native/__tests__/useRozeniteControlsPlugin.test.tsx +211 -0
- package/src/react-native/controlsRegistry.ts +101 -0
- package/src/react-native/useControlsAgentTools.ts +21 -14
- package/src/react-native/useRozeniteControlsPlugin.ts +56 -27
- package/src/shared/types.ts +9 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { useRozeniteDevToolsClient } from '@rozenite/plugin-bridge';
|
|
2
|
-
import { useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';
|
|
3
3
|
import type {
|
|
4
4
|
ControlsEventMap,
|
|
5
5
|
ControlsInvokeActionEvent,
|
|
6
6
|
ControlsUpdateRequestEvent,
|
|
7
7
|
} from '../shared/messaging';
|
|
8
|
-
import type {
|
|
8
|
+
import type { RozeniteControlsPluginOptionsInput } from '../shared/types';
|
|
9
9
|
import {
|
|
10
10
|
buildActionRegistry,
|
|
11
11
|
getActionRegistryKey,
|
|
@@ -13,23 +13,45 @@ import {
|
|
|
13
13
|
validateValue,
|
|
14
14
|
} from '../shared/serialization';
|
|
15
15
|
import { useControlsAgentTools } from './useControlsAgentTools';
|
|
16
|
+
import { controlsRegistry } from './controlsRegistry';
|
|
16
17
|
|
|
17
|
-
export const useRozeniteControlsPlugin = (
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
export const useRozeniteControlsPlugin = (
|
|
19
|
+
optionsInput: RozeniteControlsPluginOptionsInput,
|
|
20
|
+
) => {
|
|
20
21
|
const client = useRozeniteDevToolsClient<ControlsEventMap>({
|
|
21
22
|
pluginId: '@rozenite/controls-plugin',
|
|
22
23
|
});
|
|
24
|
+
const registrationIdRef = useRef<symbol>(Symbol('rozenite-controls'));
|
|
25
|
+
const registrationId = registrationIdRef.current;
|
|
26
|
+
const registrySnapshot = useSyncExternalStore(
|
|
27
|
+
controlsRegistry.subscribe,
|
|
28
|
+
controlsRegistry.getSnapshot,
|
|
29
|
+
controlsRegistry.getSnapshot,
|
|
30
|
+
);
|
|
23
31
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
return () => {
|
|
34
|
+
controlsRegistry.delete(registrationId);
|
|
35
|
+
};
|
|
36
|
+
}, [registrationId]);
|
|
29
37
|
|
|
30
38
|
useEffect(() => {
|
|
31
|
-
|
|
32
|
-
}, [
|
|
39
|
+
controlsRegistry.set(registrationId, optionsInput);
|
|
40
|
+
}, [optionsInput, registrationId]);
|
|
41
|
+
|
|
42
|
+
const isRegistryOwner = useMemo(
|
|
43
|
+
() =>
|
|
44
|
+
controlsRegistry.isOwner(registrationId, {
|
|
45
|
+
id: registrationId,
|
|
46
|
+
input: optionsInput,
|
|
47
|
+
}),
|
|
48
|
+
[optionsInput, registrySnapshot, registrationId],
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
useControlsAgentTools(
|
|
52
|
+
() => controlsRegistry.getOptions().sections,
|
|
53
|
+
isRegistryOwner,
|
|
54
|
+
);
|
|
33
55
|
|
|
34
56
|
useEffect(() => {
|
|
35
57
|
if (!client) {
|
|
@@ -38,12 +60,12 @@ export const useRozeniteControlsPlugin = ({
|
|
|
38
60
|
|
|
39
61
|
client.send('snapshot', {
|
|
40
62
|
type: 'snapshot',
|
|
41
|
-
sections:
|
|
63
|
+
sections: serializeSections(controlsRegistry.getOptions().sections),
|
|
42
64
|
});
|
|
43
|
-
}, [client,
|
|
65
|
+
}, [client, optionsInput, registrySnapshot]);
|
|
44
66
|
|
|
45
67
|
useEffect(() => {
|
|
46
|
-
if (!client) {
|
|
68
|
+
if (!client || !isRegistryOwner) {
|
|
47
69
|
return;
|
|
48
70
|
}
|
|
49
71
|
|
|
@@ -54,7 +76,9 @@ export const useRozeniteControlsPlugin = ({
|
|
|
54
76
|
value,
|
|
55
77
|
}: ControlsUpdateRequestEvent) => {
|
|
56
78
|
const key = getActionRegistryKey(sectionId, itemId);
|
|
57
|
-
const entry =
|
|
79
|
+
const entry = buildActionRegistry(
|
|
80
|
+
controlsRegistry.getOptions().sections,
|
|
81
|
+
).get(key);
|
|
58
82
|
|
|
59
83
|
if (!entry || entry.type === 'button') {
|
|
60
84
|
client.send('update-result', {
|
|
@@ -142,7 +166,7 @@ export const useRozeniteControlsPlugin = ({
|
|
|
142
166
|
} catch (error) {
|
|
143
167
|
console.warn(
|
|
144
168
|
`[Rozenite] Controls Plugin: Update failed for ${sectionId}/${itemId}.`,
|
|
145
|
-
error
|
|
169
|
+
error,
|
|
146
170
|
);
|
|
147
171
|
client.send('update-result', {
|
|
148
172
|
type: 'update-result',
|
|
@@ -162,17 +186,19 @@ export const useRozeniteControlsPlugin = ({
|
|
|
162
186
|
}: ControlsInvokeActionEvent) => {
|
|
163
187
|
if (action !== 'press') {
|
|
164
188
|
console.warn(
|
|
165
|
-
`[Rozenite] Controls Plugin: Unsupported action "${action}" for ${sectionId}/${itemId}
|
|
189
|
+
`[Rozenite] Controls Plugin: Unsupported action "${action}" for ${sectionId}/${itemId}.`,
|
|
166
190
|
);
|
|
167
191
|
return;
|
|
168
192
|
}
|
|
169
193
|
|
|
170
194
|
const key = getActionRegistryKey(sectionId, itemId);
|
|
171
|
-
const entry =
|
|
195
|
+
const entry = buildActionRegistry(
|
|
196
|
+
controlsRegistry.getOptions().sections,
|
|
197
|
+
).get(key);
|
|
172
198
|
|
|
173
199
|
if (!entry) {
|
|
174
200
|
console.warn(
|
|
175
|
-
`[Rozenite] Controls Plugin: Action target not found for ${sectionId}/${itemId}
|
|
201
|
+
`[Rozenite] Controls Plugin: Action target not found for ${sectionId}/${itemId}.`,
|
|
176
202
|
);
|
|
177
203
|
return;
|
|
178
204
|
}
|
|
@@ -180,7 +206,7 @@ export const useRozeniteControlsPlugin = ({
|
|
|
180
206
|
try {
|
|
181
207
|
if (entry.type !== 'button') {
|
|
182
208
|
console.warn(
|
|
183
|
-
`[Rozenite] Controls Plugin: Invalid press action payload for ${sectionId}/${itemId}
|
|
209
|
+
`[Rozenite] Controls Plugin: Invalid press action payload for ${sectionId}/${itemId}.`,
|
|
184
210
|
);
|
|
185
211
|
return;
|
|
186
212
|
}
|
|
@@ -189,7 +215,7 @@ export const useRozeniteControlsPlugin = ({
|
|
|
189
215
|
} catch (error) {
|
|
190
216
|
console.warn(
|
|
191
217
|
`[Rozenite] Controls Plugin: Action failed for ${sectionId}/${itemId}.`,
|
|
192
|
-
error
|
|
218
|
+
error,
|
|
193
219
|
);
|
|
194
220
|
}
|
|
195
221
|
};
|
|
@@ -198,12 +224,15 @@ export const useRozeniteControlsPlugin = ({
|
|
|
198
224
|
client.onMessage('get-snapshot', () => {
|
|
199
225
|
client.send('snapshot', {
|
|
200
226
|
type: 'snapshot',
|
|
201
|
-
sections:
|
|
227
|
+
sections: serializeSections(controlsRegistry.getOptions().sections),
|
|
202
228
|
});
|
|
203
229
|
}),
|
|
204
|
-
client.onMessage(
|
|
205
|
-
|
|
206
|
-
|
|
230
|
+
client.onMessage(
|
|
231
|
+
'update-request',
|
|
232
|
+
(event: ControlsUpdateRequestEvent) => {
|
|
233
|
+
void handleUpdateRequest(event);
|
|
234
|
+
},
|
|
235
|
+
),
|
|
207
236
|
client.onMessage('invoke-action', (event: ControlsInvokeActionEvent) => {
|
|
208
237
|
void handleInvokeAction(event);
|
|
209
238
|
}),
|
|
@@ -212,7 +241,7 @@ export const useRozeniteControlsPlugin = ({
|
|
|
212
241
|
return () => {
|
|
213
242
|
subscriptions.forEach((subscription) => subscription.remove());
|
|
214
243
|
};
|
|
215
|
-
}, [client,
|
|
244
|
+
}, [client, isRegistryOwner]);
|
|
216
245
|
|
|
217
246
|
return client;
|
|
218
247
|
};
|
package/src/shared/types.ts
CHANGED
|
@@ -98,6 +98,14 @@ export type RozeniteControlsPluginOptions = {
|
|
|
98
98
|
sections: ControlsSection[];
|
|
99
99
|
};
|
|
100
100
|
|
|
101
|
+
export type RozeniteControlsPluginOptionsUpdater = (
|
|
102
|
+
previousOptions: RozeniteControlsPluginOptions,
|
|
103
|
+
) => RozeniteControlsPluginOptions;
|
|
104
|
+
|
|
105
|
+
export type RozeniteControlsPluginOptionsInput =
|
|
106
|
+
| RozeniteControlsPluginOptions
|
|
107
|
+
| RozeniteControlsPluginOptionsUpdater;
|
|
108
|
+
|
|
101
109
|
export const createSection = <TSection extends ControlsSection>(
|
|
102
|
-
section: TSection
|
|
110
|
+
section: TSection,
|
|
103
111
|
): TSection => section;
|