Improve web-side remote desktop control user experience

This commit is contained in:
yuanyuanxiang
2026-04-20 08:20:39 +02:00
parent 5a325a202b
commit ef4d316492
6 changed files with 68 additions and 16 deletions

View File

@@ -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"

View File

@@ -649,6 +649,7 @@ inline std::string GetWebPageHTML() {
</div>
<div class="toolbar-right">
<span id="screen-status" class="screen-status connecting">Connecting...</span>
<button class="toolbar-btn-bar" id="btn-rdp-reset-bar" onclick="sendRdpReset()" title="RDP Reset">&#x21BB;</button>
<button class="toolbar-btn-bar" id="btn-mouse-bar" onclick="toggleControl()" title="Mouse Control">&#x1F5B1;</button>
<button class="toolbar-btn-bar" id="btn-keyboard-bar" onclick="toggleKeyboard()" title="Keyboard" disabled>&#x2328;</button>
<button class="fullscreen-btn" onclick="toggleFullscreen()" title="Fullscreen (F11)">&#x26F6;</button>
@@ -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) {