fix(ui): reconcile model listing in place after download (#1078)

Stop resetting the whole listing after a successful download. The legacy
flow reloaded page 1, scrolled to the top and hijacked the sidebar's
active folder whenever a custom target folder was used, which made the
Updates view lose its place (and sometimes render as an empty page).

Downloads only flip the update flag for one model, so the listing is now
reconciled in place through the virtual scroller:

- Updates view: the model's cards are removed once its newest eligible
  version is installed (the flag is model-level).
- Normal listing: the card stays; only update_available is cleared.
- Model not in the current view (different folder/filter/window):
  no-op; the sidebar folder tree alone is refreshed.
- Falling back to the legacy reload only when no virtual scroller is
  available (e.g. recipes page, duplicates mode, HF downloads).
This commit is contained in:
Will Miao
2026-08-27 18:17:19 +08:00
committed by pixelpaws
parent 2ba04bb1bd
commit e914a0e19d
3 changed files with 697 additions and 20 deletions
@@ -1426,6 +1426,32 @@ export function initVersionsTab({
}
}
/**
* True when the downloaded version is the newest version in the model's
* remote version set, i.e. the one whose install flips the backend
* update-available flag off. Unknown version sets fall back to "latest"
* so the post-download in-place reconciliation still runs by default.
* (#1078)
*/
function versionIsLatestAvailable(version) {
if (!controller.record || !Array.isArray(controller.record.versions)) {
return true;
}
const versions = controller.record.versions;
if (versions.length === 0) {
return true;
}
const target = Number(version?.versionId);
if (!Number.isFinite(target)) {
return true;
}
const maxId = versions.reduce(
(max, v) => Math.max(max, Number(v?.versionId) || 0),
0
);
return target >= maxId;
}
async function handleDownloadVersion(button, versionId) {
if (!controller.record) {
return;
@@ -1451,6 +1477,7 @@ export function initVersionsTab({
targetFolder: resolveTemplatePath ? '' : (pathInfo?.targetFolder || ''),
useDefaultPaths: resolveTemplatePath ? true : null,
useSaveDirAsRoot: resolveTemplatePath,
isLatestVersion: versionIsLatestAvailable(version),
});
if (success) {