@sqaitech/visualizer 0.30.10
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.
- package/LICENSE +21 -0
- package/README.md +9 -0
- package/dist/es/component/blackboard/index.css +33 -0
- package/dist/es/component/blackboard/index.mjs +278 -0
- package/dist/es/component/config-selector/index.mjs +104 -0
- package/dist/es/component/context-preview/index.mjs +38 -0
- package/dist/es/component/env-config/index.mjs +112 -0
- package/dist/es/component/env-config-reminder/index.css +22 -0
- package/dist/es/component/env-config-reminder/index.mjs +28 -0
- package/dist/es/component/form-field/index.mjs +163 -0
- package/dist/es/component/history-selector/index.css +135 -0
- package/dist/es/component/history-selector/index.mjs +170 -0
- package/dist/es/component/index.mjs +1 -0
- package/dist/es/component/logo/index.css +13 -0
- package/dist/es/component/logo/index.mjs +20 -0
- package/dist/es/component/misc/index.mjs +94 -0
- package/dist/es/component/nav-actions/index.mjs +32 -0
- package/dist/es/component/nav-actions/style.css +35 -0
- package/dist/es/component/player/index.css +185 -0
- package/dist/es/component/player/index.mjs +856 -0
- package/dist/es/component/playground/index.css +431 -0
- package/dist/es/component/playground/index.mjs +8 -0
- package/dist/es/component/playground/playground-demo-ui-context.json +290 -0
- package/dist/es/component/playground-result/index.css +34 -0
- package/dist/es/component/playground-result/index.mjs +62 -0
- package/dist/es/component/prompt-input/index.css +391 -0
- package/dist/es/component/prompt-input/index.mjs +730 -0
- package/dist/es/component/service-mode-control/index.mjs +105 -0
- package/dist/es/component/shiny-text/index.css +75 -0
- package/dist/es/component/shiny-text/index.mjs +15 -0
- package/dist/es/component/universal-playground/index.css +341 -0
- package/dist/es/component/universal-playground/index.mjs +302 -0
- package/dist/es/component/universal-playground/providers/context-provider.mjs +52 -0
- package/dist/es/component/universal-playground/providers/indexeddb-storage-provider.mjs +207 -0
- package/dist/es/component/universal-playground/providers/storage-provider.mjs +210 -0
- package/dist/es/hooks/usePlaygroundExecution.mjs +180 -0
- package/dist/es/hooks/usePlaygroundState.mjs +203 -0
- package/dist/es/hooks/useSafeOverrideAIConfig.mjs +24 -0
- package/dist/es/hooks/useServerValid.mjs +30 -0
- package/dist/es/icons/avatar.mjs +28 -0
- package/dist/es/icons/close.mjs +19 -0
- package/dist/es/icons/global-perspective.mjs +16 -0
- package/dist/es/icons/history.mjs +30 -0
- package/dist/es/icons/magnifying-glass.mjs +39 -0
- package/dist/es/icons/player-setting.mjs +26 -0
- package/dist/es/icons/setting.mjs +20 -0
- package/dist/es/icons/show-marker.mjs +16 -0
- package/dist/es/index.mjs +25 -0
- package/dist/es/store/history.mjs +89 -0
- package/dist/es/store/store.mjs +186 -0
- package/dist/es/types.mjs +70 -0
- package/dist/es/utils/color.mjs +35 -0
- package/dist/es/utils/constants.mjs +99 -0
- package/dist/es/utils/index.mjs +10 -0
- package/dist/es/utils/pixi-loader.mjs +16 -0
- package/dist/es/utils/playground-utils.mjs +67 -0
- package/dist/es/utils/replay-scripts.mjs +312 -0
- package/dist/lib/component/blackboard/index.css +33 -0
- package/dist/lib/component/blackboard/index.js +321 -0
- package/dist/lib/component/config-selector/index.js +148 -0
- package/dist/lib/component/context-preview/index.js +83 -0
- package/dist/lib/component/env-config/index.js +146 -0
- package/dist/lib/component/env-config-reminder/index.css +22 -0
- package/dist/lib/component/env-config-reminder/index.js +62 -0
- package/dist/lib/component/form-field/index.js +209 -0
- package/dist/lib/component/history-selector/index.css +135 -0
- package/dist/lib/component/history-selector/index.js +216 -0
- package/dist/lib/component/index.js +60 -0
- package/dist/lib/component/logo/index.css +13 -0
- package/dist/lib/component/logo/index.js +57 -0
- package/dist/lib/component/misc/index.js +150 -0
- package/dist/lib/component/nav-actions/index.js +66 -0
- package/dist/lib/component/nav-actions/style.css +35 -0
- package/dist/lib/component/player/index.css +185 -0
- package/dist/lib/component/player/index.js +902 -0
- package/dist/lib/component/playground/index.css +431 -0
- package/dist/lib/component/playground/index.js +113 -0
- package/dist/lib/component/playground/playground-demo-ui-context.json +290 -0
- package/dist/lib/component/playground-result/index.css +34 -0
- package/dist/lib/component/playground-result/index.js +106 -0
- package/dist/lib/component/prompt-input/index.css +391 -0
- package/dist/lib/component/prompt-input/index.js +774 -0
- package/dist/lib/component/service-mode-control/index.js +139 -0
- package/dist/lib/component/shiny-text/index.css +75 -0
- package/dist/lib/component/shiny-text/index.js +49 -0
- package/dist/lib/component/universal-playground/index.css +341 -0
- package/dist/lib/component/universal-playground/index.js +350 -0
- package/dist/lib/component/universal-playground/providers/context-provider.js +95 -0
- package/dist/lib/component/universal-playground/providers/indexeddb-storage-provider.js +247 -0
- package/dist/lib/component/universal-playground/providers/storage-provider.js +268 -0
- package/dist/lib/hooks/usePlaygroundExecution.js +214 -0
- package/dist/lib/hooks/usePlaygroundState.js +237 -0
- package/dist/lib/hooks/useSafeOverrideAIConfig.js +61 -0
- package/dist/lib/hooks/useServerValid.js +64 -0
- package/dist/lib/icons/avatar.js +62 -0
- package/dist/lib/icons/close.js +53 -0
- package/dist/lib/icons/global-perspective.js +50 -0
- package/dist/lib/icons/history.js +64 -0
- package/dist/lib/icons/magnifying-glass.js +73 -0
- package/dist/lib/icons/player-setting.js +60 -0
- package/dist/lib/icons/setting.js +54 -0
- package/dist/lib/icons/show-marker.js +50 -0
- package/dist/lib/index.js +187 -0
- package/dist/lib/store/history.js +96 -0
- package/dist/lib/store/store.js +196 -0
- package/dist/lib/types.js +116 -0
- package/dist/lib/utils/color.js +75 -0
- package/dist/lib/utils/constants.js +154 -0
- package/dist/lib/utils/index.js +63 -0
- package/dist/lib/utils/pixi-loader.js +56 -0
- package/dist/lib/utils/playground-utils.js +110 -0
- package/dist/lib/utils/replay-scripts.js +355 -0
- package/dist/types/component/blackboard/index.d.ts +15 -0
- package/dist/types/component/config-selector/index.d.ts +9 -0
- package/dist/types/component/context-preview/index.d.ts +9 -0
- package/dist/types/component/env-config/index.d.ts +6 -0
- package/dist/types/component/env-config-reminder/index.d.ts +6 -0
- package/dist/types/component/form-field/index.d.ts +17 -0
- package/dist/types/component/history-selector/index.d.ts +10 -0
- package/dist/types/component/index.d.ts +1 -0
- package/dist/types/component/logo/index.d.ts +5 -0
- package/dist/types/component/misc/index.d.ts +6 -0
- package/dist/types/component/nav-actions/index.d.ts +10 -0
- package/dist/types/component/player/index.d.ts +13 -0
- package/dist/types/component/playground/index.d.ts +7 -0
- package/dist/types/component/playground-result/index.d.ts +20 -0
- package/dist/types/component/prompt-input/index.d.ts +22 -0
- package/dist/types/component/service-mode-control/index.d.ts +6 -0
- package/dist/types/component/shiny-text/index.d.ts +12 -0
- package/dist/types/component/universal-playground/index.d.ts +4 -0
- package/dist/types/component/universal-playground/providers/context-provider.d.ts +37 -0
- package/dist/types/component/universal-playground/providers/indexeddb-storage-provider.d.ts +71 -0
- package/dist/types/component/universal-playground/providers/storage-provider.d.ts +58 -0
- package/dist/types/hooks/usePlaygroundExecution.d.ts +10 -0
- package/dist/types/hooks/usePlaygroundState.d.ts +26 -0
- package/dist/types/hooks/useSafeOverrideAIConfig.d.ts +16 -0
- package/dist/types/hooks/useServerValid.d.ts +1 -0
- package/dist/types/index.d.ts +27 -0
- package/dist/types/store/history.d.ts +16 -0
- package/dist/types/store/store.d.ts +36 -0
- package/dist/types/types.d.ts +161 -0
- package/dist/types/utils/color.d.ts +4 -0
- package/dist/types/utils/constants.d.ts +74 -0
- package/dist/types/utils/index.d.ts +4 -0
- package/dist/types/utils/pixi-loader.d.ts +5 -0
- package/dist/types/utils/playground-utils.d.ts +6 -0
- package/dist/types/utils/replay-scripts.d.ts +34 -0
- package/package.json +85 -0
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import "pixi.js/unsafe-eval";
|
|
4
|
+
import { Application, Container, Sprite } from "pixi.js";
|
|
5
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
6
|
+
import "./index.css";
|
|
7
|
+
import { mouseLoading, mousePointer } from "../../utils/index.mjs";
|
|
8
|
+
import { CaretRightOutlined, DownloadOutlined, ExportOutlined, LoadingOutlined } from "@ant-design/icons";
|
|
9
|
+
import { treeToList } from "@sqaitech/shared/extractor";
|
|
10
|
+
import { Dropdown, Spin, Switch, Tooltip } from "antd";
|
|
11
|
+
import global_perspective from "../../icons/global-perspective.mjs";
|
|
12
|
+
import player_setting from "../../icons/player-setting.mjs";
|
|
13
|
+
import show_marker from "../../icons/show-marker.mjs";
|
|
14
|
+
import { useBlackboardPreference } from "../../store/store.mjs";
|
|
15
|
+
import { getTextureFromCache, loadTexture } from "../../utils/pixi-loader.mjs";
|
|
16
|
+
import { rectMarkForItem } from "../blackboard/index.mjs";
|
|
17
|
+
function _define_property(obj, key, value) {
|
|
18
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
19
|
+
value: value,
|
|
20
|
+
enumerable: true,
|
|
21
|
+
configurable: true,
|
|
22
|
+
writable: true
|
|
23
|
+
});
|
|
24
|
+
else obj[key] = value;
|
|
25
|
+
return obj;
|
|
26
|
+
}
|
|
27
|
+
const canvasPaddingLeft = 0;
|
|
28
|
+
const canvasPaddingTop = 0;
|
|
29
|
+
const cubicBezier = (t, p0, p1, p2, p3)=>{
|
|
30
|
+
const t2 = 1 - t;
|
|
31
|
+
return p0 * t2 * t2 * t2 + 3 * p1 * t * t2 * t2 + 3 * p2 * t * t * t2 + p3 * t * t * t;
|
|
32
|
+
};
|
|
33
|
+
const cubicImage = (t)=>linear(t);
|
|
34
|
+
const cubicInsightElement = (t)=>cubicBezier(t, 0, 0.5, 0.5, 1);
|
|
35
|
+
const cubicMouse = (t)=>linear(t);
|
|
36
|
+
const linear = (t)=>t;
|
|
37
|
+
const sleep = (ms)=>new Promise((resolve)=>setTimeout(resolve, ms));
|
|
38
|
+
const ERROR_FRAME_CANCEL = 'frame cancel (this is an error on purpose)';
|
|
39
|
+
const frameKit = ()=>{
|
|
40
|
+
let cancelFlag = false;
|
|
41
|
+
return {
|
|
42
|
+
frame: (callback)=>{
|
|
43
|
+
if (cancelFlag) throw new Error(ERROR_FRAME_CANCEL);
|
|
44
|
+
requestAnimationFrame(()=>{
|
|
45
|
+
if (cancelFlag) throw new Error(ERROR_FRAME_CANCEL);
|
|
46
|
+
callback(performance.now());
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
timeout: (callback, ms)=>{
|
|
50
|
+
if (cancelFlag) throw new Error(ERROR_FRAME_CANCEL);
|
|
51
|
+
setTimeout(()=>{
|
|
52
|
+
if (cancelFlag) throw new Error(ERROR_FRAME_CANCEL);
|
|
53
|
+
callback();
|
|
54
|
+
}, ms);
|
|
55
|
+
},
|
|
56
|
+
cancel: ()=>{
|
|
57
|
+
cancelFlag = true;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
const singleElementFadeInDuration = 80;
|
|
62
|
+
const LAYER_ORDER_IMG = 0;
|
|
63
|
+
const LAYER_ORDER_INSIGHT = 1;
|
|
64
|
+
const LAYER_ORDER_POINTER = 2;
|
|
65
|
+
const LAYER_ORDER_SPINNING_POINTER = 3;
|
|
66
|
+
const downloadReport = (content)=>{
|
|
67
|
+
const blob = new Blob([
|
|
68
|
+
content
|
|
69
|
+
], {
|
|
70
|
+
type: 'text/html'
|
|
71
|
+
});
|
|
72
|
+
const url = URL.createObjectURL(blob);
|
|
73
|
+
const a = document.createElement('a');
|
|
74
|
+
a.href = url;
|
|
75
|
+
a.download = 'midscene_report.html';
|
|
76
|
+
a.click();
|
|
77
|
+
};
|
|
78
|
+
class RecordingSession {
|
|
79
|
+
start() {
|
|
80
|
+
const stream = this.canvas.captureStream(60);
|
|
81
|
+
const mediaRecorder = new MediaRecorder(stream, {
|
|
82
|
+
mimeType: 'video/webm'
|
|
83
|
+
});
|
|
84
|
+
mediaRecorder.ondataavailable = (event)=>{
|
|
85
|
+
if (event.data.size > 0) this.chunks.push(event.data);
|
|
86
|
+
};
|
|
87
|
+
this.mediaRecorder = mediaRecorder;
|
|
88
|
+
this.recording = true;
|
|
89
|
+
return this.mediaRecorder.start();
|
|
90
|
+
}
|
|
91
|
+
stop() {
|
|
92
|
+
var _this_mediaRecorder;
|
|
93
|
+
if (!this.recording || !this.mediaRecorder) return void console.warn('not recording');
|
|
94
|
+
this.mediaRecorder.onstop = ()=>{
|
|
95
|
+
const blob = new Blob(this.chunks, {
|
|
96
|
+
type: 'video/webm'
|
|
97
|
+
});
|
|
98
|
+
const url = URL.createObjectURL(blob);
|
|
99
|
+
const a = document.createElement('a');
|
|
100
|
+
a.href = url;
|
|
101
|
+
a.download = 'midscene_replay.webm';
|
|
102
|
+
a.click();
|
|
103
|
+
URL.revokeObjectURL(url);
|
|
104
|
+
};
|
|
105
|
+
null == (_this_mediaRecorder = this.mediaRecorder) || _this_mediaRecorder.stop();
|
|
106
|
+
this.recording = false;
|
|
107
|
+
this.mediaRecorder = null;
|
|
108
|
+
}
|
|
109
|
+
constructor(canvas){
|
|
110
|
+
_define_property(this, "canvas", void 0);
|
|
111
|
+
_define_property(this, "mediaRecorder", null);
|
|
112
|
+
_define_property(this, "chunks", void 0);
|
|
113
|
+
_define_property(this, "recording", false);
|
|
114
|
+
this.canvas = canvas;
|
|
115
|
+
this.chunks = [];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function Player(props) {
|
|
119
|
+
var _scripts_;
|
|
120
|
+
const [titleText, setTitleText] = useState('');
|
|
121
|
+
const [subTitleText, setSubTitleText] = useState('');
|
|
122
|
+
const { autoZoom, setAutoZoom, elementsVisible, setElementsVisible } = useBlackboardPreference();
|
|
123
|
+
useEffect(()=>{
|
|
124
|
+
if ((null == props ? void 0 : props.autoZoom) !== void 0) setAutoZoom(props.autoZoom);
|
|
125
|
+
}, [
|
|
126
|
+
null == props ? void 0 : props.autoZoom,
|
|
127
|
+
setAutoZoom
|
|
128
|
+
]);
|
|
129
|
+
useEffect(()=>{
|
|
130
|
+
if ((null == props ? void 0 : props.elementsVisible) !== void 0) setElementsVisible(props.elementsVisible);
|
|
131
|
+
}, [
|
|
132
|
+
null == props ? void 0 : props.elementsVisible,
|
|
133
|
+
setElementsVisible
|
|
134
|
+
]);
|
|
135
|
+
const scripts = null == props ? void 0 : props.replayScripts;
|
|
136
|
+
const imageWidth = (null == props ? void 0 : props.imageWidth) || 1920;
|
|
137
|
+
const imageHeight = (null == props ? void 0 : props.imageHeight) || 1080;
|
|
138
|
+
const fitMode = (null == props ? void 0 : props.fitMode) || 'height';
|
|
139
|
+
const currentImg = useRef((null == scripts ? void 0 : null == (_scripts_ = scripts[0]) ? void 0 : _scripts_.img) || null);
|
|
140
|
+
const divContainerRef = useRef(null);
|
|
141
|
+
const app = useMemo(()=>new Application(), []);
|
|
142
|
+
const pointerSprite = useRef(null);
|
|
143
|
+
const spinningPointerSprite = useRef(null);
|
|
144
|
+
const [replayMark, setReplayMark] = useState(0);
|
|
145
|
+
const triggerReplay = ()=>{
|
|
146
|
+
setReplayMark(Date.now());
|
|
147
|
+
};
|
|
148
|
+
const windowContentContainer = useMemo(()=>{
|
|
149
|
+
const container = new Container();
|
|
150
|
+
return container;
|
|
151
|
+
}, []);
|
|
152
|
+
const insightMarkContainer = useMemo(()=>{
|
|
153
|
+
const container = new Container();
|
|
154
|
+
container.zIndex = LAYER_ORDER_INSIGHT;
|
|
155
|
+
return container;
|
|
156
|
+
}, []);
|
|
157
|
+
useEffect(()=>{
|
|
158
|
+
insightMarkContainer.visible = elementsVisible;
|
|
159
|
+
}, [
|
|
160
|
+
elementsVisible,
|
|
161
|
+
insightMarkContainer
|
|
162
|
+
]);
|
|
163
|
+
const basicCameraState = {
|
|
164
|
+
left: 0,
|
|
165
|
+
top: 0,
|
|
166
|
+
width: imageWidth,
|
|
167
|
+
pointerLeft: Math.round(imageWidth / 2),
|
|
168
|
+
pointerTop: Math.round(imageHeight / 2)
|
|
169
|
+
};
|
|
170
|
+
const [animationProgress, setAnimationProgress] = useState(-1);
|
|
171
|
+
const cancelFlag = useRef(false);
|
|
172
|
+
useEffect(()=>{
|
|
173
|
+
cancelFlag.current = false;
|
|
174
|
+
return ()=>{
|
|
175
|
+
cancelFlag.current = true;
|
|
176
|
+
};
|
|
177
|
+
}, []);
|
|
178
|
+
const cameraState = useRef({
|
|
179
|
+
...basicCameraState
|
|
180
|
+
});
|
|
181
|
+
const resizeCanvasIfNeeded = async (newWidth, newHeight)=>{
|
|
182
|
+
if (app.screen.width !== newWidth || app.screen.height !== newHeight) {
|
|
183
|
+
app.renderer.resize(newWidth, newHeight);
|
|
184
|
+
if (divContainerRef.current) {
|
|
185
|
+
const aspectRatio = newWidth / newHeight;
|
|
186
|
+
divContainerRef.current.style.setProperty('--canvas-aspect-ratio', aspectRatio.toString());
|
|
187
|
+
}
|
|
188
|
+
const newBasicCameraState = {
|
|
189
|
+
left: 0,
|
|
190
|
+
top: 0,
|
|
191
|
+
width: newWidth,
|
|
192
|
+
pointerLeft: Math.round(newWidth / 2),
|
|
193
|
+
pointerTop: Math.round(newHeight / 2)
|
|
194
|
+
};
|
|
195
|
+
cameraState.current = newBasicCameraState;
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
const repaintImage = async (scriptWidth, scriptHeight)=>{
|
|
199
|
+
const imgToUpdate = currentImg.current;
|
|
200
|
+
if (!imgToUpdate) return void console.warn('no image to update');
|
|
201
|
+
const targetWidth = scriptWidth || imageWidth;
|
|
202
|
+
const targetHeight = scriptHeight || imageHeight;
|
|
203
|
+
await resizeCanvasIfNeeded(targetWidth, targetHeight);
|
|
204
|
+
if (!getTextureFromCache(imgToUpdate)) {
|
|
205
|
+
console.warn('image not loaded', imgToUpdate);
|
|
206
|
+
await loadTexture(imgToUpdate);
|
|
207
|
+
}
|
|
208
|
+
const texture = getTextureFromCache(imgToUpdate);
|
|
209
|
+
if (!texture) throw new Error('texture not found');
|
|
210
|
+
const sprite = Sprite.from(texture);
|
|
211
|
+
if (!sprite) throw new Error('sprite not found');
|
|
212
|
+
const mainImgLabel = 'main-img';
|
|
213
|
+
const child = windowContentContainer.getChildByLabel(mainImgLabel);
|
|
214
|
+
if (child) windowContentContainer.removeChild(child);
|
|
215
|
+
sprite.label = mainImgLabel;
|
|
216
|
+
sprite.zIndex = LAYER_ORDER_IMG;
|
|
217
|
+
sprite.width = targetWidth;
|
|
218
|
+
sprite.height = targetHeight;
|
|
219
|
+
windowContentContainer.addChild(sprite);
|
|
220
|
+
};
|
|
221
|
+
const spinningPointer = (frame)=>{
|
|
222
|
+
var _pointerSprite_current, _pointerSprite_current1;
|
|
223
|
+
if (!spinningPointerSprite.current) {
|
|
224
|
+
spinningPointerSprite.current = Sprite.from(mouseLoading);
|
|
225
|
+
spinningPointerSprite.current.zIndex = LAYER_ORDER_SPINNING_POINTER;
|
|
226
|
+
spinningPointerSprite.current.anchor.set(0.5, 0.5);
|
|
227
|
+
spinningPointerSprite.current.scale.set(0.5);
|
|
228
|
+
spinningPointerSprite.current.label = 'spinning-pointer';
|
|
229
|
+
}
|
|
230
|
+
spinningPointerSprite.current.x = (null == (_pointerSprite_current = pointerSprite.current) ? void 0 : _pointerSprite_current.x) || 0;
|
|
231
|
+
spinningPointerSprite.current.y = (null == (_pointerSprite_current1 = pointerSprite.current) ? void 0 : _pointerSprite_current1.y) || 0;
|
|
232
|
+
windowContentContainer.addChild(spinningPointerSprite.current);
|
|
233
|
+
let startTime;
|
|
234
|
+
let isCancelled = false;
|
|
235
|
+
const animate = (currentTime)=>{
|
|
236
|
+
if (isCancelled) return;
|
|
237
|
+
if (!startTime) startTime = currentTime;
|
|
238
|
+
const elapsedTime = currentTime - startTime;
|
|
239
|
+
const progress = (Math.sin(elapsedTime / 500 - Math.PI / 2) + 1) / 2;
|
|
240
|
+
const rotation = progress * Math.PI * 2;
|
|
241
|
+
if (spinningPointerSprite.current) spinningPointerSprite.current.rotation = rotation;
|
|
242
|
+
frame(animate);
|
|
243
|
+
};
|
|
244
|
+
frame(animate);
|
|
245
|
+
const stopFn = ()=>{
|
|
246
|
+
if (spinningPointerSprite.current) windowContentContainer.removeChild(spinningPointerSprite.current);
|
|
247
|
+
isCancelled = true;
|
|
248
|
+
};
|
|
249
|
+
return stopFn;
|
|
250
|
+
};
|
|
251
|
+
const updatePointer = async (img, x, y)=>{
|
|
252
|
+
var _pointerSprite_current, _pointerSprite_current1;
|
|
253
|
+
if (!getTextureFromCache(img)) {
|
|
254
|
+
console.warn('image not loaded', img);
|
|
255
|
+
await loadTexture(img);
|
|
256
|
+
}
|
|
257
|
+
const texture = getTextureFromCache(img);
|
|
258
|
+
if (!texture) throw new Error('texture not found');
|
|
259
|
+
const sprite = Sprite.from(texture);
|
|
260
|
+
let targetX = null == (_pointerSprite_current = pointerSprite.current) ? void 0 : _pointerSprite_current.x;
|
|
261
|
+
let targetY = null == (_pointerSprite_current1 = pointerSprite.current) ? void 0 : _pointerSprite_current1.y;
|
|
262
|
+
if ('number' == typeof x) targetX = x;
|
|
263
|
+
if ('number' == typeof y) targetY = y;
|
|
264
|
+
if (void 0 === targetX || void 0 === targetY) return void console.warn('invalid pointer position', x, y);
|
|
265
|
+
if (pointerSprite.current) {
|
|
266
|
+
const pointer = windowContentContainer.getChildByLabel('pointer');
|
|
267
|
+
if (pointer) windowContentContainer.removeChild(pointer);
|
|
268
|
+
}
|
|
269
|
+
pointerSprite.current = sprite;
|
|
270
|
+
pointerSprite.current.x = targetX;
|
|
271
|
+
pointerSprite.current.y = targetY;
|
|
272
|
+
pointerSprite.current.label = 'pointer';
|
|
273
|
+
pointerSprite.current.zIndex = LAYER_ORDER_POINTER;
|
|
274
|
+
windowContentContainer.addChild(pointerSprite.current);
|
|
275
|
+
};
|
|
276
|
+
const updateCamera = (state, currentWidth)=>{
|
|
277
|
+
cameraState.current = state;
|
|
278
|
+
const effectiveWidth = currentWidth || app.screen.width || imageWidth;
|
|
279
|
+
const newScale = autoZoom ? Math.max(1, effectiveWidth / state.width) : 1;
|
|
280
|
+
windowContentContainer.scale.set(newScale);
|
|
281
|
+
windowContentContainer.x = autoZoom ? Math.round(canvasPaddingLeft - state.left * newScale) : canvasPaddingLeft;
|
|
282
|
+
windowContentContainer.y = autoZoom ? Math.round(canvasPaddingTop - state.top * newScale) : canvasPaddingTop;
|
|
283
|
+
const pointer = windowContentContainer.getChildByLabel('pointer');
|
|
284
|
+
if (pointer) {
|
|
285
|
+
pointer.scale.set(1 / newScale);
|
|
286
|
+
if ('number' == typeof state.pointerLeft && 'number' == typeof state.pointerTop) {
|
|
287
|
+
pointer.x = state.pointerLeft;
|
|
288
|
+
pointer.y = state.pointerTop;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
const cameraAnimation = async (targetState, duration, frame)=>{
|
|
293
|
+
const currentCanvasWidth = app.screen.width || imageWidth;
|
|
294
|
+
const currentCanvasHeight = app.screen.height || imageHeight;
|
|
295
|
+
if (!autoZoom) {
|
|
296
|
+
const currentState = {
|
|
297
|
+
...cameraState.current
|
|
298
|
+
};
|
|
299
|
+
const startPointerLeft = currentState.pointerLeft;
|
|
300
|
+
const startPointerTop = currentState.pointerTop;
|
|
301
|
+
const startTime = performance.now();
|
|
302
|
+
const shouldMovePointer = 'number' == typeof targetState.pointerLeft && 'number' == typeof targetState.pointerTop && (targetState.pointerLeft !== startPointerLeft || targetState.pointerTop !== startPointerTop);
|
|
303
|
+
if (!shouldMovePointer) return;
|
|
304
|
+
await new Promise((resolve)=>{
|
|
305
|
+
const animate = (currentTime)=>{
|
|
306
|
+
const elapsedTime = currentTime - startTime;
|
|
307
|
+
const rawProgress = Math.min(elapsedTime / duration, 1);
|
|
308
|
+
const progress = cubicMouse(rawProgress);
|
|
309
|
+
const nextState = {
|
|
310
|
+
...currentState,
|
|
311
|
+
pointerLeft: startPointerLeft + (targetState.pointerLeft - startPointerLeft) * progress,
|
|
312
|
+
pointerTop: startPointerTop + (targetState.pointerTop - startPointerTop) * progress
|
|
313
|
+
};
|
|
314
|
+
updateCamera(nextState, currentCanvasWidth);
|
|
315
|
+
if (elapsedTime < duration) frame(animate);
|
|
316
|
+
else resolve();
|
|
317
|
+
};
|
|
318
|
+
frame(animate);
|
|
319
|
+
});
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const currentState = {
|
|
323
|
+
...cameraState.current
|
|
324
|
+
};
|
|
325
|
+
const startLeft = currentState.left;
|
|
326
|
+
const startTop = currentState.top;
|
|
327
|
+
const startPointerLeft = currentState.pointerLeft;
|
|
328
|
+
const startPointerTop = currentState.pointerTop;
|
|
329
|
+
const startScale = currentState.width / currentCanvasWidth;
|
|
330
|
+
const startTime = performance.now();
|
|
331
|
+
const shouldMovePointer = 'number' == typeof targetState.pointerLeft && 'number' == typeof targetState.pointerTop && (targetState.pointerLeft !== startPointerLeft || targetState.pointerTop !== startPointerTop);
|
|
332
|
+
const pointerMoveDuration = shouldMovePointer ? 0.375 * duration : 0;
|
|
333
|
+
const cameraMoveStart = pointerMoveDuration;
|
|
334
|
+
const cameraMoveDuration = duration - pointerMoveDuration;
|
|
335
|
+
await new Promise((resolve)=>{
|
|
336
|
+
const animate = (currentTime)=>{
|
|
337
|
+
const nextState = {
|
|
338
|
+
...cameraState.current
|
|
339
|
+
};
|
|
340
|
+
const elapsedTime = currentTime - startTime;
|
|
341
|
+
if (shouldMovePointer) if (elapsedTime <= pointerMoveDuration) {
|
|
342
|
+
const rawMouseProgress = Math.min(elapsedTime / pointerMoveDuration, 1);
|
|
343
|
+
const mouseProgress = cubicMouse(rawMouseProgress);
|
|
344
|
+
nextState.pointerLeft = startPointerLeft + (targetState.pointerLeft - startPointerLeft) * mouseProgress;
|
|
345
|
+
nextState.pointerTop = startPointerTop + (targetState.pointerTop - startPointerTop) * mouseProgress;
|
|
346
|
+
} else {
|
|
347
|
+
nextState.pointerLeft = targetState.pointerLeft;
|
|
348
|
+
nextState.pointerTop = targetState.pointerTop;
|
|
349
|
+
}
|
|
350
|
+
if (elapsedTime > cameraMoveStart) {
|
|
351
|
+
const cameraElapsedTime = elapsedTime - cameraMoveStart;
|
|
352
|
+
const rawCameraProgress = Math.min(cameraElapsedTime / cameraMoveDuration, 1);
|
|
353
|
+
const cameraProgress = cubicImage(rawCameraProgress);
|
|
354
|
+
const targetScale = targetState.width / currentCanvasWidth;
|
|
355
|
+
const progressScale = startScale + (targetScale - startScale) * cameraProgress;
|
|
356
|
+
const progressWidth = currentCanvasWidth * progressScale;
|
|
357
|
+
const progressHeight = currentCanvasHeight * progressScale;
|
|
358
|
+
nextState.width = progressWidth;
|
|
359
|
+
const progressLeft = startLeft + (targetState.left - startLeft) * cameraProgress;
|
|
360
|
+
const progressTop = startTop + (targetState.top - startTop) * cameraProgress;
|
|
361
|
+
const horizontalExceed = progressLeft + progressWidth - currentCanvasWidth;
|
|
362
|
+
const verticalExceed = progressTop + progressHeight - currentCanvasHeight;
|
|
363
|
+
nextState.left = horizontalExceed > 0 ? progressLeft + horizontalExceed : progressLeft;
|
|
364
|
+
nextState.top = verticalExceed > 0 ? progressTop + verticalExceed : progressTop;
|
|
365
|
+
}
|
|
366
|
+
updateCamera(nextState, currentCanvasWidth);
|
|
367
|
+
if (elapsedTime < duration) frame(animate);
|
|
368
|
+
else resolve();
|
|
369
|
+
};
|
|
370
|
+
frame(animate);
|
|
371
|
+
});
|
|
372
|
+
};
|
|
373
|
+
const fadeInGraphics = function(graphics, duration, frame) {
|
|
374
|
+
let targetAlpha = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : 1;
|
|
375
|
+
return new Promise((resolve)=>{
|
|
376
|
+
const startTime = performance.now();
|
|
377
|
+
const animate = (currentTime)=>{
|
|
378
|
+
const elapsedTime = currentTime - startTime;
|
|
379
|
+
const progress = Math.min(elapsedTime / duration, 1);
|
|
380
|
+
graphics.alpha = 0 === targetAlpha ? 1 - linear(progress) : linear(progress);
|
|
381
|
+
if (elapsedTime < duration) frame(animate);
|
|
382
|
+
else resolve();
|
|
383
|
+
};
|
|
384
|
+
frame(animate);
|
|
385
|
+
});
|
|
386
|
+
};
|
|
387
|
+
const fadeOutItem = async (graphics, duration, frame)=>fadeInGraphics(graphics, duration, frame, 0);
|
|
388
|
+
const insightElementsAnimation = async (elements, highlightElements, searchArea, duration, frame)=>{
|
|
389
|
+
insightMarkContainer.removeChildren();
|
|
390
|
+
const elementsToAdd = [
|
|
391
|
+
...elements
|
|
392
|
+
];
|
|
393
|
+
const totalLength = elementsToAdd.length;
|
|
394
|
+
let childrenCount = 0;
|
|
395
|
+
await new Promise((resolve)=>{
|
|
396
|
+
const startTime = performance.now();
|
|
397
|
+
const animate = (currentTime)=>{
|
|
398
|
+
const elapsedTime = currentTime - startTime;
|
|
399
|
+
const progress = cubicInsightElement(Math.min(elapsedTime / duration, 1));
|
|
400
|
+
const elementsToAddNow = Math.floor(progress * totalLength);
|
|
401
|
+
while(childrenCount < elementsToAddNow){
|
|
402
|
+
const randomIndex = Math.floor(Math.random() * elementsToAdd.length);
|
|
403
|
+
const element = elementsToAdd.splice(randomIndex, 1)[0];
|
|
404
|
+
if (element) {
|
|
405
|
+
const [insightMarkGraphic] = rectMarkForItem(element.rect, element.content, 'element');
|
|
406
|
+
insightMarkGraphic.alpha = 0;
|
|
407
|
+
insightMarkContainer.addChild(insightMarkGraphic);
|
|
408
|
+
childrenCount++;
|
|
409
|
+
fadeInGraphics(insightMarkGraphic, singleElementFadeInDuration, frame);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (elapsedTime < duration) frame(animate);
|
|
413
|
+
else {
|
|
414
|
+
while(elementsToAdd.length > 0){
|
|
415
|
+
const randomIndex = Math.floor(Math.random() * elementsToAdd.length);
|
|
416
|
+
const element = elementsToAdd.splice(randomIndex, 1)[0];
|
|
417
|
+
const [insightMarkGraphic] = rectMarkForItem(element.rect, element.content, 'element');
|
|
418
|
+
insightMarkGraphic.alpha = 1;
|
|
419
|
+
insightMarkContainer.addChild(insightMarkGraphic);
|
|
420
|
+
}
|
|
421
|
+
if (searchArea) {
|
|
422
|
+
const [searchAreaGraphic] = rectMarkForItem(searchArea, 'Search Area', 'searchArea');
|
|
423
|
+
searchAreaGraphic.alpha = 1;
|
|
424
|
+
insightMarkContainer.addChild(searchAreaGraphic);
|
|
425
|
+
}
|
|
426
|
+
highlightElements.map((element)=>{
|
|
427
|
+
const [insightMarkGraphic] = rectMarkForItem(element.rect, element.content || '', 'highlight');
|
|
428
|
+
insightMarkGraphic.alpha = 1;
|
|
429
|
+
insightMarkContainer.addChild(insightMarkGraphic);
|
|
430
|
+
});
|
|
431
|
+
resolve();
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
frame(animate);
|
|
435
|
+
});
|
|
436
|
+
};
|
|
437
|
+
const init = async ()=>{
|
|
438
|
+
if (!divContainerRef.current || !scripts) return;
|
|
439
|
+
await app.init({
|
|
440
|
+
width: imageWidth,
|
|
441
|
+
height: imageHeight,
|
|
442
|
+
background: 0xf4f4f4,
|
|
443
|
+
autoDensity: true,
|
|
444
|
+
antialias: true
|
|
445
|
+
});
|
|
446
|
+
if (!divContainerRef.current) return;
|
|
447
|
+
divContainerRef.current.appendChild(app.canvas);
|
|
448
|
+
windowContentContainer.x = 0;
|
|
449
|
+
windowContentContainer.y = 0;
|
|
450
|
+
app.stage.addChild(windowContentContainer);
|
|
451
|
+
insightMarkContainer.x = 0;
|
|
452
|
+
insightMarkContainer.y = 0;
|
|
453
|
+
windowContentContainer.addChild(insightMarkContainer);
|
|
454
|
+
};
|
|
455
|
+
const [isRecording, setIsRecording] = useState(false);
|
|
456
|
+
const recorderSessionRef = useRef(null);
|
|
457
|
+
const handleExport = ()=>{
|
|
458
|
+
if (recorderSessionRef.current) return void console.warn('recorderSession exists');
|
|
459
|
+
if (!app.canvas) return void console.warn('canvas is not initialized');
|
|
460
|
+
recorderSessionRef.current = new RecordingSession(app.canvas);
|
|
461
|
+
setIsRecording(true);
|
|
462
|
+
triggerReplay();
|
|
463
|
+
};
|
|
464
|
+
const play = ()=>{
|
|
465
|
+
let cancelFn;
|
|
466
|
+
Promise.resolve((async ()=>{
|
|
467
|
+
if (!app) throw new Error('app is not initialized');
|
|
468
|
+
if (!scripts) throw new Error("scripts is required");
|
|
469
|
+
const { frame, cancel, timeout } = frameKit();
|
|
470
|
+
cancelFn = cancel;
|
|
471
|
+
const allImages = scripts.filter((item)=>!!item.img).map((item)=>item.img);
|
|
472
|
+
await Promise.all([
|
|
473
|
+
...allImages,
|
|
474
|
+
mouseLoading,
|
|
475
|
+
mousePointer
|
|
476
|
+
].map(loadTexture));
|
|
477
|
+
insightMarkContainer.removeChildren();
|
|
478
|
+
await updatePointer(mousePointer, imageWidth / 2, imageHeight / 2);
|
|
479
|
+
await repaintImage();
|
|
480
|
+
await updateCamera({
|
|
481
|
+
...basicCameraState
|
|
482
|
+
});
|
|
483
|
+
const totalDuration = scripts.reduce((acc, item)=>acc + item.duration + (item.camera && item.insightCameraDuration ? item.insightCameraDuration : 0), 0);
|
|
484
|
+
const progressUpdateInterval = 200;
|
|
485
|
+
const startTime = performance.now();
|
|
486
|
+
setAnimationProgress(0);
|
|
487
|
+
const updateProgress = ()=>{
|
|
488
|
+
const progress = Math.min((performance.now() - startTime) / totalDuration, 1);
|
|
489
|
+
setAnimationProgress(progress);
|
|
490
|
+
if (progress < 1) return timeout(updateProgress, progressUpdateInterval);
|
|
491
|
+
};
|
|
492
|
+
frame(updateProgress);
|
|
493
|
+
if (recorderSessionRef.current) recorderSessionRef.current.start();
|
|
494
|
+
for(const index in scripts){
|
|
495
|
+
const item = scripts[index];
|
|
496
|
+
setTitleText(item.title || '');
|
|
497
|
+
setSubTitleText(item.subTitle || '');
|
|
498
|
+
if ('sleep' === item.type) await sleep(item.duration);
|
|
499
|
+
else if ('insight' === item.type) {
|
|
500
|
+
var _item_context;
|
|
501
|
+
if (!item.img) throw new Error('img is required');
|
|
502
|
+
currentImg.current = item.img;
|
|
503
|
+
await repaintImage(item.imageWidth, item.imageHeight);
|
|
504
|
+
const elements = (null == (_item_context = item.context) ? void 0 : _item_context.tree) ? treeToList(item.context.tree) : [];
|
|
505
|
+
const highlightElements = item.highlightElement ? [
|
|
506
|
+
item.highlightElement
|
|
507
|
+
] : [];
|
|
508
|
+
await insightElementsAnimation(elements, highlightElements, item.searchArea, item.duration, frame);
|
|
509
|
+
if (item.camera) {
|
|
510
|
+
if (!item.insightCameraDuration) throw new Error('insightCameraDuration is required');
|
|
511
|
+
await cameraAnimation(item.camera, item.insightCameraDuration, frame);
|
|
512
|
+
}
|
|
513
|
+
} else if ('clear-insight' === item.type) {
|
|
514
|
+
await fadeOutItem(insightMarkContainer, item.duration, frame);
|
|
515
|
+
insightMarkContainer.removeChildren();
|
|
516
|
+
insightMarkContainer.alpha = 1;
|
|
517
|
+
} else if ('img' === item.type) {
|
|
518
|
+
if (item.img && item.img !== currentImg.current) {
|
|
519
|
+
currentImg.current = item.img;
|
|
520
|
+
await repaintImage(item.imageWidth, item.imageHeight);
|
|
521
|
+
}
|
|
522
|
+
if (item.camera) await cameraAnimation(item.camera, item.duration, frame);
|
|
523
|
+
else await sleep(item.duration);
|
|
524
|
+
} else if ('pointer' === item.type) {
|
|
525
|
+
if (!item.img) throw new Error('pointer img is required');
|
|
526
|
+
await updatePointer(item.img);
|
|
527
|
+
} else if ('spinning-pointer' === item.type) {
|
|
528
|
+
const stop = spinningPointer(frame);
|
|
529
|
+
await sleep(item.duration);
|
|
530
|
+
stop();
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
if (recorderSessionRef.current) {
|
|
534
|
+
await sleep(1200);
|
|
535
|
+
recorderSessionRef.current.stop();
|
|
536
|
+
recorderSessionRef.current = null;
|
|
537
|
+
setIsRecording(false);
|
|
538
|
+
}
|
|
539
|
+
})().catch((e)=>{
|
|
540
|
+
console.error('player error', e);
|
|
541
|
+
}));
|
|
542
|
+
return ()=>{
|
|
543
|
+
null == cancelFn || cancelFn();
|
|
544
|
+
};
|
|
545
|
+
};
|
|
546
|
+
useEffect(()=>{
|
|
547
|
+
Promise.resolve((async ()=>{
|
|
548
|
+
await init();
|
|
549
|
+
if (divContainerRef.current && imageWidth && imageHeight) {
|
|
550
|
+
const aspectRatio = imageWidth / imageHeight;
|
|
551
|
+
divContainerRef.current.style.setProperty('--canvas-aspect-ratio', aspectRatio.toString());
|
|
552
|
+
divContainerRef.current.setAttribute('data-fit-mode', fitMode);
|
|
553
|
+
const playerContainer = divContainerRef.current.closest('.player-container');
|
|
554
|
+
if (playerContainer) playerContainer.setAttribute('data-fit-mode', fitMode);
|
|
555
|
+
}
|
|
556
|
+
triggerReplay();
|
|
557
|
+
})());
|
|
558
|
+
return ()=>{
|
|
559
|
+
try {
|
|
560
|
+
app.destroy(true, {
|
|
561
|
+
children: true,
|
|
562
|
+
texture: true
|
|
563
|
+
});
|
|
564
|
+
} catch (e) {
|
|
565
|
+
console.warn('destroy failed', e);
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
}, [
|
|
569
|
+
imageWidth,
|
|
570
|
+
imageHeight,
|
|
571
|
+
fitMode
|
|
572
|
+
]);
|
|
573
|
+
useEffect(()=>{
|
|
574
|
+
if (replayMark) return play();
|
|
575
|
+
}, [
|
|
576
|
+
replayMark
|
|
577
|
+
]);
|
|
578
|
+
const [mouseOverStatusIcon, setMouseOverStatusIcon] = useState(false);
|
|
579
|
+
const [mouseOverSettingsIcon, setMouseOverSettingsIcon] = useState(false);
|
|
580
|
+
const progressString = Math.round(100 * animationProgress);
|
|
581
|
+
const transitionStyle = 0 === animationProgress ? 'none' : '0.3s';
|
|
582
|
+
const canReplayNow = 1 === animationProgress;
|
|
583
|
+
useEffect(()=>{
|
|
584
|
+
if (canReplayNow) {
|
|
585
|
+
const listener = (event)=>{
|
|
586
|
+
if (' ' === event.key) triggerReplay();
|
|
587
|
+
};
|
|
588
|
+
window.addEventListener('keydown', listener);
|
|
589
|
+
return ()=>{
|
|
590
|
+
window.removeEventListener('keydown', listener);
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
}, [
|
|
594
|
+
canReplayNow
|
|
595
|
+
]);
|
|
596
|
+
let statusIconElement;
|
|
597
|
+
let statusOnClick = ()=>{};
|
|
598
|
+
if (animationProgress < 1) statusIconElement = /*#__PURE__*/ jsx(Spin, {
|
|
599
|
+
indicator: /*#__PURE__*/ jsx(LoadingOutlined, {
|
|
600
|
+
spin: true,
|
|
601
|
+
color: "#333"
|
|
602
|
+
}),
|
|
603
|
+
size: "default"
|
|
604
|
+
});
|
|
605
|
+
else if (mouseOverStatusIcon) {
|
|
606
|
+
statusIconElement = /*#__PURE__*/ jsx(Spin, {
|
|
607
|
+
indicator: /*#__PURE__*/ jsx(CaretRightOutlined, {
|
|
608
|
+
color: "#333"
|
|
609
|
+
}),
|
|
610
|
+
size: "default"
|
|
611
|
+
});
|
|
612
|
+
statusOnClick = ()=>triggerReplay();
|
|
613
|
+
} else statusIconElement = /*#__PURE__*/ jsx(Spin, {
|
|
614
|
+
indicator: /*#__PURE__*/ jsx(CaretRightOutlined, {
|
|
615
|
+
color: "#333"
|
|
616
|
+
}),
|
|
617
|
+
size: "default"
|
|
618
|
+
});
|
|
619
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
620
|
+
className: "player-container",
|
|
621
|
+
children: [
|
|
622
|
+
/*#__PURE__*/ jsx("div", {
|
|
623
|
+
className: "canvas-container",
|
|
624
|
+
ref: divContainerRef
|
|
625
|
+
}),
|
|
626
|
+
/*#__PURE__*/ jsx("div", {
|
|
627
|
+
className: "player-timeline-wrapper",
|
|
628
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
629
|
+
className: "player-timeline",
|
|
630
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
631
|
+
className: "player-timeline-progress",
|
|
632
|
+
style: {
|
|
633
|
+
width: `${progressString}%`,
|
|
634
|
+
transition: transitionStyle
|
|
635
|
+
}
|
|
636
|
+
})
|
|
637
|
+
})
|
|
638
|
+
}),
|
|
639
|
+
/*#__PURE__*/ jsx("div", {
|
|
640
|
+
className: "player-tools-wrapper",
|
|
641
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
642
|
+
className: "player-tools",
|
|
643
|
+
children: /*#__PURE__*/ jsxs("div", {
|
|
644
|
+
className: "player-control",
|
|
645
|
+
children: [
|
|
646
|
+
/*#__PURE__*/ jsxs("div", {
|
|
647
|
+
className: "status-text",
|
|
648
|
+
children: [
|
|
649
|
+
/*#__PURE__*/ jsx("div", {
|
|
650
|
+
className: "title",
|
|
651
|
+
children: titleText
|
|
652
|
+
}),
|
|
653
|
+
/*#__PURE__*/ jsx(Tooltip, {
|
|
654
|
+
title: subTitleText,
|
|
655
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
656
|
+
className: "subtitle",
|
|
657
|
+
children: subTitleText
|
|
658
|
+
})
|
|
659
|
+
})
|
|
660
|
+
]
|
|
661
|
+
}),
|
|
662
|
+
isRecording ? null : /*#__PURE__*/ jsx("div", {
|
|
663
|
+
className: "status-icon",
|
|
664
|
+
onMouseEnter: ()=>setMouseOverStatusIcon(true),
|
|
665
|
+
onMouseLeave: ()=>setMouseOverStatusIcon(false),
|
|
666
|
+
onClick: statusOnClick,
|
|
667
|
+
children: statusIconElement
|
|
668
|
+
}),
|
|
669
|
+
(null == props ? void 0 : props.reportFileContent) ? /*#__PURE__*/ jsx(Tooltip, {
|
|
670
|
+
title: "Download Report",
|
|
671
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
672
|
+
className: "status-icon",
|
|
673
|
+
onMouseEnter: ()=>setMouseOverStatusIcon(true),
|
|
674
|
+
onMouseLeave: ()=>setMouseOverStatusIcon(false),
|
|
675
|
+
onClick: ()=>downloadReport(props.reportFileContent),
|
|
676
|
+
children: /*#__PURE__*/ jsx(DownloadOutlined, {
|
|
677
|
+
color: "#333"
|
|
678
|
+
})
|
|
679
|
+
})
|
|
680
|
+
}) : null,
|
|
681
|
+
/*#__PURE__*/ jsx(Tooltip, {
|
|
682
|
+
title: isRecording ? 'Generating...' : 'Export Video',
|
|
683
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
684
|
+
className: "status-icon",
|
|
685
|
+
onClick: isRecording ? void 0 : handleExport,
|
|
686
|
+
style: {
|
|
687
|
+
opacity: isRecording ? 0.5 : 1,
|
|
688
|
+
cursor: isRecording ? 'not-allowed' : 'pointer'
|
|
689
|
+
},
|
|
690
|
+
children: isRecording ? /*#__PURE__*/ jsx(Spin, {
|
|
691
|
+
size: "default",
|
|
692
|
+
percent: progressString
|
|
693
|
+
}) : /*#__PURE__*/ jsx(ExportOutlined, {})
|
|
694
|
+
})
|
|
695
|
+
}),
|
|
696
|
+
/*#__PURE__*/ jsx(Dropdown, {
|
|
697
|
+
trigger: [
|
|
698
|
+
'hover',
|
|
699
|
+
'click'
|
|
700
|
+
],
|
|
701
|
+
placement: "bottomRight",
|
|
702
|
+
overlayStyle: {
|
|
703
|
+
minWidth: '148px'
|
|
704
|
+
},
|
|
705
|
+
dropdownRender: (menu)=>/*#__PURE__*/ jsx("div", {
|
|
706
|
+
style: {
|
|
707
|
+
borderRadius: '8px',
|
|
708
|
+
border: '1px solid rgba(0, 0, 0, 0.08)',
|
|
709
|
+
backgroundColor: '#fff',
|
|
710
|
+
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.08)',
|
|
711
|
+
overflow: 'hidden'
|
|
712
|
+
},
|
|
713
|
+
children: menu
|
|
714
|
+
}),
|
|
715
|
+
menu: {
|
|
716
|
+
style: {
|
|
717
|
+
borderRadius: '8px',
|
|
718
|
+
padding: 0
|
|
719
|
+
},
|
|
720
|
+
items: [
|
|
721
|
+
{
|
|
722
|
+
key: 'autoZoom',
|
|
723
|
+
style: {
|
|
724
|
+
height: '39px',
|
|
725
|
+
margin: 0,
|
|
726
|
+
padding: '0 12px'
|
|
727
|
+
},
|
|
728
|
+
label: /*#__PURE__*/ jsxs("div", {
|
|
729
|
+
style: {
|
|
730
|
+
display: 'flex',
|
|
731
|
+
alignItems: 'center',
|
|
732
|
+
justifyContent: 'space-between',
|
|
733
|
+
width: '100%',
|
|
734
|
+
height: '39px'
|
|
735
|
+
},
|
|
736
|
+
children: [
|
|
737
|
+
/*#__PURE__*/ jsxs("div", {
|
|
738
|
+
style: {
|
|
739
|
+
display: 'flex',
|
|
740
|
+
alignItems: 'center',
|
|
741
|
+
gap: '4px'
|
|
742
|
+
},
|
|
743
|
+
children: [
|
|
744
|
+
/*#__PURE__*/ jsx(global_perspective, {
|
|
745
|
+
style: {
|
|
746
|
+
width: '16px',
|
|
747
|
+
height: '16px'
|
|
748
|
+
}
|
|
749
|
+
}),
|
|
750
|
+
/*#__PURE__*/ jsx("span", {
|
|
751
|
+
style: {
|
|
752
|
+
fontSize: '12px',
|
|
753
|
+
marginRight: '16px'
|
|
754
|
+
},
|
|
755
|
+
children: "Focus on cursor"
|
|
756
|
+
})
|
|
757
|
+
]
|
|
758
|
+
}),
|
|
759
|
+
/*#__PURE__*/ jsx(Switch, {
|
|
760
|
+
size: "small",
|
|
761
|
+
checked: autoZoom,
|
|
762
|
+
onChange: (checked)=>{
|
|
763
|
+
setAutoZoom(checked);
|
|
764
|
+
triggerReplay();
|
|
765
|
+
},
|
|
766
|
+
onClick: (_, e)=>{
|
|
767
|
+
var _e_stopPropagation;
|
|
768
|
+
return null == e ? void 0 : null == (_e_stopPropagation = e.stopPropagation) ? void 0 : _e_stopPropagation.call(e);
|
|
769
|
+
}
|
|
770
|
+
})
|
|
771
|
+
]
|
|
772
|
+
})
|
|
773
|
+
},
|
|
774
|
+
{
|
|
775
|
+
key: 'elementsVisible',
|
|
776
|
+
style: {
|
|
777
|
+
height: '39px',
|
|
778
|
+
margin: 0,
|
|
779
|
+
padding: '0 12px'
|
|
780
|
+
},
|
|
781
|
+
label: /*#__PURE__*/ jsxs("div", {
|
|
782
|
+
style: {
|
|
783
|
+
display: 'flex',
|
|
784
|
+
alignItems: 'center',
|
|
785
|
+
justifyContent: 'space-between',
|
|
786
|
+
width: '100%',
|
|
787
|
+
height: '39px'
|
|
788
|
+
},
|
|
789
|
+
children: [
|
|
790
|
+
/*#__PURE__*/ jsxs("div", {
|
|
791
|
+
style: {
|
|
792
|
+
display: 'flex',
|
|
793
|
+
alignItems: 'center',
|
|
794
|
+
gap: '4px'
|
|
795
|
+
},
|
|
796
|
+
children: [
|
|
797
|
+
/*#__PURE__*/ jsx(show_marker, {
|
|
798
|
+
style: {
|
|
799
|
+
width: '16px',
|
|
800
|
+
height: '16px'
|
|
801
|
+
}
|
|
802
|
+
}),
|
|
803
|
+
/*#__PURE__*/ jsx("span", {
|
|
804
|
+
style: {
|
|
805
|
+
fontSize: '12px',
|
|
806
|
+
marginRight: '16px'
|
|
807
|
+
},
|
|
808
|
+
children: "Show element markers"
|
|
809
|
+
})
|
|
810
|
+
]
|
|
811
|
+
}),
|
|
812
|
+
/*#__PURE__*/ jsx(Switch, {
|
|
813
|
+
size: "small",
|
|
814
|
+
checked: elementsVisible,
|
|
815
|
+
onChange: (checked)=>{
|
|
816
|
+
setElementsVisible(checked);
|
|
817
|
+
triggerReplay();
|
|
818
|
+
},
|
|
819
|
+
onClick: (_, e)=>{
|
|
820
|
+
var _e_stopPropagation;
|
|
821
|
+
return null == e ? void 0 : null == (_e_stopPropagation = e.stopPropagation) ? void 0 : _e_stopPropagation.call(e);
|
|
822
|
+
}
|
|
823
|
+
})
|
|
824
|
+
]
|
|
825
|
+
})
|
|
826
|
+
}
|
|
827
|
+
]
|
|
828
|
+
},
|
|
829
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
830
|
+
className: "status-icon",
|
|
831
|
+
onMouseEnter: ()=>setMouseOverSettingsIcon(true),
|
|
832
|
+
onMouseLeave: ()=>setMouseOverSettingsIcon(false),
|
|
833
|
+
style: {
|
|
834
|
+
cursor: 'pointer',
|
|
835
|
+
display: 'flex',
|
|
836
|
+
alignItems: 'center',
|
|
837
|
+
justifyContent: 'center',
|
|
838
|
+
opacity: mouseOverSettingsIcon ? 1 : 0.7,
|
|
839
|
+
transition: 'opacity 0.2s'
|
|
840
|
+
},
|
|
841
|
+
children: /*#__PURE__*/ jsx(player_setting, {
|
|
842
|
+
style: {
|
|
843
|
+
width: '16px',
|
|
844
|
+
height: '16px'
|
|
845
|
+
}
|
|
846
|
+
})
|
|
847
|
+
})
|
|
848
|
+
})
|
|
849
|
+
]
|
|
850
|
+
})
|
|
851
|
+
})
|
|
852
|
+
})
|
|
853
|
+
]
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
export { Player };
|