Devices.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import { useState, useEffect, useRef } from 'react';
  2. // Devices 页面的业务逻辑 Hook
  3. export function DevicesLogic() {
  4. // 设备列表(IP:端口格式)
  5. const [devices, setDevices] = useState([]);
  6. // 加载状态
  7. const [loading, setLoading] = useState(false);
  8. // 已连接设备集合(用于控制按钮显示)
  9. const [connectedDevices, setConnectedDevices] = useState(new Set());
  10. // 预览中的设备集合
  11. const [previewingDevices, setPreviewingDevices] = useState(new Set());
  12. // 防止重复扫描标记
  13. const hasScanned = useRef(false);
  14. // 扫描设备列表(只获取已连接设备,不自动连接)
  15. const scanDevices = async () => {
  16. if (!window.electronAPI || !window.electronAPI.getADBDevices) {
  17. console.warn('Electron API 不可用');
  18. setDevices([]);
  19. return;
  20. }
  21. setLoading(true);
  22. try {
  23. const deviceList = await window.electronAPI.getADBDevices();
  24. // 过滤出 IP:端口格式的设备
  25. const ipPortList = (deviceList || [])
  26. .map(device => device?.id || device)
  27. .filter(Boolean)
  28. .filter(id => {
  29. const ipPortPattern = /^\d+\.\d+\.\d+\.\d+:\d+$/;
  30. return ipPortPattern.test(id);
  31. });
  32. console.log('devices:', ipPortList);
  33. setDevices(ipPortList);
  34. } catch (err) {
  35. console.error('扫描失败:', err);
  36. setDevices([]);
  37. } finally {
  38. setLoading(false);
  39. }
  40. };
  41. // 连接设备
  42. const connectDevice = async (ipPort) => {
  43. if (!window.electronAPI || !window.electronAPI.connectADBDevice) {
  44. console.warn('连接设备功能不可用');
  45. return;
  46. }
  47. try {
  48. await window.electronAPI.connectADBDevice(ipPort);
  49. setConnectedDevices(prev => new Set([...prev, ipPort]));
  50. } catch (err) {
  51. console.error('连接设备失败:', err);
  52. }
  53. };
  54. // 断开设备
  55. const disconnectDevice = async (ipPort) => {
  56. if (window.electronAPI && window.electronAPI.disconnectADBDevice) {
  57. try {
  58. await window.electronAPI.disconnectADBDevice(ipPort);
  59. } catch (err) {
  60. console.error('断开设备失败:', err);
  61. }
  62. }
  63. setConnectedDevices(prev => {
  64. const newSet = new Set(prev);
  65. newSet.delete(ipPort);
  66. return newSet;
  67. });
  68. // 同时取消预览状态
  69. setPreviewingDevices(prev => {
  70. const next = new Set(prev);
  71. next.delete(ipPort);
  72. return next;
  73. });
  74. };
  75. // 切换预览/取消预览
  76. const togglePreview = (ipPort) => {
  77. setPreviewingDevices(prev => {
  78. const next = new Set(prev);
  79. if (next.has(ipPort)) {
  80. next.delete(ipPort);
  81. } else {
  82. next.add(ipPort);
  83. }
  84. return next;
  85. });
  86. };
  87. // 页面加载时自动扫描
  88. useEffect(() => {
  89. if (!hasScanned.current) {
  90. hasScanned.current = true;
  91. scanDevices();
  92. }
  93. }, []);
  94. return {
  95. devices,
  96. loading,
  97. scanDevices,
  98. connectDevice,
  99. disconnectDevice,
  100. connectedDevices,
  101. previewingDevices,
  102. togglePreview,
  103. };
  104. }