From 479a23592ccbf87b2fc88890c576674929f022d5 Mon Sep 17 00:00:00 2001 From: Hermes Date: Fri, 22 May 2026 08:38:40 +0800 Subject: [PATCH] Improve ToolApp blank-edge back gestures --- code/th_01_base.js | 10 +++--- code/th_15_extra.js | 76 +++++++++++++++++++++++++++++++++++---------- manifest.json | 10 +++--- manifest.sig | 2 +- 4 files changed, 71 insertions(+), 27 deletions(-) diff --git a/code/th_01_base.js b/code/th_01_base.js index 840f7b9..5fc29d8 100644 --- a/code/th_01_base.js +++ b/code/th_01_base.js @@ -100,9 +100,9 @@ var ConfigValidator = { LONG_PRESS_TRIGGERED_MOVE_SLOP_DP: { type: "int", min: 8, max: 80, default: 28 }, LONG_PRESS_VIBRATE_MS: { type: "int", min: 10, max: 100, default: 40 }, CLICK_SLOP_DP: { type: "int", min: 2, max: 20, default: 6 }, - TOOLAPP_BACK_EDGE_WIDTH_DP: { type: "int", min: 1, max: 120, default: 56 }, + TOOLAPP_BACK_EDGE_WIDTH_DP: { type: "int", min: 1, max: 120, default: 72 }, ENABLE_TOOLAPP_INNER_BACK_STRIPS: { type: "bool", default: false }, - ENABLE_TOOLAPP_SCREEN_BACK_STRIPS: { type: "bool", default: false }, + ENABLE_TOOLAPP_SCREEN_BACK_STRIPS: { type: "bool", default: true }, TOOLAPP_BACK_COMMIT_DISTANCE_DP: { type: "int", min: 1, max: 480, default: 36 }, TOOLAPP_BACK_PROGRESS_DISTANCE_DP: { type: "int", min: 1, max: 720, default: 96 }, @@ -736,9 +736,9 @@ var ConfigManager = { LONG_PRESS_MS: 520, LONG_PRESS_TRIGGERED_MOVE_SLOP_DP: 28, CLICK_SLOP_DP: 6, - TOOLAPP_BACK_EDGE_WIDTH_DP: 56, + TOOLAPP_BACK_EDGE_WIDTH_DP: 72, ENABLE_TOOLAPP_INNER_BACK_STRIPS: false, - ENABLE_TOOLAPP_SCREEN_BACK_STRIPS: false, + ENABLE_TOOLAPP_SCREEN_BACK_STRIPS: true, TOOLAPP_BACK_COMMIT_DISTANCE_DP: 36, TOOLAPP_BACK_PROGRESS_DISTANCE_DP: 96, ENABLE_BOUNCE: true, @@ -852,7 +852,7 @@ var ConfigManager = { { key: "CLICK_SLOP_DP", name: "点击位移阈值(dp)", type: "int", min: 1, max: 40, step: 1 }, { key: "TOOLAPP_BACK_EDGE_WIDTH_DP", name: "返回起手边缘宽度", type: "int", min: 1, max: 120, step: 1 }, { key: "ENABLE_TOOLAPP_INNER_BACK_STRIPS", name: "启用旧版页面覆盖热区(不推荐)", type: "bool" }, - { key: "ENABLE_TOOLAPP_SCREEN_BACK_STRIPS", name: "启用旧版屏幕覆盖热区(已禁用)", type: "bool" }, + { key: "ENABLE_TOOLAPP_SCREEN_BACK_STRIPS", name: "启用屏幕空白区返回", type: "bool" }, { key: "TOOLAPP_BACK_COMMIT_DISTANCE_DP", name: "设置页返回触发距离", type: "int", min: 1, max: 480, step: 1 }, { key: "TOOLAPP_BACK_PROGRESS_DISTANCE_DP", name: "设置页返回动画距离", type: "int", min: 1, max: 720, step: 1 }, { key: "ENABLE_LONG_PRESS", name: "启用长按", type: "bool" }, diff --git a/code/th_15_extra.js b/code/th_15_extra.js index 64bf53a..523ec4d 100644 --- a/code/th_15_extra.js +++ b/code/th_15_extra.js @@ -1120,28 +1120,72 @@ FloatBallAppWM.prototype.hideToolAppScreenBackStrips = function() { }; FloatBallAppWM.prototype.getToolAppBackEdgeWidthPx = function() { - var stripDp = 56; + var stripDp = 72; try { - stripDp = Number(this.config.TOOLAPP_BACK_EDGE_WIDTH_DP || 56); - if (isNaN(stripDp)) stripDp = 56; + stripDp = Number(this.config.TOOLAPP_BACK_EDGE_WIDTH_DP || 72); + if (isNaN(stripDp)) stripDp = 72; if (stripDp < 1) stripDp = 1; if (stripDp > 120) stripDp = 120; } catch(e) { - stripDp = 56; + stripDp = 72; } return this.dp(stripDp); }; FloatBallAppWM.prototype.isToolAppScreenBackStripsEnabled = function() { try { return parseBooleanLike(this.config.ENABLE_TOOLAPP_SCREEN_BACK_STRIPS); } catch(e) {} - try { return String(this.config.ENABLE_TOOLAPP_SCREEN_BACK_STRIPS || "false") === "true"; } catch(e2) {} - return false; + try { return String(this.config.ENABLE_TOOLAPP_SCREEN_BACK_STRIPS || "true") === "true"; } catch(e2) {} + return true; }; FloatBallAppWM.prototype.showToolAppScreenBackStrips = function() { - // 兼容旧配置入口:不再创建覆盖 ToolApp 内容区的 MATCH_PARENT 透明触摸层。 - // 主要返回手势已迁移到 ToolApp root 的 onInterceptTouchEvent,避免遮挡列表/按钮/SeekBar/Switch。 - try { this.hideToolAppScreenBackStrips(); } catch(eHide) {} + // 只在 ToolApp 面板左右的屏幕空白区创建触摸层;绝不覆盖 ToolApp 矩形内部控件区域。 + try { + this.hideToolAppScreenBackStrips(); + if (!this.state || !this.state.wm || !this.state.viewerPanelLp) return false; + var lp0 = this.state.viewerPanelLp; + var sw = Math.max(1, Number(this.state.screen && this.state.screen.w || 0)); + var sh = Math.max(1, Number(this.state.screen && this.state.screen.h || 0)); + if (sw <= 1 || sh <= 1) { + try { var ss = this.getScreenSizePx(); sw = ss.w; sh = ss.h; } catch(eScreen) {} + } + var px = Number(lp0.x || 0); + var pw = Number(lp0.width || 0); + if (isNaN(px)) px = 0; + if (isNaN(pw) || pw <= 0) return false; + var minBlank = this.dp(3); + var leftW = Math.max(0, Math.floor(px)); + var rightX = Math.floor(px + pw); + var rightW = Math.max(0, Math.floor(sw - rightX)); + var made = false; + var arr = []; + var addBlankStrip = function(self, edge, x, w) { + if (!w || w < minBlank) return false; + var strip = self.createToolAppEdgeBackStrip(edge); + var flags = android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | + android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; + var lp = new android.view.WindowManager.LayoutParams( + w, + sh, + android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, + flags, + android.graphics.PixelFormat.TRANSLUCENT + ); + lp.gravity = android.view.Gravity.TOP | android.view.Gravity.START; + lp.x = x; + lp.y = 0; + try { self.state.wm.addView(strip, lp); arr.push(strip); return true; } catch(eAdd) { safeLog(self.L, 'w', 'add blank screen back strip fail edge=' + String(edge) + ' err=' + String(eAdd)); } + return false; + }; + if (addBlankStrip(this, 0, 0, leftW)) made = true; + if (addBlankStrip(this, 1, rightX, rightW)) made = true; + this.state.toolAppScreenBackStrips = arr; + try { if (made) safeLog(this.L, 'd', 'blank screen back strips leftW=' + String(leftW) + ' rightW=' + String(rightW) + ' panelX=' + String(px) + ' panelW=' + String(pw)); } catch(eLog) {} + return made; + } catch(e) { + try { this.hideToolAppScreenBackStrips(); } catch(eHide2) {} + safeLog(this.L, 'w', "show blank screen back strips fail: " + String(e)); + } return false; }; @@ -1216,7 +1260,7 @@ FloatBallAppWM.prototype.buildToolAppShell = function(contentView, title, canBac rootEdge = -1; var canBackNow = !!(self.state && self.state.toolAppActive && self.hasToolAppBackTarget && self.hasToolAppBackTarget()); if (canBackNow) { - var edgeW = self.getToolAppBackEdgeWidthPx ? self.getToolAppBackEdgeWidthPx() : self.dp(56); + var edgeW = self.getToolAppBackEdgeWidthPx ? self.getToolAppBackEdgeWidthPx() : self.dp(72); var rw = 0; try { rw = this.getWidth(); } catch(eW) { rw = 0; } if (rootDownX <= edgeW) rootEdge = 0; @@ -1234,10 +1278,10 @@ FloatBallAppWM.prototype.buildToolAppShell = function(contentView, title, canBac var validDir = (rootEdge === 0 && dx > 0) || (rootEdge === 1 && dx < 0); var slopDp = Number(self.config.CLICK_SLOP_DP || 6); if (isNaN(slopDp)) slopDp = 6; - if (slopDp < 3) slopDp = 3; - if (slopDp > 18) slopDp = 18; - var touchSlop = self.dp(slopDp); - if (validDir && adx > touchSlop && adx > ady * 0.85) { + if (slopDp < 1) slopDp = 1; + if (slopDp > 40) slopDp = 40; + var touchSlop = Math.max(self.dp(8), self.dp(slopDp)); + if (validDir && adx > touchSlop && adx > ady * 0.75) { rootBackActive = true; rootBackMoved = true; try { self.prepareToolAppBackPreview(rootEdge); } catch(ePrep) { try { safeLog(self.L, 'w', 'root back preview prepare fail: ' + String(ePrep)); } catch(eLogPrep) {} } @@ -1270,7 +1314,7 @@ FloatBallAppWM.prototype.buildToolAppShell = function(contentView, title, canBac var mx = ev.getX() - rootDownX; var my = ev.getY() - rootDownY; var validDir2 = (rootEdge === 0 && mx > 0) || (rootEdge === 1 && mx < 0); - if (validDir2 && Math.abs(mx) > Math.abs(my) * 0.85) { + if (validDir2 && Math.abs(mx) > Math.abs(my) * 0.75) { var triggerDp = Number(self.config.TOOLAPP_BACK_PROGRESS_DISTANCE_DP || 96); if (isNaN(triggerDp)) triggerDp = 96; if (triggerDp < 1) triggerDp = 1; @@ -1290,7 +1334,7 @@ FloatBallAppWM.prototype.buildToolAppShell = function(contentView, title, canBac if (commitDp > 480) commitDp = 480; var completeDistance = self.dp(commitDp); var okDir = (rootEdge === 0 && ux > completeDistance) || (rootEdge === 1 && ux < -completeDistance); - var ok = (action === android.view.MotionEvent.ACTION_UP) && rootBackMoved && okDir && Math.abs(ux) > Math.abs(uy) * 0.85; + var ok = (action === android.view.MotionEvent.ACTION_UP) && rootBackMoved && okDir && Math.abs(ux) > Math.abs(uy) * 0.75; var edgeDone = rootEdge; rootBackActive = false; rootBackMoved = false; diff --git a/manifest.json b/manifest.json index 11bbb46..de1b16a 100644 --- a/manifest.json +++ b/manifest.json @@ -2,8 +2,8 @@ "alg": "SHA256withRSA", "files": { "th_01_base.js": { - "sha256": "92f780e907b99c485510363252617c004d1c37ef0fde010e4fe93f9df90d207e", - "size": 57164 + "sha256": "2dfbf8e338b15d62399f5084586a7b593fd81eb6d321f5403da928434469a210", + "size": 57148 }, "th_02_core.js": { "sha256": "3c5c498d200e961d48fc9ca3f885475e770ecb32b83ec6a89d23df3f88aed1c9", @@ -58,8 +58,8 @@ "size": 304993 }, "th_15_extra.js": { - "sha256": "f74276d86315538a45e141294a913a2384a4c99b862dc8d5325e77d4fd7e93d2", - "size": 118233 + "sha256": "93dc6db5c01cdb080660e988c1665cbe742b80849b583bc485f6d1d27310f908", + "size": 120294 }, "th_16_entry.js": { "sha256": "6c59d9891cd010647f84c3db93f1cf95c7bbfb758470ea21044bf72eb8ff73d1", @@ -68,5 +68,5 @@ }, "keyId": "toolhub-targets-2026-rsa3072", "schema": 2, - "version": 20260522002703 + "version": 20260522003824 } diff --git a/manifest.sig b/manifest.sig index 08bda9d..8453754 100644 --- a/manifest.sig +++ b/manifest.sig @@ -1 +1 @@ -Gysf9o2vKtTjx3vTsUMvkdZFNuHkwkzj8NQjh9diIgleVYSs/vgbf54+k6H7DqbY+sJSFIAUitjSBEmDYc1l/xaSTmZgRE5yQqTp8Ll8sQXXKlC8r8teMzdOdNVeVyOg+zYTM+NfE5UpcpDkq+JdFZgJhCAN0I0O7MD+qTVrdnYxbYOuoGkgPuEcDrZ8S7zG6Jc+dryqLlH/QgvWZnLjb+/Id73jpT3WTNlCPKdka3+sDvvTuqQ1AHFaf9c9jJAeWme8uloK98qqEVehKtUC8lglVrK4f9ZVhhUHkvTWITwgj2ALRsCOy6IH2IlNB5Uhw1rwgDyqBnld43aKCiw4upMnVc3IZTXdLcMBqjL5XctHzhmWZN4BAtZtJQqkyysaPy2XeO6uTzqES2w7Zynfy44N/0oikcXddnQ99afD6H57z34OBSbARGxY5vRae+96kw2izkeL5KwLaYmOhBln+C6bZYBq001U2wz/QSNI+liJc209UljZ61fBcNCgtCk+ +P2H2QBMFs6oL8m45jPxIXQ/zR2glhsEnduNFmKr8/HS5vnRVDVAnfcZKxOn9wpl9XdllaeRDbr7nHGpgK1rHT7UAJbt+byDYiz50As4C52c2xGV3kq/bim6FRhKd5sSh4cumWGUhBMMPRbfgXuMQen9+B72THYOBME2xEiylyMKedrxrLh2flFT9Y5SkeNFgFAdPYxGLaazCwpn/ydGLqFPrZLNLS2an7D0+WeDDZOF0nxZEvKNoHW1wi0BFDecR4I4cJVsQw8jjL7GMt/tLOZrZXBML4R4gYM+4UQu3AxjAIi6iuw/9LFs5IzIJXDJLIO4Q2grs6avpWQGMKhVC9UpvQgijvR14S7tmHL6vgpNX+JLzoziVlzsZWWj2FLlXazsfJTkYCPiEjknJyzBaevgyZIRwYilyCeDTRwtenBiPXluyc1Y94Q2Cr02iIu6d/DF5mSi/lVV6VN/JTmGDNAwaYbOE1uVwtXs+t1hqDBJKaJBWT0UL1tmSAj1m3eVY