@midscene/playground-app 1.7.3 → 1.7.4

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.
Files changed (50) hide show
  1. package/dist/es/PlaygroundApp.css +0 -128
  2. package/dist/es/PlaygroundApp.mjs +74 -464
  3. package/dist/es/PlaygroundThemeProvider.mjs +10 -0
  4. package/dist/es/PreviewRenderer.mjs +4 -1
  5. package/dist/es/ScrcpyPanel.mjs +97 -89
  6. package/dist/es/SessionSetupPanel.css +292 -0
  7. package/dist/es/SessionSetupPanel.mjs +60 -39
  8. package/dist/es/controller/ai-config.mjs +37 -0
  9. package/dist/es/controller/auto-create.mjs +19 -0
  10. package/dist/es/controller/selectors.mjs +66 -0
  11. package/dist/es/controller/types.mjs +0 -0
  12. package/dist/es/controller/usePlaygroundController.mjs +356 -0
  13. package/dist/es/icons/dropdown-chevron.mjs +61 -0
  14. package/dist/es/icons/midscene-logo.mjs +247 -0
  15. package/dist/es/index.mjs +4 -1
  16. package/dist/es/panels/PlaygroundConversationPanel.css +20 -0
  17. package/dist/es/panels/PlaygroundConversationPanel.mjs +134 -0
  18. package/dist/es/scrcpy-preview.mjs +30 -0
  19. package/dist/lib/PlaygroundApp.css +0 -128
  20. package/dist/lib/PlaygroundApp.js +70 -460
  21. package/dist/lib/PlaygroundThemeProvider.js +44 -0
  22. package/dist/lib/PreviewRenderer.js +4 -1
  23. package/dist/lib/ScrcpyPanel.js +96 -88
  24. package/dist/lib/SessionSetupPanel.css +292 -0
  25. package/dist/lib/SessionSetupPanel.js +70 -38
  26. package/dist/lib/controller/ai-config.js +74 -0
  27. package/dist/lib/controller/auto-create.js +59 -0
  28. package/dist/lib/controller/selectors.js +103 -0
  29. package/dist/lib/controller/types.js +18 -0
  30. package/dist/lib/controller/usePlaygroundController.js +390 -0
  31. package/dist/lib/icons/dropdown-chevron.js +95 -0
  32. package/dist/lib/icons/midscene-logo.js +281 -0
  33. package/dist/lib/index.js +14 -2
  34. package/dist/lib/panels/PlaygroundConversationPanel.css +20 -0
  35. package/dist/lib/panels/PlaygroundConversationPanel.js +168 -0
  36. package/dist/lib/scrcpy-preview.js +79 -0
  37. package/dist/types/PlaygroundPreview.d.ts +6 -0
  38. package/dist/types/PlaygroundThemeProvider.d.ts +2 -0
  39. package/dist/types/PreviewRenderer.d.ts +7 -1
  40. package/dist/types/ScrcpyPanel.d.ts +14 -1
  41. package/dist/types/SessionSetupPanel.d.ts +4 -3
  42. package/dist/types/controller/ai-config.d.ts +4 -0
  43. package/dist/types/controller/auto-create.d.ts +15 -0
  44. package/dist/types/controller/selectors.d.ts +5 -0
  45. package/dist/types/controller/types.d.ts +36 -0
  46. package/dist/types/controller/usePlaygroundController.d.ts +9 -0
  47. package/dist/types/index.d.ts +5 -0
  48. package/dist/types/panels/PlaygroundConversationPanel.d.ts +20 -0
  49. package/dist/types/scrcpy-preview.d.ts +11 -0
  50. package/package.json +4 -3
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ PlaygroundConversationPanel: ()=>PlaygroundConversationPanel
28
+ });
29
+ const jsx_runtime_namespaceObject = require("react/jsx-runtime");
30
+ const visualizer_namespaceObject = require("@midscene/visualizer");
31
+ const external_antd_namespaceObject = require("antd");
32
+ const external_SessionSetupPanel_js_namespaceObject = require("../SessionSetupPanel.js");
33
+ const selectors_js_namespaceObject = require("../controller/selectors.js");
34
+ require("./PlaygroundConversationPanel.css");
35
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
36
+ try {
37
+ var info = gen[key](arg);
38
+ var value = info.value;
39
+ } catch (error) {
40
+ reject(error);
41
+ return;
42
+ }
43
+ if (info.done) resolve(value);
44
+ else Promise.resolve(value).then(_next, _throw);
45
+ }
46
+ function _async_to_generator(fn) {
47
+ return function() {
48
+ var self = this, args = arguments;
49
+ return new Promise(function(resolve, reject) {
50
+ var gen = fn.apply(self, args);
51
+ function _next(value) {
52
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
53
+ }
54
+ function _throw(err) {
55
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
56
+ }
57
+ _next(void 0);
58
+ });
59
+ };
60
+ }
61
+ function PlaygroundConversationPanel({ controller, appVersion, title = 'Playground', branding, playgroundConfig, header, className, notConnectedFallback }) {
62
+ const { state, actions } = controller;
63
+ const mergedConfig = (0, selectors_js_namespaceObject.buildConversationConfig)(state, playgroundConfig);
64
+ const mergedBranding = (0, selectors_js_namespaceObject.buildConversationBranding)(state.runtimeInfo, title, appVersion, state.deviceType, branding);
65
+ return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("div", {
66
+ className: [
67
+ 'playground-conversation-panel',
68
+ className
69
+ ].filter(Boolean).join(' '),
70
+ children: [
71
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_antd_namespaceObject.Modal, {
72
+ open: null !== state.countdown,
73
+ footer: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_antd_namespaceObject.Button, {
74
+ onClick: actions.finishCountdown,
75
+ type: "default",
76
+ children: "Skip countdown"
77
+ }),
78
+ closable: true,
79
+ maskClosable: true,
80
+ onCancel: actions.finishCountdown,
81
+ centered: true,
82
+ width: 400,
83
+ style: {
84
+ top: '30%'
85
+ },
86
+ styles: {
87
+ mask: {
88
+ backgroundColor: 'rgba(0, 0, 0, 0.75)'
89
+ }
90
+ },
91
+ children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("div", {
92
+ style: {
93
+ textAlign: 'center',
94
+ padding: '40px 20px'
95
+ },
96
+ children: [
97
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", {
98
+ style: {
99
+ fontSize: '72px',
100
+ fontWeight: 'bold',
101
+ color: 'GO!' === state.countdown ? '#52c41a' : '#1890ff',
102
+ marginBottom: '24px',
103
+ lineHeight: 1
104
+ },
105
+ children: state.countdown
106
+ }),
107
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", {
108
+ style: {
109
+ fontSize: '18px',
110
+ fontWeight: 500,
111
+ marginBottom: '12px'
112
+ },
113
+ children: "Automation Starting Soon"
114
+ }),
115
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("div", {
116
+ style: {
117
+ fontSize: '14px',
118
+ color: 'rgba(0, 0, 0, 0.65)'
119
+ },
120
+ children: [
121
+ "The selected session requested a countdown before execution.",
122
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("br", {}),
123
+ "Please wait until the run starts."
124
+ ]
125
+ })
126
+ ]
127
+ })
128
+ }),
129
+ header,
130
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", {
131
+ className: "playground-conversation-body",
132
+ children: state.serverOnline ? state.sessionViewState.connected ? /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(visualizer_namespaceObject.UniversalPlayground, {
133
+ playgroundSDK: state.playgroundSDK,
134
+ config: mergedConfig,
135
+ branding: mergedBranding,
136
+ className: "playground-container"
137
+ }) : void 0 !== notConnectedFallback ? /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(jsx_runtime_namespaceObject.Fragment, {
138
+ children: notConnectedFallback
139
+ }) : /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_SessionSetupPanel_js_namespaceObject.SessionSetupPanel, {
140
+ form: state.form,
141
+ sessionSetup: state.sessionSetup,
142
+ sessionSetupError: state.sessionSetupError,
143
+ sessionViewState: state.sessionViewState,
144
+ sessionLoading: state.sessionLoading,
145
+ sessionMutating: state.sessionMutating,
146
+ onCreateSession: ()=>_async_to_generator(function*() {
147
+ yield actions.createSession();
148
+ })()
149
+ }) : /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", {
150
+ className: "playground-conversation-offline",
151
+ children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_antd_namespaceObject.Alert, {
152
+ type: "warning",
153
+ showIcon: true,
154
+ message: "Playground server offline",
155
+ description: "Reconnect the runtime to continue using the Android playground."
156
+ })
157
+ })
158
+ })
159
+ ]
160
+ });
161
+ }
162
+ exports.PlaygroundConversationPanel = __webpack_exports__.PlaygroundConversationPanel;
163
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
164
+ "PlaygroundConversationPanel"
165
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
166
+ Object.defineProperty(exports, '__esModule', {
167
+ value: true
168
+ });
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ SCRCPY_METADATA_TIMEOUT_MS: ()=>SCRCPY_METADATA_TIMEOUT_MS,
28
+ getScrcpyDecoderStatusText: ()=>getScrcpyDecoderStatusText,
29
+ getScrcpyPreviewStatusText: ()=>getScrcpyPreviewStatusText,
30
+ getScrcpyMetadataTimeoutMessage: ()=>getScrcpyMetadataTimeoutMessage,
31
+ isScrcpyPreviewStatusEvent: ()=>isScrcpyPreviewStatusEvent,
32
+ getDefaultScrcpyWaitingStatusText: ()=>getDefaultScrcpyWaitingStatusText
33
+ });
34
+ const constants_namespaceObject = require("@midscene/shared/constants");
35
+ const SCRCPY_METADATA_TIMEOUT_MS = constants_namespaceObject.SCRCPY_PREVIEW_METADATA_TIMEOUT_MS;
36
+ function isScrcpyPreviewStatusEvent(value) {
37
+ return 'object' == typeof value && null !== value && 'message' in value && 'string' == typeof value.message;
38
+ }
39
+ function getDefaultScrcpyWaitingStatusText() {
40
+ return 'Preparing Android device connection…';
41
+ }
42
+ function getScrcpyDecoderStatusText() {
43
+ return 'Starting video decoder…';
44
+ }
45
+ function getScrcpyPreviewStatusText(status, waitingMessage = getDefaultScrcpyWaitingStatusText()) {
46
+ switch(status){
47
+ case 'connected':
48
+ return 'Live scrcpy preview connected';
49
+ case 'waiting-for-stream':
50
+ return waitingMessage;
51
+ case 'error':
52
+ return 'Unable to start scrcpy preview';
53
+ case 'disconnected':
54
+ return 'scrcpy preview disconnected, retrying…';
55
+ default:
56
+ return 'Connecting to scrcpy preview server…';
57
+ }
58
+ }
59
+ function getScrcpyMetadataTimeoutMessage(timeoutMs = SCRCPY_METADATA_TIMEOUT_MS) {
60
+ const seconds = Math.max(1, Math.round(timeoutMs / 1000));
61
+ return `Timed out waiting ${seconds}s for scrcpy video stream metadata.`;
62
+ }
63
+ exports.SCRCPY_METADATA_TIMEOUT_MS = __webpack_exports__.SCRCPY_METADATA_TIMEOUT_MS;
64
+ exports.getDefaultScrcpyWaitingStatusText = __webpack_exports__.getDefaultScrcpyWaitingStatusText;
65
+ exports.getScrcpyDecoderStatusText = __webpack_exports__.getScrcpyDecoderStatusText;
66
+ exports.getScrcpyMetadataTimeoutMessage = __webpack_exports__.getScrcpyMetadataTimeoutMessage;
67
+ exports.getScrcpyPreviewStatusText = __webpack_exports__.getScrcpyPreviewStatusText;
68
+ exports.isScrcpyPreviewStatusEvent = __webpack_exports__.isScrcpyPreviewStatusEvent;
69
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
70
+ "SCRCPY_METADATA_TIMEOUT_MS",
71
+ "getDefaultScrcpyWaitingStatusText",
72
+ "getScrcpyDecoderStatusText",
73
+ "getScrcpyMetadataTimeoutMessage",
74
+ "getScrcpyPreviewStatusText",
75
+ "isScrcpyPreviewStatusEvent"
76
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
77
+ Object.defineProperty(exports, '__esModule', {
78
+ value: true
79
+ });
@@ -1,5 +1,11 @@
1
1
  import type { PlaygroundRuntimeInfo, PlaygroundSDK } from '@midscene/playground';
2
+ import type { ReactNode } from 'react';
3
+ import type { ScrcpyErrorOverlayRenderer } from './ScrcpyPanel';
4
+ import type { ScrcpyPreviewStatus } from './scrcpy-preview';
2
5
  export interface PlaygroundPreviewProps {
6
+ connectingOverlay?: ReactNode;
7
+ onScrcpyStatusChange?: (status: ScrcpyPreviewStatus) => void;
8
+ renderErrorOverlay?: ScrcpyErrorOverlayRenderer;
3
9
  playgroundSDK: PlaygroundSDK;
4
10
  runtimeInfo: PlaygroundRuntimeInfo | null;
5
11
  serverUrl: string;
@@ -0,0 +1,2 @@
1
+ import type { PropsWithChildren } from 'react';
2
+ export declare function PlaygroundThemeProvider({ children }: PropsWithChildren): import("react").JSX.Element;
@@ -1,10 +1,16 @@
1
1
  import type { PlaygroundRuntimeInfo, PlaygroundSDK } from '@midscene/playground';
2
+ import type { ReactNode } from 'react';
3
+ import { type ScrcpyErrorOverlayRenderer } from './ScrcpyPanel';
4
+ import type { ScrcpyPreviewStatus } from './scrcpy-preview';
2
5
  interface PreviewRendererProps {
6
+ connectingOverlay?: ReactNode;
7
+ onScrcpyStatusChange?: (status: ScrcpyPreviewStatus) => void;
8
+ renderErrorOverlay?: ScrcpyErrorOverlayRenderer;
3
9
  playgroundSDK: PlaygroundSDK;
4
10
  runtimeInfo: PlaygroundRuntimeInfo | null;
5
11
  serverUrl: string;
6
12
  serverOnline: boolean;
7
13
  isUserOperating: boolean;
8
14
  }
9
- export declare function PreviewRenderer({ playgroundSDK, runtimeInfo, serverUrl, serverOnline, isUserOperating, }: PreviewRendererProps): import("react").JSX.Element;
15
+ export declare function PreviewRenderer({ connectingOverlay, onScrcpyStatusChange, renderErrorOverlay, playgroundSDK, runtimeInfo, serverUrl, serverOnline, isUserOperating, }: PreviewRendererProps): import("react").JSX.Element;
10
16
  export {};
@@ -1,6 +1,19 @@
1
+ import React, { type ReactNode } from 'react';
2
+ import { type ScrcpyPreviewStatus } from './scrcpy-preview';
3
+ export interface ScrcpyErrorOverlayContext {
4
+ errorMessage: string | null;
5
+ retry: () => void;
6
+ status: ScrcpyPreviewStatus;
7
+ statusText: string;
8
+ }
9
+ export type ScrcpyErrorOverlayRenderer = (context: ScrcpyErrorOverlayContext) => ReactNode;
1
10
  interface ScrcpyPanelProps {
11
+ connectingOverlay?: ReactNode;
12
+ onStatusChange?: (status: ScrcpyPreviewStatus) => void;
13
+ renderErrorOverlay?: ScrcpyErrorOverlayRenderer;
2
14
  serverUrl?: string;
15
+ metadataTimeoutMs?: number;
3
16
  reconnectInterval?: number;
4
17
  }
5
- export declare function ScrcpyPanel({ serverUrl, reconnectInterval, }: ScrcpyPanelProps): import("react").JSX.Element;
18
+ export declare function ScrcpyPanel({ connectingOverlay, onStatusChange, renderErrorOverlay, serverUrl, metadataTimeoutMs, reconnectInterval, }: ScrcpyPanelProps): React.JSX.Element;
6
19
  export {};
@@ -1,14 +1,15 @@
1
1
  import type { PlaygroundSessionSetup } from '@midscene/playground';
2
2
  import type { FormInstance } from 'antd';
3
+ import type { PlaygroundFormValues } from './controller/types';
3
4
  import type { PlaygroundSessionViewState } from './session-state';
5
+ import './SessionSetupPanel.less';
4
6
  export interface SessionSetupPanelProps {
5
- form: FormInstance<Record<string, unknown>>;
7
+ form: FormInstance<PlaygroundFormValues>;
6
8
  sessionSetup: PlaygroundSessionSetup | null;
7
9
  sessionSetupError: string | null;
8
10
  sessionViewState: PlaygroundSessionViewState;
9
11
  sessionLoading: boolean;
10
12
  sessionMutating: boolean;
11
13
  onCreateSession: () => void | Promise<void>;
12
- onRefreshTargets: () => void | Promise<void>;
13
14
  }
14
- export declare function SessionSetupPanel({ form, sessionSetup, sessionSetupError, sessionViewState, sessionLoading, sessionMutating, onCreateSession, onRefreshTargets, }: SessionSetupPanelProps): import("react").JSX.Element;
15
+ export declare function SessionSetupPanel({ form, sessionSetup, sessionSetupError, sessionViewState, sessionLoading, sessionMutating, onCreateSession, }: SessionSetupPanelProps): import("react").JSX.Element;
@@ -0,0 +1,4 @@
1
+ import type { PlaygroundSDK } from '@midscene/playground';
2
+ export type PlaygroundAiConfig = Record<string, string>;
3
+ export declare function hasPlaygroundAiConfig(config: PlaygroundAiConfig): boolean;
4
+ export declare function applyPlaygroundAiConfig(playgroundSDK: Pick<PlaygroundSDK, 'overrideConfig'>, config: PlaygroundAiConfig): Promise<boolean>;
@@ -0,0 +1,15 @@
1
+ export type AutoCreateInput = Record<string, unknown> | null | undefined;
2
+ export interface ResolveAutoCreateDecisionOptions {
3
+ autoCreateInput: AutoCreateInput;
4
+ lastAttemptedSignature: string | null;
5
+ blockedSignature: string | null;
6
+ }
7
+ export interface AutoCreateDecision {
8
+ signature: string | null;
9
+ shouldCreate: boolean;
10
+ }
11
+ export declare function serializeAutoCreateInput(autoCreateInput: AutoCreateInput): string | null;
12
+ export declare function resolveAutoCreateDecision({ autoCreateInput, lastAttemptedSignature, blockedSignature, }: ResolveAutoCreateDecisionOptions): AutoCreateDecision;
13
+ export declare function shouldResetAutoCreateBlock(options?: {
14
+ silent?: boolean;
15
+ }): boolean;
@@ -0,0 +1,5 @@
1
+ import type { PlaygroundRuntimeInfo } from '@midscene/playground';
2
+ import type { PlaygroundBranding, UniversalPlaygroundConfig } from '@midscene/visualizer';
3
+ import type { PlaygroundControllerState } from './types';
4
+ export declare function buildConversationConfig(state: Pick<PlaygroundControllerState, 'deviceType' | 'executionUxHints' | 'countdownSeconds'>, playgroundConfig?: Partial<UniversalPlaygroundConfig>): UniversalPlaygroundConfig;
5
+ export declare function buildConversationBranding(runtimeInfo: PlaygroundRuntimeInfo | null, title: string, appVersion: string, deviceType: string, branding?: Partial<PlaygroundBranding>): PlaygroundBranding;
@@ -0,0 +1,36 @@
1
+ import type { PlaygroundRuntimeInfo, PlaygroundSDK, PlaygroundSessionSetup } from '@midscene/playground';
2
+ import type { DeviceType, ExecutionUxHint } from '@midscene/visualizer';
3
+ import type { FormInstance } from 'antd';
4
+ import type { PlaygroundSessionViewState } from '../session-state';
5
+ export type PlaygroundFormValue = boolean | null | number | string | undefined;
6
+ export type PlaygroundFormValues = Record<string, PlaygroundFormValue>;
7
+ export interface PlaygroundControllerState {
8
+ playgroundSDK: PlaygroundSDK;
9
+ form: FormInstance<PlaygroundFormValues>;
10
+ formValues: Record<string, unknown>;
11
+ serverOnline: boolean;
12
+ isUserOperating: boolean;
13
+ deviceType: DeviceType;
14
+ runtimeInfo: PlaygroundRuntimeInfo | null;
15
+ executionUxHints: ExecutionUxHint[];
16
+ sessionViewState: PlaygroundSessionViewState;
17
+ sessionSetup: PlaygroundSessionSetup | null;
18
+ sessionSetupError: string | null;
19
+ sessionLoading: boolean;
20
+ sessionMutating: boolean;
21
+ countdown: number | string | null;
22
+ countdownSeconds: number;
23
+ }
24
+ export interface PlaygroundControllerActions {
25
+ refreshServerState: () => Promise<void>;
26
+ refreshSessionSetup: (input?: Record<string, unknown>) => Promise<void>;
27
+ createSession: (input?: Record<string, unknown>, options?: {
28
+ silent?: boolean;
29
+ }) => Promise<boolean>;
30
+ destroySession: () => Promise<void>;
31
+ finishCountdown: () => void;
32
+ }
33
+ export interface PlaygroundControllerResult {
34
+ state: PlaygroundControllerState;
35
+ actions: PlaygroundControllerActions;
36
+ }
@@ -0,0 +1,9 @@
1
+ import { type DeviceType } from '@midscene/visualizer';
2
+ import type { PlaygroundControllerResult } from './types';
3
+ export interface UsePlaygroundControllerOptions {
4
+ serverUrl: string;
5
+ defaultDeviceType?: DeviceType;
6
+ pollIntervalMs?: number;
7
+ countdownSeconds?: number;
8
+ }
9
+ export declare function usePlaygroundController({ serverUrl, defaultDeviceType, pollIntervalMs, countdownSeconds, }: UsePlaygroundControllerOptions): PlaygroundControllerResult;
@@ -1,5 +1,10 @@
1
1
  export { PlaygroundApp } from './PlaygroundApp';
2
2
  export { PlaygroundPreview } from './PlaygroundPreview';
3
+ export { PlaygroundThemeProvider } from './PlaygroundThemeProvider';
4
+ export { PlaygroundConversationPanel } from './panels/PlaygroundConversationPanel';
3
5
  export type { PlaygroundAppProps } from './PlaygroundApp';
4
6
  export type { PlaygroundPreviewProps } from './PlaygroundPreview';
7
+ export type { PlaygroundConversationPanelProps } from './panels/PlaygroundConversationPanel';
5
8
  export type { DeviceType } from '@midscene/visualizer';
9
+ export type { PlaygroundControllerActions, PlaygroundControllerResult, PlaygroundControllerState, } from './controller/types';
10
+ export { usePlaygroundController } from './controller/usePlaygroundController';
@@ -0,0 +1,20 @@
1
+ import { type PlaygroundBranding, type UniversalPlaygroundConfig } from '@midscene/visualizer';
2
+ import type { ReactNode } from 'react';
3
+ import type { PlaygroundControllerResult } from '../controller/types';
4
+ import './PlaygroundConversationPanel.less';
5
+ export interface PlaygroundConversationPanelProps {
6
+ controller: PlaygroundControllerResult;
7
+ appVersion: string;
8
+ title?: string;
9
+ branding?: Partial<PlaygroundBranding>;
10
+ playgroundConfig?: Partial<UniversalPlaygroundConfig>;
11
+ header?: ReactNode;
12
+ className?: string;
13
+ /**
14
+ * Custom content shown while the session is not yet connected.
15
+ * When supplied, replaces the built-in `SessionSetupPanel`, letting hosts
16
+ * drive device selection elsewhere.
17
+ */
18
+ notConnectedFallback?: ReactNode;
19
+ }
20
+ export declare function PlaygroundConversationPanel({ controller, appVersion, title, branding, playgroundConfig, header, className, notConnectedFallback, }: PlaygroundConversationPanelProps): import("react").JSX.Element;
@@ -0,0 +1,11 @@
1
+ export declare const SCRCPY_METADATA_TIMEOUT_MS: number;
2
+ export type ScrcpyPreviewStatus = 'connecting' | 'waiting-for-stream' | 'connected' | 'disconnected' | 'error';
3
+ export interface ScrcpyPreviewStatusEvent {
4
+ message: string;
5
+ phase?: string;
6
+ }
7
+ export declare function isScrcpyPreviewStatusEvent(value: unknown): value is ScrcpyPreviewStatusEvent;
8
+ export declare function getDefaultScrcpyWaitingStatusText(): string;
9
+ export declare function getScrcpyDecoderStatusText(): string;
10
+ export declare function getScrcpyPreviewStatusText(status: ScrcpyPreviewStatus, waitingMessage?: string): string;
11
+ export declare function getScrcpyMetadataTimeoutMessage(timeoutMs?: number): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midscene/playground-app",
3
- "version": "1.7.3",
3
+ "version": "1.7.4",
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,8 +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/playground": "1.7.3",
32
- "@midscene/visualizer": "1.7.3"
31
+ "@midscene/shared": "1.7.4",
32
+ "@midscene/playground": "1.7.4",
33
+ "@midscene/visualizer": "1.7.4"
33
34
  },
34
35
  "devDependencies": {
35
36
  "@rsbuild/plugin-less": "^1.5.0",