@midscene/visualizer 0.1.4 → 0.2.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 (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +4 -21
  3. package/dist/es/component/blackboard.js +32 -8
  4. package/dist/es/component/color.js +2 -4
  5. package/dist/es/component/detail-panel.js +28 -14
  6. package/dist/es/component/detail-side.css +1 -1
  7. package/dist/es/component/detail-side.js +99 -28
  8. package/dist/es/component/global-hover-preview.css +2 -2
  9. package/dist/es/component/global-hover-preview.js +25 -12
  10. package/dist/es/component/panel-title.css +3 -3
  11. package/dist/es/component/sidebar.css +7 -12
  12. package/dist/es/component/sidebar.js +31 -19
  13. package/dist/es/component/store.js +8 -2
  14. package/dist/es/component/timeline.css +1 -1
  15. package/dist/es/component/timeline.js +52 -19
  16. package/dist/es/demo-dump.json +1 -0
  17. package/dist/es/index.css +13 -9
  18. package/dist/es/index.js +44 -26
  19. package/dist/es/utils.js +9 -10
  20. package/dist/lib/component/blackboard.js +31 -7
  21. package/dist/lib/component/color.js +2 -4
  22. package/dist/lib/component/detail-panel.js +23 -13
  23. package/dist/lib/component/detail-side.css +1 -1
  24. package/dist/lib/component/detail-side.js +98 -27
  25. package/dist/lib/component/global-hover-preview.css +2 -2
  26. package/dist/lib/component/global-hover-preview.js +26 -13
  27. package/dist/lib/component/panel-title.css +3 -3
  28. package/dist/lib/component/sidebar.css +7 -12
  29. package/dist/lib/component/sidebar.js +31 -19
  30. package/dist/lib/component/store.js +8 -2
  31. package/dist/lib/component/timeline.css +1 -1
  32. package/dist/lib/component/timeline.js +52 -19
  33. package/dist/lib/demo-dump.json +1 -0
  34. package/dist/lib/index.css +13 -9
  35. package/dist/lib/index.js +43 -25
  36. package/dist/lib/utils.js +9 -10
  37. package/dist/types/component/store.d.ts +1 -1
  38. package/dist/types/index.d.ts +1 -1
  39. package/dist/types/utils.d.ts +1 -1
  40. package/package.json +9 -9
@@ -21,7 +21,10 @@ __export(global_hover_preview_exports, {
21
21
  default: () => global_hover_preview_default
22
22
  });
23
23
  module.exports = __toCommonJS(global_hover_preview_exports);
24
- var import_jsx_runtime = require("react/jsx-runtime");
24
+ var import_jsx_runtime = (
25
+ // biome-ignore lint/a11y/useAltText: <explanation>
26
+ require("react/jsx-runtime")
27
+ );
25
28
  var import_react = require("react");
26
29
  var import_store = require("./store");
27
30
  var import_global_hover_preview = require("./global-hover-preview.css");
@@ -31,7 +34,9 @@ const GlobalHoverPreview = () => {
31
34
  const wrapperRef = (0, import_react.useRef)(null);
32
35
  const hoverTask = (0, import_store.useExecutionDump)((store) => store.hoverTask);
33
36
  const hoverTimestamp = (0, import_store.useExecutionDump)((store) => store.hoverTimestamp);
34
- const hoverPreviewConfig = (0, import_store.useExecutionDump)((store) => store.hoverPreviewConfig);
37
+ const hoverPreviewConfig = (0, import_store.useExecutionDump)(
38
+ (store) => store.hoverPreviewConfig
39
+ );
35
40
  const [imageW, setImageW] = (0, import_react.useState)(size);
36
41
  const [imageH, setImageH] = (0, import_react.useState)(size);
37
42
  const images = (_a = hoverTask == null ? void 0 : hoverTask.recorder) == null ? void 0 : _a.filter((item) => {
@@ -52,18 +57,26 @@ const GlobalHoverPreview = () => {
52
57
  left = x + widthInPractice > clientWidth ? clientWidth - widthInPractice : x;
53
58
  top = y + heightInPractice > clientHeight ? clientHeight - heightInPractice : y;
54
59
  }
55
- return shouldShow ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "global-hover-preview", style: { left, top }, ref: wrapperRef, children: (images == null ? void 0 : images.length) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
56
- "img",
60
+ return shouldShow ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
61
+ "div",
57
62
  {
58
- src: images[0],
59
- onLoad: (img) => {
60
- const imgElement = img.target;
61
- const width = imgElement.naturalWidth;
62
- const height = imgElement.naturalHeight;
63
- setImageW(width);
64
- setImageH(height);
65
- }
63
+ className: "global-hover-preview",
64
+ style: { left, top },
65
+ ref: wrapperRef,
66
+ children: (images == null ? void 0 : images.length) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
67
+ "img",
68
+ {
69
+ src: images[0],
70
+ onLoad: (img) => {
71
+ const imgElement = img.target;
72
+ const width = imgElement.naturalWidth;
73
+ const height = imgElement.naturalHeight;
74
+ setImageW(width);
75
+ setImageH(height);
76
+ }
77
+ }
78
+ ) : null
66
79
  }
67
- ) : null }) : null;
80
+ ) : null;
68
81
  };
69
82
  var global_hover_preview_default = GlobalHoverPreview;
@@ -1,8 +1,8 @@
1
1
  .task-list-name {
2
2
  padding: 2px 10px;
3
3
  font-weight: bold;
4
- background: #DDDDDD;
5
- border-top: 1px solid #CCCCCC;
6
- border-bottom: 1px solid #CCCCCC;
4
+ background: #F8F8F8;
5
+ border-top: 1px solid #E5E5E5;
6
+ border-bottom: 1px solid #E5E5E5;
7
7
  margin-top: -1px;
8
8
  }
@@ -4,9 +4,9 @@
4
4
  justify-content: space-between;
5
5
  width: 100%;
6
6
  height: 100%;
7
- border-right: 1px solid #CCCCCC;
7
+ border-right: 1px solid #E5E5E5;
8
8
  overflow: auto;
9
- background: #f7f7f7;
9
+ background: #F8F8F8;
10
10
  }
11
11
  .side-bar .brand {
12
12
  padding: 10px 5px;
@@ -25,7 +25,7 @@
25
25
  border-top: 1px solid none;
26
26
  }
27
27
  .side-bar .side-seperator.side-seperator-line {
28
- border-top: 1px solid #CCCCCC;
28
+ border-top: 1px solid #E5E5E5;
29
29
  }
30
30
  .side-bar .side-seperator.side-seperator-space-up {
31
31
  margin-top: 10px;
@@ -35,7 +35,7 @@
35
35
  }
36
36
  .side-bar .side-sub-title {
37
37
  padding: 0 10px;
38
- font-weight: bold;
38
+ margin-bottom: 6px;
39
39
  }
40
40
  .side-bar .side-item {
41
41
  cursor: pointer;
@@ -43,15 +43,10 @@
43
43
  padding: 2px 0;
44
44
  }
45
45
  .side-bar .side-item:hover {
46
- background: #A3D6D2;
47
- color: #333;
46
+ background: #dcdcdc80;
48
47
  }
49
48
  .side-bar .side-item.selected {
50
- background: #06B1AB;
51
- color: #ffffff;
52
- }
53
- .side-bar .side-item.selected .status-text {
54
- color: #ffffff;
49
+ background: #bfc4da80;
55
50
  }
56
51
  .side-bar .side-item .side-item-content {
57
52
  padding: 0 10px 0 calc(10px + 16px);
@@ -73,7 +68,7 @@
73
68
  margin-top: -5px;
74
69
  }
75
70
  .side-bar .side-item-name .status-icon-success {
76
- color: #3a773a;
71
+ color: #2B8243;
77
72
  }
78
73
  .side-bar .side-item-name .status-icon-fail {
79
74
  color: #ff0a0a;
@@ -33,14 +33,14 @@ __export(sidebar_exports, {
33
33
  module.exports = __toCommonJS(sidebar_exports);
34
34
  var import_jsx_runtime = require("react/jsx-runtime");
35
35
  var import_sidebar = require("./sidebar.css");
36
- var import_react = require("react");
36
+ var import_store = require("./store");
37
+ var import_utils = require("../utils");
37
38
  var import_icons = require("@ant-design/icons");
38
39
  var import_antd = require("antd");
39
- var import_panel_title = __toESM(require("./panel-title"));
40
- var import_misc = require("./misc");
40
+ var import_react = require("react");
41
41
  var import_logo_plain2 = __toESM(require("./assets/logo-plain2.js"));
42
- var import_store = require("./store");
43
- var import_utils = require("../utils");
42
+ var import_misc = require("./misc");
43
+ var import_panel_title = __toESM(require("./panel-title"));
44
44
  const SideItem = (props) => {
45
45
  var _a, _b, _c;
46
46
  const { task, onClick, selected } = props;
@@ -88,7 +88,7 @@ const SideItem = (props) => {
88
88
  },
89
89
  children: [
90
90
  " ",
91
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `side-item-name`, children: [
91
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "side-item-name", children: [
92
92
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: `status-icon status-icon-${task.status}`, children: statusIcon }),
93
93
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "title", children: (0, import_utils.typeStr)(task) }),
94
94
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "status-text", children: statusText })
@@ -103,10 +103,14 @@ const Sidebar = (props) => {
103
103
  const setActiveTask = (0, import_store.useExecutionDump)((store) => store.setActiveTask);
104
104
  const activeTask = (0, import_store.useExecutionDump)((store) => store.activeTask);
105
105
  const setHoverTask = (0, import_store.useExecutionDump)((store) => store.setHoverTask);
106
- const setHoverPreviewConfig = (0, import_store.useExecutionDump)((store) => store.setHoverPreviewConfig);
106
+ const setHoverPreviewConfig = (0, import_store.useExecutionDump)(
107
+ (store) => store.setHoverPreviewConfig
108
+ );
107
109
  const reset = (0, import_store.useExecutionDump)((store) => store.reset);
108
110
  const allTasks = (0, import_store.useAllCurrentTasks)();
109
- const currentSelectedIndex = allTasks == null ? void 0 : allTasks.findIndex((task) => task === activeTask);
111
+ const currentSelectedIndex = allTasks == null ? void 0 : allTasks.findIndex(
112
+ (task) => task === activeTask
113
+ );
110
114
  (0, import_react.useEffect)(() => {
111
115
  const handleKeyDown = (e) => {
112
116
  if (!(allTasks == null ? void 0 : allTasks.length) || (allTasks == null ? void 0 : allTasks.length) <= 1) {
@@ -182,22 +186,30 @@ const Sidebar = (props) => {
182
186
  }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "no tasks" });
183
187
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "side-bar", children: [
184
188
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "top-controls", children: [
185
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "brand", onClick: reset, style: { display: (props == null ? void 0 : props.hideLogo) ? "none" : "flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
186
- import_logo_plain2.default,
189
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
190
+ "div",
187
191
  {
188
- style: { width: 70, height: 70, margin: "auto" },
189
- onClick: () => {
190
- if (props.logoAction) {
191
- props.logoAction();
192
- } else {
193
- location.reload();
192
+ className: "brand",
193
+ onClick: reset,
194
+ style: { display: (props == null ? void 0 : props.hideLogo) ? "none" : "flex" },
195
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
196
+ import_logo_plain2.default,
197
+ {
198
+ style: { width: 70, height: 70, margin: "auto" },
199
+ onClick: () => {
200
+ if (props.logoAction) {
201
+ props.logoAction();
202
+ } else {
203
+ location.reload();
204
+ }
205
+ }
194
206
  }
195
- }
207
+ )
196
208
  }
197
- ) }),
209
+ ),
198
210
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "task-list", children: sideList }),
199
211
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "side-seperator side-seperator-line side-seperator-space-up" }),
200
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "task-meta-section", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "task-meta", children: "use Command + ⬆︎ / ⬇︎ to switch" }) })
212
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "task-meta-section", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "task-meta", children: "switch: Command + Up / Down" }) })
201
213
  ] }),
202
214
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "bottom-controls", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Button, { onClick: reset, type: "text", className: "unload_btn", children: "Unload" }) })
203
215
  ] });
@@ -82,10 +82,11 @@ const useExecutionDump = (0, import_zustand.create)((set, get) => {
82
82
  }
83
83
  },
84
84
  setActiveTask(task) {
85
+ var _a;
85
86
  set({ activeTask: task });
86
87
  console.log("task set", task);
87
88
  if (task.type === "Insight") {
88
- syncToInsightDump(task.log.dump);
89
+ syncToInsightDump((_a = task.log) == null ? void 0 : _a.dump);
89
90
  } else {
90
91
  resetInsightDump();
91
92
  }
@@ -124,7 +125,12 @@ const useAllCurrentTasks = () => {
124
125
  };
125
126
  const useInsightDump = (0, import_zustand.create)((set) => {
126
127
  let loadId = 0;
127
- const initData = { _loadId: 0, highlightSectionNames: [], highlightElements: [], data: null };
128
+ const initData = {
129
+ _loadId: 0,
130
+ highlightSectionNames: [],
131
+ highlightElements: [],
132
+ data: null
133
+ };
128
134
  return __spreadProps(__spreadValues({}, initData), {
129
135
  loadData: (data) => {
130
136
  set({
@@ -4,7 +4,7 @@
4
4
  flex-shrink: 0;
5
5
  width: 100%;
6
6
  height: 100%;
7
- border-bottom: 1px solid #CCCCCC;
7
+ border-bottom: 1px solid #E5E5E5;
8
8
  position: relative;
9
9
  box-sizing: border-box;
10
10
  }
@@ -69,8 +69,8 @@ __export(timeline_exports, {
69
69
  });
70
70
  module.exports = __toCommonJS(timeline_exports);
71
71
  var import_jsx_runtime = require("react/jsx-runtime");
72
- var import_react = require("react");
73
72
  var PIXI = __toESM(require("pixi.js"));
73
+ var import_react = require("react");
74
74
  var import_timeline = require("./timeline.css");
75
75
  var import_store = require("./store");
76
76
  function cloneSprite(sprite) {
@@ -98,17 +98,18 @@ const TimelineWidget = (props) => {
98
98
  const allScreenshots = props.screenshots || [];
99
99
  const maxTime = allScreenshots[allScreenshots.length - 1].timeOffset;
100
100
  const sizeRatio = 2;
101
- const titleBg = 14540253;
102
- const sideBg = 16250871;
101
+ const titleBg = 16316664;
102
+ const sideBg = 16777215;
103
103
  const gridTextColor = 0;
104
104
  const shotBorderColor = 7829367;
105
- const gridLineColor = 13421772;
106
- const gridHighlightColor = 438699;
105
+ const gridLineColor = 15066597;
106
+ const gridHighlightColor = 12567770;
107
+ const highlightMaskAlpha = 0.6;
107
108
  const timeContentFontSize = 20;
108
109
  const commonPadding = 12;
109
110
  const timeTextTop = commonPadding;
110
111
  const timeTitleBottom = timeTextTop * 2 + timeContentFontSize;
111
- const highlightMaskAlpha = 0.6;
112
+ const hoverMaskColor = 14474460;
112
113
  const hoverMaskAlpha = 0.3;
113
114
  const closestScreenshotItemOnXY = (x, _y) => {
114
115
  let closestScreenshot;
@@ -213,6 +214,11 @@ const TimelineWidget = (props) => {
213
214
  titleBgSection.drawRect(0, 0, canvasWidth, timeTitleBottom);
214
215
  titleBgSection.endFill();
215
216
  gridsContainer.addChild(titleBgSection);
217
+ const titleBottomBorder = new PIXI.Graphics();
218
+ titleBottomBorder.beginFill(gridLineColor);
219
+ titleBottomBorder.drawRect(0, timeTitleBottom, canvasWidth, sizeRatio);
220
+ titleBottomBorder.endFill();
221
+ gridsContainer.addChild(titleBottomBorder);
216
222
  const gridHeight = canvasHeight;
217
223
  for (let i = 1; i <= gridCount; i++) {
218
224
  const gridLine = new PIXI.Graphics();
@@ -248,7 +254,9 @@ const TimelineWidget = (props) => {
248
254
  const originalWidth = img.width;
249
255
  const originalHeight = img.height;
250
256
  const screenshotHeight = screenshotMaxHeight;
251
- const screenshotWidth = Math.floor(screenshotHeight / originalHeight * originalWidth);
257
+ const screenshotWidth = Math.floor(
258
+ screenshotHeight / originalHeight * originalWidth
259
+ );
252
260
  const screenshotX = leftForTimeOffset(screenshot.timeOffset);
253
261
  allScreenshots[index].x = screenshotX;
254
262
  allScreenshots[index].y = screenshotTop;
@@ -256,7 +264,12 @@ const TimelineWidget = (props) => {
256
264
  allScreenshots[index].height = screenshotMaxHeight;
257
265
  const border = new PIXI.Graphics();
258
266
  border.lineStyle(sizeRatio, shotBorderColor, 1);
259
- border.drawRect(screenshotX, screenshotTop, screenshotWidth, screenshotMaxHeight);
267
+ border.drawRect(
268
+ screenshotX,
269
+ screenshotTop,
270
+ screenshotWidth,
271
+ screenshotMaxHeight
272
+ );
260
273
  border.endFill();
261
274
  container.addChild(border);
262
275
  screenshotSprite.x = screenshotX;
@@ -268,18 +281,28 @@ const TimelineWidget = (props) => {
268
281
  });
269
282
  const highlightMaskUpdater = (start, end, hoverStart, hoverEnd) => {
270
283
  highlightMaskContainer.removeChildren();
271
- const mask = (start2, end2, alpha) => {
284
+ const mask = (start2, end2, color, alpha) => {
272
285
  if (typeof start2 === "undefined" || typeof end2 === "undefined" || end2 === 0) {
273
286
  return;
274
287
  }
275
288
  const leftBorder = new PIXI.Graphics();
276
289
  leftBorder.beginFill(gridHighlightColor, 1);
277
- leftBorder.drawRect(leftForTimeOffset(start2), 0, sizeRatio, canvasHeight);
290
+ leftBorder.drawRect(
291
+ leftForTimeOffset(start2),
292
+ 0,
293
+ sizeRatio,
294
+ canvasHeight
295
+ );
278
296
  leftBorder.endFill();
279
297
  highlightMaskContainer.addChild(leftBorder);
280
298
  const rightBorder = new PIXI.Graphics();
281
299
  rightBorder.beginFill(gridHighlightColor, 1);
282
- rightBorder.drawRect(leftForTimeOffset(end2), 0, sizeRatio, canvasHeight);
300
+ rightBorder.drawRect(
301
+ leftForTimeOffset(end2),
302
+ 0,
303
+ sizeRatio,
304
+ canvasHeight
305
+ );
283
306
  rightBorder.endFill();
284
307
  highlightMaskContainer.addChild(rightBorder);
285
308
  const mask2 = new PIXI.Graphics();
@@ -293,10 +316,15 @@ const TimelineWidget = (props) => {
293
316
  mask2.endFill();
294
317
  highlightMaskContainer.addChild(mask2);
295
318
  };
296
- mask(start, end, highlightMaskAlpha);
297
- mask(hoverStart, hoverEnd, hoverMaskAlpha);
319
+ mask(start, end, gridHighlightColor, highlightMaskAlpha);
320
+ mask(hoverStart, hoverEnd, hoverMaskColor, hoverMaskAlpha);
298
321
  };
299
- highlightMaskUpdater((_a2 = props.highlightMask) == null ? void 0 : _a2.startMs, (_b2 = props.highlightMask) == null ? void 0 : _b2.endMs, 0, 0);
322
+ highlightMaskUpdater(
323
+ (_a2 = props.highlightMask) == null ? void 0 : _a2.startMs,
324
+ (_b2 = props.highlightMask) == null ? void 0 : _b2.endMs,
325
+ 0,
326
+ 0
327
+ );
300
328
  containerUpdaterRef.current = highlightMaskUpdater;
301
329
  app.stage.interactive = true;
302
330
  const onPointerMove = (event) => {
@@ -304,7 +332,10 @@ const TimelineWidget = (props) => {
304
332
  const x = event.offsetX * sizeRatio;
305
333
  const y = event.offsetY * sizeRatio;
306
334
  indicatorContainer.removeChildren();
307
- const { closestScreenshot, closestIndex } = closestScreenshotItemOnXY(x, y);
335
+ const { closestScreenshot, closestIndex } = closestScreenshotItemOnXY(
336
+ x,
337
+ y
338
+ );
308
339
  if (closestIndex < 0) {
309
340
  (_a3 = props.onUnhighlight) == null ? void 0 : _a3.call(props);
310
341
  return;
@@ -317,9 +348,9 @@ const TimelineWidget = (props) => {
317
348
  newSpirit.drawRect(
318
349
  x,
319
350
  // follow mouse
320
- closestScreenshot.y,
321
- closestScreenshot.width,
322
- closestScreenshot.height
351
+ closestScreenshot == null ? void 0 : closestScreenshot.y,
352
+ closestScreenshot == null ? void 0 : closestScreenshot.width,
353
+ closestScreenshot == null ? void 0 : closestScreenshot.height
323
354
  );
324
355
  newSpirit.endFill();
325
356
  indicatorContainer.addChild(newSpirit);
@@ -381,7 +412,9 @@ const Timeline = () => {
381
412
  const activeTask = (0, import_store.useExecutionDump)((store) => store.activeTask);
382
413
  const hoverTask = (0, import_store.useExecutionDump)((store) => store.hoverTask);
383
414
  const setHoverTask = (0, import_store.useExecutionDump)((store) => store.setHoverTask);
384
- const setHoverPreviewConfig = (0, import_store.useExecutionDump)((store) => store.setHoverPreviewConfig);
415
+ const setHoverPreviewConfig = (0, import_store.useExecutionDump)(
416
+ (store) => store.setHoverPreviewConfig
417
+ );
385
418
  let startingTime = -1;
386
419
  let idCount = 1;
387
420
  const idTaskMap = {};