fix(ui): preserve model grid return position

This commit is contained in:
DemonGatanjieu
2026-08-03 18:20:11 +08:00
parent 37f2bac512
commit f64871bcd2
5 changed files with 41 additions and 3 deletions
+14
View File
@@ -1,5 +1,19 @@
# AI Changelog
## [Snapshot] 2026-08-03 - Preserve model grid return position
**Implemented**
- Renamed the model-detail fallback action from "Back to grid" to the shorter "Back" label.
- Captured the active model folder plus grid `scrollTop` and `scrollLeft` before opening detail.
- Restored the saved grid viewport when returning from the root model detail view, while leaving recipe-detail return state isolated.
**Validation**
- `node --check web/modules/ui_detail.js web/modules/ui_grid.js web/modules/ui_recipe_detail.js`
- `node tests/recipe_parser_roundtrip.mjs`
- `python_embeded/python.exe tests/test_recipe_roundtrip.py`
- `git diff --check`
## [Snapshot] 2026-08-03 - Keep model navigation inside Overview
**Implemented**
+4
View File
@@ -5,6 +5,10 @@ This document serves as an architectural retrospective and UX diagnostic log for
## 56. UI Refactors Must Preserve Reachable Semantic Tabs
When a visual refactor merges information into a compact overview, do not remove a semantic tab until every dependent interaction has an intentional replacement. Model preview loading, model navigation, and return-state restoration were still designed around a Models tab, so removing only the tab made those actions unreachable. Keep tab state, asynchronous loading conditions, and return paths aligned with the visible navigation.
## 57. Detail Return Must Restore the List Viewport
Opening a detail panel should capture the list's semantic location and viewport, not only the selected item. Restore the folder/type and `scrollTop`/`scrollLeft` when the user returns to the grid, while keeping recipe-detail return state separate from browser-grid state. This prevents a visually correct Back action from still feeling like a navigation reset.
这份文档旨在记录 Anomalous 插件开发过程中的架构演进、UX 设计教训以及核心 Bug 排查经验。
---
+1 -1
View File
@@ -4,7 +4,7 @@ This document provides a high-level overview of the Anomalous Model Browser plug
## Current recipe interaction correction (2026-08-03)
The recipe detail view keeps Overview, Parameters, and Versions tabs. The Overview contains the model composition blocks; each resolved model name or preview is an explicit entry into the browser model detail view. Model previews are demand-loaded when Overview opens, and returning from model detail restores the recipe detail view. List-card Append actions await the shared canvas transaction before reporting success or restoring the button state. Export confirmation uses three states (cancel, exclude, include); cancellation must stop the export flow rather than silently becoming an exclusion.
The recipe detail view keeps Overview, Parameters, and Versions tabs. The Overview contains the model composition blocks; each resolved model name or preview is an explicit entry into the browser model detail view. Model previews are demand-loaded when Overview opens, and returning from model detail restores the recipe detail view. The model browser stores the active grid folder and scroll coordinates before opening detail and restores them when returning to the grid. List-card Append actions await the shared canvas transaction before reporting success or restoring the button state. Export confirmation uses three states (cancel, exclude, include); cancellation must stop the export flow rather than silently becoming an exclusion.
## 1. Project Philosophy (设计理念)
* **Zero Frameworks**: No React, Vue, or build tools. Everything is Vanilla JS and CSS for maximum compatibility, minimum overhead, and zero compilation steps.
+2 -2
View File
@@ -25,7 +25,7 @@ export const i18n = {
noModels: '此文件夹中没有找到模型。',
noPreview: '暂无预览图',
clickScan: '点击扫描',
back: '⬅️ 返回网格',
back: '⬅️ 返回',
delModel: '🗑️ 删除',
delConfirm: '确定彻底删除',
delConfirm2: '及其所有关联配置、预览图和缓存文件吗?此操作不可逆!',
@@ -275,7 +275,7 @@ export const i18n = {
noModels: 'No models found in this folder.',
noPreview: 'No preview available',
clickScan: 'Click Scan',
back: '⬅️ Back to grid',
back: '⬅️ Back',
delModel: '🗑️ Delete',
delConfirm: 'Are you sure you want to permanently delete',
delConfirm2: ' and all its associated configs, previews, and cache files? This action is irreversible!',
+20
View File
@@ -49,6 +49,15 @@ export function showDetail(model) {
}
if (this.detailMouseMoveHandler) window.removeEventListener('mousemove', this.detailMouseMoveHandler);
if (this.detailMouseUpHandler) window.removeEventListener('mouseup', this.detailMouseUpHandler);
if (!this.recipeModelReturn && this.grid && this.grid.style.display !== 'none') {
this.gridReturnState = {
type: this.currentType,
pathIdx: this.currentPathIdx,
subfolder: this.currentSubfolder,
scrollTop: this.grid.scrollTop,
scrollLeft: this.grid.scrollLeft,
};
}
this.grid.style.display = 'none';
this.detailPanel.style.display = 'flex';
this.stopMediaInContainer(this.detailPanel); this.detailPanel.innerHTML = '';
@@ -126,6 +135,17 @@ export function showDetail(model) {
this.detailPanel.style.display = 'none';
this.stopMediaInContainer(this.detailPanel); this.detailPanel.innerHTML = '';
this.grid.style.display = 'grid';
const gridReturnState = this.gridReturnState;
this.gridReturnState = null;
if (gridReturnState
&& gridReturnState.type === this.currentType
&& gridReturnState.pathIdx === this.currentPathIdx
&& gridReturnState.subfolder === this.currentSubfolder) {
requestAnimationFrame(() => {
this.grid.scrollTop = gridReturnState.scrollTop || 0;
this.grid.scrollLeft = gridReturnState.scrollLeft || 0;
});
}
}
};