@midscene/visualizer 0.5.2-beta-20241009023204.0 → 0.5.2

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.
@@ -119,7 +119,7 @@ const DetailPanel = () => {
119
119
  const options = availableViewTypes.map((type) => {
120
120
  if (type === VIEW_TYPE_REPLAY) {
121
121
  return {
122
- label: "Task Replay",
122
+ label: "Replay",
123
123
  value: type,
124
124
  icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.VideoCameraOutlined, {})
125
125
  };
@@ -1,51 +1,97 @@
1
1
  .player-container {
2
- width: 100%;
3
- height: 100%;
2
+ width: fit-content;
3
+ max-width: 100%;
4
+ max-height: 100%;
5
+ padding: 12px;
6
+ padding-bottom: 0;
7
+ background: #434443DD;
8
+ box-sizing: border-box;
9
+ border: 1px solid #979797;
10
+ border-radius: 6px;
11
+ line-height: 100%;
12
+ margin: 0 auto;
4
13
  display: flex;
5
14
  flex-direction: column;
6
- justify-content: center;
7
- position: relative;
8
- }
9
- .player-container .player-top-placeholder {
10
- width: 100%;
11
- height: 1px;
15
+ overflow: hidden;
12
16
  }
13
17
  .player-container .canvas-container {
14
- width: 100%;
15
- height: 90%;
16
- text-align: center;
17
- position: relative;
18
+ flex-grow: 1;
19
+ display: flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+ overflow: hidden;
18
23
  }
19
- .player-container canvas {
20
- border: 1px solid #06B1AB;
24
+ .player-container .canvas-container canvas {
21
25
  max-width: 100%;
22
26
  max-height: 100%;
23
27
  box-sizing: border-box;
24
- position: absolute;
25
- top: 50%;
26
- left: 50%;
27
- transform: translate(-50%, -50%);
28
+ display: block;
29
+ margin: 0 auto;
28
30
  }
29
- .player-container .player-controls {
31
+ .player-container .player-timeline {
32
+ width: 100%;
33
+ height: 4px;
34
+ background: #666;
35
+ position: relative;
36
+ margin-top: -2px;
37
+ }
38
+ .player-container .player-timeline .player-timeline-progress {
39
+ transition-timing-function: linear;
30
40
  position: absolute;
31
- bottom: 20px;
41
+ top: 0;
32
42
  left: 0;
33
- width: 100%;
34
- background: rgba(0, 0, 0, 0.7);
35
- border-radius: 8px;
36
- padding: 20px 15px;
43
+ height: 4px;
44
+ background: #06b1ab;
45
+ }
46
+ .player-container .player-controls {
47
+ margin-top: calc(12px * 1.2);
48
+ margin-bottom: calc(12px * 1.2);
49
+ max-width: 100%;
50
+ overflow: hidden;
37
51
  color: #FFF;
38
- font-size: 18px;
39
- line-height: 1.2;
40
- transition: 0.2s;
52
+ font-size: 16px;
41
53
  box-sizing: border-box;
54
+ display: flex;
55
+ flex-direction: row;
56
+ flex-shrink: 0;
57
+ }
58
+ .player-container .player-controls .status-icon {
59
+ transition: 0.2s;
60
+ width: 40px;
61
+ height: 40px;
62
+ margin-right: 12px;
63
+ background: #666;
64
+ border-radius: 6px;
65
+ display: flex;
66
+ align-items: center;
67
+ justify-content: center;
68
+ flex-shrink: 0;
69
+ }
70
+ .player-container .player-controls .status-text {
71
+ flex-grow: 1;
72
+ overflow: hidden;
73
+ position: relative;
42
74
  }
43
75
  .player-container .player-controls .title {
44
76
  font-weight: bold;
77
+ height: 20px;
78
+ line-height: 20px;
79
+ overflow: hidden;
80
+ text-overflow: ellipsis;
81
+ white-space: nowrap;
82
+ position: absolute;
83
+ top: 0;
84
+ left: 0;
85
+ width: 100%;
45
86
  }
46
87
  .player-container .player-controls .subtitle {
47
- white-space: nowrap;
48
- text-overflow: ellipsis;
49
- overflow: hidden;
88
+ height: 20px;
89
+ line-height: 20px;
50
90
  width: 100%;
91
+ overflow: hidden;
92
+ text-overflow: ellipsis;
93
+ white-space: nowrap;
94
+ position: absolute;
95
+ top: 18px;
96
+ left: 0;
51
97
  }
@@ -71,6 +71,8 @@ var PIXI = __toESM(require("pixi.js"));
71
71
  var import_react = require("react");
72
72
  var import_player = require("./player.css");
73
73
  var import_utils = require("../utils");
74
+ var import_icons = require("@ant-design/icons");
75
+ var import_antd = require("antd");
74
76
  var import_blackboard = require("./blackboard");
75
77
  var import_store = require("./store");
76
78
  const canvasPaddingLeft = 0;
@@ -80,7 +82,7 @@ const cubicBezier = (t, p0, p1, p2, p3) => {
80
82
  return p0 * t2 * t2 * t2 + 3 * p1 * t * t2 * t2 + 3 * p2 * t * t * t2 + p3 * t * t * t;
81
83
  };
82
84
  const cubicImage = (t) => {
83
- return cubicBezier(t, 0, 0.69, 0.43, 1);
85
+ return linear(t);
84
86
  };
85
87
  const cubicInsightElement = (t) => {
86
88
  return cubicBezier(t, 0, 0.5, 0.5, 1);
@@ -94,6 +96,38 @@ const linear = (t) => {
94
96
  const sleep = (ms) => {
95
97
  return new Promise((resolve) => setTimeout(resolve, ms));
96
98
  };
99
+ const ERROR_FRAME_CANCEL = "frame cancel";
100
+ const frameKit = () => {
101
+ let cancelFlag = false;
102
+ return {
103
+ frame: (callback) => {
104
+ if (cancelFlag) {
105
+ throw new Error(ERROR_FRAME_CANCEL);
106
+ }
107
+ requestAnimationFrame(() => {
108
+ if (cancelFlag) {
109
+ throw new Error(ERROR_FRAME_CANCEL);
110
+ }
111
+ callback(performance.now());
112
+ });
113
+ },
114
+ timeout: (callback, ms) => {
115
+ if (cancelFlag) {
116
+ throw new Error(ERROR_FRAME_CANCEL);
117
+ }
118
+ setTimeout(() => {
119
+ if (cancelFlag) {
120
+ throw new Error(ERROR_FRAME_CANCEL);
121
+ }
122
+ callback();
123
+ }, ms);
124
+ },
125
+ cancel: () => {
126
+ console.log("set frame cancel");
127
+ cancelFlag = true;
128
+ }
129
+ };
130
+ };
97
131
  const singleElementFadeInDuration = 80;
98
132
  const LAYER_ORDER_IMG = 0;
99
133
  const LAYER_ORDER_INSIGHT = 1;
@@ -118,6 +152,7 @@ const Player = () => {
118
152
  const imgSpriteMap = (0, import_react.useRef)(/* @__PURE__ */ new Map());
119
153
  const pointerSprite = (0, import_react.useRef)(null);
120
154
  const spinningPointerSprite = (0, import_react.useRef)(null);
155
+ const [replayMark, setReplayMark] = (0, import_react.useState)(0);
121
156
  const windowContentContainer = (0, import_react.useMemo)(() => {
122
157
  const container = new PIXI.Container();
123
158
  return container;
@@ -136,6 +171,7 @@ const Player = () => {
136
171
  top: imageHeight / 2
137
172
  }
138
173
  };
174
+ const [animationProgress, setAnimationProgress] = (0, import_react.useState)(-1);
139
175
  const cancelFlag = (0, import_react.useRef)(false);
140
176
  (0, import_react.useEffect)(() => {
141
177
  cancelFlag.current = false;
@@ -143,14 +179,6 @@ const Player = () => {
143
179
  cancelFlag.current = true;
144
180
  };
145
181
  }, []);
146
- const frame = (callback) => {
147
- requestAnimationFrame(() => {
148
- if (cancelFlag.current) {
149
- return;
150
- }
151
- callback(performance.now());
152
- });
153
- };
154
182
  const cameraState = (0, import_react.useRef)(__spreadValues({}, basicCameraState));
155
183
  const preloadImage = (img) => __async(void 0, null, function* () {
156
184
  if (imgSpriteMap.current.has(img))
@@ -182,7 +210,7 @@ const Player = () => {
182
210
  sprite.zIndex = LAYER_ORDER_IMG;
183
211
  windowContentContainer.addChild(sprite);
184
212
  });
185
- const spinningPointer = () => __async(void 0, null, function* () {
213
+ const spinningPointer = (frame) => {
186
214
  var _a2, _b;
187
215
  if (!spinningPointerSprite.current) {
188
216
  spinningPointerSprite.current = PIXI.Sprite.from(import_utils.mouseLoading);
@@ -217,7 +245,7 @@ const Player = () => {
217
245
  isCancelled = true;
218
246
  };
219
247
  return stopFn;
220
- });
248
+ };
221
249
  const updatePointer = (img, x, y) => __async(void 0, null, function* () {
222
250
  var _a2, _b;
223
251
  if (!imgSpriteMap.current.has(img)) {
@@ -270,7 +298,7 @@ const Player = () => {
270
298
  pointer.scale.set(1 / newScale);
271
299
  }
272
300
  };
273
- const cameraAnimation = (targetState, duration) => __async(void 0, null, function* () {
301
+ const cameraAnimation = (targetState, duration, frame) => __async(void 0, null, function* () {
274
302
  const currentState = __spreadValues({}, cameraState.current);
275
303
  const startLeft = currentState.left;
276
304
  const startTop = currentState.top;
@@ -323,7 +351,7 @@ const Player = () => {
323
351
  frame(animate);
324
352
  });
325
353
  });
326
- const fadeInGraphics = (graphics, duration, targetAlpha = 1) => {
354
+ const fadeInGraphics = (graphics, duration, frame, targetAlpha = 1) => {
327
355
  return new Promise((resolve) => {
328
356
  const startTime = performance.now();
329
357
  const animate = (currentTime) => {
@@ -339,13 +367,14 @@ const Player = () => {
339
367
  frame(animate);
340
368
  });
341
369
  };
342
- const fadeOutItem = (graphics, duration) => __async(void 0, null, function* () {
343
- return fadeInGraphics(graphics, duration, 0);
370
+ const fadeOutItem = (graphics, duration, frame) => __async(void 0, null, function* () {
371
+ return fadeInGraphics(graphics, duration, frame, 0);
344
372
  });
345
- const insightElementsAnimation = (elements, highlightElements, duration) => __async(void 0, null, function* () {
373
+ const insightElementsAnimation = (elements, highlightElements, duration, frame) => __async(void 0, null, function* () {
346
374
  insightMarkContainer.removeChildren();
347
375
  const elementsToAdd = [...elements];
348
376
  const totalLength = elementsToAdd.length;
377
+ let childrenCount = 0;
349
378
  yield new Promise((resolve) => {
350
379
  const startTime = performance.now();
351
380
  const animate = (currentTime) => {
@@ -354,7 +383,7 @@ const Player = () => {
354
383
  Math.min(elapsedTime / duration, 1)
355
384
  );
356
385
  const elementsToAddNow = Math.floor(progress * totalLength);
357
- while (insightMarkContainer.children.length < elementsToAddNow) {
386
+ while (childrenCount < elementsToAddNow) {
358
387
  const randomIndex = Math.floor(Math.random() * elementsToAdd.length);
359
388
  const element = elementsToAdd.splice(randomIndex, 1)[0];
360
389
  if (element) {
@@ -365,7 +394,12 @@ const Player = () => {
365
394
  );
366
395
  insightMarkGraphic.alpha = 0;
367
396
  insightMarkContainer.addChild(insightMarkGraphic);
368
- fadeInGraphics(insightMarkGraphic, singleElementFadeInDuration);
397
+ childrenCount++;
398
+ fadeInGraphics(
399
+ insightMarkGraphic,
400
+ singleElementFadeInDuration,
401
+ frame
402
+ );
369
403
  }
370
404
  }
371
405
  if (elapsedTime < duration) {
@@ -399,30 +433,57 @@ const Player = () => {
399
433
  frame(animate);
400
434
  });
401
435
  });
402
- (0, import_react.useEffect)(() => {
436
+ const init = () => __async(void 0, null, function* () {
437
+ if (!divContainerRef.current || !scripts)
438
+ return;
439
+ yield app.init({
440
+ width: canvasWidth,
441
+ height: canvasHeight,
442
+ background: 16053492
443
+ });
444
+ divContainerRef.current.appendChild(app.canvas);
445
+ windowContentContainer.x = 0;
446
+ windowContentContainer.y = 0;
447
+ app.stage.addChild(windowContentContainer);
448
+ insightMarkContainer.x = 0;
449
+ insightMarkContainer.y = 0;
450
+ windowContentContainer.addChild(insightMarkContainer);
451
+ });
452
+ const play = () => {
403
453
  let cancelFn;
404
454
  Promise.resolve(
405
455
  (() => __async(void 0, null, function* () {
406
- if (!divContainerRef.current || !scripts || !app)
407
- return;
408
- yield app.init({
409
- width: canvasWidth,
410
- height: canvasHeight,
411
- background: 16053492
412
- });
413
- divContainerRef.current.appendChild(app.canvas);
456
+ if (!app) {
457
+ throw new Error("app is not initialized");
458
+ }
459
+ if (!scripts) {
460
+ throw new Error("scripts is required");
461
+ }
462
+ const { frame, cancel, timeout } = frameKit();
463
+ cancelFn = cancel;
414
464
  const allImages = scripts.filter((item) => !!item.img).map((item) => item.img);
415
465
  yield Promise.all([...allImages, import_utils.mouseLoading].map(preloadImage));
416
- windowContentContainer.x = 0;
417
- windowContentContainer.y = 0;
418
- app.stage.addChild(windowContentContainer);
419
- insightMarkContainer.x = 0;
420
- insightMarkContainer.y = 0;
421
- windowContentContainer.addChild(insightMarkContainer);
466
+ insightMarkContainer.removeChildren();
422
467
  yield updatePointer(import_utils.mousePointer, imageWidth / 2, imageHeight / 2);
423
468
  yield repaintImage();
424
- yield updateCamera(cameraState.current);
425
- for (const item of scripts) {
469
+ yield updateCamera(__spreadValues({}, basicCameraState));
470
+ const totalDuration = scripts.reduce((acc, item) => {
471
+ return acc + item.duration + (item.insightCameraDuration || 0);
472
+ }, 0);
473
+ const progressUpdateInterval = 300;
474
+ const startTime = performance.now();
475
+ setAnimationProgress(0);
476
+ const updateProgress = () => {
477
+ const progress = Math.min(
478
+ (performance.now() - startTime) / totalDuration,
479
+ 1
480
+ );
481
+ setAnimationProgress(progress);
482
+ return timeout(updateProgress, progressUpdateInterval);
483
+ };
484
+ frame(updateProgress);
485
+ for (const index in scripts) {
486
+ const item = scripts[index];
426
487
  setTitleText(item.title || "");
427
488
  setSubTitleText(item.subTitle || "");
428
489
  if (item.type === "sleep") {
@@ -438,13 +499,21 @@ const Player = () => {
438
499
  yield insightElementsAnimation(
439
500
  elements,
440
501
  highlightElements,
441
- item.duration
502
+ item.duration,
503
+ frame
442
504
  );
443
505
  if (item.camera) {
444
- yield cameraAnimation(item.camera, item.duration);
506
+ if (!item.insightCameraDuration) {
507
+ throw new Error("insightCameraDuration is required");
508
+ }
509
+ yield cameraAnimation(
510
+ item.camera,
511
+ item.insightCameraDuration,
512
+ frame
513
+ );
445
514
  }
446
515
  } else if (item.type === "clear-insight") {
447
- yield fadeOutItem(insightMarkContainer, item.duration);
516
+ yield fadeOutItem(insightMarkContainer, item.duration, frame);
448
517
  insightMarkContainer.removeChildren();
449
518
  insightMarkContainer.alpha = 1;
450
519
  } else if (item.type === "img") {
@@ -453,7 +522,7 @@ const Player = () => {
453
522
  yield repaintImage();
454
523
  }
455
524
  if (item.camera) {
456
- yield cameraAnimation(item.camera, item.duration);
525
+ yield cameraAnimation(item.camera, item.duration, frame);
457
526
  } else {
458
527
  yield sleep(item.duration);
459
528
  }
@@ -463,29 +532,98 @@ const Player = () => {
463
532
  }
464
533
  yield updatePointer(item.img);
465
534
  } else if (item.type === "spinning-pointer") {
466
- const cancelFn2 = yield spinningPointer();
535
+ const stop = spinningPointer(frame);
467
536
  yield sleep(item.duration);
468
- cancelFn2();
537
+ stop();
469
538
  }
470
539
  }
540
+ }))().catch((e) => {
541
+ console.error("player error", e);
542
+ })
543
+ );
544
+ return () => {
545
+ cancelFn == null ? void 0 : cancelFn();
546
+ };
547
+ };
548
+ (0, import_react.useEffect)(() => {
549
+ Promise.resolve(
550
+ (() => __async(void 0, null, function* () {
551
+ yield init();
552
+ setReplayMark(Date.now());
471
553
  }))()
472
554
  );
473
555
  return () => {
474
556
  try {
475
- cancelFn == null ? void 0 : cancelFn();
476
557
  app.destroy(true, { children: true, texture: true });
477
558
  } catch (e) {
478
559
  console.warn("destroy failed", e);
479
560
  }
480
561
  };
481
562
  }, []);
482
- const showControl = !!titleText;
563
+ (0, import_react.useEffect)(() => {
564
+ if (replayMark) {
565
+ return play();
566
+ }
567
+ }, [replayMark]);
568
+ const progressString = Math.round(animationProgress * 100);
569
+ const transitionStyle = animationProgress === 0 ? "none" : "0.3s";
570
+ const [mouseOverStatusIcon, setMouseOverStatusIcon] = (0, import_react.useState)(false);
571
+ let statusIconElement;
572
+ const statusStyle = {};
573
+ let statusOnClick = () => {
574
+ };
575
+ if (animationProgress < 1) {
576
+ statusIconElement = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Spin, { indicator: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.LoadingOutlined, { spin: true }), size: "default" });
577
+ } else if (mouseOverStatusIcon) {
578
+ statusIconElement = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Spin, { indicator: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.PlayCircleOutlined, {}), size: "default" });
579
+ statusStyle.cursor = "pointer";
580
+ statusStyle.background = "#888";
581
+ statusOnClick = () => setReplayMark(Date.now());
582
+ } else {
583
+ statusIconElement = // <Spin indicator={<CheckCircleOutlined />} size="default" />
584
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Spin, { indicator: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.PlayCircleOutlined, {}), size: "default" });
585
+ }
483
586
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "player-container", children: [
484
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "player-top-placeholder", children: " " }),
485
587
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "canvas-container", ref: divContainerRef }),
486
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "player-controls", style: { opacity: showControl ? 1 : 0 }, children: [
487
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "title", children: titleText }),
488
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "subtitle", children: subTitleText })
588
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "player-timeline", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
589
+ "div",
590
+ {
591
+ className: "player-timeline-progress",
592
+ style: {
593
+ width: `${progressString}%`,
594
+ transition: transitionStyle
595
+ }
596
+ }
597
+ ) }),
598
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "player-controls", children: [
599
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
600
+ "div",
601
+ {
602
+ className: "status-icon",
603
+ onMouseEnter: () => setMouseOverStatusIcon(true),
604
+ onMouseLeave: () => setMouseOverStatusIcon(false),
605
+ style: statusStyle,
606
+ onClick: statusOnClick,
607
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
608
+ import_antd.ConfigProvider,
609
+ {
610
+ theme: {
611
+ components: {
612
+ Spin: {
613
+ dotSize: 24,
614
+ colorPrimary: "rgb(6,177,171)"
615
+ }
616
+ }
617
+ },
618
+ children: statusIconElement
619
+ }
620
+ )
621
+ }
622
+ ),
623
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "status-text", children: [
624
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "title", children: titleText }),
625
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "subtitle", children: subTitleText })
626
+ ] })
489
627
  ] })
490
628
  ] });
491
629
  };
@@ -34,13 +34,13 @@ var __copyProps = (to, from, except, desc) => {
34
34
  return to;
35
35
  };
36
36
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
37
- var player_scripts_exports = {};
38
- __export(player_scripts_exports, {
37
+ var replay_scripts_exports = {};
38
+ __export(replay_scripts_exports, {
39
39
  cameraStateForRect: () => cameraStateForRect,
40
40
  generateAnimationScripts: () => generateAnimationScripts,
41
41
  mergeTwoCameraState: () => mergeTwoCameraState
42
42
  });
43
- module.exports = __toCommonJS(player_scripts_exports);
43
+ module.exports = __toCommonJS(replay_scripts_exports);
44
44
  var import_player = require("./player.css");
45
45
  var import_utils = require("../utils");
46
46
  const stillDuration = 1200;
@@ -56,7 +56,7 @@ const cameraStateForRect = (rect, imageWidth, imageHeight) => {
56
56
  } else {
57
57
  rectWidthOnPage = rect.height / imageHeight * imageWidth;
58
58
  }
59
- const cameraPaddingRatio = rectWidthOnPage < 50 ? 0.3 : 0.2;
59
+ const cameraPaddingRatio = rectWidthOnPage > 400 ? 0.1 : rectWidthOnPage > 50 ? 0.2 : 0.3;
60
60
  const cameraWidth = Math.min(
61
61
  imageWidth,
62
62
  rectWidthOnPage + imageWidth * cameraPaddingRatio * 2
@@ -126,6 +126,7 @@ const generateAnimationScripts = (execution, imageWidth, imageHeight) => {
126
126
  let currentCameraState = fullPageCameraState;
127
127
  let insightOnTop = false;
128
128
  const taskCount = execution.tasks.length;
129
+ let initSubTitle = "";
129
130
  execution.tasks.forEach((task, index) => {
130
131
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
131
132
  if (task.type === "Planning") {
@@ -134,10 +135,12 @@ const generateAnimationScripts = (execution, imageWidth, imageHeight) => {
134
135
  scripts.push({
135
136
  type: "img",
136
137
  img: (_b = (_a = planningTask.recorder) == null ? void 0 : _a[0]) == null ? void 0 : _b.screenshot,
138
+ camera: fullPageCameraState,
137
139
  duration: stillDuration,
138
140
  title: (0, import_utils.typeStr)(task),
139
141
  subTitle: (0, import_utils.paramStr)(task)
140
142
  });
143
+ initSubTitle = (0, import_utils.paramStr)(task);
141
144
  }
142
145
  } else if (task.type === "Insight") {
143
146
  const insightTask = task;
@@ -164,6 +167,7 @@ const generateAnimationScripts = (execution, imageWidth, imageHeight) => {
164
167
  insightDump,
165
168
  camera: currentCameraState === fullPageCameraState || !insightCameraState ? void 0 : mergeTwoCameraState(currentCameraState, insightCameraState),
166
169
  duration: insightContentLength > 20 ? locateDuration : locateDuration * 0.5,
170
+ insightCameraDuration: locateDuration,
167
171
  title,
168
172
  subTitle
169
173
  });
@@ -224,14 +228,12 @@ const generateAnimationScripts = (execution, imageWidth, imageHeight) => {
224
228
  }
225
229
  });
226
230
  scripts.push({
231
+ title: "Done",
232
+ subTitle: initSubTitle,
227
233
  type: "img",
228
234
  duration: stillDuration * 0.5,
229
235
  camera: fullPageCameraState
230
236
  });
231
- scripts.push({
232
- type: "sleep",
233
- duration: stillDuration
234
- });
235
237
  return scripts;
236
238
  };
237
239
  // Annotate the CommonJS export names for ESM import in node:
@@ -52,7 +52,7 @@ __export(store_exports, {
52
52
  });
53
53
  module.exports = __toCommonJS(store_exports);
54
54
  var Z = __toESM(require("zustand"));
55
- var import_player_scripts = require("./player-scripts");
55
+ var import_replay_scripts = require("./replay-scripts");
56
56
  const { create } = Z;
57
57
  const useBlackboardPreference = create((set) => ({
58
58
  bgVisible: true,
@@ -124,7 +124,7 @@ const useExecutionDump = create((set, get) => {
124
124
  activeTask: task,
125
125
  activeExecution: parentExecution,
126
126
  _executionDumpLoadId: ++_executionDumpLoadId,
127
- activeExecutionAnimation: (0, import_player_scripts.generateAnimationScripts)(
127
+ activeExecutionAnimation: (0, import_replay_scripts.generateAnimationScripts)(
128
128
  parentExecution,
129
129
  width,
130
130
  height
@@ -125,7 +125,7 @@ footer.mt-8 {
125
125
  text-align: center;
126
126
  margin-top: 10px;
127
127
  }
128
- .main-right .main-canvas-container {
128
+ .main-right .main-content-container {
129
129
  flex-grow: 1;
130
130
  height: 100%;
131
131
  background: #ffffff;
package/dist/lib/index.js CHANGED
@@ -180,7 +180,7 @@ function Visualizer(props) {
180
180
  autoSaveId: "page-detail-layout-v2",
181
181
  direction: "horizontal",
182
182
  children: [
183
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_resizable_panels.Panel, { defaultSize: 75, maxSize: 95, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "main-canvas-container", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_detail_panel.default, {}) }) }),
183
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_resizable_panels.Panel, { defaultSize: 75, maxSize: 95, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "main-content-container", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_detail_panel.default, {}) }) }),
184
184
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_resizable_panels.PanelResizeHandle, {}),
185
185
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_resizable_panels.Panel, { maxSize: 95, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "main-side", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_detail_side.default, {}) }) })
186
186
  ]