@midscene/visualizer 0.30.9 → 0.30.11-beta-20251218071621.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
@@ -42,15 +42,38 @@ const external_antd_namespaceObject = require("antd");
42
42
  const external_react_namespaceObject = require("react");
43
43
  var external_react_default = /*#__PURE__*/ __webpack_require__.n(external_react_namespaceObject);
44
44
  const history_js_namespaceObject = require("../../store/history.js");
45
+ const store_js_namespaceObject = require("../../store/store.js");
45
46
  const external_types_js_namespaceObject = require("../../types.js");
46
47
  const constants_js_namespaceObject = require("../../utils/constants.js");
47
48
  const playground_utils_js_namespaceObject = require("../../utils/playground-utils.js");
48
49
  const index_js_namespaceObject = require("../config-selector/index.js");
49
50
  const external_form_field_index_js_namespaceObject = require("../form-field/index.js");
50
51
  const external_history_selector_index_js_namespaceObject = require("../history-selector/index.js");
52
+ function _define_property(obj, key, value) {
53
+ if (key in obj) Object.defineProperty(obj, key, {
54
+ value: value,
55
+ enumerable: true,
56
+ configurable: true,
57
+ writable: true
58
+ });
59
+ else obj[key] = value;
60
+ return obj;
61
+ }
62
+ function _object_spread(target) {
63
+ for(var i = 1; i < arguments.length; i++){
64
+ var source = null != arguments[i] ? arguments[i] : {};
65
+ var ownKeys = Object.keys(source);
66
+ if ("function" == typeof Object.getOwnPropertySymbols) ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
67
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
68
+ }));
69
+ ownKeys.forEach(function(key) {
70
+ _define_property(target, key, source[key]);
71
+ });
72
+ }
73
+ return target;
74
+ }
51
75
  const { TextArea } = external_antd_namespaceObject.Input;
52
- const PromptInput = (param)=>{
53
- let { runButtonEnabled, form, serviceMode, selectedType, dryMode, stoppable, loading, onRun, onStop, clearPromptAfterRun = true, actionSpace, hideDomAndScreenshotOptions = false } = param;
76
+ const PromptInput = ({ runButtonEnabled, form, serviceMode, selectedType, dryMode, stoppable, loading, onRun, onStop, clearPromptAfterRun = true, actionSpace, hideDomAndScreenshotOptions = false, deviceType })=>{
54
77
  const [hoveringSettings, setHoveringSettings] = (0, external_react_namespaceObject.useState)(false);
55
78
  const [promptValue, setPromptValue] = (0, external_react_namespaceObject.useState)('');
56
79
  const placeholder = (0, playground_utils_js_namespaceObject.getPlaceholderForType)(selectedType);
@@ -62,6 +85,8 @@ const PromptInput = (param)=>{
62
85
  const lastSelectedType = (0, history_js_namespaceObject.useHistoryStore)((state)=>state.lastSelectedType);
63
86
  const addHistory = (0, history_js_namespaceObject.useHistoryStore)((state)=>state.addHistory);
64
87
  const setLastSelectedType = (0, history_js_namespaceObject.useHistoryStore)((state)=>state.setLastSelectedType);
88
+ const planningStrategy = (0, store_js_namespaceObject.useEnvConfig)((state)=>state.planningStrategy);
89
+ const setPlanningStrategy = (0, store_js_namespaceObject.useEnvConfig)((state)=>state.setPlanningStrategy);
65
90
  const historyForSelectedType = (0, external_react_namespaceObject.useMemo)(()=>history[selectedType] || [], [
66
91
  history,
67
92
  selectedType
@@ -142,12 +167,14 @@ const PromptInput = (param)=>{
142
167
  const hasTracking = 'In-Browser-Extension' === serviceMode;
143
168
  const hasDeepThink = showDeepThinkOption;
144
169
  const hasDataExtraction = showDataExtractionOptions && !hideDomAndScreenshotOptions;
145
- return hasTracking || hasDeepThink || hasDataExtraction;
170
+ const hasDeviceOptions = 'android' === deviceType || 'ios' === deviceType;
171
+ return hasTracking || hasDeepThink || hasDataExtraction || hasDeviceOptions;
146
172
  }, [
147
173
  serviceMode,
148
174
  showDeepThinkOption,
149
175
  showDataExtractionOptions,
150
- hideDomAndScreenshotOptions
176
+ hideDomAndScreenshotOptions,
177
+ deviceType
151
178
  ]);
152
179
  const availableDropdownMethods = (0, external_react_namespaceObject.useMemo)(()=>{
153
180
  const metadataMethods = Object.keys(constants_js_namespaceObject.apiMetadata);
@@ -474,21 +501,11 @@ const PromptInput = (param)=>{
474
501
  marginBottom,
475
502
  placeholder
476
503
  };
477
- if (isLocateFieldFlag) fields.push(/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_form_field_index_js_namespaceObject.LocateField, {
478
- ...fieldProps
479
- }, key));
480
- else if ((null == (_actualField__def = actualField._def) ? void 0 : _actualField__def.typeName) === 'ZodEnum') fields.push(/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_form_field_index_js_namespaceObject.EnumField, {
481
- ...fieldProps
482
- }, key));
483
- else if ((null == (_actualField__def1 = actualField._def) ? void 0 : _actualField__def1.typeName) === 'ZodNumber') fields.push(/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_form_field_index_js_namespaceObject.NumberField, {
484
- ...fieldProps
485
- }, key));
486
- else if ((null == (_actualField__def2 = actualField._def) ? void 0 : _actualField__def2.typeName) === 'ZodBoolean') fields.push(/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_form_field_index_js_namespaceObject.BooleanField, {
487
- ...fieldProps
488
- }, key));
489
- else fields.push(/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_form_field_index_js_namespaceObject.TextField, {
490
- ...fieldProps
491
- }, key));
504
+ if (isLocateFieldFlag) fields.push(/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_form_field_index_js_namespaceObject.LocateField, _object_spread({}, fieldProps), key));
505
+ else if ((null == (_actualField__def = actualField._def) ? void 0 : _actualField__def.typeName) === 'ZodEnum') fields.push(/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_form_field_index_js_namespaceObject.EnumField, _object_spread({}, fieldProps), key));
506
+ else if ((null == (_actualField__def1 = actualField._def) ? void 0 : _actualField__def1.typeName) === 'ZodNumber') fields.push(/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_form_field_index_js_namespaceObject.NumberField, _object_spread({}, fieldProps), key));
507
+ else if ((null == (_actualField__def2 = actualField._def) ? void 0 : _actualField__def2.typeName) === 'ZodBoolean') fields.push(/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_form_field_index_js_namespaceObject.BooleanField, _object_spread({}, fieldProps), key));
508
+ else fields.push(/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_form_field_index_js_namespaceObject.TextField, _object_spread({}, fieldProps), key));
492
509
  });
493
510
  if ('aiScroll' === selectedType) {
494
511
  const directionField = fields.find((field)=>/*#__PURE__*/ external_react_default().isValidElement(field) && 'direction' === field.props.name);
@@ -544,7 +561,7 @@ const PromptInput = (param)=>{
544
561
  loading: loading,
545
562
  children: text
546
563
  });
547
- if (dryMode) return 'aiAction' === selectedType ? /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_antd_namespaceObject.Tooltip, {
564
+ if (dryMode) return 'aiAct' === selectedType ? /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_antd_namespaceObject.Tooltip, {
548
565
  title: "Start executing until some interaction actions need to be performed. You can see the process of planning and locating.",
549
566
  children: runButton('Dry Run')
550
567
  }) : runButton('Run');
@@ -684,6 +701,7 @@ const PromptInput = (param)=>{
684
701
  'click'
685
702
  ],
686
703
  disabled: !runButtonEnabled,
704
+ overlayClassName: "more-apis-dropdown",
687
705
  children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(external_antd_namespaceObject.Button, {
688
706
  className: `more-apis-button ${!constants_js_namespaceObject.defaultMainButtons.includes(selectedType) ? 'selected-from-dropdown' : ''}`,
689
707
  children: [
@@ -710,7 +728,8 @@ const PromptInput = (param)=>{
710
728
  enableTracking: 'In-Browser-Extension' === serviceMode,
711
729
  showDeepThinkOption: showDeepThinkOption,
712
730
  showDataExtractionOptions: showDataExtractionOptions,
713
- hideDomAndScreenshotOptions: hideDomAndScreenshotOptions
731
+ hideDomAndScreenshotOptions: hideDomAndScreenshotOptions,
732
+ deviceType: deviceType
714
733
  })
715
734
  }),
716
735
  /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_history_selector_index_js_namespaceObject.HistorySelector, {
@@ -756,9 +775,48 @@ const PromptInput = (param)=>{
756
775
  (0, playground_utils_js_namespaceObject.actionNameForType)(selectedType)
757
776
  ]
758
777
  }),
759
- /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", {
760
- className: "form-controller-wrapper",
761
- children: renderActionButton()
778
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("div", {
779
+ className: `form-controller-wrapper ${'aiAct' === selectedType ? 'with-strategy' : ''}`,
780
+ children: [
781
+ 'aiAct' === selectedType && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_antd_namespaceObject.Dropdown, {
782
+ menu: {
783
+ items: [
784
+ {
785
+ key: 'standard',
786
+ label: 'Standard',
787
+ onClick: ()=>setPlanningStrategy('standard')
788
+ },
789
+ {
790
+ key: 'fast',
791
+ label: 'Fast',
792
+ onClick: ()=>setPlanningStrategy('fast')
793
+ }
794
+ ],
795
+ selectedKeys: [
796
+ planningStrategy
797
+ ]
798
+ },
799
+ trigger: [
800
+ 'click'
801
+ ],
802
+ children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("a", {
803
+ onClick: (e)=>e.preventDefault(),
804
+ className: "planning-strategy-selector",
805
+ children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(external_antd_namespaceObject.Space, {
806
+ size: 4,
807
+ children: [
808
+ 'fast' === planningStrategy ? 'Fast' : 'Standard',
809
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(icons_namespaceObject.DownOutlined, {
810
+ style: {
811
+ fontSize: 10
812
+ }
813
+ })
814
+ ]
815
+ })
816
+ })
817
+ }),
818
+ renderActionButton()
819
+ ]
762
820
  })
763
821
  ]
764
822
  })
@@ -766,9 +824,9 @@ const PromptInput = (param)=>{
766
824
  });
767
825
  };
768
826
  exports.PromptInput = __webpack_exports__.PromptInput;
769
- for(var __webpack_i__ in __webpack_exports__)if (-1 === [
827
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
770
828
  "PromptInput"
771
- ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
829
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
772
830
  Object.defineProperty(exports, '__esModule', {
773
831
  value: true
774
832
  });
@@ -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
+