fix(frontend): dispose missing models virtualizer on full refresh

This commit is contained in:
Dariusz L
2026-08-04 19:29:25 +02:00
parent f1620a7659
commit a093edd004
2 changed files with 47 additions and 2 deletions
+17 -1
View File
@@ -2150,6 +2150,10 @@ test('content-preserving Missing Models refresh patches the browser instead of c
missingBrowserMethodsSource,
'setupMissingModelsVirtualizer'
);
const destroyMissingModelsVirtualizer = extractMethod(
missingBrowserMethodsSource,
'destroyMissingModelsVirtualizer'
);
const displayMissingModels = extractMethod(
missingBrowserMethodsSource,
'displayMissingModels'
@@ -2175,6 +2179,18 @@ test('content-preserving Missing Models refresh patches the browser instead of c
setupMissingModelsVirtualizer,
/rowsHost\.innerHTML/
);
assert.match(
destroyMissingModelsVirtualizer,
/removeEventListener\('scroll', state\.onScroll\)/
);
assert.match(
destroyMissingModelsVirtualizer,
/resizeObserver\?\.disconnect\?\./
);
assert.match(
destroyMissingModelsVirtualizer,
/_mrMissingVirtualState = null/
);
assert.doesNotMatch(
patchMissingModelsBrowserElement,
/currentBrowser\.replaceWith\(nextBrowser\)/
@@ -2197,7 +2213,7 @@ test('content-preserving Missing Models refresh patches the browser instead of c
);
assert.match(
displayMissingModels,
/if \(!browserPatched\) \{\s*container\.innerHTML = browserHtml;/
/if \(!browserPatched\) \{\s*this\.destroyMissingModelsVirtualizer\(container\);\s*container\.innerHTML = browserHtml;/
);
});
+30 -1
View File
@@ -514,6 +514,26 @@ export const missingBrowserMethods = {
list?._mrMissingVirtualState?.update?.(force);
},
destroyMissingModelsVirtualizer(container) {
const list = container?.matches?.('.mr-missing-list')
? container
: container?.querySelector?.('.mr-missing-list');
const state = list?._mrMissingVirtualState;
if (!state) return false;
if (state.onScroll) {
list.removeEventListener('scroll', state.onScroll);
}
state.resizeObserver?.disconnect?.();
if (state.animationFrame) {
cancelAnimationFrame(state.animationFrame);
state.animationFrame = null;
}
state.destroyed = true;
list._mrMissingVirtualState = null;
return true;
},
getMissingBrowserVirtualRowHeight(list = null) {
const target = list instanceof HTMLElement
? list
@@ -607,6 +627,9 @@ export const missingBrowserMethods = {
}
const existingState = list._mrMissingVirtualState;
if (existingState && existingState.rowsHost !== rowsHost) {
this.destroyMissingModelsVirtualizer(list);
}
const state = existingState && existingState.rowsHost === rowsHost
? existingState
: {
@@ -620,6 +643,8 @@ export const missingBrowserMethods = {
end: -1,
resizeObserver: null,
onScroll: null,
animationFrame: null,
destroyed: false,
update: null
};
@@ -629,7 +654,7 @@ export const missingBrowserMethods = {
state.virtualScroll.style.height = `${Math.max(0, sortedMissingModels.length * state.rowHeight)}px`;
state.update = (force = false) => {
if (!list.isConnected || !rowsHost.isConnected) return;
if (state.destroyed || !list.isConnected || !rowsHost.isConnected) return;
const rowHeight = state.rowHeight || MISSING_ROW_FALLBACK_HEIGHT;
const header = list.querySelector('.mr-missing-list-head');
@@ -2428,12 +2453,14 @@ export const missingBrowserMethods = {
}
if (!hasAnyModelsToDisplay && activeCount === 0) {
this.destroyMissingModelsVirtualizer(container);
container.innerHTML = this.renderStatusMessage('All models are available! No missing models found.', 'success');
return;
}
// If no missing models but downloads are active, show a waiting message
if (rawMissingCount === 0 && activeCount > 0 && !resolvedModels.length) {
this.destroyMissingModelsVirtualizer(container);
container.innerHTML = this.renderStatusMessage(
`${activeCount} download${activeCount > 1 ? 's' : ''} in progress. Local matches will refresh when complete.`,
'info'
@@ -2455,6 +2482,7 @@ export const missingBrowserMethods = {
const keepCurrentBrowser = preserveBrowser
&& Boolean(container.querySelector('.mr-missing-browser'));
if (!keepCurrentBrowser) {
this.destroyMissingModelsVirtualizer(container);
container.innerHTML = this.renderStatusMessage('Loading model folders...', 'info');
}
@@ -2574,6 +2602,7 @@ export const missingBrowserMethods = {
const browserPatched = options.preserveBrowser
&& this.patchMissingModelsBrowserElement(container, browserHtml);
if (!browserPatched) {
this.destroyMissingModelsVirtualizer(container);
container.innerHTML = browserHtml;
}
this.wireMissingModelsBrowser(container, data, sortedMissingModels);