@midscene/playground-app 1.9.7-beta-20260616025249.0 → 1.9.7
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/es/DeviceInteractionLayer.mjs +24 -5
- package/dist/es/PlaygroundThemeProvider.mjs +5 -2
- package/dist/es/PreviewRenderer.mjs +40 -5
- package/dist/es/controller/usePlaygroundController.mjs +4 -1
- package/dist/lib/DeviceInteractionLayer.js +24 -5
- package/dist/lib/PlaygroundThemeProvider.js +4 -1
- package/dist/lib/PreviewRenderer.js +40 -5
- package/dist/lib/controller/usePlaygroundController.js +5 -2
- package/dist/types/DeviceInteractionLayer.d.ts +1 -1
- package/package.json +4 -4
|
@@ -114,20 +114,32 @@ function DeviceInteractionLayer({ enabled, deviceSize, onTap, onSwipe, scrollEna
|
|
|
114
114
|
const activePointer = useRef(null);
|
|
115
115
|
const composingRef = useRef(false);
|
|
116
116
|
const keyboardArmedRef = useRef(false);
|
|
117
|
+
const keyboardFocusRequestIdRef = useRef(0);
|
|
117
118
|
const lastKeyboardPointRef = useRef(null);
|
|
118
119
|
const pendingWheelRef = useRef(null);
|
|
119
120
|
const wheelTimerRef = useRef(null);
|
|
120
121
|
const focusKeyboardSink = useCallback(()=>{
|
|
121
122
|
if (keyboardEnabled) {
|
|
122
|
-
var _keyboardSinkRef_current;
|
|
123
123
|
keyboardArmedRef.current = true;
|
|
124
|
-
|
|
124
|
+
const sink = keyboardSinkRef.current;
|
|
125
|
+
if (sink && document.activeElement !== sink) sink.focus({
|
|
125
126
|
preventScroll: true
|
|
126
127
|
});
|
|
127
128
|
}
|
|
128
129
|
}, [
|
|
129
130
|
keyboardEnabled
|
|
130
131
|
]);
|
|
132
|
+
const refocusKeyboardSinkAfterTap = useCallback((focusRequestId, interaction)=>{
|
|
133
|
+
if (!keyboardEnabled) return;
|
|
134
|
+
Promise.resolve(interaction).catch(()=>void 0).then(()=>{
|
|
135
|
+
window.setTimeout(()=>{
|
|
136
|
+
if (keyboardArmedRef.current && keyboardFocusRequestIdRef.current === focusRequestId) focusKeyboardSink();
|
|
137
|
+
}, 0);
|
|
138
|
+
});
|
|
139
|
+
}, [
|
|
140
|
+
focusKeyboardSink,
|
|
141
|
+
keyboardEnabled
|
|
142
|
+
]);
|
|
131
143
|
const positionKeyboardSink = useCallback((clientX, clientY)=>{
|
|
132
144
|
const overlay = overlayRef.current;
|
|
133
145
|
const sink = keyboardSinkRef.current;
|
|
@@ -161,6 +173,8 @@ function DeviceInteractionLayer({ enabled, deviceSize, onTap, onSwipe, scrollEna
|
|
|
161
173
|
return;
|
|
162
174
|
}
|
|
163
175
|
positionKeyboardSink(event.clientX, event.clientY);
|
|
176
|
+
const keyboardFocusRequestId = keyboardFocusRequestIdRef.current + 1;
|
|
177
|
+
keyboardFocusRequestIdRef.current = keyboardFocusRequestId;
|
|
164
178
|
focusKeyboardSink();
|
|
165
179
|
try {
|
|
166
180
|
overlayRef.current.setPointerCapture(event.pointerId);
|
|
@@ -169,7 +183,8 @@ function DeviceInteractionLayer({ enabled, deviceSize, onTap, onSwipe, scrollEna
|
|
|
169
183
|
startX: event.clientX,
|
|
170
184
|
startY: event.clientY,
|
|
171
185
|
startTime: performance.now(),
|
|
172
|
-
contentRect
|
|
186
|
+
contentRect,
|
|
187
|
+
keyboardFocusRequestId
|
|
173
188
|
};
|
|
174
189
|
event.preventDefault();
|
|
175
190
|
}, [
|
|
@@ -196,12 +211,13 @@ function DeviceInteractionLayer({ enabled, deviceSize, onTap, onSwipe, scrollEna
|
|
|
196
211
|
const endPoint = projectToDevice(event.clientX, event.clientY, active.contentRect);
|
|
197
212
|
if (!startPoint || !endPoint) return;
|
|
198
213
|
lastKeyboardPointRef.current = endPoint;
|
|
199
|
-
if (distance <= tapMaxDistance && duration <= tapMaxDurationMs) null == onTap
|
|
214
|
+
if (distance <= tapMaxDistance && duration <= tapMaxDurationMs) refocusKeyboardSinkAfterTap(active.keyboardFocusRequestId, null == onTap ? void 0 : onTap(startPoint));
|
|
200
215
|
else null == onSwipe || onSwipe(startPoint, endPoint, Math.round(duration));
|
|
201
216
|
}, [
|
|
202
217
|
onTap,
|
|
203
218
|
onSwipe,
|
|
204
219
|
projectToDevice,
|
|
220
|
+
refocusKeyboardSinkAfterTap,
|
|
205
221
|
tapMaxDistance,
|
|
206
222
|
tapMaxDurationMs
|
|
207
223
|
]);
|
|
@@ -423,8 +439,11 @@ function DeviceInteractionLayer({ enabled, deviceSize, onTap, onSwipe, scrollEna
|
|
|
423
439
|
top: 0,
|
|
424
440
|
width: 32,
|
|
425
441
|
height: 24,
|
|
426
|
-
opacity: 0
|
|
442
|
+
opacity: 0,
|
|
427
443
|
pointerEvents: 'none',
|
|
444
|
+
appearance: 'none',
|
|
445
|
+
boxShadow: 'none',
|
|
446
|
+
overflow: 'hidden',
|
|
428
447
|
resize: 'none',
|
|
429
448
|
border: 0,
|
|
430
449
|
padding: 0,
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { globalThemeConfig } from "@midscene/visualizer";
|
|
3
|
-
import { ConfigProvider } from "antd";
|
|
3
|
+
import { App, ConfigProvider } from "antd";
|
|
4
4
|
function PlaygroundThemeProvider({ children }) {
|
|
5
5
|
return /*#__PURE__*/ jsx(ConfigProvider, {
|
|
6
6
|
theme: globalThemeConfig(),
|
|
7
|
-
children:
|
|
7
|
+
children: /*#__PURE__*/ jsx(App, {
|
|
8
|
+
component: false,
|
|
9
|
+
children: children
|
|
10
|
+
})
|
|
8
11
|
});
|
|
9
12
|
}
|
|
10
13
|
export { PlaygroundThemeProvider };
|
|
@@ -2,7 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { PREVIEW_TEXT_INPUT_BATCH_DELAY_MS } from "@midscene/shared/constants";
|
|
3
3
|
import { ScreenshotViewer } from "@midscene/visualizer";
|
|
4
4
|
import { WebCodecsVideoDecoder } from "@yume-chan/scrcpy-decoder-webcodecs";
|
|
5
|
-
import { Alert,
|
|
5
|
+
import { Alert, App, Popover } from "antd";
|
|
6
6
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
7
7
|
import { DeviceInteractionLayer } from "./DeviceInteractionLayer.mjs";
|
|
8
8
|
import { ScrcpyPanel } from "./ScrcpyPanel.mjs";
|
|
@@ -34,6 +34,29 @@ function _async_to_generator(fn) {
|
|
|
34
34
|
});
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
|
+
function _define_property(obj, key, value) {
|
|
38
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
39
|
+
value: value,
|
|
40
|
+
enumerable: true,
|
|
41
|
+
configurable: true,
|
|
42
|
+
writable: true
|
|
43
|
+
});
|
|
44
|
+
else obj[key] = value;
|
|
45
|
+
return obj;
|
|
46
|
+
}
|
|
47
|
+
function _object_spread(target) {
|
|
48
|
+
for(var i = 1; i < arguments.length; i++){
|
|
49
|
+
var source = null != arguments[i] ? arguments[i] : {};
|
|
50
|
+
var ownKeys = Object.keys(source);
|
|
51
|
+
if ("function" == typeof Object.getOwnPropertySymbols) ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
52
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
53
|
+
}));
|
|
54
|
+
ownKeys.forEach(function(key) {
|
|
55
|
+
_define_property(target, key, source[key]);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return target;
|
|
59
|
+
}
|
|
37
60
|
function isNonLocalhostHttp() {
|
|
38
61
|
try {
|
|
39
62
|
const { protocol, hostname } = window.location;
|
|
@@ -44,6 +67,7 @@ function isNonLocalhostHttp() {
|
|
|
44
67
|
}
|
|
45
68
|
}
|
|
46
69
|
function PreviewRenderer({ connectingOverlay, onDeviceSizeChange, onScrcpyStatusChange, renderErrorOverlay, scrcpyViewportStyle, screenshotViewerMode, playgroundSDK, runtimeInfo, serverUrl, serverOnline, isUserOperating }) {
|
|
70
|
+
const { message } = App.useApp();
|
|
47
71
|
const previewConnection = resolvePreviewConnectionInfo(runtimeInfo, serverUrl);
|
|
48
72
|
const [deviceSize, setDeviceSize] = useState(null);
|
|
49
73
|
const [streamSize, setStreamSize] = useState(null);
|
|
@@ -51,6 +75,7 @@ function PreviewRenderer({ connectingOverlay, onDeviceSizeChange, onScrcpyStatus
|
|
|
51
75
|
const [scrcpyStatus, setScrcpyStatus] = useState('connecting');
|
|
52
76
|
const manualControlQueueRef = useRef(Promise.resolve());
|
|
53
77
|
const pendingTextInputRef = useRef('');
|
|
78
|
+
const pendingTextInputPointRef = useRef(null);
|
|
54
79
|
const textInputTimerRef = useRef(null);
|
|
55
80
|
const textInputFlushPromiseRef = useRef(null);
|
|
56
81
|
const previewContentRef = useRef(null);
|
|
@@ -65,7 +90,9 @@ function PreviewRenderer({ connectingOverlay, onDeviceSizeChange, onScrcpyStatus
|
|
|
65
90
|
const nextTask = manualControlQueueRef.current.then(task, task);
|
|
66
91
|
manualControlQueueRef.current = nextTask.catch(()=>void 0);
|
|
67
92
|
return nextTask;
|
|
68
|
-
}, [
|
|
93
|
+
}, [
|
|
94
|
+
message
|
|
95
|
+
]);
|
|
69
96
|
useEffect(()=>{
|
|
70
97
|
if (!serverOnline) {
|
|
71
98
|
setDeviceSize(null);
|
|
@@ -136,19 +163,24 @@ function PreviewRenderer({ connectingOverlay, onDeviceSizeChange, onScrcpyStatus
|
|
|
136
163
|
const flushPendingTextInput = useCallback(()=>{
|
|
137
164
|
clearTextInputTimer();
|
|
138
165
|
const text = pendingTextInputRef.current;
|
|
166
|
+
const point = pendingTextInputPointRef.current;
|
|
139
167
|
if (!text) {
|
|
140
168
|
var _textInputFlushPromiseRef_current;
|
|
141
169
|
return null != (_textInputFlushPromiseRef_current = textInputFlushPromiseRef.current) ? _textInputFlushPromiseRef_current : Promise.resolve();
|
|
142
170
|
}
|
|
143
171
|
pendingTextInputRef.current = '';
|
|
172
|
+
pendingTextInputPointRef.current = null;
|
|
144
173
|
var _textInputFlushPromiseRef_current1;
|
|
145
174
|
const previousFlush = null != (_textInputFlushPromiseRef_current1 = textInputFlushPromiseRef.current) ? _textInputFlushPromiseRef_current1 : Promise.resolve();
|
|
146
175
|
const flushPromise = previousFlush.catch(()=>void 0).then(()=>_async_to_generator(function*() {
|
|
147
|
-
const res = yield enqueueManualControl(()=>playgroundSDK.interact({
|
|
176
|
+
const res = yield enqueueManualControl(()=>playgroundSDK.interact(_object_spread({
|
|
148
177
|
actionType: 'Input',
|
|
149
178
|
value: text,
|
|
150
179
|
mode: 'typeOnly'
|
|
151
|
-
}
|
|
180
|
+
}, point ? {
|
|
181
|
+
x: point.x,
|
|
182
|
+
y: point.y
|
|
183
|
+
} : {})));
|
|
152
184
|
if (!res.ok) showManualControlError('Input failed', res.error);
|
|
153
185
|
})());
|
|
154
186
|
const trackedFlushPromise = flushPromise.finally(()=>{
|
|
@@ -187,9 +219,10 @@ function PreviewRenderer({ connectingOverlay, onDeviceSizeChange, onScrcpyStatus
|
|
|
187
219
|
playgroundSDK,
|
|
188
220
|
showManualControlError
|
|
189
221
|
]);
|
|
190
|
-
const handleTextInput = useCallback((text)=>{
|
|
222
|
+
const handleTextInput = useCallback((text, point)=>{
|
|
191
223
|
if (!text) return;
|
|
192
224
|
pendingTextInputRef.current += text;
|
|
225
|
+
if (point) pendingTextInputPointRef.current = point;
|
|
193
226
|
clearTextInputTimer();
|
|
194
227
|
textInputTimerRef.current = setTimeout(()=>{
|
|
195
228
|
flushPendingTextInput();
|
|
@@ -202,6 +235,7 @@ function PreviewRenderer({ connectingOverlay, onDeviceSizeChange, onScrcpyStatus
|
|
|
202
235
|
if (serverOnline && previewInteractionEnabled && manualKeyboardEnabled) return;
|
|
203
236
|
clearTextInputTimer();
|
|
204
237
|
pendingTextInputRef.current = '';
|
|
238
|
+
pendingTextInputPointRef.current = null;
|
|
205
239
|
}, [
|
|
206
240
|
clearTextInputTimer,
|
|
207
241
|
manualKeyboardEnabled,
|
|
@@ -211,6 +245,7 @@ function PreviewRenderer({ connectingOverlay, onDeviceSizeChange, onScrcpyStatus
|
|
|
211
245
|
useEffect(()=>()=>{
|
|
212
246
|
if (serverOnline && previewInteractionEnabled && manualKeyboardEnabled && pendingTextInputRef.current) return void flushPendingTextInput();
|
|
213
247
|
clearTextInputTimer();
|
|
248
|
+
pendingTextInputPointRef.current = null;
|
|
214
249
|
}, [
|
|
215
250
|
clearTextInputTimer,
|
|
216
251
|
flushPendingTextInput,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PlaygroundSDK } from "@midscene/playground";
|
|
2
2
|
import { notifyError, useEnvConfig } from "@midscene/visualizer";
|
|
3
|
-
import {
|
|
3
|
+
import { App, Form } from "antd";
|
|
4
4
|
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
5
5
|
import { resolveAutoCreateSessionInput } from "../session-setup.mjs";
|
|
6
6
|
import { buildSessionInitialValues, resolveSessionViewState } from "../session-state.mjs";
|
|
@@ -81,6 +81,7 @@ function getPlatformSelectorFieldKey(setup) {
|
|
|
81
81
|
return null == setup ? void 0 : null == (_setup_platformSelector = setup.platformSelector) ? void 0 : _setup_platformSelector.fieldKey;
|
|
82
82
|
}
|
|
83
83
|
function usePlaygroundController({ serverUrl, defaultDeviceType = 'web', pollIntervalMs = 5000, countdownSeconds = 3, initialFormValues, onCountdownFinish }) {
|
|
84
|
+
const { message } = App.useApp();
|
|
84
85
|
const [form] = Form.useForm();
|
|
85
86
|
const initialFormValuesRef = useRef(initialFormValues);
|
|
86
87
|
useLayoutEffect(()=>{
|
|
@@ -266,6 +267,7 @@ function usePlaygroundController({ serverUrl, defaultDeviceType = 'web', pollInt
|
|
|
266
267
|
})(), [
|
|
267
268
|
applyAiConfig,
|
|
268
269
|
form,
|
|
270
|
+
message,
|
|
269
271
|
playgroundSDK,
|
|
270
272
|
refreshServerState
|
|
271
273
|
]);
|
|
@@ -288,6 +290,7 @@ function usePlaygroundController({ serverUrl, defaultDeviceType = 'web', pollInt
|
|
|
288
290
|
}
|
|
289
291
|
})(), [
|
|
290
292
|
form,
|
|
293
|
+
message,
|
|
291
294
|
playgroundSDK,
|
|
292
295
|
refreshServerState,
|
|
293
296
|
refreshSessionSetup,
|
|
@@ -155,20 +155,32 @@ function DeviceInteractionLayer({ enabled, deviceSize, onTap, onSwipe, scrollEna
|
|
|
155
155
|
const activePointer = (0, external_react_namespaceObject.useRef)(null);
|
|
156
156
|
const composingRef = (0, external_react_namespaceObject.useRef)(false);
|
|
157
157
|
const keyboardArmedRef = (0, external_react_namespaceObject.useRef)(false);
|
|
158
|
+
const keyboardFocusRequestIdRef = (0, external_react_namespaceObject.useRef)(0);
|
|
158
159
|
const lastKeyboardPointRef = (0, external_react_namespaceObject.useRef)(null);
|
|
159
160
|
const pendingWheelRef = (0, external_react_namespaceObject.useRef)(null);
|
|
160
161
|
const wheelTimerRef = (0, external_react_namespaceObject.useRef)(null);
|
|
161
162
|
const focusKeyboardSink = (0, external_react_namespaceObject.useCallback)(()=>{
|
|
162
163
|
if (keyboardEnabled) {
|
|
163
|
-
var _keyboardSinkRef_current;
|
|
164
164
|
keyboardArmedRef.current = true;
|
|
165
|
-
|
|
165
|
+
const sink = keyboardSinkRef.current;
|
|
166
|
+
if (sink && document.activeElement !== sink) sink.focus({
|
|
166
167
|
preventScroll: true
|
|
167
168
|
});
|
|
168
169
|
}
|
|
169
170
|
}, [
|
|
170
171
|
keyboardEnabled
|
|
171
172
|
]);
|
|
173
|
+
const refocusKeyboardSinkAfterTap = (0, external_react_namespaceObject.useCallback)((focusRequestId, interaction)=>{
|
|
174
|
+
if (!keyboardEnabled) return;
|
|
175
|
+
Promise.resolve(interaction).catch(()=>void 0).then(()=>{
|
|
176
|
+
window.setTimeout(()=>{
|
|
177
|
+
if (keyboardArmedRef.current && keyboardFocusRequestIdRef.current === focusRequestId) focusKeyboardSink();
|
|
178
|
+
}, 0);
|
|
179
|
+
});
|
|
180
|
+
}, [
|
|
181
|
+
focusKeyboardSink,
|
|
182
|
+
keyboardEnabled
|
|
183
|
+
]);
|
|
172
184
|
const positionKeyboardSink = (0, external_react_namespaceObject.useCallback)((clientX, clientY)=>{
|
|
173
185
|
const overlay = overlayRef.current;
|
|
174
186
|
const sink = keyboardSinkRef.current;
|
|
@@ -202,6 +214,8 @@ function DeviceInteractionLayer({ enabled, deviceSize, onTap, onSwipe, scrollEna
|
|
|
202
214
|
return;
|
|
203
215
|
}
|
|
204
216
|
positionKeyboardSink(event.clientX, event.clientY);
|
|
217
|
+
const keyboardFocusRequestId = keyboardFocusRequestIdRef.current + 1;
|
|
218
|
+
keyboardFocusRequestIdRef.current = keyboardFocusRequestId;
|
|
205
219
|
focusKeyboardSink();
|
|
206
220
|
try {
|
|
207
221
|
overlayRef.current.setPointerCapture(event.pointerId);
|
|
@@ -210,7 +224,8 @@ function DeviceInteractionLayer({ enabled, deviceSize, onTap, onSwipe, scrollEna
|
|
|
210
224
|
startX: event.clientX,
|
|
211
225
|
startY: event.clientY,
|
|
212
226
|
startTime: performance.now(),
|
|
213
|
-
contentRect
|
|
227
|
+
contentRect,
|
|
228
|
+
keyboardFocusRequestId
|
|
214
229
|
};
|
|
215
230
|
event.preventDefault();
|
|
216
231
|
}, [
|
|
@@ -237,12 +252,13 @@ function DeviceInteractionLayer({ enabled, deviceSize, onTap, onSwipe, scrollEna
|
|
|
237
252
|
const endPoint = projectToDevice(event.clientX, event.clientY, active.contentRect);
|
|
238
253
|
if (!startPoint || !endPoint) return;
|
|
239
254
|
lastKeyboardPointRef.current = endPoint;
|
|
240
|
-
if (distance <= tapMaxDistance && duration <= tapMaxDurationMs) null == onTap
|
|
255
|
+
if (distance <= tapMaxDistance && duration <= tapMaxDurationMs) refocusKeyboardSinkAfterTap(active.keyboardFocusRequestId, null == onTap ? void 0 : onTap(startPoint));
|
|
241
256
|
else null == onSwipe || onSwipe(startPoint, endPoint, Math.round(duration));
|
|
242
257
|
}, [
|
|
243
258
|
onTap,
|
|
244
259
|
onSwipe,
|
|
245
260
|
projectToDevice,
|
|
261
|
+
refocusKeyboardSinkAfterTap,
|
|
246
262
|
tapMaxDistance,
|
|
247
263
|
tapMaxDurationMs
|
|
248
264
|
]);
|
|
@@ -464,8 +480,11 @@ function DeviceInteractionLayer({ enabled, deviceSize, onTap, onSwipe, scrollEna
|
|
|
464
480
|
top: 0,
|
|
465
481
|
width: 32,
|
|
466
482
|
height: 24,
|
|
467
|
-
opacity: 0
|
|
483
|
+
opacity: 0,
|
|
468
484
|
pointerEvents: 'none',
|
|
485
|
+
appearance: 'none',
|
|
486
|
+
boxShadow: 'none',
|
|
487
|
+
overflow: 'hidden',
|
|
469
488
|
resize: 'none',
|
|
470
489
|
border: 0,
|
|
471
490
|
padding: 0,
|
|
@@ -32,7 +32,10 @@ const external_antd_namespaceObject = require("antd");
|
|
|
32
32
|
function PlaygroundThemeProvider({ children }) {
|
|
33
33
|
return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_antd_namespaceObject.ConfigProvider, {
|
|
34
34
|
theme: (0, visualizer_namespaceObject.globalThemeConfig)(),
|
|
35
|
-
children:
|
|
35
|
+
children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_antd_namespaceObject.App, {
|
|
36
|
+
component: false,
|
|
37
|
+
children: children
|
|
38
|
+
})
|
|
36
39
|
});
|
|
37
40
|
}
|
|
38
41
|
exports.PlaygroundThemeProvider = __webpack_exports__.PlaygroundThemeProvider;
|
|
@@ -62,6 +62,29 @@ function _async_to_generator(fn) {
|
|
|
62
62
|
});
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
+
function _define_property(obj, key, value) {
|
|
66
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
67
|
+
value: value,
|
|
68
|
+
enumerable: true,
|
|
69
|
+
configurable: true,
|
|
70
|
+
writable: true
|
|
71
|
+
});
|
|
72
|
+
else obj[key] = value;
|
|
73
|
+
return obj;
|
|
74
|
+
}
|
|
75
|
+
function _object_spread(target) {
|
|
76
|
+
for(var i = 1; i < arguments.length; i++){
|
|
77
|
+
var source = null != arguments[i] ? arguments[i] : {};
|
|
78
|
+
var ownKeys = Object.keys(source);
|
|
79
|
+
if ("function" == typeof Object.getOwnPropertySymbols) ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
80
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
81
|
+
}));
|
|
82
|
+
ownKeys.forEach(function(key) {
|
|
83
|
+
_define_property(target, key, source[key]);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return target;
|
|
87
|
+
}
|
|
65
88
|
function isNonLocalhostHttp() {
|
|
66
89
|
try {
|
|
67
90
|
const { protocol, hostname } = window.location;
|
|
@@ -72,6 +95,7 @@ function isNonLocalhostHttp() {
|
|
|
72
95
|
}
|
|
73
96
|
}
|
|
74
97
|
function PreviewRenderer({ connectingOverlay, onDeviceSizeChange, onScrcpyStatusChange, renderErrorOverlay, scrcpyViewportStyle, screenshotViewerMode, playgroundSDK, runtimeInfo, serverUrl, serverOnline, isUserOperating }) {
|
|
98
|
+
const { message } = external_antd_namespaceObject.App.useApp();
|
|
75
99
|
const previewConnection = (0, external_runtime_info_js_namespaceObject.resolvePreviewConnectionInfo)(runtimeInfo, serverUrl);
|
|
76
100
|
const [deviceSize, setDeviceSize] = (0, external_react_namespaceObject.useState)(null);
|
|
77
101
|
const [streamSize, setStreamSize] = (0, external_react_namespaceObject.useState)(null);
|
|
@@ -79,6 +103,7 @@ function PreviewRenderer({ connectingOverlay, onDeviceSizeChange, onScrcpyStatus
|
|
|
79
103
|
const [scrcpyStatus, setScrcpyStatus] = (0, external_react_namespaceObject.useState)('connecting');
|
|
80
104
|
const manualControlQueueRef = (0, external_react_namespaceObject.useRef)(Promise.resolve());
|
|
81
105
|
const pendingTextInputRef = (0, external_react_namespaceObject.useRef)('');
|
|
106
|
+
const pendingTextInputPointRef = (0, external_react_namespaceObject.useRef)(null);
|
|
82
107
|
const textInputTimerRef = (0, external_react_namespaceObject.useRef)(null);
|
|
83
108
|
const textInputFlushPromiseRef = (0, external_react_namespaceObject.useRef)(null);
|
|
84
109
|
const previewContentRef = (0, external_react_namespaceObject.useRef)(null);
|
|
@@ -93,7 +118,9 @@ function PreviewRenderer({ connectingOverlay, onDeviceSizeChange, onScrcpyStatus
|
|
|
93
118
|
const nextTask = manualControlQueueRef.current.then(task, task);
|
|
94
119
|
manualControlQueueRef.current = nextTask.catch(()=>void 0);
|
|
95
120
|
return nextTask;
|
|
96
|
-
}, [
|
|
121
|
+
}, [
|
|
122
|
+
message
|
|
123
|
+
]);
|
|
97
124
|
(0, external_react_namespaceObject.useEffect)(()=>{
|
|
98
125
|
if (!serverOnline) {
|
|
99
126
|
setDeviceSize(null);
|
|
@@ -149,7 +176,7 @@ function PreviewRenderer({ connectingOverlay, onDeviceSizeChange, onScrcpyStatus
|
|
|
149
176
|
const showInsecureContextHint = 'scrcpy' === previewConnection.type && !scrcpy_decoder_webcodecs_namespaceObject.WebCodecsVideoDecoder.isSupported && isNonLocalhostHttp();
|
|
150
177
|
const previewInteractionEnabled = 'none' !== previewConnection.type && (!scrcpyAvailable || 'connected' === scrcpyStatus);
|
|
151
178
|
const showManualControlError = (0, external_react_namespaceObject.useCallback)((fallback, error)=>{
|
|
152
|
-
|
|
179
|
+
message.open({
|
|
153
180
|
type: 'error',
|
|
154
181
|
content: error || fallback,
|
|
155
182
|
key: 'manual-control-error'
|
|
@@ -164,19 +191,24 @@ function PreviewRenderer({ connectingOverlay, onDeviceSizeChange, onScrcpyStatus
|
|
|
164
191
|
const flushPendingTextInput = (0, external_react_namespaceObject.useCallback)(()=>{
|
|
165
192
|
clearTextInputTimer();
|
|
166
193
|
const text = pendingTextInputRef.current;
|
|
194
|
+
const point = pendingTextInputPointRef.current;
|
|
167
195
|
if (!text) {
|
|
168
196
|
var _textInputFlushPromiseRef_current;
|
|
169
197
|
return null != (_textInputFlushPromiseRef_current = textInputFlushPromiseRef.current) ? _textInputFlushPromiseRef_current : Promise.resolve();
|
|
170
198
|
}
|
|
171
199
|
pendingTextInputRef.current = '';
|
|
200
|
+
pendingTextInputPointRef.current = null;
|
|
172
201
|
var _textInputFlushPromiseRef_current1;
|
|
173
202
|
const previousFlush = null != (_textInputFlushPromiseRef_current1 = textInputFlushPromiseRef.current) ? _textInputFlushPromiseRef_current1 : Promise.resolve();
|
|
174
203
|
const flushPromise = previousFlush.catch(()=>void 0).then(()=>_async_to_generator(function*() {
|
|
175
|
-
const res = yield enqueueManualControl(()=>playgroundSDK.interact({
|
|
204
|
+
const res = yield enqueueManualControl(()=>playgroundSDK.interact(_object_spread({
|
|
176
205
|
actionType: 'Input',
|
|
177
206
|
value: text,
|
|
178
207
|
mode: 'typeOnly'
|
|
179
|
-
}
|
|
208
|
+
}, point ? {
|
|
209
|
+
x: point.x,
|
|
210
|
+
y: point.y
|
|
211
|
+
} : {})));
|
|
180
212
|
if (!res.ok) showManualControlError('Input failed', res.error);
|
|
181
213
|
})());
|
|
182
214
|
const trackedFlushPromise = flushPromise.finally(()=>{
|
|
@@ -215,9 +247,10 @@ function PreviewRenderer({ connectingOverlay, onDeviceSizeChange, onScrcpyStatus
|
|
|
215
247
|
playgroundSDK,
|
|
216
248
|
showManualControlError
|
|
217
249
|
]);
|
|
218
|
-
const handleTextInput = (0, external_react_namespaceObject.useCallback)((text)=>{
|
|
250
|
+
const handleTextInput = (0, external_react_namespaceObject.useCallback)((text, point)=>{
|
|
219
251
|
if (!text) return;
|
|
220
252
|
pendingTextInputRef.current += text;
|
|
253
|
+
if (point) pendingTextInputPointRef.current = point;
|
|
221
254
|
clearTextInputTimer();
|
|
222
255
|
textInputTimerRef.current = setTimeout(()=>{
|
|
223
256
|
flushPendingTextInput();
|
|
@@ -230,6 +263,7 @@ function PreviewRenderer({ connectingOverlay, onDeviceSizeChange, onScrcpyStatus
|
|
|
230
263
|
if (serverOnline && previewInteractionEnabled && manualKeyboardEnabled) return;
|
|
231
264
|
clearTextInputTimer();
|
|
232
265
|
pendingTextInputRef.current = '';
|
|
266
|
+
pendingTextInputPointRef.current = null;
|
|
233
267
|
}, [
|
|
234
268
|
clearTextInputTimer,
|
|
235
269
|
manualKeyboardEnabled,
|
|
@@ -239,6 +273,7 @@ function PreviewRenderer({ connectingOverlay, onDeviceSizeChange, onScrcpyStatus
|
|
|
239
273
|
(0, external_react_namespaceObject.useEffect)(()=>()=>{
|
|
240
274
|
if (serverOnline && previewInteractionEnabled && manualKeyboardEnabled && pendingTextInputRef.current) return void flushPendingTextInput();
|
|
241
275
|
clearTextInputTimer();
|
|
276
|
+
pendingTextInputPointRef.current = null;
|
|
242
277
|
}, [
|
|
243
278
|
clearTextInputTimer,
|
|
244
279
|
flushPendingTextInput,
|
|
@@ -109,6 +109,7 @@ function getPlatformSelectorFieldKey(setup) {
|
|
|
109
109
|
return null == setup ? void 0 : null == (_setup_platformSelector = setup.platformSelector) ? void 0 : _setup_platformSelector.fieldKey;
|
|
110
110
|
}
|
|
111
111
|
function usePlaygroundController({ serverUrl, defaultDeviceType = 'web', pollIntervalMs = 5000, countdownSeconds = 3, initialFormValues, onCountdownFinish }) {
|
|
112
|
+
const { message } = external_antd_namespaceObject.App.useApp();
|
|
112
113
|
const [form] = external_antd_namespaceObject.Form.useForm();
|
|
113
114
|
const initialFormValuesRef = (0, external_react_namespaceObject.useRef)(initialFormValues);
|
|
114
115
|
(0, external_react_namespaceObject.useLayoutEffect)(()=>{
|
|
@@ -277,7 +278,7 @@ function usePlaygroundController({ serverUrl, defaultDeviceType = 'web', pollInt
|
|
|
277
278
|
const values = null != input ? input : yield form.validateFields();
|
|
278
279
|
yield playgroundSDK.createSession(values);
|
|
279
280
|
if ((0, external_auto_create_js_namespaceObject.shouldResetAutoCreateBlock)(options)) autoCreateBlockedSignatureRef.current = null;
|
|
280
|
-
if (!(null == options ? void 0 : options.silent))
|
|
281
|
+
if (!(null == options ? void 0 : options.silent)) message.success('Agent created');
|
|
281
282
|
yield refreshServerState();
|
|
282
283
|
return true;
|
|
283
284
|
} catch (error) {
|
|
@@ -294,6 +295,7 @@ function usePlaygroundController({ serverUrl, defaultDeviceType = 'web', pollInt
|
|
|
294
295
|
})(), [
|
|
295
296
|
applyAiConfig,
|
|
296
297
|
form,
|
|
298
|
+
message,
|
|
297
299
|
playgroundSDK,
|
|
298
300
|
refreshServerState
|
|
299
301
|
]);
|
|
@@ -303,7 +305,7 @@ function usePlaygroundController({ serverUrl, defaultDeviceType = 'web', pollInt
|
|
|
303
305
|
sessionMutatingRef.current = true;
|
|
304
306
|
setSessionMutating(true);
|
|
305
307
|
yield playgroundSDK.destroySession();
|
|
306
|
-
|
|
308
|
+
message.success('Session disconnected');
|
|
307
309
|
yield refreshServerState();
|
|
308
310
|
yield refreshSessionSetup();
|
|
309
311
|
} catch (error) {
|
|
@@ -316,6 +318,7 @@ function usePlaygroundController({ serverUrl, defaultDeviceType = 'web', pollInt
|
|
|
316
318
|
}
|
|
317
319
|
})(), [
|
|
318
320
|
form,
|
|
321
|
+
message,
|
|
319
322
|
playgroundSDK,
|
|
320
323
|
refreshServerState,
|
|
321
324
|
refreshSessionSetup,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@midscene/playground-app",
|
|
3
|
-
"version": "1.9.7
|
|
3
|
+
"version": "1.9.7",
|
|
4
4
|
"description": "Reusable React shell for Midscene playground applications",
|
|
5
5
|
"repository": "https://github.com/web-infra-dev/midscene",
|
|
6
6
|
"homepage": "https://midscenejs.com/",
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"antd": "^5.21.6",
|
|
29
29
|
"react-resizable-panels": "2.0.22",
|
|
30
30
|
"socket.io-client": "4.8.1",
|
|
31
|
-
"@midscene/shared": "1.9.7
|
|
32
|
-
"@midscene/
|
|
33
|
-
"@midscene/
|
|
31
|
+
"@midscene/shared": "1.9.7",
|
|
32
|
+
"@midscene/visualizer": "1.9.7",
|
|
33
|
+
"@midscene/playground": "1.9.7"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@rsbuild/plugin-less": "^1.5.0",
|