From ef4d316492e19ab965079641e3a59b395c10858d Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Mon, 20 Apr 2026 08:20:39 +0200 Subject: [PATCH] Improve web-side remote desktop control user experience --- ReadMe.md | 4 +-- ReadMe_EN.md | 4 +-- ReadMe_TW.md | 4 +-- 2019Remote.sln => YAMA.sln | 7 ++-- server/2015Remote/UIBranding.h | 4 +-- server/2015Remote/WebPage.h | 61 +++++++++++++++++++++++++++++++--- 6 files changed, 68 insertions(+), 16 deletions(-) rename 2019Remote.sln => YAMA.sln (95%) diff --git a/ReadMe.md b/ReadMe.md index 838bb74..d8ccc48 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -640,8 +640,8 @@ make | **Telegram** | [@doge_grandfather](https://t.me/doge_grandfather) | | **Email** | [yuanyuanxiang163@gmail.com](mailto:yuanyuanxiang163@gmail.com) | | **LinkedIn** | [wishyuanqi](https://www.linkedin.com/in/wishyuanqi) | -| **Issues** | [问题反馈](https://github.com/yuanyuanxiang/SimpleRemoter/issues) | -| **PR** | [贡献代码](https://github.com/yuanyuanxiang/SimpleRemoter/pulls) | +| **Issues** | [问题反馈](https://t.me/SimpleRemoter) | +| **PR** | [贡献代码](https://git.simpleremoter.com/) | ### 赞助支持 diff --git a/ReadMe_EN.md b/ReadMe_EN.md index d92d3ab..19f8701 100644 --- a/ReadMe_EN.md +++ b/ReadMe_EN.md @@ -625,8 +625,8 @@ For complete update history, see: [history.md](./history.md) | **Telegram** | [@doge_grandfather](https://t.me/doge_grandfather) | | **Email** | [yuanyuanxiang163@gmail.com](mailto:yuanyuanxiang163@gmail.com) | | **LinkedIn** | [wishyuanqi](https://www.linkedin.com/in/wishyuanqi) | -| **Issues** | [Report Issues](https://github.com/yuanyuanxiang/SimpleRemoter/issues) | -| **PR** | [Contribute](https://github.com/yuanyuanxiang/SimpleRemoter/pulls) | +| **Issues** | [Report Issues](https://t.me/SimpleRemoter) | +| **PR** | [Contribute](https://git.simpleremoter.com/) | ### Sponsorship diff --git a/ReadMe_TW.md b/ReadMe_TW.md index f0be249..e38713e 100644 --- a/ReadMe_TW.md +++ b/ReadMe_TW.md @@ -624,8 +624,8 @@ make | **Telegram** | [@doge_grandfather](https://t.me/doge_grandfather) | | **Email** | [yuanyuanxiang163@gmail.com](mailto:yuanyuanxiang163@gmail.com) | | **LinkedIn** | [wishyuanqi](https://www.linkedin.com/in/wishyuanqi) | -| **Issues** | [問題回報](https://github.com/yuanyuanxiang/SimpleRemoter/issues) | -| **PR** | [貢獻程式碼](https://github.com/yuanyuanxiang/SimpleRemoter/pulls) | +| **Issues** | [問題回報](https://t.me/SimpleRemoter) | +| **PR** | [貢獻程式碼](https://git.simpleremoter.com/) | ### 贊助支持 diff --git a/2019Remote.sln b/YAMA.sln similarity index 95% rename from 2019Remote.sln rename to YAMA.sln index cf5eb1b..15996f2 100644 --- a/2019Remote.sln +++ b/YAMA.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 18 -VisualStudioVersion = 18.6.11709.129 insiders +VisualStudioVersion = 18.6.11709.129 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Yama", "server\2015Remote\2015Remote_vs2015.vcxproj", "{D58E96CD-C41F-4DD1-9502-EF1CB7AC65E5}" EndProject @@ -11,12 +11,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestRun", "client\TestRun_v EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ServerDll", "client\ClientDll_vs2015.vcxproj", "{BEBAF888-532D-40D3-A8DD-DDAAF69F49AA}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{70702583-26EE-47E0-9847-4D58F9449F4C}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Architectures", "Architectures", "{70702583-26EE-47E0-9847-4D58F9449F4C}" ProjectSection(SolutionItems) = preProject Dependencies.md = Dependencies.md - history.md = history.md + docs\MultiLayerLicense.md = docs\MultiLayerLicense.md ReadMe.md = ReadMe.md ReadMe_EN.md = ReadMe_EN.md + ReadMe_TW.md = ReadMe_TW.md EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TinyRun", "client\TinyRun.vcxproj", "{E3F3A477-05BA-431D-B002-28EF8BFA6E86}" diff --git a/server/2015Remote/UIBranding.h b/server/2015Remote/UIBranding.h index 4865a65..b4b1639 100644 --- a/server/2015Remote/UIBranding.h +++ b/server/2015Remote/UIBranding.h @@ -268,10 +268,10 @@ #define BRAND_URL_FEEDBACK "https://t.me/SimpleRemoter" // 帮助文档链接(帮助菜单 → 什么是这个) -#define BRAND_URL_WIKI "https://github.com/yuanyuanxiang/SimpleRemoter/wiki" +#define BRAND_URL_WIKI "https://git.simpleremoter.com/" // 请求授权链接(工具菜单 → 请求授权) -#define BRAND_URL_REQUEST_AUTH "https://github.com/yuanyuanxiang/SimpleRemoter/wiki#请求授权" +#define BRAND_URL_REQUEST_AUTH "https://simpleremoter.com/" // 获取插件 #define BRAND_URL_GET_PLUGIN "This feature has not been implemented!\nPlease contact: 962914132@qq.com" diff --git a/server/2015Remote/WebPage.h b/server/2015Remote/WebPage.h index 639e275..1e230bd 100644 --- a/server/2015Remote/WebPage.h +++ b/server/2015Remote/WebPage.h @@ -649,6 +649,7 @@ inline std::string GetWebPageHTML() {
Connecting... + @@ -747,14 +748,35 @@ inline std::string GetWebPageHTML() { return viewMode === 'grid' ? 12 : 50; } + // Page visibility state for background detection (iOS PWA) + let isPageVisible = !document.hidden; + let reconnectTimer = null; + + function scheduleReconnect() { + if (reconnectTimer) return; // Already scheduled + if (!isPageVisible) return; // Don't reconnect in background + reconnectTimer = setTimeout(() => { + reconnectTimer = null; + if (isPageVisible) connectWebSocket(); + }, 3000); + } + + function cancelReconnect() { + if (reconnectTimer) { + clearTimeout(reconnectTimer); + reconnectTimer = null; + } + } + function connectWebSocket() { + if (!isPageVisible) return; // Don't connect in background const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:'; updateWsStatus('connecting'); try { ws = new WebSocket(protocol + '//' + location.host + '/ws'); } catch (e) { updateWsStatus('disconnected'); - setTimeout(connectWebSocket, 3000); + scheduleReconnect(); return; } ws.binaryType = 'arraybuffer'; @@ -767,7 +789,7 @@ inline std::string GetWebPageHTML() { getDevices(); } }; - ws.onclose = () => { stopPingInterval(); updateWsStatus('disconnected'); setTimeout(connectWebSocket, 3000); }; + ws.onclose = () => { stopPingInterval(); updateWsStatus('disconnected'); scheduleReconnect(); }; ws.onerror = (e) => console.error('WS error:', e); ws.onmessage = (event) => { if (typeof event.data === 'string') handleSignaling(JSON.parse(event.data)); @@ -1631,6 +1653,10 @@ inline std::string GetWebPageHTML() { showZoomIndicator(); } applyZoomTransform(); + // Update cursor overlay to follow canvas transform + if (cursorState.initialized) { + updateCursorOverlay(cursorState.x, cursorState.y); + } return; } @@ -1715,10 +1741,14 @@ inline std::string GetWebPageHTML() { if (zoomState.isPinching) { if (e.touches.length < 2) { zoomState.isPinching = false; - // Update pan center for smooth transition to pan mode + // Update pan center and lastX/lastY for smooth transition if (e.touches.length === 1) { - zoomState.pinchCenterX = e.touches[0].clientX; - zoomState.pinchCenterY = e.touches[0].clientY; + const touch = e.touches[0]; + zoomState.pinchCenterX = touch.clientX; + zoomState.pinchCenterY = touch.clientY; + // Reset lastX/lastY to prevent delta jump on next move + touchState.lastX = touch.clientX; + touchState.lastY = touch.clientY; } } touchState.touchCount = e.touches.length; @@ -1930,6 +1960,27 @@ inline std::string GetWebPageHTML() { if (e.key === 'Enter' && document.querySelector('.page.active').id === 'login-page') login(); }); + // Handle page visibility change (iOS PWA background/foreground) + document.addEventListener('visibilitychange', () => { + isPageVisible = !document.hidden; + if (document.hidden) { + // Page going to background - close connection and cancel reconnect + cancelReconnect(); + stopPingInterval(); + if (ws) { + ws.onclose = null; // Prevent triggering reconnect + ws.close(); + ws = null; + } + updateWsStatus('disconnected'); + } else { + // Page coming to foreground - reconnect + if (!ws || ws.readyState !== WebSocket.OPEN) { + connectWebSocket(); + } + } + }); + window.onload = function() { const compat = checkWebCodecs(); if (!compat.supported) {