|
|
@@ -1,7 +1,126 @@
|
|
|
+import { useEffect, useRef, useState, useCallback } from 'react';
|
|
|
+
|
|
|
+// 截屏逻辑:监听设备预览事件,轮询 adb 截屏并展示
|
|
|
export function ScreenShotLogic() {
|
|
|
- // business logic placeholder
|
|
|
+ const [currentDevice, setCurrentDevice] = useState(null);
|
|
|
+ const [imageSrc, setImageSrc] = useState(null);
|
|
|
+ const stopFlag = useRef(false);
|
|
|
+ const waitForLoadRef = useRef(null);
|
|
|
+ const activeDeviceRef = useRef(null);
|
|
|
+ const loopIdRef = useRef(null);
|
|
|
+ const frameCounterRef = useRef(0);
|
|
|
+
|
|
|
+ // 截屏循环:请求截图 -> 显示 -> 等待加载 -> 再请求下一帧
|
|
|
+ const startLoop = useCallback(async (device) => {
|
|
|
+ // 避免同时多个循环
|
|
|
+ const loopId = Symbol('loop');
|
|
|
+ loopIdRef.current = loopId;
|
|
|
+
|
|
|
+ const runOnce = async () => {
|
|
|
+ // 检查是否应该停止循环
|
|
|
+ if (stopFlag.current || loopIdRef.current !== loopId || activeDeviceRef.current !== device) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 请求屏幕截图
|
|
|
+ if (!window.electronAPI || !window.electronAPI.captureScreenshot) {
|
|
|
+ console.warn('截屏 API 不可用');
|
|
|
+ await delay(500);
|
|
|
+ runOnce();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const res = await window.electronAPI.captureScreenshot(device);
|
|
|
+
|
|
|
+ if (!res?.success || !res.data) {
|
|
|
+ // 截图失败,等待后重试
|
|
|
+ await delay(400);
|
|
|
+ runOnce();
|
|
|
+ } else {
|
|
|
+ // 截图成功,更新图片并等待加载完成
|
|
|
+ const stamp = frameCounterRef.current++;
|
|
|
+ const dataUrl = `data:image/png;base64,${res.data}#${stamp}`;
|
|
|
+
|
|
|
+ // 创建等待图片加载的 Promise
|
|
|
+ const waitPromise = new Promise((resolve) => {
|
|
|
+ waitForLoadRef.current = resolve;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 更新图片源
|
|
|
+ setImageSrc(dataUrl);
|
|
|
+
|
|
|
+ // 等待图片加载完成(onLoad 触发)或超时(1秒),然后请求下一帧
|
|
|
+ await Promise.race([waitPromise, delay(1000)]);
|
|
|
+
|
|
|
+ // 继续下一帧
|
|
|
+ runOnce();
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ console.error('截屏循环异常:', err);
|
|
|
+ await delay(500);
|
|
|
+ runOnce();
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 开始循环
|
|
|
+ runOnce();
|
|
|
+ }, []);
|
|
|
+
|
|
|
+ // 监听来自 Devices 的开始/停止预览事件
|
|
|
+ useEffect(() => {
|
|
|
+ const handleStart = (e) => {
|
|
|
+ const device = e.detail?.device;
|
|
|
+ if (!device) return;
|
|
|
+
|
|
|
+ // 停止之前的循环(如果有)
|
|
|
+ stopFlag.current = true;
|
|
|
+
|
|
|
+ // 启动新的预览循环
|
|
|
+ stopFlag.current = false;
|
|
|
+ activeDeviceRef.current = device;
|
|
|
+ setCurrentDevice(device);
|
|
|
+ setImageSrc(null); // 清空之前的图片
|
|
|
+ startLoop(device);
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleStop = (e) => {
|
|
|
+ const device = e.detail?.device;
|
|
|
+ // 只有当前预览设备才停止
|
|
|
+ if (!device || device === activeDeviceRef.current) {
|
|
|
+ stopFlag.current = true;
|
|
|
+ activeDeviceRef.current = null;
|
|
|
+ loopIdRef.current = null;
|
|
|
+ setCurrentDevice(null);
|
|
|
+ setImageSrc(null);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ window.addEventListener('start-preview', handleStart);
|
|
|
+ window.addEventListener('stop-preview', handleStop);
|
|
|
+
|
|
|
+ return () => {
|
|
|
+ window.removeEventListener('start-preview', handleStart);
|
|
|
+ window.removeEventListener('stop-preview', handleStop);
|
|
|
+ stopFlag.current = true;
|
|
|
+ };
|
|
|
+ }, [startLoop]);
|
|
|
+
|
|
|
+ // 提供给组件的 onLoad 回调,通知图片已加载,可以请求下一帧
|
|
|
+ const notifyImageLoaded = useCallback(() => {
|
|
|
+ if (waitForLoadRef.current) {
|
|
|
+ waitForLoadRef.current();
|
|
|
+ waitForLoadRef.current = null;
|
|
|
+ }
|
|
|
+ }, []);
|
|
|
|
|
|
return {
|
|
|
- // expose data or methods here
|
|
|
+ currentDevice,
|
|
|
+ imageSrc,
|
|
|
+ notifyImageLoaded,
|
|
|
};
|
|
|
}
|
|
|
+
|
|
|
+function delay(ms) {
|
|
|
+ return new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
+}
|