فهرست منبع

改善刷新按钮和刷新次数

User 5 ماه پیش
والد
کامیت
5356ab0131

+ 17 - 2
BAT-TOOL/0-ENABLE-TCPIP.BAT

@@ -1,15 +1,30 @@
 @echo off
+chcp 65001 >nul
+setlocal enabledelayedexpansion
+
 echo ========================================
 echo Enable ADB TCP/IP Mode (Port 5555)
 echo ========================================
 echo.
 
+REM Get the directory where this batch file is located
+set "SCRIPT_DIR=%~dp0"
+set "PROJECT_ROOT=%SCRIPT_DIR%.."
+
+REM Read ADB path from config.js using PowerShell
+echo [0/2] Reading ADB path from config.js...
+for /f "delims=" %%i in ('powershell -Command "$content = Get-Content '%PROJECT_ROOT%\config.js' -Raw; $content = $content -replace 'module\.exports\s*=\s*', ''; $content = $content -replace ';', ''; $content = $content.Trim(); $json = $content | ConvertFrom-Json; $adbPath = $json.'adb-path'; if ($adbPath) { Write-Output ($adbPath.TrimEnd('\') + '\adb.exe') } else { Write-Output 'adb' }"') do set "ADB_PATH=%%i"
+
+if "%ADB_PATH%"=="" set "ADB_PATH=adb"
+echo Using ADB: %ADB_PATH%
+echo.
+
 echo [1/2] List connected devices...
-adb devices
+"%ADB_PATH%" devices
 echo.
 
 echo [2/2] Enable TCP/IP mode...
-adb tcpip 5555
+"%ADB_PATH%" tcpip 5555
 echo.
 
 echo ========================================

+ 27 - 12
BAT-TOOL/0-TEST-CONNECT.BAT

@@ -1,9 +1,24 @@
 @echo off
 chcp 65001 >nul
+setlocal enabledelayedexpansion
+
 echo ========================================
 echo Test ADB Connection
 echo ========================================
 echo.
+
+REM Get the directory where this batch file is located
+set "SCRIPT_DIR=%~dp0"
+set "PROJECT_ROOT=%SCRIPT_DIR%.."
+
+REM Read ADB path from config.js using PowerShell
+echo [0/6] Reading ADB path from config.js...
+for /f "delims=" %%i in ('powershell -Command "$content = Get-Content '%PROJECT_ROOT%\config.js' -Raw; $content = $content -replace 'module\.exports\s*=\s*', ''; $content = $content -replace ';', ''; $content = $content.Trim(); $json = $content | ConvertFrom-Json; $adbPath = $json.'adb-path'; if ($adbPath) { Write-Output ($adbPath.TrimEnd('\') + '\adb.exe') } else { Write-Output 'adb' }"') do set "ADB_PATH=%%i"
+
+if "%ADB_PATH%"=="" set "ADB_PATH=adb"
+echo Using ADB: %ADB_PATH%
+echo.
+
 echo Please enter the last two digits of the IP address:
 set /p IP_LAST_TWO="Last two digits (e.g., 0.15): "
 if "%IP_LAST_TWO%"=="" (
@@ -18,18 +33,18 @@ echo.
 echo Connecting to %DEVICE_ADDRESS%...
 echo.
 
-echo [1/5] Check if ADB is available...
-adb version >nul 2>&1
+echo [1/6] Check if ADB is available...
+"%ADB_PATH%" version >nul 2>&1
 if errorlevel 1 (
-    echo Error: ADB not installed or not in PATH
-    echo Please ensure Android SDK Platform Tools is installed
+    echo Error: ADB not found at: %ADB_PATH%
+    echo Please check config.js and ensure ADB path is correct
     pause
     exit /b 1
 )
 echo ADB is available
 echo.
 
-echo [2/5] Test network connectivity (ping %DEVICE_IP%)...
+echo [2/6] Test network connectivity (ping %DEVICE_IP%)...
 ping -n 2 %DEVICE_IP% >nul 2>&1
 if errorlevel 1 (
     echo Cannot ping %DEVICE_IP%
@@ -40,7 +55,7 @@ if errorlevel 1 (
     echo.
 )
 
-echo [3/5] Check if port %DEVICE_PORT% is open...
+echo [3/6] Check if port %DEVICE_PORT% is open...
 powershell -Command "Test-NetConnection -ComputerName %DEVICE_IP% -Port %DEVICE_PORT% -InformationLevel Quiet" >nul 2>&1
 if errorlevel 1 (
     echo Port %DEVICE_PORT% may not be open or blocked by firewall
@@ -50,12 +65,12 @@ if errorlevel 1 (
     echo.
 )
 
-echo [4/5] Disconnect old connection (if any)...
-adb disconnect %DEVICE_ADDRESS% >nul 2>&1
+echo [4/6] Disconnect old connection (if any)...
+"%ADB_PATH%" disconnect %DEVICE_ADDRESS% >nul 2>&1
 timeout /t 1 /nobreak >nul
 
 echo Attempting to connect %DEVICE_ADDRESS%...
-adb connect %DEVICE_ADDRESS%
+"%ADB_PATH%" connect %DEVICE_ADDRESS%
 set CONNECT_RESULT=%ERRORLEVEL%
 
 echo.
@@ -83,7 +98,7 @@ if %CONNECT_RESULT% equ 0 (
     echo.
     echo 4. If phone doesn't have "Wireless debugging" option, try:
     echo    a) Connect phone to computer via USB
-    echo    b) Run: adb tcpip 5555
+    echo    b) Run: 0-ENABLE-TCPIP.BAT
     echo    c) Unplug USB, then run this script again
     echo.
     echo 5. Check if phone and computer are on same Wi-Fi network
@@ -92,9 +107,9 @@ if %CONNECT_RESULT% equ 0 (
     echo.
 )
 
-echo [5/5] Check device list...
+echo [5/6] Check device list...
 echo.
-adb devices
+"%ADB_PATH%" devices
 echo.
 
 echo ========================================

+ 2 - 2
config.js

@@ -1,3 +1,3 @@
-{
+module.exports = {
 	"adb-path": "C:\\Users\\GIGABYTE\\AppData\\Local\\Android\\Sdk\\platform-tools"
-}
+};

+ 38 - 41
main-js/adb/device-manager.js

@@ -11,24 +11,11 @@ function getMainWindow() {
   return windows.length > 0 ? windows[0] : null;
 }
 
-// 获取已连接的 ADB 设备列表
+// 获取 ADB 设备列表(每次都重新扫描网络)
 export async function getADBDevices() {
   try {
-    const adbPath = getCachedAdbPath();
-    const { stdout } = await execAsync(`${adbPath} devices`);
-    const lines = stdout.split('\n').slice(1);
-    const devices = [];
-    
-    for (const line of lines) {
-      const parts = line.trim().split(/\s+/);
-      if (parts.length >= 2 && parts[0] && parts[1] === 'device') {
-        devices.push({
-          id: parts[0],
-          status: parts[1]
-        });
-      }
-    }
-    return devices;
+    // 每次都重新扫描网络设备,不记录已连接的设备
+    return await scanNetworkDevices(null);
   } catch (error) {
     console.error('获取设备列表失败:', error);
     return [];
@@ -40,18 +27,39 @@ export async function scanNetworkDevices(event) {
   const adbPath = getCachedAdbPath();
   const baseIP = '192.168.0';
   const port = 5555;
-  const maxConcurrent = 20; // 限制并发数,避免过载
+  const maxConcurrent = 50; // 限制并发数,避免过载
   const connectTimeout = 1500; // 连接超时时间(毫秒)
   
+  const foundDevices = new Set(); // 使用 Set 避免重复
+  
   // 生成 IP 地址列表
   const ipList = [];
   for (let i = 1; i <= 255; i++) {
     ipList.push(`${baseIP}.${i}`);
   }
   
-  const foundDevices = new Set(); // 使用 Set 避免重复
+  // 推送设备发现的辅助函数
+  const pushDevice = (ipPort) => {
+    if (!foundDevices.has(ipPort)) {
+      foundDevices.add(ipPort);
+      const device = {
+        id: ipPort,
+        status: 'device'
+      };
+      // 实时发送发现的设备
+      if (event && event.sender) {
+        event.sender.send('device-found', device);
+      } else {
+        const mainWindow = getMainWindow();
+        if (mainWindow) {
+          mainWindow.webContents.send('device-found', device);
+        }
+      }
+      console.log('发现设备:', ipPort);
+    }
+  };
   
-  // 分批并发扫描
+  // 分批并发扫描,扫描到一个显示一个
   for (let i = 0; i < ipList.length; i += maxConcurrent) {
     const batch = ipList.slice(i, i + maxConcurrent);
     const promises = batch.map(async (ip) => {
@@ -69,41 +77,30 @@ export async function scanNetworkDevices(event) {
         // 连接失败是正常的,继续检查设备列表
       }
       
-      // 直接使用 adb -s IP:PORT devices 命令检查该设备是否在列表中
+      // 调用 adb devices 命令获取所有设备列表,检查是否包含端口 5555 的设备
       try {
-        const { stdout } = await execAsync(`${adbPath} -s ${ipPort} devices`, {
+        const { stdout } = await execAsync(`${adbPath} devices`, {
           timeout: 2000,
           maxBuffer: 1024 * 1024
         });
         
-        // 检查输出中是否包含 IP:PORT,如果有则说明设备存在
-        if (stdout.includes(ipPort)) {
-          // 发现设备,实时推送
-          if (!foundDevices.has(ipPort)) {
-            foundDevices.add(ipPort);
-            const device = {
-              id: ipPort,
-              status: 'device'
-            };
-            // 实时发送发现的设备
-            if (event && event.sender) {
-              event.sender.send('device-found', device);
-            } else {
-              const mainWindow = getMainWindow();
-              if (mainWindow) {
-                mainWindow.webContents.send('device-found', device);
-              }
-            }
-            console.log('发现设备:', ipPort);
-          }
+        // 检查输出中是否包含该 IP:PORT(匹配端口 5555)
+        // 使用正则表达式匹配 IP:5555 格式
+        const devicePattern = new RegExp(`${ip.replace(/\./g, '\\.')}:${port}\\s+device`, 'i');
+        if (devicePattern.test(stdout)) {
+          // 发现设备,立即推送显示(不等待整批完成)
+          pushDevice(ipPort);
           return ipPort;
         }
+        // 如果没有匹配到,说明没有设备
       } catch (checkError) {
         // 检查失败,忽略
       }
       return null;
     });
     
+    // 并发执行当前批次,但不等待所有完成才推送
+    // 每个 promise 一旦发现设备就会立即推送
     await Promise.all(promises);
   }
   

+ 9 - 2
main-js/config.js

@@ -11,8 +11,15 @@ export function loadConfig() {
     const configPath = path.join(__dirname, '..', 'config.js');
     if (existsSync(configPath)) {
       const configContent = readFileSync(configPath, 'utf-8');
-      // 解析 JSON(移除可能的注释和尾随逗号)
-      const jsonContent = configContent.replace(/\/\/.*$/gm, '').replace(/,(\s*[}\]])/g, '$1');
+      // 解析 CommonJS 格式的配置文件
+      // 移除 module.exports = 和分号,转换为纯 JSON
+      let jsonContent = configContent
+        .replace(/module\.exports\s*=\s*/g, '')  // 移除 module.exports =
+        .replace(/;[\s]*$/, '')                   // 移除末尾分号
+        .replace(/\/\/.*$/gm, '')                 // 移除单行注释
+        .replace(/,(\s*[}\]])/g, '$1')            // 移除尾随逗号
+        .trim();
+      
       return JSON.parse(jsonContent);
     }
   } catch (error) {

+ 1 - 1
package.json

@@ -9,7 +9,7 @@
     "build": "vite build",
     "preview": "vite preview",
     "electron": "electron .",
-    "electron:dev": "concurrently \"npm run dev\" \"wait-on http://localhost:5173 && electron .\"",
+    "electron:dev": "concurrently -k --success first \"npm run dev\" \"wait-on http://localhost:5173 && electron .\"",
     "electron:build": "npm run build && electron ."
   },
   "keywords": [],

+ 25 - 1
src/pages/Chat/Chat.css

@@ -1,3 +1,27 @@
 .Chat-container {
-  padding: 20px;
+  display: grid;
+  grid-template-rows: 7fr 3fr;
+  height: 100%;
+  width: 100%;
+  padding: 0;
+  margin: 0;
+  box-sizing: border-box;
+  align-items: stretch;
+  overflow: hidden; /* prevent internal scrollbars */
+  container-type: inline-size; /* enable cqw-based scaling */
+  border: 1px solid #3efc0f;
+}
+
+.Chat-history {
+  min-height: 0;
+  margin: 0;
+  padding: 0;
+  overflow: hidden;
+}
+
+.Chat-input {
+  min-height: 0;
+  margin: 0;
+  padding: 0;
+  overflow: hidden;
 }

+ 8 - 1
src/pages/Chat/Chat.jsx

@@ -1,12 +1,19 @@
 import './Chat.css';
 import { ChatLogic } from './Chat.js';
+import History from './History/History.jsx';
+import Input from './Input/Input.jsx';
 
 function Chat() {
   const logic = ChatLogic();
 
   return (
     <div className="Chat-container">
-      <h1>Chat</h1>
+      <div className="Chat-history">
+        <History />
+      </div>
+      <div className="Chat-input">
+        <Input />
+      </div>
     </div>
   );
 }

+ 9 - 0
src/pages/Chat/History/History.css

@@ -0,0 +1,9 @@
+.History-container {
+  height: 100%;
+  width: 100%;
+  margin: 0;
+  padding: 20px;
+  box-sizing: border-box;
+  overflow-y: auto;
+  border: 1px solid #1b02f8;
+}

+ 1 - 1
src/pages/Setting/Setting.js → src/pages/Chat/History/History.js

@@ -1,4 +1,4 @@
-export function SettingLogic() {
+export function HistoryLogic() {
   // business logic placeholder
 
   return {

+ 14 - 0
src/pages/Chat/History/History.jsx

@@ -0,0 +1,14 @@
+import './History.css';
+import { HistoryLogic } from './History.js';
+
+function History() {
+  const logic = HistoryLogic();
+
+  return (
+    <div className="History-container">
+      <h2>History</h2>
+    </div>
+  );
+}
+
+export default History;

+ 9 - 0
src/pages/Chat/Input/Input.css

@@ -0,0 +1,9 @@
+.Input-container {
+  height: 100%;
+  width: 100%;
+  margin: 0;
+  padding: 20px;
+  box-sizing: border-box;
+  overflow-y: auto;
+  border: 1px solid #ff0000;
+}

+ 7 - 0
src/pages/Chat/Input/Input.js

@@ -0,0 +1,7 @@
+export function InputLogic() {
+  // business logic placeholder
+
+  return {
+    // expose data or methods here
+  };
+}

+ 14 - 0
src/pages/Chat/Input/Input.jsx

@@ -0,0 +1,14 @@
+import './Input.css';
+import { InputLogic } from './Input.js';
+
+function Input() {
+  const logic = InputLogic();
+
+  return (
+    <div className="Input-container">
+      <h2>Input</h2>
+    </div>
+  );
+}
+
+export default Input;

+ 18 - 12
src/pages/Devices/Devices.css

@@ -17,7 +17,7 @@
 .devices-header {
   width: 100%;
   display: grid;
-  grid-template-columns: 65% 35%;
+  grid-template-columns: 1fr auto;
   align-items: center;
   gap: clamp(0.5rem, 1.5vw, 1rem);
   box-sizing: border-box;
@@ -46,26 +46,30 @@
 
 /* 刷新按钮 */
 .refresh-btn {
-  justify-self: start;
-  width: 80%;
+  justify-self: end;
+  inline-size: min(100%, clamp(70px, 28cqw, 120px)); /* scale by header width */
+  max-inline-size: 100%;
+  min-inline-size: 0;
   display: flex;
   align-items: center;
   justify-content: center;
-  gap: clamp(0.15rem, 0.8cqw, 0.4rem);
-  padding: clamp(0.36rem, 1.1cqw, 0.6rem) clamp(0.6rem, 1.5cqw, 1rem);
+  gap: clamp(0.12rem, 1.2cqw, 0.35rem);
+  min-height: clamp(30px, 7cqw, 36px);
+  padding: clamp(0.26rem, 1.1cqw, 0.42rem) clamp(0.42rem, 1.8cqw, 0.82rem); /* shrink padding as header narrows */
   background: #1a1a1a;
   color: white;
   border: none;
-  border-radius: clamp(6px, 1vw, 8px);
+  border-radius: clamp(6px, 1cqw, 8px);
   cursor: pointer;
-  /* about 80% of original size */
-  font-size: clamp(0.6rem, 2.1cqw, 0.84rem); /* scale text/icon with button */
+  font-size: clamp(0.48rem, 2.2cqw, 0.82rem); /* text scales with container */
   font-weight: 500;
   transition: all 0.2s ease;
-  line-height: 1.2;
+  line-height: 1.1;
   user-select: none;
   white-space: nowrap;
-  flex-shrink: 0;
+  flex-shrink: 1;
+  box-sizing: border-box;
+  overflow: hidden; /* ensure it never spills outside the header */
 }
 
 .refresh-btn:hover:not(.disabled) {
@@ -78,13 +82,15 @@
 }
 
 .refresh-btn.disabled {
-  opacity: 0.4;
+  opacity: 1;
   cursor: not-allowed;
-  background: #ccc;
+  background: #e5e7eb; /* clearer contrast for loading state */
+  color: #374151;
 }
 
 .refresh-btn.disabled:hover {
   transform: none;
+  background: #e5e7eb;
 }
 
 /* 刷新图标 */

+ 15 - 21
src/pages/Devices/Devices.js

@@ -24,11 +24,18 @@ export function DevicesLogic() {
     setLoading(true);
     // 清空现有设备列表,准备重新扫描
     setDevices([]);
+
+    // 本轮扫描内去重,防止同一设备被重复推送
+    const seenThisScan = new Set();
     
     // 设置实时监听设备发现事件
     const handleDeviceFound = (device) => {
       const deviceId = device?.id || device;
       if (deviceId && /^\d+\.\d+\.\d+\.\d+:\d+$/.test(deviceId)) {
+        if (seenThisScan.has(deviceId)) {
+          return;
+        }
+        seenThisScan.add(deviceId);
         setDevices(prev => {
           // 避免重复添加
           if (prev.includes(deviceId)) {
@@ -46,32 +53,19 @@ export function DevicesLogic() {
     }
     
     try {
-      // 先获取当前已连接的设备
-      const currentDevices = await window.electronAPI.getADBDevices();
-      const currentIPPorts = currentDevices
-        .map(device => device?.id || device)
-        .filter(id => id && /^\d+\.\d+\.\d+\.\d+:\d+$/.test(id));
-      
-      if (currentIPPorts.length > 0) {
-        setDevices(currentIPPorts);
-      }
-      
-      // 然后进行网络扫描(会实时推送发现的设备)
+      // 直接进行网络扫描(只跑一轮)
       console.log('开始网络扫描...');
-      await window.electronAPI.scanADBDevices();
+      const scannedDevices = await window.electronAPI.scanADBDevices();
       console.log('网络扫描完成');
-      
-      // 扫描完成后,再次获取所有设备,确保没有遗漏
-      const finalDevices = await window.electronAPI.getADBDevices();
-      const finalIPPorts = finalDevices
+
+      // 汇总扫描结果(去重)
+      const scannedIPPorts = (scannedDevices || [])
         .map(device => device?.id || device)
         .filter(id => id && /^\d+\.\d+\.\d+\.\d+:\d+$/.test(id));
       
-      // 合并并去重
-      setDevices(prev => {
-        const allDevices = new Set([...prev, ...finalIPPorts]);
-        return Array.from(allDevices);
-      });
+      if (scannedIPPorts.length > 0) {
+        setDevices(prev => Array.from(new Set([...prev, ...scannedIPPorts])));
+      }
     } catch (err) {
       console.error('扫描失败:', err);
     } finally {

+ 1 - 1
src/pages/Devices/Devices.jsx

@@ -24,7 +24,7 @@ function Devices() {
           onClick={loading ? undefined : scanDevices}
         >
           <div className={`refresh-icon ${loading ? 'spinning' : ''}`}>↻</div>
-          {loading ? '扫描中...' : '刷新'}
+          {loading ? '扫描中' : '刷新'}
         </div>
       </div>
       

+ 0 - 3
src/pages/Setting/Setting.css

@@ -1,3 +0,0 @@
-.Setting-container {
-  padding: 20px;
-}

+ 0 - 14
src/pages/Setting/Setting.jsx

@@ -1,14 +0,0 @@
-import './Setting.css';
-import { SettingLogic } from './Setting.js';
-
-function Setting() {
-  const logic = SettingLogic();
-
-  return (
-    <div className="Setting-container">
-      <h1>Setting</h1>
-    </div>
-  );
-}
-
-export default Setting;

+ 4 - 1
src/pages/home.css

@@ -12,7 +12,10 @@
 
 .devices-container,
 .screenshot-container,
-.setting-container {
+.chat-container {
   width: 100%;
+  height: 100%;
+  min-height: 0;
   box-sizing: border-box;
+  overflow: hidden;
 }

+ 3 - 3
src/pages/home.js

@@ -4,15 +4,15 @@ export function HomeLogic() {
 
   const [showDevices, setShowDevices] = useState(true);
   const [showScreenShot, setShowScreenShot] = useState(true);
-  const [showSetting, setShowSetting] = useState(true);
+  const [showChat, setShowChat] = useState(true);
 
   return {
     showDevices,
     setShowDevices,
     showScreenShot,
     setShowScreenShot,
-    showSetting,
-    setShowSetting,
+    showChat,
+    setShowChat,
     // expose data or methods here
   };
 }

+ 5 - 5
src/pages/home.jsx

@@ -2,15 +2,15 @@ import './Home.css';
 import { HomeLogic } from './Home.js';
 import Devices from './Devices/Devices.jsx';
 import ScreenShot from './ScreenShot/ScreenShot.jsx';
-import Setting from './Setting/Setting.jsx';
+import Chat from './Chat/Chat.jsx';
 
 function Home() {
   const { showDevices, 
     setShowDevices, 
     showScreenShot, 
     setShowScreenShot,
-    showSetting,
-    setShowSetting,
+    showChat,
+    setShowChat,
   } = HomeLogic();
 
   return (
@@ -21,8 +21,8 @@ function Home() {
       <div className="screenshot-container">
         {showScreenShot && <ScreenShot />}
       </div>
-      <div className="setting-container">
-        {showSetting && <Setting />}
+      <div className="chat-container">
+        {showChat && <Chat />}
       </div>
     </div>
   );