| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- import { ipcMain } from 'electron';
- import { exec } from 'child_process';
- import { promisify } from 'util';
- import { getCachedAdbPath } from '../config.js';
- const execAsync = promisify(exec);
- // 默认每次滚动距离(像素)
- const DEFAULT_SCROLL_DISTANCE = 100;
- // 默认滚动持续时间(毫秒),使用较长的时间模拟真实手指滑动
- const DEFAULT_SCROLL_DURATION = 500;
- /**
- * 计算滚动操作的坐标(小幅度滚动)
- * @param {string} direction - 滚动方向: up-down, down-up, left-right, right-left
- * @param {number} width - 设备宽度
- * @param {number} height - 设备高度
- * @param {number} scrollDistance - 每次滚动距离(像素),默认10px
- * @returns {Object} 包含起始和结束坐标的对象 {x1, y1, x2, y2}
- */
- function calculateScrollCoordinates(direction, width, height, scrollDistance = DEFAULT_SCROLL_DISTANCE) {
- // 滚动从屏幕中心开始
- const centerX = Math.round(width / 2);
- const centerY = Math.round(height / 2);
- let x1, y1, x2, y2;
- switch (direction) {
- case 'up-down':
- // 从上往下滚动(向下滚动)
- x1 = x2 = centerX;
- y1 = centerY;
- y2 = centerY + scrollDistance;
- break;
-
- case 'down-up':
- // 从下往上滚动(向上滚动)
- x1 = x2 = centerX;
- y1 = centerY;
- y2 = centerY - scrollDistance;
- break;
-
- case 'left-right':
- // 从左往右滚动(向右滚动)
- y1 = y2 = centerY;
- x1 = centerX;
- x2 = centerX + scrollDistance;
- break;
-
- case 'right-left':
- // 从右往左滚动(向左滚动)
- y1 = y2 = centerY;
- x1 = centerX;
- x2 = centerX - scrollDistance;
- break;
-
- default:
- throw new Error(`未知的滚动方向: ${direction}`);
- }
- return { x1, y1, x2, y2 };
- }
- /**
- * 发送滚动操作到设备
- * 使用触摸屏事件模拟真实的手指滑动,避免触发 tap 事件
- * @param {string} ipPort - 设备 ID
- * @param {string} direction - 滚动方向: up-down, down-up, left-right, right-left
- * @param {number} width - 设备宽度
- * @param {number} height - 设备高度
- * @param {number} scrollDistance - 每次滚动距离(像素),默认10px
- * @param {number} duration - 滚动持续时间(毫秒),默认500ms
- * @returns {Promise<Object>} 执行结果 {success, error?}
- */
- export async function sendScroll(ipPort, direction, width, height, scrollDistance = DEFAULT_SCROLL_DISTANCE, duration = DEFAULT_SCROLL_DURATION) {
- if (!ipPort) {
- return { success: false, error: '缺少设备 ID' };
- }
-
- if (!direction) {
- return { success: false, error: '缺少滚动方向' };
- }
-
- const validDirections = ['up-down', 'down-up', 'left-right', 'right-left'];
- if (!validDirections.includes(direction)) {
- return { success: false, error: `无效的滚动方向: ${direction},应为: ${validDirections.join(', ')}` };
- }
-
- if (typeof width !== 'number' || typeof height !== 'number') {
- return { success: false, error: '设备宽度和高度必须是数字' };
- }
-
- if (width <= 0 || height <= 0) {
- return { success: false, error: '设备宽度和高度必须大于0' };
- }
-
- try {
- const adbPath = getCachedAdbPath();
-
- // 计算滚动坐标
- const { x1, y1, x2, y2 } = calculateScrollCoordinates(direction, width, height, scrollDistance);
-
- // 使用 input touchscreen swipe 命令来模拟真实的触摸滑动
- // 这个命令会模拟手指在屏幕上慢慢滑动,不会触发 tap 事件
- // 使用较长的持续时间(至少 300ms)确保被识别为滑动而不是点击
- const actualDuration = Math.max(duration, 300); // 确保至少 300ms
-
- const command = `${adbPath} -s ${ipPort} shell input touchscreen swipe ${x1} ${y1} ${x2} ${y2} ${actualDuration}`;
-
- await execAsync(command, {
- timeout: 10000,
- maxBuffer: 1024 * 1024
- });
-
- console.log(`成功滚动: ${direction} (${x1},${y1}) -> (${x2},${y2}), 持续时间: ${actualDuration}ms`);
- return { success: true };
- } catch (error) {
- console.error('滚动失败:', error.message);
- return { success: false, error: error.message };
- }
- }
- // 注册 IPC 处理器
- export function registerIpcHandlers() {
- // IPC 处理程序:发送滚动操作到设备
- ipcMain.handle('send-scroll', async (event, ipPort, direction, width, height, scrollDistance, duration) => {
- return await sendScroll(ipPort, direction, width, height, scrollDistance, duration);
- });
- }
|