From 00508c9cde69a9f4a837155c2d650bbc29b186c6 Mon Sep 17 00:00:00 2001 From: 7015725 Date: Sat, 23 May 2026 04:55:18 +0800 Subject: [PATCH] Preserve ToolApp scroll position on back --- code/th_15_extra.js | 81 +++++++++++++++++++++++++++++++++++++++++++-- manifest.json | 6 ++-- manifest.sig | 2 +- 3 files changed, 83 insertions(+), 6 deletions(-) diff --git a/code/th_15_extra.js b/code/th_15_extra.js index a4e4a61..0cf354d 100644 --- a/code/th_15_extra.js +++ b/code/th_15_extra.js @@ -559,6 +559,7 @@ FloatBallAppWM.prototype.closeToolApp = function() { this.state.toolAppBackPreviewEntryKey = null; this.state.toolAppTitleView = null; this.state.toolAppBackButton = null; + this.state.toolAppScrollY = 0; } catch (e) { safeLog(this.L, 'e', "closeToolApp fail: " + String(e)); } }; @@ -673,9 +674,73 @@ FloatBallAppWM.prototype.getToolAppSnapshotKey = function(entry) { return String(entry && entry.route || ""); }; +FloatBallAppWM.prototype.findToolAppFirstScrollView = function(root) { + try { + if (!root) return null; + if (root instanceof android.widget.ScrollView) return root; + if (!root.getChildCount) return null; + var count = root.getChildCount(); + for (var i = 0; i < count; i++) { + var found = this.findToolAppFirstScrollView(root.getChildAt(i)); + if (found) return found; + } + } catch(e) {} + return null; +}; + +FloatBallAppWM.prototype.captureToolAppCurrentScrollY = function() { + try { + var host = this.state ? this.state.toolAppContentHost : null; + var sv = this.findToolAppFirstScrollView ? this.findToolAppFirstScrollView(host) : null; + if (!sv) return null; + var y = Number(sv.getScrollY ? sv.getScrollY() : 0); + if (isNaN(y) || y < 0) y = 0; + return Math.floor(y); + } catch(e) {} + return null; +}; + +FloatBallAppWM.prototype.saveToolAppCurrentStackScroll = function() { + try { + var st = this.state.toolAppNavStack; + if (!st || !st.length) return false; + var y = this.captureToolAppCurrentScrollY ? this.captureToolAppCurrentScrollY() : null; + if (y === null || y === undefined) return false; + st[st.length - 1].toolAppScrollY = y; + this.state.toolAppScrollY = y; + return true; + } catch(e) {} + return false; +}; + +FloatBallAppWM.prototype.restoreToolAppScrollLater = function(root, entry) { + try { + if (!root) return false; + var y = 0; + if (entry && entry.toolAppScrollY !== undefined && entry.toolAppScrollY !== null) y = Number(entry.toolAppScrollY); + else if (this.state && this.state.toolAppScrollY !== undefined && this.state.toolAppScrollY !== null) y = Number(this.state.toolAppScrollY); + if (isNaN(y) || y < 0) y = 0; + y = Math.floor(y); + if (y <= 0) return false; + var self = this; + root.post(new java.lang.Runnable({ run: function() { + try { + var sv = self.findToolAppFirstScrollView ? self.findToolAppFirstScrollView(root) : null; + if (sv) sv.scrollTo(0, y); + } catch(ePost) {} + }})); + return true; + } catch(e) {} + return false; +}; + FloatBallAppWM.prototype.captureToolAppPageSnapshot = function(route) { var r = this.isToolAppRoute(route) ? String(route) : (this.isToolAppRoute(this.state.toolAppRoute) ? String(this.state.toolAppRoute) : "settings"); var s = this.state || {}; + var liveScrollY = null; + try { + if (String(s.toolAppRoute || "") === r && this.captureToolAppCurrentScrollY) liveScrollY = this.captureToolAppCurrentScrollY(); + } catch(eLiveScroll) { liveScrollY = null; } var entry = { route: r, settingsGroupKey: (s.settingsGroupKey !== undefined && s.settingsGroupKey !== null) ? String(s.settingsGroupKey) : "", @@ -689,7 +754,8 @@ FloatBallAppWM.prototype.captureToolAppPageSnapshot = function(route) { toolAppSubPage: (s.toolAppSubPage !== undefined) ? s.toolAppSubPage : null, toolAppSubKey: (s.toolAppSubKey !== undefined) ? s.toolAppSubKey : null, toolAppSubPayload: (s.toolAppSubPayload !== undefined) ? this.cloneToolAppSnapshotValue(s.toolAppSubPayload, 0) : null, - toolAppPayload: (s.toolAppPayload !== undefined) ? this.cloneToolAppSnapshotValue(s.toolAppPayload, 0) : null + toolAppPayload: (s.toolAppPayload !== undefined) ? this.cloneToolAppSnapshotValue(s.toolAppPayload, 0) : null, + toolAppScrollY: (String(s.toolAppRoute || "") === r) ? ((liveScrollY !== null && liveScrollY !== undefined) ? liveScrollY : ((s.toolAppScrollY !== undefined) ? s.toolAppScrollY : 0)) : 0 }; if (r !== "settings_group") entry.settingsGroupKey = ""; if (r !== "settings") { entry.settingsHomeSelectedItemId = null; entry.settingsHomeSelectedCategoryId = null; } @@ -719,6 +785,8 @@ FloatBallAppWM.prototype.applyToolAppPageSnapshot = function(entry) { this.state.toolAppSubKey = (entry.toolAppSubKey !== undefined) ? entry.toolAppSubKey : null; this.state.toolAppSubPayload = (entry.toolAppSubPayload !== undefined) ? this.cloneToolAppSnapshotValue(entry.toolAppSubPayload, 0) : null; this.state.toolAppPayload = (entry.toolAppPayload !== undefined) ? this.cloneToolAppSnapshotValue(entry.toolAppPayload, 0) : null; + this.state.toolAppScrollY = (entry.toolAppScrollY !== undefined && entry.toolAppScrollY !== null) ? Number(entry.toolAppScrollY) : 0; + if (isNaN(this.state.toolAppScrollY) || this.state.toolAppScrollY < 0) this.state.toolAppScrollY = 0; return true; } catch(e) { safeLog(this.L, 'w', "apply tool app snapshot fail: " + String(e)); } return false; @@ -739,7 +807,8 @@ FloatBallAppWM.prototype.cloneToolAppPageSnapshot = function(entry) { toolAppSubPage: (entry.toolAppSubPage !== undefined) ? entry.toolAppSubPage : null, toolAppSubKey: (entry.toolAppSubKey !== undefined) ? entry.toolAppSubKey : null, toolAppSubPayload: (entry.toolAppSubPayload !== undefined) ? this.cloneToolAppSnapshotValue(entry.toolAppSubPayload, 0) : null, - toolAppPayload: (entry.toolAppPayload !== undefined) ? this.cloneToolAppSnapshotValue(entry.toolAppPayload, 0) : null + toolAppPayload: (entry.toolAppPayload !== undefined) ? this.cloneToolAppSnapshotValue(entry.toolAppPayload, 0) : null, + toolAppScrollY: (entry.toolAppScrollY !== undefined && entry.toolAppScrollY !== null) ? Number(entry.toolAppScrollY) : 0 }; }; @@ -835,6 +904,7 @@ FloatBallAppWM.prototype.buildToolAppPreviewBody = function(entry) { try { raw.setBackground(null); } catch (eBg) {} try { raw.setElevation(0); } catch (eEl) {} host.addView(raw, new android.widget.FrameLayout.LayoutParams(-1, -1)); + try { if (this.restoreToolAppScrollLater) this.restoreToolAppScrollLater(raw, entry); } catch(ePreviewScroll) {} var hostLp = new android.widget.LinearLayout.LayoutParams(-1, 0, 1); hostLp.setMargins((spec && (spec.isExpandedWidth || spec.isWideWidth)) ? this.dp(4) : this.dp(6), 0, (spec && (spec.isExpandedWidth || spec.isWideWidth)) ? this.dp(4) : this.dp(6), (spec && (spec.isExpandedWidth || spec.isWideWidth)) ? this.dp(4) : this.dp(6)); body.addView(host, hostLp); @@ -1536,6 +1606,11 @@ FloatBallAppWM.prototype.setToolAppContent = function(contentView) { try { contentView.setBackground(null); } catch(eBg) { safeLog(null, 'e', "catch " + String(eBg)); } try { contentView.setElevation(0); } catch(eEl) { safeLog(null, 'e', "catch " + String(eEl)); } host.addView(contentView, new android.widget.FrameLayout.LayoutParams(-1, -1)); + try { + var st = this.state.toolAppNavStack || []; + var top = st.length ? st[st.length - 1] : null; + if (this.restoreToolAppScrollLater) this.restoreToolAppScrollLater(contentView, top); + } catch(eRestoreScroll) {} return true; } catch (e) { safeLog(this.L, 'e', "setToolAppContent fail: " + String(e)); @@ -1617,6 +1692,7 @@ FloatBallAppWM.prototype.showToolApp = function(route, resetStack) { this.state.pendingUserCfg = null; this.state.pendingDirty = false; this.state.previewMode = false; + this.state.toolAppScrollY = 0; } if (resetStack || !this.state.toolAppNavStack || !this.state.toolAppNavStack.length) { this.state.toolAppNavStack = [this.makeToolAppStackEntry(r)]; @@ -1658,6 +1734,7 @@ FloatBallAppWM.prototype.showToolApp = function(route, resetStack) { FloatBallAppWM.prototype.pushToolAppPage = function(route) { if (!this.isToolAppRoute(route)) return; + try { if (this.saveToolAppCurrentStackScroll) this.saveToolAppCurrentStackScroll(); } catch(eSaveScrollPush) {} if (!this.state.toolAppNavStack) this.state.toolAppNavStack = []; if (this.state.toolAppNavStack.length <= 0) { this.state.toolAppNavStack.push(this.makeToolAppStackEntry(this.state.toolAppRoute || "settings")); diff --git a/manifest.json b/manifest.json index 40c1fa5..4cffaf7 100644 --- a/manifest.json +++ b/manifest.json @@ -70,8 +70,8 @@ "size": 20484 }, "th_15_extra.js": { - "sha256": "5b39db203b748f9d9919b6e19fc9fae5b5b5dcce6f46ade0f8e5cd2729f223aa", - "size": 123635 + "sha256": "c62972b4aa3c5dbc2463369fc96639683f6ea4d50a05e9befcc5b6a01679706c", + "size": 127020 }, "th_16_entry.js": { "sha256": "652aa70214a9419923785e528a067d3828094fde48fc9c8c57cfda1e08206e25", @@ -80,5 +80,5 @@ }, "keyId": "toolhub-targets-2026-rsa3072", "schema": 2, - "version": 20260522191219 + "version": 20260522205509 } diff --git a/manifest.sig b/manifest.sig index 35d2b2d..4f4f90e 100644 --- a/manifest.sig +++ b/manifest.sig @@ -1 +1 @@ -c7CEARIR2JCXq4UkAGC9hQ2L7q9fM1CbSAZY5RazdoIijLBSNuXEmEgYVmlJNuJ4+hfU5vTCXgU8AkTL/NG4Q17fm27uFqQLkzqwb/9stQHvs3I4By9fWm11w9pcr17620vHe8alqjLslmLijUy0GSKy3r+nVQKFYWmveem5tdZNm6dXxbMG+2ePuPkc+CP02/vOQz9kx8C2eCFBjlcS+x/lOlpVYWXAqGGV7SseymOLe4RkGozz84p3fl8snFNOjA9F7CThAdEbd/UrC6UAM4VhVoaRuwHblWyxjTiRL4+OluIHWRnFDMpB7R3u/kp+mnon0v5gNlN4QIIVo4/jgVbWirsRAzw5+UM6Zft7T1P/j8MXAv8BrQzmMElU71vzReWyEmWvu6BjUi88R55IlZ8Fu5xjm6ttXCW0fB2miZ0Je52E3PdYKGzLMULtv2M07X71oSdqjd60g25R1ulGph6izuWKwxnabcSRLnvjgdhGl2qJUvMAn0LjCeARPFNC +SVao3uez5Z2KGYM67Z2dBrE9SPCjndmDaO89a1ybmqkRUCECt/MWc1MWhFyOcUqt57Pq0ljwNCWSdDLnbjZA7+AQPaEOhJdlyemJeeD+TkT9lQKXHxnSwn5Uq9wxYeRdpp3xid4+oRDwYLNUWp+cxTdFjiC2Aah7RWS4rm/T+t+3iqaHfqEav9dw1C1vskvRqaQfuNRF5ss/JDfR20UcoqtiHgFsB2VTyYP5MAs0Mj4po8DpOk4C1eLjS8dzZwW8r26xWvU/U7r4nTtOzsc07G/kX4aGq6G/TMaB6YYqMo9zDkBTvXgGx7SLC28W/tw5yTgvLN0cghdK5QmvB2dVxW7PC3njl5a/ew+qohfJ7GPCV4YJ8XxAFiUaI+wfT2mMGvTyWUlY6DWnCzzZh2x+7OFpQjiKlerJY0iugbC4bhQXpU2C5lnd6ER6hQVKFeeKTydzDTyEWHcJ59vx1wyz3oIkDH8BfHCIhgdlAhRiJWB2abaMPX6he5BcNcsGHPgA