@midscene/visualizer 0.20.2-beta-20250704092743.0 → 0.21.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 (37) hide show
  1. package/dist/es/assets/close.909351c0.svg +4 -0
  2. package/dist/es/assets/history.164a4eab.svg +4 -0
  3. package/dist/es/assets/magnifying-glass.9498e70e.svg +12 -0
  4. package/dist/es/assets/setting.80ab7285.svg +11 -0
  5. package/dist/es/component/env-config.js +27 -9
  6. package/dist/es/component/player.css +35 -6
  7. package/dist/es/component/player.js +16 -1
  8. package/dist/es/component/playground/ConfigSelector.js +4 -21
  9. package/dist/es/component/playground/HistorySelector.js +152 -24
  10. package/dist/es/component/playground/PlaygroundResult.js +6 -4
  11. package/dist/es/component/playground/PromptInput.js +46 -29
  12. package/dist/es/component/playground/ServiceModeControl.js +1 -0
  13. package/dist/es/component/playground/index.css +199 -142
  14. package/dist/es/component/playground/playground-constants.js +2 -1
  15. package/dist/es/component/store/store.js +5 -0
  16. package/dist/index.css +234 -148
  17. package/dist/index.js +1 -1
  18. package/dist/lib/assets/close.909351c0.svg +4 -0
  19. package/dist/lib/assets/history.164a4eab.svg +4 -0
  20. package/dist/lib/assets/magnifying-glass.9498e70e.svg +12 -0
  21. package/dist/lib/assets/setting.80ab7285.svg +11 -0
  22. package/dist/lib/component/env-config.js +26 -8
  23. package/dist/lib/component/player.css +35 -6
  24. package/dist/lib/component/player.js +16 -1
  25. package/dist/lib/component/playground/ConfigSelector.js +2 -19
  26. package/dist/lib/component/playground/HistorySelector.js +150 -22
  27. package/dist/lib/component/playground/PlaygroundResult.js +6 -4
  28. package/dist/lib/component/playground/PromptInput.js +46 -29
  29. package/dist/lib/component/playground/ServiceModeControl.js +1 -0
  30. package/dist/lib/component/playground/index.css +199 -142
  31. package/dist/lib/component/playground/playground-constants.js +2 -1
  32. package/dist/lib/component/store/store.js +5 -0
  33. package/dist/types/component/env-config.d.ts +3 -1
  34. package/dist/types/component/player.d.ts +1 -0
  35. package/dist/types/component/playground/PlaygroundResult.d.ts +1 -0
  36. package/dist/types/component/store/store.d.ts +1 -0
  37. package/package.json +5 -5
@@ -0,0 +1,4 @@
1
+ <svg width="18" height="16" viewBox="0 0 18 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M3.12354 2.66667L14.2863 13.3333" stroke="#333333" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
3
+ <path d="M3.12354 13.3333L14.2863 2.66667" stroke="#333333" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M6.63002 9.02131C3.76823 15.1469 8.82714 19.522 12.6931 19.522C16.5591 19.522 19.6931 16.388 19.6931 12.522C19.6931 8.65598 16.5591 5.52197 12.6931 5.52197C10.1024 5.52197 7.84043 6.92936 6.63002 9.02131Z" stroke="black" stroke-opacity="0.85" stroke-width="1.33" stroke-linecap="round" stroke-linejoin="round"/>
3
+ <path d="M12.6948 8.32198L12.6943 12.5251L15.6621 15.4928" stroke="black" stroke-opacity="0.85" stroke-width="1.33" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
@@ -0,0 +1,12 @@
1
+ <svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g clip-path="url(#clip0_541_8555)">
3
+ <path d="M8.39697 14.2909C11.9178 14.2909 14.772 11.4367 14.772 7.91589C14.772 4.39509 11.9178 1.54089 8.39697 1.54089C4.87617 1.54089 2.02197 4.39509 2.02197 7.91589C2.02197 11.4367 4.87617 14.2909 8.39697 14.2909Z" stroke="black" stroke-opacity="0.65" stroke-width="1.5" stroke-linejoin="round"/>
4
+ <path d="M10.5185 5.41956C9.97563 4.87667 9.22563 4.54089 8.39718 4.54089C7.56877 4.54089 6.81877 4.87667 6.27588 5.41956" stroke="black" stroke-opacity="0.65" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
5
+ <path d="M12.98 12.499L16.162 15.681" stroke="black" stroke-opacity="0.65" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
6
+ </g>
7
+ <defs>
8
+ <clipPath id="clip0_541_8555">
9
+ <rect width="18" height="18" fill="white" transform="translate(0.521973 0.0408936)"/>
10
+ </clipPath>
11
+ </defs>
12
+ </svg>
@@ -0,0 +1,11 @@
1
+ <svg width="27" height="27" viewBox="0 0 27 27" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M19.5269 8.85531H17.5269" stroke="black" stroke-opacity="0.85" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
3
+ <path d="M14.8599 7.52197V10.1886" stroke="black" stroke-opacity="0.85" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path d="M14.8602 8.85531H7.52686" stroke="black" stroke-opacity="0.85" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
5
+ <path d="M10.1935 13.522H7.52686" stroke="black" stroke-opacity="0.85" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
6
+ <path d="M12.8599 12.1886V14.8553" stroke="black" stroke-opacity="0.85" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
7
+ <path d="M20.1932 13.522H12.8599" stroke="black" stroke-opacity="0.85" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
8
+ <path d="M19.5269 18.1886H17.5269" stroke="black" stroke-opacity="0.85" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
9
+ <path d="M14.8599 16.8553V19.522" stroke="black" stroke-opacity="0.85" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
10
+ <path d="M14.8602 18.1886H7.52686" stroke="black" stroke-opacity="0.85" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
11
+ </svg>
@@ -7,20 +7,24 @@ var buffer = {
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
8
  import { SettingOutlined } from "@ant-design/icons";
9
9
  import { Input, Modal, Tooltip } from "antd";
10
- import { useRef, useState } from "react";
10
+ import { useEffect, useRef, useState } from "react";
11
11
  import { useEnvConfig } from "./store/store";
12
12
  function EnvConfig({
13
13
  showTooltipWhenEmpty = true,
14
- tooltipPlacement = "bottom"
14
+ showModelName = true,
15
+ tooltipPlacement = "bottom",
16
+ mode = "icon"
15
17
  }) {
16
- const { config, configString, loadConfig } = useEnvConfig();
18
+ const { config, configString, loadConfig, syncFromStorage } = useEnvConfig();
17
19
  const [isModalOpen, setIsModalOpen] = useState(false);
18
20
  const [tempConfigString, setTempConfigString] = useState(configString);
19
21
  const midsceneModelName = config.MIDSCENE_MODEL_NAME;
20
22
  const componentRef = useRef(null);
21
23
  const showModal = (e) => {
24
+ syncFromStorage();
22
25
  setIsModalOpen(true);
23
26
  e.preventDefault();
27
+ e.stopPropagation();
24
28
  };
25
29
  const handleOk = () => {
26
30
  setIsModalOpen(false);
@@ -29,6 +33,11 @@ function EnvConfig({
29
33
  const handleCancel = () => {
30
34
  setIsModalOpen(false);
31
35
  };
36
+ useEffect(() => {
37
+ if (isModalOpen) {
38
+ setTempConfigString(configString);
39
+ }
40
+ }, [isModalOpen, configString]);
32
41
  return /* @__PURE__ */ jsxs(
33
42
  "div",
34
43
  {
@@ -37,13 +46,12 @@ function EnvConfig({
37
46
  justifyContent: "flex-end",
38
47
  gap: "10px",
39
48
  alignItems: "center",
40
- width: "100%",
41
49
  height: "100%",
42
50
  minHeight: "32px"
43
51
  },
44
52
  ref: componentRef,
45
53
  children: [
46
- midsceneModelName,
54
+ showModelName ? midsceneModelName : null,
47
55
  /* @__PURE__ */ jsx(
48
56
  Tooltip,
49
57
  {
@@ -52,10 +60,17 @@ function EnvConfig({
52
60
  align: { offset: [-10, 5] },
53
61
  open: (
54
62
  // undefined for default behavior of tooltip, hover for show
55
- showTooltipWhenEmpty ? Object.keys(config).length === 0 : void 0
63
+ // close tooltip when modal is open
64
+ isModalOpen ? false : showTooltipWhenEmpty ? Object.keys(config).length === 0 : void 0
56
65
  ),
57
- getPopupContainer: () => componentRef.current,
58
- children: /* @__PURE__ */ jsx(SettingOutlined, { onClick: showModal })
66
+ children: mode === "icon" ? /* @__PURE__ */ jsx(SettingOutlined, { onClick: showModal }) : /* @__PURE__ */ jsx(
67
+ "span",
68
+ {
69
+ onClick: showModal,
70
+ style: { color: "#006AFF", cursor: "pointer" },
71
+ children: "set up"
72
+ }
73
+ )
59
74
  }
60
75
  ),
61
76
  /* @__PURE__ */ jsxs(
@@ -66,7 +81,10 @@ function EnvConfig({
66
81
  onOk: handleOk,
67
82
  onCancel: handleCancel,
68
83
  okText: "Save",
69
- style: { width: "800px" },
84
+ style: { width: "800px", height: "100%", marginTop: "10%" },
85
+ destroyOnClose: true,
86
+ maskClosable: true,
87
+ centered: true,
70
88
  children: [
71
89
  /* @__PURE__ */ jsx(
72
90
  Input.TextArea,
@@ -3,10 +3,10 @@
3
3
  height: 100%;
4
4
  max-width: 100%;
5
5
  max-height: 100%;
6
- padding: 8px;
7
- background: #fff;
6
+ padding: 12px;
7
+ background: #F5F5F5;
8
8
  box-sizing: border-box;
9
- border: 1px solid #0000000F;
9
+ border: 1px solid #F5F5F5;
10
10
  border-radius: 8px;
11
11
  line-height: 100%;
12
12
  margin: 0 auto;
@@ -16,26 +16,55 @@
16
16
  min-height: 300px;
17
17
  position: relative;
18
18
  }
19
+ .player-container[data-fit-mode=height] {
20
+ background: #fff;
21
+ }
22
+ .player-container[data-fit-mode=height] .canvas-container {
23
+ background-color: #F5F5F5;
24
+ }
19
25
  .player-container .canvas-container {
20
- flex: 1 1;
26
+ flex: 0 0 auto;
21
27
  min-height: 200px;
28
+ width: 100%;
22
29
  display: flex;
23
30
  justify-content: center;
24
31
  align-items: center;
25
32
  overflow: hidden;
26
- padding: 8px;
27
33
  margin-bottom: 12px;
28
34
  position: relative;
29
- background-color: #F5F5F5;
35
+ background-color: #fff;
30
36
  border-radius: inherit;
37
+ aspect-ratio: var(--canvas-aspect-ratio, 16/9);
31
38
  }
32
39
  .player-container .canvas-container canvas {
40
+ width: 100%;
41
+ height: auto;
33
42
  max-width: 100%;
34
43
  max-height: 100%;
35
44
  box-sizing: border-box;
36
45
  display: block;
37
46
  margin: 0 auto;
38
47
  object-fit: contain;
48
+ border: none;
49
+ }
50
+ .player-container .canvas-container[data-fit-mode=height] {
51
+ flex: 1 1 auto;
52
+ aspect-ratio: unset;
53
+ min-height: 0;
54
+ height: auto;
55
+ }
56
+ .player-container .canvas-container[data-fit-mode=height] canvas {
57
+ height: 100%;
58
+ width: auto;
59
+ max-width: 100%;
60
+ max-height: 100%;
61
+ }
62
+ .player-container .canvas-container[data-fit-mode=width] {
63
+ aspect-ratio: var(--canvas-aspect-ratio, 16/9);
64
+ }
65
+ .player-container .canvas-container[data-fit-mode=width] canvas {
66
+ width: 100%;
67
+ height: auto;
39
68
  }
40
69
  .player-container .player-timeline-wrapper {
41
70
  width: 100%;
@@ -176,6 +176,7 @@ function Player(props) {
176
176
  const scripts = props == null ? void 0 : props.replayScripts;
177
177
  const imageWidth = (props == null ? void 0 : props.imageWidth) || 1920;
178
178
  const imageHeight = (props == null ? void 0 : props.imageHeight) || 1080;
179
+ const fitMode = (props == null ? void 0 : props.fitMode) || "height";
179
180
  const currentImg = useRef(((_a = scripts == null ? void 0 : scripts[0]) == null ? void 0 : _a.img) || null);
180
181
  const divContainerRef = useRef(null);
181
182
  const app = useMemo(() => new PIXI.Application(), []);
@@ -629,6 +630,20 @@ function Player(props) {
629
630
  Promise.resolve(
630
631
  (() => __async(this, null, function* () {
631
632
  yield init();
633
+ if (divContainerRef.current && imageWidth && imageHeight) {
634
+ const aspectRatio = imageWidth / imageHeight;
635
+ divContainerRef.current.style.setProperty(
636
+ "--canvas-aspect-ratio",
637
+ aspectRatio.toString()
638
+ );
639
+ divContainerRef.current.setAttribute("data-fit-mode", fitMode);
640
+ const playerContainer = divContainerRef.current.closest(
641
+ ".player-container"
642
+ );
643
+ if (playerContainer) {
644
+ playerContainer.setAttribute("data-fit-mode", fitMode);
645
+ }
646
+ }
632
647
  triggerReplay();
633
648
  }))()
634
649
  );
@@ -639,7 +654,7 @@ function Player(props) {
639
654
  console.warn("destroy failed", e);
640
655
  }
641
656
  };
642
- }, []);
657
+ }, [imageWidth, imageHeight, fitMode]);
643
658
  useEffect(() => {
644
659
  if (replayMark) {
645
660
  return play();
@@ -4,9 +4,9 @@ import console from "console-browserify";
4
4
  var buffer = {
5
5
  Buffer
6
6
  };
7
- import { jsx, jsxs } from "react/jsx-runtime";
8
- import { AimOutlined } from "@ant-design/icons";
9
- import { Checkbox, Dropdown, Space } from "antd";
7
+ import { jsx } from "react/jsx-runtime";
8
+ import { Checkbox, Dropdown } from "antd";
9
+ import SettingOutlined from "../../assets/setting.80ab7285.svg";
10
10
  import { useEnvConfig } from "../store/store";
11
11
  import { deepThinkTip, trackingTip } from "./playground-constants";
12
12
  const ConfigSelector = ({
@@ -25,10 +25,7 @@ const ConfigSelector = ({
25
25
  return null;
26
26
  }
27
27
  const configItems = buildConfigItems();
28
- return /* @__PURE__ */ jsx("div", { className: "config-selector", children: /* @__PURE__ */ jsx(Dropdown, { menu: { items: configItems }, children: /* @__PURE__ */ jsxs(Space, { children: [
29
- /* @__PURE__ */ jsx(AimOutlined, {}),
30
- renderSettingsDisplay()
31
- ] }) }) });
28
+ return /* @__PURE__ */ jsx("div", { className: "selector-trigger", children: /* @__PURE__ */ jsx(Dropdown, { menu: { items: configItems }, trigger: ["click"], children: /* @__PURE__ */ jsx(SettingOutlined, { width: 24, height: 24 }) }) });
32
29
  function buildConfigItems() {
33
30
  const items = [];
34
31
  if (enableTracking) {
@@ -61,20 +58,6 @@ const ConfigSelector = ({
61
58
  }
62
59
  return items;
63
60
  }
64
- function renderSettingsDisplay() {
65
- const displayParts = [];
66
- if (enableTracking) {
67
- const trackingText = forceSameTabNavigation ? trackingTip : "don't track popup";
68
- displayParts.push(trackingText);
69
- }
70
- if (showDeepThinkOption && deepThink) {
71
- displayParts.push(deepThinkTip);
72
- }
73
- if (displayParts.length === 2) {
74
- displayParts.splice(1, 0, "/");
75
- }
76
- return displayParts.join(" ");
77
- }
78
61
  };
79
62
  export {
80
63
  ConfigSelector
@@ -4,36 +4,164 @@ import console from "console-browserify";
4
4
  var buffer = {
5
5
  Buffer
6
6
  };
7
- import { jsx, jsxs } from "react/jsx-runtime";
8
- import { HistoryOutlined } from "@ant-design/icons";
9
- import { Dropdown, Space } from "antd";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ import { Button, Input, Modal, Typography } from "antd";
9
+ import { useMemo, useState } from "react";
10
+ import CloseOutlined from "../../assets/close.909351c0.svg";
11
+ import HistoryOutlined from "../../assets/history.164a4eab.svg";
12
+ import MagnifyingGlass from "../../assets/magnifying-glass.9498e70e.svg";
10
13
  import { useHistoryStore } from "../store/history";
11
- import { actionNameForType } from "./playground-utils";
14
+ const { Text } = Typography;
12
15
  const HistorySelector = ({
13
16
  onSelect
14
17
  }) => {
18
+ const [isModalOpen, setIsModalOpen] = useState(false);
19
+ const [searchText, setSearchText] = useState("");
15
20
  const history = useHistoryStore((state) => state.history);
16
21
  const clearHistory = useHistoryStore((state) => state.clearHistory);
17
- const items = history.map((item, index) => ({
18
- label: /* @__PURE__ */ jsxs("a", { onClick: () => onSelect(item), children: [
19
- actionNameForType(item.type),
20
- " - ",
21
- item.prompt.slice(0, 50),
22
- item.prompt.length > 50 ? "..." : ""
23
- ] }),
24
- key: String(index)
25
- }));
26
- if (history.length === 0) {
27
- return null;
28
- }
29
- items.push({
30
- type: "divider"
31
- });
32
- items.push({
33
- label: /* @__PURE__ */ jsx("a", { onClick: () => clearHistory(), children: /* @__PURE__ */ jsx(Space, { children: "Clear History" }) }),
34
- key: "clear"
35
- });
36
- return /* @__PURE__ */ jsx("div", { className: "history-selector", children: /* @__PURE__ */ jsx(Dropdown, { menu: { items }, children: /* @__PURE__ */ jsx(Space, { children: /* @__PURE__ */ jsx(HistoryOutlined, { style: { fontSize: 14 } }) }) }) });
22
+ const groupedHistory = useMemo(() => {
23
+ const now = Date.now();
24
+ const sevenDaysAgo = now - 7 * 24 * 60 * 60 * 1e3;
25
+ const oneYearAgo = now - 365 * 24 * 60 * 60 * 1e3;
26
+ const filteredHistory = history.filter(
27
+ (item) => item.prompt.toLowerCase().includes(searchText.toLowerCase())
28
+ );
29
+ const groups = {
30
+ recent7Days: filteredHistory.filter(
31
+ (item) => item.timestamp >= sevenDaysAgo
32
+ ),
33
+ recent1Year: filteredHistory.filter(
34
+ (item) => item.timestamp < sevenDaysAgo && item.timestamp >= oneYearAgo
35
+ ),
36
+ older: filteredHistory.filter((item) => item.timestamp < oneYearAgo)
37
+ };
38
+ return groups;
39
+ }, [history, searchText]);
40
+ const handleHistoryClick = (item) => {
41
+ onSelect(item);
42
+ setIsModalOpen(false);
43
+ };
44
+ const handleClearHistory = () => {
45
+ clearHistory();
46
+ setSearchText("");
47
+ setIsModalOpen(false);
48
+ };
49
+ const renderHistoryGroup = (title, items) => {
50
+ if (items.length === 0)
51
+ return null;
52
+ return /* @__PURE__ */ jsxs("div", { className: "history-group", children: [
53
+ /* @__PURE__ */ jsx("div", { className: "history-group-title", children: title }),
54
+ items.map((item, index) => /* @__PURE__ */ jsx(
55
+ "div",
56
+ {
57
+ className: "history-item",
58
+ onClick: () => handleHistoryClick(item),
59
+ children: item.prompt
60
+ },
61
+ `${item.timestamp}-${index}`
62
+ ))
63
+ ] }, title);
64
+ };
65
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
66
+ /* @__PURE__ */ jsx("div", { className: "selector-trigger", onClick: () => setIsModalOpen(true), children: /* @__PURE__ */ jsx(HistoryOutlined, { width: 24, height: 24 }) }),
67
+ /* @__PURE__ */ jsx(
68
+ Modal,
69
+ {
70
+ open: isModalOpen,
71
+ onCancel: () => setIsModalOpen(false),
72
+ footer: null,
73
+ width: "100%",
74
+ closable: false,
75
+ centered: false,
76
+ transitionName: "",
77
+ maskTransitionName: "",
78
+ style: {
79
+ margin: 0,
80
+ padding: 0,
81
+ maxWidth: "none",
82
+ top: "auto",
83
+ bottom: 0
84
+ },
85
+ styles: {
86
+ wrapper: {
87
+ alignItems: "flex-end",
88
+ justifyContent: "center",
89
+ paddingBottom: 0,
90
+ display: "flex"
91
+ },
92
+ body: {
93
+ height: "70vh",
94
+ padding: 0,
95
+ margin: 0
96
+ },
97
+ content: {
98
+ height: "70vh",
99
+ borderRadius: "12px 12px 0 0",
100
+ margin: 0,
101
+ padding: 0,
102
+ marginBottom: 0,
103
+ position: "fixed",
104
+ bottom: 0,
105
+ left: 0,
106
+ right: 0
107
+ }
108
+ },
109
+ maskClosable: true,
110
+ destroyOnClose: true,
111
+ children: /* @__PURE__ */ jsxs("div", { className: "history-modal-container", children: [
112
+ /* @__PURE__ */ jsxs("div", { className: "history-modal-header", children: [
113
+ /* @__PURE__ */ jsxs(Text, { strong: true, style: { fontSize: "16px" }, children: [
114
+ "History (",
115
+ history.length,
116
+ ")"
117
+ ] }),
118
+ /* @__PURE__ */ jsx(
119
+ Button,
120
+ {
121
+ size: "small",
122
+ type: "text",
123
+ icon: /* @__PURE__ */ jsx(CloseOutlined, { width: 16, height: 16 }),
124
+ onClick: () => setIsModalOpen(false),
125
+ className: "close-button"
126
+ }
127
+ )
128
+ ] }),
129
+ /* @__PURE__ */ jsx("div", { className: "history-search-section", children: /* @__PURE__ */ jsxs("div", { className: "search-input-wrapper", children: [
130
+ /* @__PURE__ */ jsx(
131
+ Input,
132
+ {
133
+ placeholder: "Search",
134
+ value: searchText,
135
+ onChange: (e) => setSearchText(e.target.value),
136
+ prefix: /* @__PURE__ */ jsx(MagnifyingGlass, { width: 18, height: 18 }),
137
+ className: "search-input",
138
+ allowClear: true
139
+ }
140
+ ),
141
+ /* @__PURE__ */ jsx(
142
+ Button,
143
+ {
144
+ type: "link",
145
+ onClick: handleClearHistory,
146
+ className: "clear-button",
147
+ disabled: history.length === 0,
148
+ children: "Clear"
149
+ }
150
+ )
151
+ ] }) }),
152
+ /* @__PURE__ */ jsx("div", { className: "history-content", children: history.length === 0 ? (
153
+ /* no history record */
154
+ /* @__PURE__ */ jsx("div", { className: "no-results", children: /* @__PURE__ */ jsx(Text, { type: "secondary", children: "No history record" }) })
155
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
156
+ renderHistoryGroup("Last 7 days", groupedHistory.recent7Days),
157
+ renderHistoryGroup("Last 1 year", groupedHistory.recent1Year),
158
+ renderHistoryGroup("Earlier", groupedHistory.older),
159
+ searchText && groupedHistory.recent7Days.length === 0 && groupedHistory.recent1Year.length === 0 && groupedHistory.older.length === 0 && /* @__PURE__ */ jsx("div", { className: "no-results", children: /* @__PURE__ */ jsx(Text, { type: "secondary", children: "No matching history record" }) })
160
+ ] }) })
161
+ ] })
162
+ }
163
+ )
164
+ ] });
37
165
  };
38
166
  export {
39
167
  HistorySelector
@@ -19,7 +19,8 @@ const PlaygroundResultView = ({
19
19
  replayCounter,
20
20
  loadingProgressText,
21
21
  verticalMode = false,
22
- notReadyMessage
22
+ notReadyMessage,
23
+ fitMode
23
24
  }) => {
24
25
  let resultWrapperClassName = "result-wrapper";
25
26
  if (verticalMode) {
@@ -43,14 +44,15 @@ const PlaygroundResultView = ({
43
44
  replayScripts: replayScriptsInfo.scripts,
44
45
  imageWidth: replayScriptsInfo.width,
45
46
  imageHeight: replayScriptsInfo.height,
46
- reportFileContent: (serviceMode === "In-Browser-Extension" || serviceMode === "Server") && (result == null ? void 0 : result.reportHTML) ? result == null ? void 0 : result.reportHTML : null
47
+ reportFileContent: (serviceMode === "In-Browser-Extension" || serviceMode === "Server") && (result == null ? void 0 : result.reportHTML) ? result == null ? void 0 : result.reportHTML : null,
48
+ fitMode
47
49
  },
48
50
  replayCounter
49
51
  );
50
- } else if (result == null ? void 0 : result.result) {
51
- resultDataToShow = typeof (result == null ? void 0 : result.result) === "string" ? /* @__PURE__ */ jsx("pre", { children: result == null ? void 0 : result.result }) : /* @__PURE__ */ jsx("pre", { children: JSON.stringify(result == null ? void 0 : result.result, null, 2) });
52
52
  } else if (result == null ? void 0 : result.error) {
53
53
  resultDataToShow = /* @__PURE__ */ jsx("pre", { children: result == null ? void 0 : result.error });
54
+ } else if ((result == null ? void 0 : result.result) !== void 0) {
55
+ resultDataToShow = typeof (result == null ? void 0 : result.result) === "string" ? /* @__PURE__ */ jsx("pre", { children: result == null ? void 0 : result.result }) : /* @__PURE__ */ jsx("pre", { children: JSON.stringify(result == null ? void 0 : result.result, null, 2) });
54
56
  }
55
57
  return /* @__PURE__ */ jsx(
56
58
  "div",
@@ -25,6 +25,7 @@ const PromptInput = ({
25
25
  onStop
26
26
  }) => {
27
27
  const [hoveringSettings, setHoveringSettings] = useState(false);
28
+ const [promptValue, setPromptValue] = useState("");
28
29
  const placeholder = getPlaceholderForType(selectedType);
29
30
  const textAreaRef = useRef(null);
30
31
  const history = useHistoryStore((state) => state.history);
@@ -36,22 +37,34 @@ const PromptInput = ({
36
37
  type: lastHistory.type || "aiAction",
37
38
  prompt: lastHistory.prompt || ""
38
39
  });
40
+ setPromptValue(lastHistory.prompt || "");
39
41
  } else {
40
42
  form.setFieldsValue({
41
43
  type: "aiAction",
42
44
  prompt: ""
43
45
  });
46
+ setPromptValue("");
44
47
  }
45
- }, [lastHistory, form]);
48
+ }, []);
46
49
  const handleSelectHistory = useCallback(
47
50
  (historyItem) => {
48
51
  form.setFieldsValue({
49
52
  prompt: historyItem.prompt,
50
53
  type: historyItem.type
51
54
  });
55
+ setPromptValue(historyItem.prompt);
56
+ },
57
+ [form]
58
+ );
59
+ const handlePromptChange = useCallback(
60
+ (e) => {
61
+ const value = e.target.value;
62
+ setPromptValue(value);
63
+ form.setFieldValue("prompt", value);
52
64
  },
53
65
  [form]
54
66
  );
67
+ const isRunButtonEnabled = runButtonEnabled && promptValue.trim().length > 0;
55
68
  const handleRunWithHistory = useCallback(() => {
56
69
  const values = form.getFieldsValue();
57
70
  if (values.prompt) {
@@ -62,10 +75,12 @@ const PromptInput = ({
62
75
  });
63
76
  }
64
77
  onRun();
78
+ setPromptValue("");
79
+ form.setFieldValue("prompt", "");
65
80
  }, [form, addHistory, onRun]);
66
81
  const handleKeyDown = useCallback(
67
82
  (e) => {
68
- if (e.key === "Enter" && e.metaKey) {
83
+ if (e.key === "Enter" && e.metaKey && isRunButtonEnabled) {
69
84
  handleRunWithHistory();
70
85
  e.preventDefault();
71
86
  e.stopPropagation();
@@ -84,7 +99,7 @@ const PromptInput = ({
84
99
  }, 0);
85
100
  }
86
101
  },
87
- [handleRunWithHistory]
102
+ [handleRunWithHistory, isRunButtonEnabled]
88
103
  );
89
104
  const handleMouseEnter = useCallback(() => {
90
105
  setHoveringSettings(true);
@@ -98,9 +113,9 @@ const PromptInput = ({
98
113
  {
99
114
  type: "primary",
100
115
  icon: /* @__PURE__ */ jsx(SendOutlined, {}),
101
- style: { borderRadius: 20 },
116
+ style: { borderRadius: 20, zIndex: 999 },
102
117
  onClick: handleRunWithHistory,
103
- disabled: !runButtonEnabled,
118
+ disabled: !isRunButtonEnabled,
104
119
  loading,
105
120
  children: text
106
121
  }
@@ -114,7 +129,7 @@ const PromptInput = ({
114
129
  {
115
130
  icon: /* @__PURE__ */ jsx(BorderOutlined, {}),
116
131
  onClick: onStop,
117
- style: { borderRadius: 20 },
132
+ style: { borderRadius: 20, zIndex: 999 },
118
133
  children: "Stop"
119
134
  }
120
135
  );
@@ -125,11 +140,11 @@ const PromptInput = ({
125
140
  loading,
126
141
  handleRunWithHistory,
127
142
  onStop,
128
- runButtonEnabled,
143
+ isRunButtonEnabled,
129
144
  selectedType,
130
145
  stoppable
131
146
  ]);
132
- return /* @__PURE__ */ jsxs("div", { className: "form-part input-wrapper", children: [
147
+ return /* @__PURE__ */ jsxs("div", { className: "prompt-input-wrapper", children: [
133
148
  /* @__PURE__ */ jsxs(Space, { className: "mode-radio-group-wrapper", children: [
134
149
  /* @__PURE__ */ jsx(Form.Item, { name: "type", style: { margin: 0 }, children: /* @__PURE__ */ jsxs(
135
150
  Radio.Group,
@@ -145,43 +160,45 @@ const PromptInput = ({
145
160
  ]
146
161
  }
147
162
  ) }),
148
- /* @__PURE__ */ jsx(HistorySelector, { onSelect: handleSelectHistory })
163
+ /* @__PURE__ */ jsxs("div", { className: "action-icons", children: [
164
+ /* @__PURE__ */ jsx(HistorySelector, { onSelect: handleSelectHistory }),
165
+ /* @__PURE__ */ jsx(
166
+ "div",
167
+ {
168
+ className: hoveringSettings ? "settings-wrapper settings-wrapper-hover" : "settings-wrapper",
169
+ onMouseEnter: handleMouseEnter,
170
+ onMouseLeave: handleMouseLeave,
171
+ children: /* @__PURE__ */ jsx(
172
+ ConfigSelector,
173
+ {
174
+ enableTracking: serviceMode === "In-Browser-Extension",
175
+ showDeepThinkOption: selectedType === "aiTap"
176
+ }
177
+ )
178
+ }
179
+ )
180
+ ] })
149
181
  ] }),
150
182
  /* @__PURE__ */ jsxs(
151
183
  "div",
152
184
  {
153
- className: `main-side-console-input ${!runButtonEnabled ? "disabled" : ""}`,
185
+ className: `main-side-console-input ${!runButtonEnabled ? "disabled" : ""} ${loading ? "loading" : ""}`,
154
186
  children: [
155
187
  /* @__PURE__ */ jsx(Form.Item, { name: "prompt", style: { margin: 0 }, children: /* @__PURE__ */ jsx(
156
188
  TextArea,
157
189
  {
158
190
  className: "main-side-console-input-textarea",
159
191
  disabled: !runButtonEnabled,
160
- rows: 2,
192
+ rows: 4,
161
193
  placeholder,
162
194
  autoFocus: true,
163
195
  onKeyDown: handleKeyDown,
196
+ onChange: handlePromptChange,
197
+ value: promptValue,
164
198
  ref: textAreaRef
165
199
  }
166
200
  ) }),
167
- /* @__PURE__ */ jsxs("div", { className: "form-controller-wrapper", children: [
168
- /* @__PURE__ */ jsx(
169
- "div",
170
- {
171
- className: hoveringSettings ? "settings-wrapper settings-wrapper-hover" : "settings-wrapper",
172
- onMouseEnter: handleMouseEnter,
173
- onMouseLeave: handleMouseLeave,
174
- children: /* @__PURE__ */ jsx(
175
- ConfigSelector,
176
- {
177
- enableTracking: serviceMode === "In-Browser-Extension",
178
- showDeepThinkOption: selectedType === "aiTap"
179
- }
180
- )
181
- }
182
- ),
183
- renderActionButton()
184
- ] })
201
+ /* @__PURE__ */ jsx("div", { className: "form-controller-wrapper", children: renderActionButton() })
185
202
  ]
186
203
  }
187
204
  )