@midscene/visualizer 0.26.2-beta-20250812091127.0 → 0.26.3-beta-20250813021342.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 (124) hide show
  1. package/dist/es/blank_polyfill.mjs +2 -0
  2. package/dist/es/component/blackboard.css +12 -5
  3. package/dist/es/component/blackboard.mjs +266 -0
  4. package/dist/es/component/color.mjs +35 -0
  5. package/dist/es/component/describer.css +9 -5
  6. package/dist/es/component/describer.mjs +128 -0
  7. package/dist/es/component/env-config.mjs +112 -0
  8. package/dist/es/component/github-star.css +1 -0
  9. package/dist/es/component/github-star.mjs +20 -0
  10. package/dist/es/component/logo.css +5 -3
  11. package/dist/es/component/logo.mjs +20 -0
  12. package/dist/es/component/misc.mjs +54 -0
  13. package/dist/es/component/pixi-loader.mjs +16 -0
  14. package/dist/es/component/player.css +88 -70
  15. package/dist/es/component/player.mjs +628 -0
  16. package/dist/es/component/playground/ConfigSelector.mjs +53 -0
  17. package/dist/es/component/playground/ContextPreview.mjs +39 -0
  18. package/dist/es/component/playground/HistorySelector.mjs +193 -0
  19. package/dist/es/component/playground/PlaygroundResult.mjs +60 -0
  20. package/dist/es/component/playground/PromptInput.mjs +225 -0
  21. package/dist/es/component/playground/ServiceModeControl.mjs +100 -0
  22. package/dist/es/component/playground/index.css +140 -98
  23. package/dist/es/component/playground/playground-constants.mjs +45 -0
  24. package/dist/es/component/playground/playground-utils.mjs +89 -0
  25. package/dist/es/component/playground/useServerValid.mjs +27 -0
  26. package/dist/es/component/playground/useStaticPageAgent.mjs +12 -0
  27. package/dist/es/component/replay-scripts.mjs +271 -0
  28. package/dist/es/component/shiny-text.css +33 -22
  29. package/dist/es/component/shiny-text.mjs +15 -0
  30. package/dist/es/component/store/history.mjs +55 -0
  31. package/dist/es/component/store/store.mjs +128 -0
  32. package/dist/es/icons/close.mjs +19 -0
  33. package/dist/es/icons/history.mjs +30 -0
  34. package/dist/es/icons/magnifying-glass.mjs +39 -0
  35. package/dist/es/icons/setting.mjs +20 -0
  36. package/dist/es/index.mjs +21 -0
  37. package/dist/es/init.mjs +10 -0
  38. package/dist/es/{utils.js → utils.mjs} +51 -75
  39. package/dist/lib/blank_polyfill.js +34 -38
  40. package/dist/lib/component/blackboard.css +12 -5
  41. package/dist/lib/component/blackboard.js +293 -306
  42. package/dist/lib/component/color.js +64 -74
  43. package/dist/lib/component/describer.css +9 -5
  44. package/dist/lib/component/describer.js +158 -198
  45. package/dist/lib/component/env-config.js +142 -147
  46. package/dist/lib/component/github-star.css +1 -0
  47. package/dist/lib/component/github-star.js +51 -62
  48. package/dist/lib/component/logo.css +5 -3
  49. package/dist/lib/component/logo.js +53 -56
  50. package/dist/lib/component/misc.js +85 -84
  51. package/dist/lib/component/pixi-loader.js +49 -80
  52. package/dist/lib/component/player.css +88 -70
  53. package/dist/lib/component/player.js +627 -738
  54. package/dist/lib/component/playground/ConfigSelector.js +91 -92
  55. package/dist/lib/component/playground/ContextPreview.js +80 -72
  56. package/dist/lib/component/playground/HistorySelector.js +234 -197
  57. package/dist/lib/component/playground/PlaygroundResult.js +100 -103
  58. package/dist/lib/component/playground/PromptInput.js +250 -237
  59. package/dist/lib/component/playground/ServiceModeControl.js +124 -124
  60. package/dist/lib/component/playground/index.css +140 -98
  61. package/dist/lib/component/playground/playground-constants.js +97 -73
  62. package/dist/lib/component/playground/playground-types.js +17 -31
  63. package/dist/lib/component/playground/playground-utils.js +140 -168
  64. package/dist/lib/component/playground/useServerValid.js +55 -86
  65. package/dist/lib/component/playground/useStaticPageAgent.js +45 -51
  66. package/dist/lib/component/replay-scripts.js +291 -373
  67. package/dist/lib/component/shiny-text.css +33 -22
  68. package/dist/lib/component/shiny-text.js +46 -57
  69. package/dist/lib/component/store/history.js +58 -64
  70. package/dist/lib/component/store/store.js +132 -128
  71. package/dist/lib/icons/close.js +53 -0
  72. package/dist/lib/icons/history.js +64 -0
  73. package/dist/lib/icons/magnifying-glass.js +73 -0
  74. package/dist/lib/icons/setting.js +54 -0
  75. package/dist/lib/index.js +158 -124
  76. package/dist/lib/init.js +39 -46
  77. package/dist/lib/utils.js +105 -109
  78. package/dist/types/blank_polyfill.d.ts +2 -2
  79. package/dist/types/component/playground/ConfigSelector.d.ts +1 -0
  80. package/dist/types/component/playground/ContextPreview.d.ts +1 -0
  81. package/dist/types/component/playground/HistorySelector.d.ts +1 -0
  82. package/dist/types/component/playground/PlaygroundResult.d.ts +1 -0
  83. package/dist/types/component/playground/PromptInput.d.ts +1 -0
  84. package/dist/types/component/playground/ServiceModeControl.d.ts +1 -0
  85. package/package.json +16 -18
  86. package/dist/es/assets/close.909351c0.svg +0 -4
  87. package/dist/es/assets/history.164a4eab.svg +0 -4
  88. package/dist/es/assets/magnifying-glass.9498e70e.svg +0 -12
  89. package/dist/es/assets/setting.80ab7285.svg +0 -11
  90. package/dist/es/blank_polyfill.js +0 -10
  91. package/dist/es/component/blackboard.js +0 -286
  92. package/dist/es/component/color.js +0 -49
  93. package/dist/es/component/describer.js +0 -173
  94. package/dist/es/component/env-config.js +0 -117
  95. package/dist/es/component/github-star.js +0 -31
  96. package/dist/es/component/logo.js +0 -25
  97. package/dist/es/component/misc.js +0 -63
  98. package/dist/es/component/pixi-loader.js +0 -51
  99. package/dist/es/component/player.js +0 -746
  100. package/dist/es/component/playground/ConfigSelector.js +0 -64
  101. package/dist/es/component/playground/ContextPreview.js +0 -42
  102. package/dist/es/component/playground/HistorySelector.js +0 -168
  103. package/dist/es/component/playground/PlaygroundResult.js +0 -73
  104. package/dist/es/component/playground/PromptInput.js +0 -212
  105. package/dist/es/component/playground/ServiceModeControl.js +0 -100
  106. package/dist/es/component/playground/playground-constants.js +0 -39
  107. package/dist/es/component/playground/playground-types.js +0 -6
  108. package/dist/es/component/playground/playground-utils.js +0 -141
  109. package/dist/es/component/playground/useServerValid.js +0 -58
  110. package/dist/es/component/playground/useStaticPageAgent.js +0 -20
  111. package/dist/es/component/replay-scripts.js +0 -361
  112. package/dist/es/component/shiny-text.js +0 -30
  113. package/dist/es/component/store/history.js +0 -34
  114. package/dist/es/component/store/store.js +0 -99
  115. package/dist/es/index.js +0 -79
  116. package/dist/es/init.js +0 -17
  117. package/dist/index.css +0 -595
  118. package/dist/index.js +0 -1
  119. package/dist/lib/assets/close.909351c0.svg +0 -4
  120. package/dist/lib/assets/history.164a4eab.svg +0 -4
  121. package/dist/lib/assets/magnifying-glass.9498e70e.svg +0 -12
  122. package/dist/lib/assets/setting.80ab7285.svg +0 -11
  123. package/dist/lib/component/common.css +0 -0
  124. /package/dist/es/component/{common.css → playground/playground-types.mjs} +0 -0
@@ -1,746 +0,0 @@
1
- "use client";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
6
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
- var __spreadValues = (a, b) => {
8
- for (var prop in b || (b = {}))
9
- if (__hasOwnProp.call(b, prop))
10
- __defNormalProp(a, prop, b[prop]);
11
- if (__getOwnPropSymbols)
12
- for (var prop of __getOwnPropSymbols(b)) {
13
- if (__propIsEnum.call(b, prop))
14
- __defNormalProp(a, prop, b[prop]);
15
- }
16
- return a;
17
- };
18
- var __publicField = (obj, key, value) => {
19
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
20
- return value;
21
- };
22
- var __async = (__this, __arguments, generator) => {
23
- return new Promise((resolve, reject) => {
24
- var fulfilled = (value) => {
25
- try {
26
- step(generator.next(value));
27
- } catch (e) {
28
- reject(e);
29
- }
30
- };
31
- var rejected = (value) => {
32
- try {
33
- step(generator.throw(value));
34
- } catch (e) {
35
- reject(e);
36
- }
37
- };
38
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
39
- step((generator = generator.apply(__this, __arguments)).next());
40
- });
41
- };
42
- import Buffer2 from "buffer";
43
- import processBrowser from "process/browser";
44
- import console from "console-browserify";
45
- var buffer = {
46
- Buffer: Buffer2
47
- };
48
- import { jsx, jsxs } from "react/jsx-runtime";
49
- import "pixi.js/unsafe-eval";
50
- import * as PIXI from "pixi.js";
51
- import { useEffect, useMemo, useRef, useState } from "react";
52
- import "./player.css";
53
- import { mouseLoading, mousePointer } from "../utils";
54
- import {
55
- CaretRightOutlined,
56
- DownloadOutlined,
57
- ExportOutlined,
58
- LoadingOutlined
59
- } from "@ant-design/icons";
60
- import { treeToList } from "@midscene/shared/extractor";
61
- import { Spin, Tooltip } from "antd";
62
- import { rectMarkForItem } from "./blackboard";
63
- import { getTextureFromCache, loadTexture } from "./pixi-loader";
64
- const canvasPaddingLeft = 0;
65
- const canvasPaddingTop = 0;
66
- const cubicBezier = (t, p0, p1, p2, p3) => {
67
- const t2 = 1 - t;
68
- return p0 * t2 * t2 * t2 + 3 * p1 * t * t2 * t2 + 3 * p2 * t * t * t2 + p3 * t * t * t;
69
- };
70
- const cubicImage = (t) => {
71
- return linear(t);
72
- };
73
- const cubicInsightElement = (t) => {
74
- return cubicBezier(t, 0, 0.5, 0.5, 1);
75
- };
76
- const cubicMouse = (t) => {
77
- return linear(t);
78
- };
79
- const linear = (t) => {
80
- return t;
81
- };
82
- const sleep = (ms) => {
83
- return new Promise((resolve) => setTimeout(resolve, ms));
84
- };
85
- const ERROR_FRAME_CANCEL = "frame cancel (this is an error on purpose)";
86
- const frameKit = () => {
87
- let cancelFlag = false;
88
- return {
89
- frame: (callback) => {
90
- if (cancelFlag) {
91
- throw new Error(ERROR_FRAME_CANCEL);
92
- }
93
- requestAnimationFrame(() => {
94
- if (cancelFlag) {
95
- throw new Error(ERROR_FRAME_CANCEL);
96
- }
97
- callback(performance.now());
98
- });
99
- },
100
- timeout: (callback, ms) => {
101
- if (cancelFlag) {
102
- throw new Error(ERROR_FRAME_CANCEL);
103
- }
104
- setTimeout(() => {
105
- if (cancelFlag) {
106
- throw new Error(ERROR_FRAME_CANCEL);
107
- }
108
- callback();
109
- }, ms);
110
- },
111
- cancel: () => {
112
- cancelFlag = true;
113
- }
114
- };
115
- };
116
- const singleElementFadeInDuration = 80;
117
- const LAYER_ORDER_IMG = 0;
118
- const LAYER_ORDER_INSIGHT = 1;
119
- const LAYER_ORDER_POINTER = 2;
120
- const LAYER_ORDER_SPINNING_POINTER = 3;
121
- const downloadReport = (content) => {
122
- const blob = new Blob([content], { type: "text/html" });
123
- const url = URL.createObjectURL(blob);
124
- const a = document.createElement("a");
125
- a.href = url;
126
- a.download = "midscene_report.html";
127
- a.click();
128
- };
129
- class RecordingSession {
130
- constructor(canvas) {
131
- __publicField(this, "canvas");
132
- __publicField(this, "mediaRecorder", null);
133
- __publicField(this, "chunks");
134
- __publicField(this, "recording", false);
135
- this.canvas = canvas;
136
- this.chunks = [];
137
- }
138
- start() {
139
- const stream = this.canvas.captureStream(60);
140
- const mediaRecorder = new MediaRecorder(stream, {
141
- mimeType: "video/webm"
142
- });
143
- mediaRecorder.ondataavailable = (event) => {
144
- if (event.data.size > 0) {
145
- this.chunks.push(event.data);
146
- }
147
- };
148
- this.mediaRecorder = mediaRecorder;
149
- this.recording = true;
150
- return this.mediaRecorder.start();
151
- }
152
- stop() {
153
- var _a;
154
- if (!this.recording || !this.mediaRecorder) {
155
- console.warn("not recording");
156
- return;
157
- }
158
- this.mediaRecorder.onstop = () => {
159
- const blob = new Blob(this.chunks, { type: "video/webm" });
160
- const url = URL.createObjectURL(blob);
161
- const a = document.createElement("a");
162
- a.href = url;
163
- a.download = "midscene_replay.webm";
164
- a.click();
165
- URL.revokeObjectURL(url);
166
- };
167
- (_a = this.mediaRecorder) == null ? void 0 : _a.stop();
168
- this.recording = false;
169
- this.mediaRecorder = null;
170
- }
171
- }
172
- function Player(props) {
173
- var _a;
174
- const [titleText, setTitleText] = useState("");
175
- const [subTitleText, setSubTitleText] = useState("");
176
- const scripts = props == null ? void 0 : props.replayScripts;
177
- const imageWidth = (props == null ? void 0 : props.imageWidth) || 1920;
178
- const imageHeight = (props == null ? void 0 : props.imageHeight) || 1080;
179
- const fitMode = (props == null ? void 0 : props.fitMode) || "height";
180
- const currentImg = useRef(((_a = scripts == null ? void 0 : scripts[0]) == null ? void 0 : _a.img) || null);
181
- const divContainerRef = useRef(null);
182
- const app = useMemo(() => new PIXI.Application(), []);
183
- const pointerSprite = useRef(null);
184
- const spinningPointerSprite = useRef(null);
185
- const [replayMark, setReplayMark] = useState(0);
186
- const triggerReplay = () => {
187
- setReplayMark(Date.now());
188
- };
189
- const windowContentContainer = useMemo(() => {
190
- const container = new PIXI.Container();
191
- return container;
192
- }, []);
193
- const insightMarkContainer = useMemo(() => {
194
- const container = new PIXI.Container();
195
- container.zIndex = LAYER_ORDER_INSIGHT;
196
- return container;
197
- }, []);
198
- const basicCameraState = {
199
- left: 0,
200
- top: 0,
201
- width: imageWidth,
202
- pointerLeft: Math.round(imageWidth / 2),
203
- pointerTop: Math.round(imageHeight / 2)
204
- };
205
- const [animationProgress, setAnimationProgress] = useState(-1);
206
- const cancelFlag = useRef(false);
207
- useEffect(() => {
208
- cancelFlag.current = false;
209
- return () => {
210
- cancelFlag.current = true;
211
- };
212
- }, []);
213
- const cameraState = useRef(__spreadValues({}, basicCameraState));
214
- const repaintImage = () => __async(this, null, function* () {
215
- const imgToUpdate = currentImg.current;
216
- if (!imgToUpdate) {
217
- console.warn("no image to update");
218
- return;
219
- }
220
- if (!getTextureFromCache(imgToUpdate)) {
221
- console.warn("image not loaded", imgToUpdate);
222
- yield loadTexture(imgToUpdate);
223
- }
224
- const texture = getTextureFromCache(imgToUpdate);
225
- if (!texture) {
226
- throw new Error("texture not found");
227
- }
228
- const sprite = PIXI.Sprite.from(texture);
229
- if (!sprite) {
230
- throw new Error("sprite not found");
231
- }
232
- const mainImgLabel = "main-img";
233
- const child = windowContentContainer.getChildByLabel(mainImgLabel);
234
- if (child) {
235
- windowContentContainer.removeChild(child);
236
- }
237
- sprite.label = mainImgLabel;
238
- sprite.zIndex = LAYER_ORDER_IMG;
239
- sprite.width = imageWidth;
240
- sprite.height = imageHeight;
241
- windowContentContainer.addChild(sprite);
242
- });
243
- const spinningPointer = (frame) => {
244
- var _a2, _b;
245
- if (!spinningPointerSprite.current) {
246
- spinningPointerSprite.current = PIXI.Sprite.from(mouseLoading);
247
- spinningPointerSprite.current.zIndex = LAYER_ORDER_SPINNING_POINTER;
248
- spinningPointerSprite.current.anchor.set(0.5, 0.5);
249
- spinningPointerSprite.current.scale.set(0.5);
250
- spinningPointerSprite.current.label = "spinning-pointer";
251
- }
252
- spinningPointerSprite.current.x = ((_a2 = pointerSprite.current) == null ? void 0 : _a2.x) || 0;
253
- spinningPointerSprite.current.y = ((_b = pointerSprite.current) == null ? void 0 : _b.y) || 0;
254
- windowContentContainer.addChild(spinningPointerSprite.current);
255
- let startTime;
256
- let isCancelled = false;
257
- const animate = (currentTime) => {
258
- if (isCancelled)
259
- return;
260
- if (!startTime)
261
- startTime = currentTime;
262
- const elapsedTime = currentTime - startTime;
263
- const progress = (Math.sin(elapsedTime / 500 - Math.PI / 2) + 1) / 2;
264
- const rotation = progress * Math.PI * 2;
265
- if (spinningPointerSprite.current) {
266
- spinningPointerSprite.current.rotation = rotation;
267
- }
268
- frame(animate);
269
- };
270
- frame(animate);
271
- const stopFn = () => {
272
- if (spinningPointerSprite.current) {
273
- windowContentContainer.removeChild(spinningPointerSprite.current);
274
- }
275
- isCancelled = true;
276
- };
277
- return stopFn;
278
- };
279
- const updatePointer = (img, x, y) => __async(this, null, function* () {
280
- var _a2, _b;
281
- if (!getTextureFromCache(img)) {
282
- console.warn("image not loaded", img);
283
- yield loadTexture(img);
284
- }
285
- const texture = getTextureFromCache(img);
286
- if (!texture) {
287
- throw new Error("texture not found");
288
- }
289
- const sprite = PIXI.Sprite.from(texture);
290
- let targetX = (_a2 = pointerSprite.current) == null ? void 0 : _a2.x;
291
- let targetY = (_b = pointerSprite.current) == null ? void 0 : _b.y;
292
- if (typeof x === "number") {
293
- targetX = x;
294
- }
295
- if (typeof y === "number") {
296
- targetY = y;
297
- }
298
- if (typeof targetX === "undefined" || typeof targetY === "undefined") {
299
- console.warn("invalid pointer position", x, y);
300
- return;
301
- }
302
- if (pointerSprite.current) {
303
- const pointer = windowContentContainer.getChildByLabel("pointer");
304
- if (pointer) {
305
- windowContentContainer.removeChild(pointer);
306
- }
307
- }
308
- pointerSprite.current = sprite;
309
- pointerSprite.current.x = targetX;
310
- pointerSprite.current.y = targetY;
311
- pointerSprite.current.label = "pointer";
312
- pointerSprite.current.zIndex = LAYER_ORDER_POINTER;
313
- windowContentContainer.addChild(pointerSprite.current);
314
- });
315
- const updateCamera = (state) => {
316
- cameraState.current = state;
317
- const newScale = Math.max(1, imageWidth / state.width);
318
- windowContentContainer.scale.set(newScale);
319
- windowContentContainer.x = Math.round(
320
- canvasPaddingLeft - state.left * newScale
321
- );
322
- windowContentContainer.y = Math.round(
323
- canvasPaddingTop - state.top * newScale
324
- );
325
- const pointer = windowContentContainer.getChildByLabel("pointer");
326
- if (pointer) {
327
- pointer.scale.set(1 / newScale);
328
- if (typeof state.pointerLeft === "number" && typeof state.pointerTop === "number") {
329
- pointer.x = state.pointerLeft;
330
- pointer.y = state.pointerTop;
331
- }
332
- }
333
- };
334
- const cameraAnimation = (targetState, duration, frame) => __async(this, null, function* () {
335
- const currentState = __spreadValues({}, cameraState.current);
336
- const startLeft = currentState.left;
337
- const startTop = currentState.top;
338
- const startPointerLeft = currentState.pointerLeft;
339
- const startPointerTop = currentState.pointerTop;
340
- const startScale = currentState.width / imageWidth;
341
- const startTime = performance.now();
342
- const shouldMovePointer = typeof targetState.pointerLeft === "number" && typeof targetState.pointerTop === "number" && (targetState.pointerLeft !== startPointerLeft || targetState.pointerTop !== startPointerTop);
343
- const pointerMoveDuration = shouldMovePointer ? duration * 0.375 : 0;
344
- const cameraMoveStart = pointerMoveDuration;
345
- const cameraMoveDuration = duration - pointerMoveDuration;
346
- yield new Promise((resolve) => {
347
- const animate = (currentTime) => {
348
- const nextState = __spreadValues({}, cameraState.current);
349
- const elapsedTime = currentTime - startTime;
350
- if (shouldMovePointer) {
351
- if (elapsedTime <= pointerMoveDuration) {
352
- const rawMouseProgress = Math.min(
353
- elapsedTime / pointerMoveDuration,
354
- 1
355
- );
356
- const mouseProgress = cubicMouse(rawMouseProgress);
357
- nextState.pointerLeft = startPointerLeft + (targetState.pointerLeft - startPointerLeft) * mouseProgress;
358
- nextState.pointerTop = startPointerTop + (targetState.pointerTop - startPointerTop) * mouseProgress;
359
- } else {
360
- nextState.pointerLeft = targetState.pointerLeft;
361
- nextState.pointerTop = targetState.pointerTop;
362
- }
363
- }
364
- if (elapsedTime > cameraMoveStart) {
365
- const cameraElapsedTime = elapsedTime - cameraMoveStart;
366
- const rawCameraProgress = Math.min(
367
- cameraElapsedTime / cameraMoveDuration,
368
- 1
369
- );
370
- const cameraProgress = cubicImage(rawCameraProgress);
371
- const targetScale = targetState.width / imageWidth;
372
- const progressScale = startScale + (targetScale - startScale) * cameraProgress;
373
- const progressWidth = imageWidth * progressScale;
374
- const progressHeight = imageHeight * progressScale;
375
- nextState.width = progressWidth;
376
- const progressLeft = startLeft + (targetState.left - startLeft) * cameraProgress;
377
- const progressTop = startTop + (targetState.top - startTop) * cameraProgress;
378
- const horizontalExceed = progressLeft + progressWidth - imageWidth;
379
- const verticalExceed = progressTop + progressHeight - imageHeight;
380
- nextState.left = horizontalExceed > 0 ? progressLeft + horizontalExceed : progressLeft;
381
- nextState.top = verticalExceed > 0 ? progressTop + verticalExceed : progressTop;
382
- }
383
- updateCamera(nextState);
384
- if (elapsedTime < duration) {
385
- frame(animate);
386
- } else {
387
- resolve();
388
- }
389
- };
390
- frame(animate);
391
- });
392
- });
393
- const fadeInGraphics = (graphics, duration, frame, targetAlpha = 1) => {
394
- return new Promise((resolve) => {
395
- const startTime = performance.now();
396
- const animate = (currentTime) => {
397
- const elapsedTime = currentTime - startTime;
398
- const progress = Math.min(elapsedTime / duration, 1);
399
- graphics.alpha = targetAlpha === 0 ? 1 - linear(progress) : linear(progress);
400
- if (elapsedTime < duration) {
401
- frame(animate);
402
- } else {
403
- resolve();
404
- }
405
- };
406
- frame(animate);
407
- });
408
- };
409
- const fadeOutItem = (graphics, duration, frame) => __async(this, null, function* () {
410
- return fadeInGraphics(graphics, duration, frame, 0);
411
- });
412
- const insightElementsAnimation = (elements, highlightElements, searchArea, duration, frame) => __async(this, null, function* () {
413
- insightMarkContainer.removeChildren();
414
- const elementsToAdd = [...elements];
415
- const totalLength = elementsToAdd.length;
416
- let childrenCount = 0;
417
- yield new Promise((resolve) => {
418
- const startTime = performance.now();
419
- const animate = (currentTime) => {
420
- const elapsedTime = currentTime - startTime;
421
- const progress = cubicInsightElement(
422
- Math.min(elapsedTime / duration, 1)
423
- );
424
- const elementsToAddNow = Math.floor(progress * totalLength);
425
- while (childrenCount < elementsToAddNow) {
426
- const randomIndex = Math.floor(Math.random() * elementsToAdd.length);
427
- const element = elementsToAdd.splice(randomIndex, 1)[0];
428
- if (element) {
429
- const [insightMarkGraphic] = rectMarkForItem(
430
- element.rect,
431
- element.content,
432
- "element"
433
- );
434
- insightMarkGraphic.alpha = 0;
435
- insightMarkContainer.addChild(insightMarkGraphic);
436
- childrenCount++;
437
- fadeInGraphics(
438
- insightMarkGraphic,
439
- singleElementFadeInDuration,
440
- frame
441
- );
442
- }
443
- }
444
- if (elapsedTime < duration) {
445
- frame(animate);
446
- } else {
447
- while (elementsToAdd.length > 0) {
448
- const randomIndex = Math.floor(
449
- Math.random() * elementsToAdd.length
450
- );
451
- const element = elementsToAdd.splice(randomIndex, 1)[0];
452
- const [insightMarkGraphic] = rectMarkForItem(
453
- element.rect,
454
- element.content,
455
- "element"
456
- );
457
- insightMarkGraphic.alpha = 1;
458
- insightMarkContainer.addChild(insightMarkGraphic);
459
- }
460
- if (searchArea) {
461
- const [searchAreaGraphic] = rectMarkForItem(
462
- searchArea,
463
- "Search Area",
464
- "searchArea"
465
- );
466
- searchAreaGraphic.alpha = 1;
467
- insightMarkContainer.addChild(searchAreaGraphic);
468
- }
469
- highlightElements.map((element) => {
470
- const [insightMarkGraphic] = rectMarkForItem(
471
- element.rect,
472
- element.content || "",
473
- "highlight"
474
- );
475
- insightMarkGraphic.alpha = 1;
476
- insightMarkContainer.addChild(insightMarkGraphic);
477
- });
478
- resolve();
479
- }
480
- };
481
- frame(animate);
482
- });
483
- });
484
- const init = () => __async(this, null, function* () {
485
- if (!divContainerRef.current || !scripts)
486
- return;
487
- yield app.init({
488
- width: imageWidth,
489
- height: imageHeight,
490
- background: 16053492,
491
- autoDensity: true,
492
- antialias: true
493
- });
494
- if (!divContainerRef.current)
495
- return;
496
- divContainerRef.current.appendChild(app.canvas);
497
- windowContentContainer.x = 0;
498
- windowContentContainer.y = 0;
499
- app.stage.addChild(windowContentContainer);
500
- insightMarkContainer.x = 0;
501
- insightMarkContainer.y = 0;
502
- windowContentContainer.addChild(insightMarkContainer);
503
- });
504
- const [isRecording, setIsRecording] = useState(false);
505
- const recorderSessionRef = useRef(null);
506
- const handleExport = () => {
507
- if (recorderSessionRef.current) {
508
- console.warn("recorderSession exists");
509
- return;
510
- }
511
- if (!app.canvas) {
512
- console.warn("canvas is not initialized");
513
- return;
514
- }
515
- recorderSessionRef.current = new RecordingSession(app.canvas);
516
- setIsRecording(true);
517
- triggerReplay();
518
- };
519
- const play = () => {
520
- let cancelFn;
521
- Promise.resolve(
522
- (() => __async(this, null, function* () {
523
- var _a2;
524
- if (!app) {
525
- throw new Error("app is not initialized");
526
- }
527
- if (!scripts) {
528
- throw new Error("scripts is required");
529
- }
530
- const { frame, cancel, timeout } = frameKit();
531
- cancelFn = cancel;
532
- const allImages = scripts.filter((item) => !!item.img).map((item) => item.img);
533
- yield Promise.all(
534
- [...allImages, mouseLoading, mousePointer].map(loadTexture)
535
- );
536
- insightMarkContainer.removeChildren();
537
- yield updatePointer(mousePointer, imageWidth / 2, imageHeight / 2);
538
- yield repaintImage();
539
- yield updateCamera(__spreadValues({}, basicCameraState));
540
- const totalDuration = scripts.reduce((acc, item) => {
541
- return acc + item.duration + (item.camera && item.insightCameraDuration ? item.insightCameraDuration : 0);
542
- }, 0);
543
- const progressUpdateInterval = 200;
544
- const startTime = performance.now();
545
- setAnimationProgress(0);
546
- const updateProgress = () => {
547
- const progress = Math.min(
548
- (performance.now() - startTime) / totalDuration,
549
- 1
550
- );
551
- setAnimationProgress(progress);
552
- if (progress < 1) {
553
- return timeout(updateProgress, progressUpdateInterval);
554
- }
555
- };
556
- frame(updateProgress);
557
- if (recorderSessionRef.current) {
558
- recorderSessionRef.current.start();
559
- }
560
- for (const index in scripts) {
561
- const item = scripts[index];
562
- setTitleText(item.title || "");
563
- setSubTitleText(item.subTitle || "");
564
- if (item.type === "sleep") {
565
- yield sleep(item.duration);
566
- } else if (item.type === "insight") {
567
- if (!item.img) {
568
- throw new Error("img is required");
569
- }
570
- currentImg.current = item.img;
571
- yield repaintImage();
572
- const elements = ((_a2 = item.context) == null ? void 0 : _a2.tree) ? treeToList(item.context.tree) : [];
573
- const highlightElements = item.highlightElement ? [item.highlightElement] : [];
574
- yield insightElementsAnimation(
575
- elements,
576
- highlightElements,
577
- item.searchArea,
578
- item.duration,
579
- frame
580
- );
581
- if (item.camera) {
582
- if (!item.insightCameraDuration) {
583
- throw new Error("insightCameraDuration is required");
584
- }
585
- yield cameraAnimation(
586
- item.camera,
587
- item.insightCameraDuration,
588
- frame
589
- );
590
- }
591
- } else if (item.type === "clear-insight") {
592
- yield fadeOutItem(insightMarkContainer, item.duration, frame);
593
- insightMarkContainer.removeChildren();
594
- insightMarkContainer.alpha = 1;
595
- } else if (item.type === "img") {
596
- if (item.img && item.img !== currentImg.current) {
597
- currentImg.current = item.img;
598
- yield repaintImage();
599
- }
600
- if (item.camera) {
601
- yield cameraAnimation(item.camera, item.duration, frame);
602
- } else {
603
- yield sleep(item.duration);
604
- }
605
- } else if (item.type === "pointer") {
606
- if (!item.img) {
607
- throw new Error("pointer img is required");
608
- }
609
- yield updatePointer(item.img);
610
- } else if (item.type === "spinning-pointer") {
611
- const stop = spinningPointer(frame);
612
- yield sleep(item.duration);
613
- stop();
614
- }
615
- }
616
- if (recorderSessionRef.current) {
617
- recorderSessionRef.current.stop();
618
- recorderSessionRef.current = null;
619
- setIsRecording(false);
620
- }
621
- }))().catch((e) => {
622
- console.error("player error", e);
623
- })
624
- );
625
- return () => {
626
- cancelFn == null ? void 0 : cancelFn();
627
- };
628
- };
629
- useEffect(() => {
630
- Promise.resolve(
631
- (() => __async(this, null, function* () {
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
- }
647
- triggerReplay();
648
- }))()
649
- );
650
- return () => {
651
- try {
652
- app.destroy(true, { children: true, texture: true });
653
- } catch (e) {
654
- console.warn("destroy failed", e);
655
- }
656
- };
657
- }, [imageWidth, imageHeight, fitMode]);
658
- useEffect(() => {
659
- if (replayMark) {
660
- return play();
661
- }
662
- }, [replayMark]);
663
- const [mouseOverStatusIcon, setMouseOverStatusIcon] = useState(false);
664
- const progressString = Math.round(animationProgress * 100);
665
- const transitionStyle = animationProgress === 0 ? "none" : "0.3s";
666
- const canReplayNow = animationProgress === 1;
667
- useEffect(() => {
668
- if (canReplayNow) {
669
- const listener = (event) => {
670
- if (event.key === " ") {
671
- triggerReplay();
672
- }
673
- };
674
- window.addEventListener("keydown", listener);
675
- return () => {
676
- window.removeEventListener("keydown", listener);
677
- };
678
- }
679
- }, [canReplayNow]);
680
- let statusIconElement;
681
- let statusOnClick = () => {
682
- };
683
- if (animationProgress < 1) {
684
- statusIconElement = /* @__PURE__ */ jsx(Spin, { indicator: /* @__PURE__ */ jsx(LoadingOutlined, { spin: true, color: "#333" }), size: "default" });
685
- } else if (mouseOverStatusIcon) {
686
- statusIconElement = /* @__PURE__ */ jsx(Spin, { indicator: /* @__PURE__ */ jsx(CaretRightOutlined, { color: "#333" }), size: "default" });
687
- statusOnClick = () => triggerReplay();
688
- } else {
689
- statusIconElement = // <Spin indicator={<CheckCircleOutlined />} size="default" />
690
- /* @__PURE__ */ jsx(Spin, { indicator: /* @__PURE__ */ jsx(CaretRightOutlined, { color: "#333" }), size: "default" });
691
- }
692
- return /* @__PURE__ */ jsxs("div", { className: "player-container", children: [
693
- /* @__PURE__ */ jsx("div", { className: "canvas-container", ref: divContainerRef }),
694
- /* @__PURE__ */ jsx("div", { className: "player-timeline-wrapper", children: /* @__PURE__ */ jsx("div", { className: "player-timeline", children: /* @__PURE__ */ jsx(
695
- "div",
696
- {
697
- className: "player-timeline-progress",
698
- style: {
699
- width: `${progressString}%`,
700
- transition: transitionStyle
701
- }
702
- }
703
- ) }) }),
704
- /* @__PURE__ */ jsx("div", { className: "player-tools-wrapper", children: /* @__PURE__ */ jsx("div", { className: "player-tools", children: /* @__PURE__ */ jsxs("div", { className: "player-control", children: [
705
- /* @__PURE__ */ jsxs("div", { className: "status-text", children: [
706
- /* @__PURE__ */ jsx("div", { className: "title", children: titleText }),
707
- /* @__PURE__ */ jsx(Tooltip, { title: subTitleText, children: /* @__PURE__ */ jsx("div", { className: "subtitle", children: subTitleText }) })
708
- ] }),
709
- isRecording ? null : /* @__PURE__ */ jsx(
710
- "div",
711
- {
712
- className: "status-icon",
713
- onMouseEnter: () => setMouseOverStatusIcon(true),
714
- onMouseLeave: () => setMouseOverStatusIcon(false),
715
- onClick: statusOnClick,
716
- children: statusIconElement
717
- }
718
- ),
719
- (props == null ? void 0 : props.reportFileContent) ? /* @__PURE__ */ jsx(Tooltip, { title: "Download Report", children: /* @__PURE__ */ jsx(
720
- "div",
721
- {
722
- className: "status-icon",
723
- onMouseEnter: () => setMouseOverStatusIcon(true),
724
- onMouseLeave: () => setMouseOverStatusIcon(false),
725
- onClick: () => downloadReport(props.reportFileContent),
726
- children: /* @__PURE__ */ jsx(DownloadOutlined, { color: "#333" })
727
- }
728
- ) }) : null,
729
- /* @__PURE__ */ jsx(Tooltip, { title: isRecording ? "Generating..." : "Export Video", children: /* @__PURE__ */ jsx(
730
- "div",
731
- {
732
- className: "status-icon",
733
- onClick: isRecording ? void 0 : handleExport,
734
- style: {
735
- opacity: isRecording ? 0.5 : 1,
736
- cursor: isRecording ? "not-allowed" : "pointer"
737
- },
738
- children: isRecording ? /* @__PURE__ */ jsx(Spin, { size: "default", percent: progressString }) : /* @__PURE__ */ jsx(ExportOutlined, {})
739
- }
740
- ) })
741
- ] }) }) })
742
- ] });
743
- }
744
- export {
745
- Player
746
- };