@midscene/visualizer 0.30.10 → 1.0.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.
Files changed (123) hide show
  1. package/dist/es/component/blackboard/index.css +8 -0
  2. package/dist/es/component/blackboard/index.mjs +137 -68
  3. package/dist/es/component/config-selector/index.mjs +102 -4
  4. package/dist/es/component/context-preview/index.mjs +1 -2
  5. package/dist/es/component/env-config/index.mjs +1 -2
  6. package/dist/es/component/env-config-reminder/index.css +8 -0
  7. package/dist/es/component/env-config-reminder/index.mjs +1 -2
  8. package/dist/es/component/form-field/index.mjs +5 -10
  9. package/dist/es/component/history-selector/index.css +38 -1
  10. package/dist/es/component/history-selector/index.mjs +1 -2
  11. package/dist/es/component/logo/index.mjs +7 -3
  12. package/dist/es/component/misc/index.mjs +1 -4
  13. package/dist/es/component/nav-actions/index.mjs +1 -2
  14. package/dist/es/component/nav-actions/style.css +1 -1
  15. package/dist/es/component/player/index.css +26 -0
  16. package/dist/es/component/player/index.mjs +376 -364
  17. package/dist/es/component/playground/index.css +291 -31
  18. package/dist/es/component/playground-result/index.css +10 -0
  19. package/dist/es/component/playground-result/index.mjs +129 -10
  20. package/dist/es/component/prompt-input/index.css +281 -31
  21. package/dist/es/component/prompt-input/index.mjs +83 -25
  22. package/dist/es/component/screenshot-viewer/index.css +214 -0
  23. package/dist/es/component/screenshot-viewer/index.mjs +282 -0
  24. package/dist/es/component/service-mode-control/index.mjs +1 -2
  25. package/dist/es/component/shiny-text/index.css +35 -3
  26. package/dist/es/component/shiny-text/index.mjs +3 -3
  27. package/dist/es/component/universal-playground/index.css +61 -1
  28. package/dist/es/component/universal-playground/index.mjs +106 -83
  29. package/dist/es/component/universal-playground/providers/context-provider.mjs +56 -18
  30. package/dist/es/component/universal-playground/providers/indexeddb-storage-provider.mjs +213 -139
  31. package/dist/es/component/universal-playground/providers/storage-provider.mjs +199 -121
  32. package/dist/es/hooks/usePlaygroundExecution.mjs +297 -146
  33. package/dist/es/hooks/usePlaygroundState.mjs +141 -75
  34. package/dist/es/hooks/useSafeOverrideAIConfig.mjs +2 -6
  35. package/dist/es/hooks/useServerValid.mjs +37 -12
  36. package/dist/es/hooks/useTheme.mjs +25 -0
  37. package/dist/es/icons/avatar.mjs +46 -4
  38. package/dist/es/icons/close.mjs +46 -4
  39. package/dist/es/icons/global-perspective.mjs +47 -5
  40. package/dist/es/icons/history.mjs +48 -6
  41. package/dist/es/icons/magnifying-glass.mjs +47 -5
  42. package/dist/es/icons/player-setting.mjs +48 -6
  43. package/dist/es/icons/setting.mjs +47 -5
  44. package/dist/es/icons/show-marker.mjs +47 -5
  45. package/dist/es/index.mjs +4 -4
  46. package/dist/es/store/history.mjs +46 -7
  47. package/dist/es/store/store.mjs +68 -2
  48. package/dist/es/types.mjs +1 -1
  49. package/dist/es/utils/constants.mjs +7 -3
  50. package/dist/es/utils/index.mjs +4 -1
  51. package/dist/es/utils/pixi-loader.mjs +37 -11
  52. package/dist/es/utils/replay-scripts.mjs +160 -111
  53. package/dist/lib/component/blackboard/index.css +8 -0
  54. package/dist/lib/component/blackboard/index.js +139 -70
  55. package/dist/lib/component/config-selector/index.js +103 -5
  56. package/dist/lib/component/context-preview/index.js +3 -4
  57. package/dist/lib/component/env-config/index.js +3 -4
  58. package/dist/lib/component/env-config-reminder/index.css +8 -0
  59. package/dist/lib/component/env-config-reminder/index.js +3 -4
  60. package/dist/lib/component/form-field/index.js +10 -15
  61. package/dist/lib/component/history-selector/index.css +38 -1
  62. package/dist/lib/component/history-selector/index.js +3 -4
  63. package/dist/lib/component/index.js +6 -8
  64. package/dist/lib/component/logo/index.js +9 -5
  65. package/dist/lib/component/misc/index.js +6 -9
  66. package/dist/lib/component/nav-actions/index.js +3 -4
  67. package/dist/lib/component/nav-actions/style.css +1 -1
  68. package/dist/lib/component/player/index.css +26 -0
  69. package/dist/lib/component/player/index.js +376 -365
  70. package/dist/lib/component/playground/index.css +291 -31
  71. package/dist/lib/component/playground/index.js +31 -33
  72. package/dist/lib/component/playground-result/index.css +10 -0
  73. package/dist/lib/component/playground-result/index.js +131 -12
  74. package/dist/lib/component/prompt-input/index.css +281 -31
  75. package/dist/lib/component/prompt-input/index.js +84 -26
  76. package/dist/lib/component/screenshot-viewer/index.css +214 -0
  77. package/dist/lib/component/screenshot-viewer/index.js +316 -0
  78. package/dist/lib/component/service-mode-control/index.js +3 -4
  79. package/dist/lib/component/shiny-text/index.css +35 -3
  80. package/dist/lib/component/shiny-text/index.js +5 -5
  81. package/dist/lib/component/universal-playground/index.css +61 -1
  82. package/dist/lib/component/universal-playground/index.js +108 -84
  83. package/dist/lib/component/universal-playground/providers/context-provider.js +58 -20
  84. package/dist/lib/component/universal-playground/providers/indexeddb-storage-provider.js +217 -143
  85. package/dist/lib/component/universal-playground/providers/storage-provider.js +207 -129
  86. package/dist/lib/hooks/usePlaygroundExecution.js +299 -148
  87. package/dist/lib/hooks/usePlaygroundState.js +143 -77
  88. package/dist/lib/hooks/useSafeOverrideAIConfig.js +4 -8
  89. package/dist/lib/hooks/useServerValid.js +39 -14
  90. package/dist/lib/hooks/useTheme.js +59 -0
  91. package/dist/lib/icons/avatar.js +48 -6
  92. package/dist/lib/icons/close.js +48 -6
  93. package/dist/lib/icons/global-perspective.js +49 -7
  94. package/dist/lib/icons/history.js +50 -8
  95. package/dist/lib/icons/magnifying-glass.js +49 -7
  96. package/dist/lib/icons/player-setting.js +50 -8
  97. package/dist/lib/icons/setting.js +49 -7
  98. package/dist/lib/icons/show-marker.js +49 -7
  99. package/dist/lib/index.js +44 -34
  100. package/dist/lib/store/history.js +48 -9
  101. package/dist/lib/store/store.js +74 -8
  102. package/dist/lib/types.js +3 -3
  103. package/dist/lib/utils/color.js +2 -2
  104. package/dist/lib/utils/constants.js +20 -4
  105. package/dist/lib/utils/index.js +10 -4
  106. package/dist/lib/utils/pixi-loader.js +41 -15
  107. package/dist/lib/utils/playground-utils.js +4 -4
  108. package/dist/lib/utils/replay-scripts.js +164 -115
  109. package/dist/types/component/config-selector/index.d.ts +2 -0
  110. package/dist/types/component/player/index.d.ts +0 -1
  111. package/dist/types/component/playground-result/index.d.ts +1 -0
  112. package/dist/types/component/prompt-input/index.d.ts +2 -1
  113. package/dist/types/component/screenshot-viewer/index.d.ts +15 -0
  114. package/dist/types/hooks/usePlaygroundExecution.d.ts +1 -1
  115. package/dist/types/hooks/usePlaygroundState.d.ts +3 -3
  116. package/dist/types/hooks/useTheme.d.ts +7 -0
  117. package/dist/types/index.d.ts +3 -3
  118. package/dist/types/store/store.d.ts +18 -1
  119. package/dist/types/types.d.ts +14 -4
  120. package/dist/types/utils/constants.d.ts +5 -1
  121. package/dist/types/utils/index.d.ts +1 -0
  122. package/dist/types/utils/replay-scripts.d.ts +1 -1
  123. package/package.json +12 -22
@@ -0,0 +1,214 @@
1
+ .screenshot-viewer {
2
+ flex-direction: column;
3
+ height: 100%;
4
+ display: flex;
5
+ }
6
+
7
+ .screenshot-viewer.offline, .screenshot-viewer.loading, .screenshot-viewer.error {
8
+ text-align: center;
9
+ color: #666;
10
+ justify-content: center;
11
+ align-items: center;
12
+ }
13
+
14
+ .screenshot-viewer.offline .screenshot-placeholder h3, .screenshot-viewer.loading .screenshot-placeholder h3, .screenshot-viewer.error .screenshot-placeholder h3 {
15
+ color: #1890ff;
16
+ text-transform: capitalize;
17
+ margin-bottom: 12px;
18
+ font-size: 18px;
19
+ }
20
+
21
+ .screenshot-viewer.offline .screenshot-placeholder p, .screenshot-viewer.loading .screenshot-placeholder p, .screenshot-viewer.error .screenshot-placeholder p {
22
+ color: #666;
23
+ margin: 0;
24
+ }
25
+
26
+ .screenshot-viewer.offline .screenshot-placeholder p.error-message, .screenshot-viewer.loading .screenshot-placeholder p.error-message, .screenshot-viewer.error .screenshot-placeholder p.error-message {
27
+ color: #ff4d4f;
28
+ }
29
+
30
+ .screenshot-viewer .screenshot-header {
31
+ justify-content: space-between;
32
+ align-items: center;
33
+ height: 56px;
34
+ display: flex;
35
+ }
36
+
37
+ .screenshot-viewer .screenshot-header .screenshot-title {
38
+ flex-direction: column;
39
+ gap: 4px;
40
+ display: flex;
41
+ }
42
+
43
+ .screenshot-viewer .screenshot-header .screenshot-title h3 {
44
+ color: #000;
45
+ text-transform: capitalize;
46
+ align-items: center;
47
+ gap: 8px;
48
+ margin: 0;
49
+ font-size: 14px;
50
+ font-weight: 600;
51
+ display: flex;
52
+ }
53
+
54
+ .screenshot-viewer .screenshot-header .screenshot-title .screenshot-subtitle {
55
+ color: #999;
56
+ margin: 0;
57
+ font-size: 12px;
58
+ }
59
+
60
+ .screenshot-viewer .screenshot-container {
61
+ background: #f2f4f7;
62
+ border-radius: 16px;
63
+ flex-direction: column;
64
+ flex: 1;
65
+ padding: 0 15px;
66
+ display: flex;
67
+ overflow: hidden;
68
+ }
69
+
70
+ .screenshot-viewer .screenshot-container .screenshot-overlay {
71
+ z-index: 10;
72
+ justify-content: space-between;
73
+ align-items: flex-start;
74
+ padding: 12px 5px 8px;
75
+ display: flex;
76
+ }
77
+
78
+ .screenshot-viewer .screenshot-container .screenshot-overlay .device-name-overlay {
79
+ color: rgba(0, 0, 0, .85);
80
+ text-transform: capitalize;
81
+ align-items: center;
82
+ gap: 8px;
83
+ font-size: 12px;
84
+ font-weight: 500;
85
+ display: flex;
86
+ }
87
+
88
+ .screenshot-viewer .screenshot-container .screenshot-overlay .device-name-overlay .info-icon {
89
+ opacity: .8;
90
+ cursor: pointer;
91
+ font-size: 12px;
92
+ }
93
+
94
+ .screenshot-viewer .screenshot-container .screenshot-overlay .device-name-overlay .info-icon:hover {
95
+ opacity: 1;
96
+ }
97
+
98
+ .screenshot-viewer .screenshot-container .screenshot-overlay .screenshot-controls {
99
+ opacity: 1;
100
+ box-sizing: border-box;
101
+ border-radius: 4px;
102
+ align-items: center;
103
+ gap: 10px;
104
+ height: 18px;
105
+ padding: 4px 8px;
106
+ display: flex;
107
+ }
108
+
109
+ .screenshot-viewer .screenshot-container .screenshot-overlay .screenshot-controls .last-update-time {
110
+ color: #666;
111
+ white-space: nowrap;
112
+ text-overflow: ellipsis;
113
+ font-size: 12px;
114
+ overflow: hidden;
115
+ }
116
+
117
+ .screenshot-viewer .screenshot-container .screenshot-overlay .screenshot-controls .operation-indicator {
118
+ align-items: center;
119
+ gap: 4px;
120
+ font-size: 12px;
121
+ display: flex;
122
+ }
123
+
124
+ .screenshot-viewer .screenshot-container .screenshot-overlay .screenshot-controls .ant-btn {
125
+ box-shadow: none;
126
+ background: none;
127
+ border: none;
128
+ justify-content: center;
129
+ align-items: center;
130
+ width: 16px;
131
+ min-width: 16px;
132
+ height: 16px;
133
+ padding: 0;
134
+ display: flex;
135
+ }
136
+
137
+ .screenshot-viewer .screenshot-container .screenshot-overlay .screenshot-controls .ant-btn:hover {
138
+ background-color: rgba(0, 0, 0, .06);
139
+ border-radius: 2px;
140
+ transition: all .2s;
141
+ transform: scale(1.1);
142
+ }
143
+
144
+ .screenshot-viewer .screenshot-container .screenshot-overlay .screenshot-controls .ant-btn .anticon {
145
+ color: #666;
146
+ font-size: 12px;
147
+ transition: color .2s;
148
+ }
149
+
150
+ .screenshot-viewer .screenshot-container .screenshot-content {
151
+ flex: 1;
152
+ justify-content: center;
153
+ align-items: center;
154
+ min-height: 0;
155
+ display: flex;
156
+ }
157
+
158
+ .screenshot-viewer .screenshot-container .screenshot-content .screenshot-image {
159
+ object-fit: contain;
160
+ border-radius: 12px;
161
+ max-width: 100%;
162
+ height: auto;
163
+ max-height: 100%;
164
+ }
165
+
166
+ .screenshot-viewer .screenshot-container .screenshot-content .screenshot-placeholder {
167
+ text-align: center;
168
+ color: #999;
169
+ }
170
+
171
+ [data-theme="dark"] .screenshot-viewer.offline, [data-theme="dark"] .screenshot-viewer.loading, [data-theme="dark"] .screenshot-viewer.error {
172
+ color: #f8fafd;
173
+ }
174
+
175
+ [data-theme="dark"] .screenshot-viewer.offline .screenshot-placeholder h3, [data-theme="dark"] .screenshot-viewer.loading .screenshot-placeholder h3, [data-theme="dark"] .screenshot-viewer.error .screenshot-placeholder h3 {
176
+ color: #1890ff;
177
+ }
178
+
179
+ [data-theme="dark"] .screenshot-viewer.offline .screenshot-placeholder p, [data-theme="dark"] .screenshot-viewer.loading .screenshot-placeholder p, [data-theme="dark"] .screenshot-viewer.error .screenshot-placeholder p {
180
+ color: #f8fafd;
181
+ }
182
+
183
+ [data-theme="dark"] .screenshot-viewer.offline .screenshot-placeholder p.error-message, [data-theme="dark"] .screenshot-viewer.loading .screenshot-placeholder p.error-message, [data-theme="dark"] .screenshot-viewer.error .screenshot-placeholder p.error-message {
184
+ color: #ff4d4f;
185
+ }
186
+
187
+ [data-theme="dark"] .screenshot-viewer .screenshot-header .screenshot-title h3 {
188
+ color: #f8fafd;
189
+ }
190
+
191
+ [data-theme="dark"] .screenshot-viewer .screenshot-header .screenshot-title .screenshot-subtitle {
192
+ color: rgba(255, 255, 255, .45);
193
+ }
194
+
195
+ [data-theme="dark"] .screenshot-viewer .screenshot-container {
196
+ background: #141414;
197
+ }
198
+
199
+ [data-theme="dark"] .screenshot-viewer .screenshot-container .screenshot-overlay .device-name-overlay, [data-theme="dark"] .screenshot-viewer .screenshot-container .screenshot-overlay .screenshot-controls .last-update-time {
200
+ color: #f8fafd;
201
+ }
202
+
203
+ [data-theme="dark"] .screenshot-viewer .screenshot-container .screenshot-overlay .screenshot-controls .ant-btn:hover {
204
+ background-color: rgba(255, 255, 255, .08);
205
+ }
206
+
207
+ [data-theme="dark"] .screenshot-viewer .screenshot-container .screenshot-overlay .screenshot-controls .ant-btn .anticon {
208
+ color: #f8fafd;
209
+ }
210
+
211
+ [data-theme="dark"] .screenshot-viewer .screenshot-container .screenshot-content .screenshot-placeholder {
212
+ color: rgba(255, 255, 255, .45);
213
+ }
214
+
@@ -0,0 +1,282 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { InfoCircleOutlined, ReloadOutlined } from "@ant-design/icons";
3
+ import { Button, Spin, Tooltip } from "antd";
4
+ import { useCallback, useEffect, useRef, useState } from "react";
5
+ import "./index.css";
6
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
7
+ try {
8
+ var info = gen[key](arg);
9
+ var value = info.value;
10
+ } catch (error) {
11
+ reject(error);
12
+ return;
13
+ }
14
+ if (info.done) resolve(value);
15
+ else Promise.resolve(value).then(_next, _throw);
16
+ }
17
+ function _async_to_generator(fn) {
18
+ return function() {
19
+ var self = this, args = arguments;
20
+ return new Promise(function(resolve, reject) {
21
+ var gen = fn.apply(self, args);
22
+ function _next(value) {
23
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
24
+ }
25
+ function _throw(err) {
26
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
27
+ }
28
+ _next(void 0);
29
+ });
30
+ };
31
+ }
32
+ function ScreenshotViewer({ getScreenshot, getInterfaceInfo, serverOnline, isUserOperating = false }) {
33
+ const [screenshot, setScreenshot] = useState(null);
34
+ const [loading, setLoading] = useState(false);
35
+ const [error, setError] = useState(null);
36
+ const [lastUpdateTime, setLastUpdateTime] = useState(0);
37
+ const [interfaceInfo, setInterfaceInfo] = useState(null);
38
+ const pollingIntervalRef = useRef(null);
39
+ const isPollingPausedRef = useRef(false);
40
+ const fetchScreenshot = useCallback((isManual = false)=>_async_to_generator(function*() {
41
+ if (!serverOnline) return;
42
+ setLoading(true);
43
+ if (isManual) setError(null);
44
+ try {
45
+ const result = yield getScreenshot();
46
+ console.log('Screenshot API response:', result);
47
+ if (null == result ? void 0 : result.screenshot) {
48
+ const screenshotData = result.screenshot.toString().trim();
49
+ if (screenshotData) {
50
+ setScreenshot(screenshotData);
51
+ setError(null);
52
+ setLastUpdateTime(Date.now());
53
+ } else setError('Empty screenshot data received');
54
+ } else setError('No screenshot data in response');
55
+ } catch (err) {
56
+ console.error('Screenshot fetch error:', err);
57
+ setError(err instanceof Error ? err.message : 'Failed to fetch screenshot');
58
+ } finally{
59
+ setLoading(false);
60
+ }
61
+ })(), [
62
+ getScreenshot,
63
+ serverOnline
64
+ ]);
65
+ const fetchInterfaceInfo = useCallback(()=>_async_to_generator(function*() {
66
+ if (!serverOnline || !getInterfaceInfo) return;
67
+ try {
68
+ const info = yield getInterfaceInfo();
69
+ if (info) setInterfaceInfo(info);
70
+ } catch (err) {
71
+ console.error('Interface info fetch error:', err);
72
+ }
73
+ })(), [
74
+ getInterfaceInfo,
75
+ serverOnline
76
+ ]);
77
+ const startPolling = useCallback(()=>{
78
+ if (pollingIntervalRef.current) clearInterval(pollingIntervalRef.current);
79
+ console.log('Starting screenshot polling (5s interval)');
80
+ pollingIntervalRef.current = setInterval(()=>{
81
+ if (!isPollingPausedRef.current && serverOnline) fetchScreenshot(false);
82
+ }, 5000);
83
+ }, [
84
+ fetchScreenshot,
85
+ serverOnline
86
+ ]);
87
+ const stopPolling = useCallback(()=>{
88
+ if (pollingIntervalRef.current) {
89
+ console.log('Stopping screenshot polling');
90
+ clearInterval(pollingIntervalRef.current);
91
+ pollingIntervalRef.current = null;
92
+ }
93
+ }, []);
94
+ const pausePolling = useCallback(()=>{
95
+ console.log('Pausing screenshot polling');
96
+ isPollingPausedRef.current = true;
97
+ }, []);
98
+ const resumePolling = useCallback(()=>{
99
+ console.log('Resuming screenshot polling');
100
+ isPollingPausedRef.current = false;
101
+ }, []);
102
+ const handleManualRefresh = useCallback(()=>{
103
+ fetchScreenshot(true);
104
+ }, [
105
+ fetchScreenshot
106
+ ]);
107
+ useEffect(()=>{
108
+ if (!serverOnline) {
109
+ setScreenshot(null);
110
+ setError(null);
111
+ setInterfaceInfo(null);
112
+ stopPolling();
113
+ return;
114
+ }
115
+ fetchScreenshot(false);
116
+ fetchInterfaceInfo();
117
+ startPolling();
118
+ return ()=>{
119
+ stopPolling();
120
+ };
121
+ }, [
122
+ serverOnline,
123
+ startPolling,
124
+ stopPolling,
125
+ fetchScreenshot,
126
+ fetchInterfaceInfo
127
+ ]);
128
+ useEffect(()=>{
129
+ if (!serverOnline) return;
130
+ if (isUserOperating) pausePolling();
131
+ else {
132
+ resumePolling();
133
+ fetchScreenshot(false);
134
+ }
135
+ }, [
136
+ isUserOperating,
137
+ pausePolling,
138
+ resumePolling,
139
+ fetchScreenshot,
140
+ serverOnline
141
+ ]);
142
+ useEffect(()=>()=>{
143
+ stopPolling();
144
+ }, [
145
+ stopPolling
146
+ ]);
147
+ if (!serverOnline) return /*#__PURE__*/ jsx("div", {
148
+ className: "screenshot-viewer offline",
149
+ children: /*#__PURE__*/ jsxs("div", {
150
+ className: "screenshot-placeholder",
151
+ children: [
152
+ /*#__PURE__*/ jsx("h3", {
153
+ children: "\uD83D\uDCF1 Screen Preview"
154
+ }),
155
+ /*#__PURE__*/ jsx("p", {
156
+ children: "Start the playground server to see real-time screenshots"
157
+ })
158
+ ]
159
+ })
160
+ });
161
+ if (loading && !screenshot) return /*#__PURE__*/ jsxs("div", {
162
+ className: "screenshot-viewer loading",
163
+ children: [
164
+ /*#__PURE__*/ jsx(Spin, {
165
+ size: "large"
166
+ }),
167
+ /*#__PURE__*/ jsx("p", {
168
+ children: "Loading screenshot..."
169
+ })
170
+ ]
171
+ });
172
+ if (error && !screenshot) return /*#__PURE__*/ jsx("div", {
173
+ className: "screenshot-viewer error",
174
+ children: /*#__PURE__*/ jsxs("div", {
175
+ className: "screenshot-placeholder",
176
+ children: [
177
+ /*#__PURE__*/ jsx("h3", {
178
+ children: "\uD83D\uDCF1 Screen Preview"
179
+ }),
180
+ /*#__PURE__*/ jsx("p", {
181
+ className: "error-message",
182
+ children: error
183
+ })
184
+ ]
185
+ })
186
+ });
187
+ const formatLastUpdateTime = (timestamp)=>{
188
+ if (!timestamp) return '';
189
+ const now = Date.now();
190
+ const diff = Math.floor((now - timestamp) / 1000);
191
+ if (diff < 60) return `${diff}s ago`;
192
+ if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
193
+ return new Date(timestamp).toLocaleTimeString();
194
+ };
195
+ return /*#__PURE__*/ jsxs("div", {
196
+ className: "screenshot-viewer",
197
+ children: [
198
+ /*#__PURE__*/ jsx("div", {
199
+ className: "screenshot-header",
200
+ children: /*#__PURE__*/ jsx("div", {
201
+ className: "screenshot-title",
202
+ children: /*#__PURE__*/ jsx("h3", {
203
+ children: (null == interfaceInfo ? void 0 : interfaceInfo.type) ? interfaceInfo.type : 'Device Name'
204
+ })
205
+ })
206
+ }),
207
+ /*#__PURE__*/ jsxs("div", {
208
+ className: "screenshot-container",
209
+ children: [
210
+ /*#__PURE__*/ jsxs("div", {
211
+ className: "screenshot-overlay",
212
+ children: [
213
+ /*#__PURE__*/ jsxs("div", {
214
+ className: "device-name-overlay",
215
+ children: [
216
+ "Device Name",
217
+ /*#__PURE__*/ jsx(Tooltip, {
218
+ title: null == interfaceInfo ? void 0 : interfaceInfo.description,
219
+ children: /*#__PURE__*/ jsx(InfoCircleOutlined, {
220
+ size: 16,
221
+ className: "info-icon"
222
+ })
223
+ })
224
+ ]
225
+ }),
226
+ /*#__PURE__*/ jsxs("div", {
227
+ className: "screenshot-controls",
228
+ children: [
229
+ lastUpdateTime > 0 && /*#__PURE__*/ jsxs("span", {
230
+ className: "last-update-time",
231
+ children: [
232
+ "Last updated ",
233
+ formatLastUpdateTime(lastUpdateTime)
234
+ ]
235
+ }),
236
+ /*#__PURE__*/ jsx(Tooltip, {
237
+ title: "Refresh screenshot",
238
+ children: /*#__PURE__*/ jsx(Button, {
239
+ icon: /*#__PURE__*/ jsx(ReloadOutlined, {}),
240
+ onClick: handleManualRefresh,
241
+ loading: loading,
242
+ size: "small"
243
+ })
244
+ }),
245
+ isUserOperating && /*#__PURE__*/ jsxs("span", {
246
+ className: "operation-indicator",
247
+ children: [
248
+ /*#__PURE__*/ jsx(Spin, {
249
+ size: "small"
250
+ }),
251
+ " Operating..."
252
+ ]
253
+ })
254
+ ]
255
+ })
256
+ ]
257
+ }),
258
+ /*#__PURE__*/ jsx("div", {
259
+ className: "screenshot-content",
260
+ children: screenshot ? /*#__PURE__*/ jsx("img", {
261
+ src: screenshot.startsWith('data:image/') ? screenshot : `data:image/png;base64,${screenshot}`,
262
+ alt: "Device Screenshot",
263
+ className: "screenshot-image",
264
+ onLoad: ()=>console.log('Screenshot image loaded successfully'),
265
+ onError: (e)=>{
266
+ console.error('Screenshot image load error:', e);
267
+ console.error('Screenshot data preview:', screenshot.substring(0, 100));
268
+ setError('Failed to load screenshot image');
269
+ }
270
+ }) : /*#__PURE__*/ jsx("div", {
271
+ className: "screenshot-placeholder",
272
+ children: /*#__PURE__*/ jsx("p", {
273
+ children: "No screenshot available"
274
+ })
275
+ })
276
+ })
277
+ ]
278
+ })
279
+ ]
280
+ });
281
+ }
282
+ export { ScreenshotViewer as default };
@@ -15,8 +15,7 @@ const SWITCH_BUTTON_TEXT = {
15
15
  Server: 'Switch to In-Browser Mode',
16
16
  'In-Browser': 'Switch to Server Mode'
17
17
  };
18
- const ServiceModeControl = (param)=>{
19
- let { serviceMode } = param;
18
+ const ServiceModeControl = ({ serviceMode })=>{
20
19
  const { setServiceMode, config } = useEnvConfig();
21
20
  const serverValid = useServerValid('Server' === serviceMode);
22
21
  const renderServerTip = ()=>{
@@ -13,6 +13,23 @@
13
13
  overflow: hidden;
14
14
  }
15
15
 
16
+ .shiny-text.theme-blue {
17
+ background-image: linear-gradient(45deg, #2b83ff, #6a11cb, #2575fc, #4481eb);
18
+ }
19
+
20
+ .shiny-text.theme-purple {
21
+ background-image: linear-gradient(45deg, #667eea, #764ba2, #b06ab3, #9d50bb);
22
+ }
23
+
24
+ .shiny-text.theme-green {
25
+ background-image: linear-gradient(45deg, #11998e, #38ef7d, #2dd4bf, #10b981);
26
+ }
27
+
28
+ .shiny-text.theme-rainbow {
29
+ background-image: linear-gradient(45deg, #ff0080, #ff8c00, #40e0d0, #9d50bb, #ff0080);
30
+ background-size: 400%;
31
+ }
32
+
16
33
  .shiny-text:after {
17
34
  content: "";
18
35
  width: 120%;
@@ -28,9 +45,9 @@
28
45
  }
29
46
 
30
47
  .shiny-text.disabled {
31
- background: #2b83ff;
32
- -webkit-background-clip: text;
33
- background-clip: text;
48
+ color: #000;
49
+ background: none;
50
+ font-weight: normal;
34
51
  animation: none;
35
52
  }
36
53
 
@@ -39,6 +56,21 @@
39
56
  display: none;
40
57
  }
41
58
 
59
+ [data-theme="dark"] .shiny-text {
60
+ color: rgba(0, 0, 0, 0);
61
+ -webkit-text-fill-color: transparent;
62
+ text-shadow: none;
63
+ background-image: linear-gradient(45deg, #a78bfa, #c084fc, #e879f9, #c084fc);
64
+ background-size: 300%;
65
+ -webkit-background-clip: text;
66
+ background-clip: text;
67
+ animation: 8s infinite textGradient;
68
+ }
69
+
70
+ [data-theme="dark"] .shiny-text:after {
71
+ background: linear-gradient(90deg, rgba(197, 184, 255, 0) 0%, rgba(197, 184, 255, .05) 10%, rgba(197, 184, 255, .15) 50%, rgba(197, 184, 255, .05) 90%, rgba(197, 184, 255, 0) 100%);
72
+ }
73
+
42
74
  @keyframes shine {
43
75
  0% {
44
76
  opacity: .7;
@@ -1,12 +1,12 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import "./index.css";
3
- const ShinyText = (param)=>{
4
- let { text, disabled = false, speed = 5, className = '' } = param;
3
+ const ShinyText = ({ text, disabled = false, speed = 5, className = '', colorTheme = 'blue' })=>{
5
4
  const style = {
6
5
  '--animation-duration': `${speed}s`
7
6
  };
7
+ const themeClass = `theme-${colorTheme}`;
8
8
  return /*#__PURE__*/ jsx("div", {
9
- className: `shiny-text ${disabled ? 'disabled' : ''} ${className}`,
9
+ className: `shiny-text ${themeClass} ${disabled ? 'disabled' : ''} ${className}`,
10
10
  style: style,
11
11
  children: text
12
12
  });
@@ -160,7 +160,6 @@
160
160
  }
161
161
 
162
162
  .playground-container .progress-description {
163
- color: #000;
164
163
  padding: 8px 0;
165
164
  font-size: 14px;
166
165
  line-height: 22px;
@@ -339,3 +338,64 @@
339
338
  text-decoration: underline;
340
339
  }
341
340
 
341
+ [data-theme="dark"] .universal-playground .error-hint {
342
+ color: rgba(255, 255, 255, .45);
343
+ }
344
+
345
+ [data-theme="dark"] .universal-playground .status-indicator {
346
+ color: #f8fafd;
347
+ }
348
+
349
+ [data-theme="dark"] .universal-playground .status-indicator.error {
350
+ color: #ff4d4f;
351
+ }
352
+
353
+ [data-theme="dark"] .universal-playground .status-indicator.success {
354
+ color: #52c41a;
355
+ }
356
+
357
+ [data-theme="dark"] .universal-playground .operation-label {
358
+ color: #f8fafd;
359
+ }
360
+
361
+ [data-theme="dark"] .universal-playground .alert-message {
362
+ color: #f8fafd;
363
+ background-color: rgba(82, 38, 7, .3);
364
+ }
365
+
366
+ [data-theme="dark"] .universal-playground .operation-item .operation-icon-wrapper {
367
+ background-color: rgba(255, 255, 255, .08);
368
+ }
369
+
370
+ [data-theme="dark"] .universal-playground .operation-item .operation-content {
371
+ background-color: rgba(0, 0, 0, 0);
372
+ }
373
+
374
+ [data-theme="dark"] .universal-playground .operation-item .operation-content .operation-title {
375
+ color: rgba(255, 255, 255, .45);
376
+ }
377
+
378
+ [data-theme="dark"] .universal-playground .playground-footer {
379
+ background-color: rgba(255, 255, 255, .04);
380
+ }
381
+
382
+ [data-theme="dark"] .universal-playground .playground-footer .status-text {
383
+ color: #f8fafd;
384
+ }
385
+
386
+ [data-theme="dark"] .universal-playground .results-info {
387
+ color: rgba(255, 255, 255, .45);
388
+ }
389
+
390
+ [data-theme="dark"] .universal-playground .result-section .result-title, [data-theme="dark"] .universal-playground .result-section .result-details, [data-theme="dark"] .universal-playground .result-section .result-value {
391
+ color: #f8fafd;
392
+ }
393
+
394
+ [data-theme="dark"] .universal-playground .result-section .result-value.success {
395
+ color: #52c41a;
396
+ }
397
+
398
+ [data-theme="dark"] .universal-playground .result-section .result-value.error {
399
+ color: #ff4d4f;
400
+ }
401
+