Preserve ToolApp scroll position on back

This commit is contained in:
7015725
2026-05-23 04:55:18 +08:00
parent 407cd2200c
commit 00508c9cde
3 changed files with 83 additions and 6 deletions

View File

@@ -559,6 +559,7 @@ FloatBallAppWM.prototype.closeToolApp = function() {
this.state.toolAppBackPreviewEntryKey = null; this.state.toolAppBackPreviewEntryKey = null;
this.state.toolAppTitleView = null; this.state.toolAppTitleView = null;
this.state.toolAppBackButton = null; this.state.toolAppBackButton = null;
this.state.toolAppScrollY = 0;
} catch (e) { safeLog(this.L, 'e', "closeToolApp fail: " + String(e)); } } catch (e) { safeLog(this.L, 'e', "closeToolApp fail: " + String(e)); }
}; };
@@ -673,9 +674,73 @@ FloatBallAppWM.prototype.getToolAppSnapshotKey = function(entry) {
return String(entry && entry.route || ""); 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) { FloatBallAppWM.prototype.captureToolAppPageSnapshot = function(route) {
var r = this.isToolAppRoute(route) ? String(route) : (this.isToolAppRoute(this.state.toolAppRoute) ? String(this.state.toolAppRoute) : "settings"); var r = this.isToolAppRoute(route) ? String(route) : (this.isToolAppRoute(this.state.toolAppRoute) ? String(this.state.toolAppRoute) : "settings");
var s = this.state || {}; var s = this.state || {};
var liveScrollY = null;
try {
if (String(s.toolAppRoute || "") === r && this.captureToolAppCurrentScrollY) liveScrollY = this.captureToolAppCurrentScrollY();
} catch(eLiveScroll) { liveScrollY = null; }
var entry = { var entry = {
route: r, route: r,
settingsGroupKey: (s.settingsGroupKey !== undefined && s.settingsGroupKey !== null) ? String(s.settingsGroupKey) : "", 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, toolAppSubPage: (s.toolAppSubPage !== undefined) ? s.toolAppSubPage : null,
toolAppSubKey: (s.toolAppSubKey !== undefined) ? s.toolAppSubKey : null, toolAppSubKey: (s.toolAppSubKey !== undefined) ? s.toolAppSubKey : null,
toolAppSubPayload: (s.toolAppSubPayload !== undefined) ? this.cloneToolAppSnapshotValue(s.toolAppSubPayload, 0) : 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_group") entry.settingsGroupKey = "";
if (r !== "settings") { entry.settingsHomeSelectedItemId = null; entry.settingsHomeSelectedCategoryId = null; } 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.toolAppSubKey = (entry.toolAppSubKey !== undefined) ? entry.toolAppSubKey : null;
this.state.toolAppSubPayload = (entry.toolAppSubPayload !== undefined) ? this.cloneToolAppSnapshotValue(entry.toolAppSubPayload, 0) : 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.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; return true;
} catch(e) { safeLog(this.L, 'w', "apply tool app snapshot fail: " + String(e)); } } catch(e) { safeLog(this.L, 'w', "apply tool app snapshot fail: " + String(e)); }
return false; return false;
@@ -739,7 +807,8 @@ FloatBallAppWM.prototype.cloneToolAppPageSnapshot = function(entry) {
toolAppSubPage: (entry.toolAppSubPage !== undefined) ? entry.toolAppSubPage : null, toolAppSubPage: (entry.toolAppSubPage !== undefined) ? entry.toolAppSubPage : null,
toolAppSubKey: (entry.toolAppSubKey !== undefined) ? entry.toolAppSubKey : null, toolAppSubKey: (entry.toolAppSubKey !== undefined) ? entry.toolAppSubKey : null,
toolAppSubPayload: (entry.toolAppSubPayload !== undefined) ? this.cloneToolAppSnapshotValue(entry.toolAppSubPayload, 0) : 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.setBackground(null); } catch (eBg) {}
try { raw.setElevation(0); } catch (eEl) {} try { raw.setElevation(0); } catch (eEl) {}
host.addView(raw, new android.widget.FrameLayout.LayoutParams(-1, -1)); 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); 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)); 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); 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.setBackground(null); } catch(eBg) { safeLog(null, 'e', "catch " + String(eBg)); }
try { contentView.setElevation(0); } catch(eEl) { safeLog(null, 'e', "catch " + String(eEl)); } try { contentView.setElevation(0); } catch(eEl) { safeLog(null, 'e', "catch " + String(eEl)); }
host.addView(contentView, new android.widget.FrameLayout.LayoutParams(-1, -1)); 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; return true;
} catch (e) { } catch (e) {
safeLog(this.L, 'e', "setToolAppContent fail: " + String(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.pendingUserCfg = null;
this.state.pendingDirty = false; this.state.pendingDirty = false;
this.state.previewMode = false; this.state.previewMode = false;
this.state.toolAppScrollY = 0;
} }
if (resetStack || !this.state.toolAppNavStack || !this.state.toolAppNavStack.length) { if (resetStack || !this.state.toolAppNavStack || !this.state.toolAppNavStack.length) {
this.state.toolAppNavStack = [this.makeToolAppStackEntry(r)]; this.state.toolAppNavStack = [this.makeToolAppStackEntry(r)];
@@ -1658,6 +1734,7 @@ FloatBallAppWM.prototype.showToolApp = function(route, resetStack) {
FloatBallAppWM.prototype.pushToolAppPage = function(route) { FloatBallAppWM.prototype.pushToolAppPage = function(route) {
if (!this.isToolAppRoute(route)) return; if (!this.isToolAppRoute(route)) return;
try { if (this.saveToolAppCurrentStackScroll) this.saveToolAppCurrentStackScroll(); } catch(eSaveScrollPush) {}
if (!this.state.toolAppNavStack) this.state.toolAppNavStack = []; if (!this.state.toolAppNavStack) this.state.toolAppNavStack = [];
if (this.state.toolAppNavStack.length <= 0) { if (this.state.toolAppNavStack.length <= 0) {
this.state.toolAppNavStack.push(this.makeToolAppStackEntry(this.state.toolAppRoute || "settings")); this.state.toolAppNavStack.push(this.makeToolAppStackEntry(this.state.toolAppRoute || "settings"));

View File

@@ -70,8 +70,8 @@
"size": 20484 "size": 20484
}, },
"th_15_extra.js": { "th_15_extra.js": {
"sha256": "5b39db203b748f9d9919b6e19fc9fae5b5b5dcce6f46ade0f8e5cd2729f223aa", "sha256": "c62972b4aa3c5dbc2463369fc96639683f6ea4d50a05e9befcc5b6a01679706c",
"size": 123635 "size": 127020
}, },
"th_16_entry.js": { "th_16_entry.js": {
"sha256": "652aa70214a9419923785e528a067d3828094fde48fc9c8c57cfda1e08206e25", "sha256": "652aa70214a9419923785e528a067d3828094fde48fc9c8c57cfda1e08206e25",
@@ -80,5 +80,5 @@
}, },
"keyId": "toolhub-targets-2026-rsa3072", "keyId": "toolhub-targets-2026-rsa3072",
"schema": 2, "schema": 2,
"version": 20260522191219 "version": 20260522205509
} }

View File

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