Skip to content

Commit af1cbf8

Browse files
committed
fix: dispatch scroll event on view switch to fix empty file list
The .files-list element is the actual scroll container (confirmed via DOM inspection — scrollTop > 0 on .files-list when scrolled, not on window or #app-content-vue). When switching between list and grid view, the virtual scroll does not automatically recalculate visible rows for the new item sizes, leaving a blank screen until the user manually scrolls. Fix: watch for files-list--grid class changes on .files-list via MutationObserver, then dispatch a synthetic scroll event on the same element via setTimeout so CSS has fully reflowed before the event fires. This triggers the virtual scroll to recalculate visible rows at the current position without changing the user's scroll position.
1 parent 0d6ab1e commit af1cbf8

1 file changed

Lines changed: 6 additions & 39 deletions

File tree

src/nmcfiles.ts

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -245,58 +245,25 @@ if (document.readyState === 'loading') {
245245
setupPendingShare()
246246
}
247247

248-
/**
249-
* Fix for empty screen when switching between grid and list view.
250-
*
251-
* Root cause: the .files-list element is the actual scroll container. When the
252-
* view class changes (list to grid or vice versa), the virtual scroll does not
253-
* automatically recalculate visible rows for the new item sizes, leaving a blank
254-
* screen until the user scrolls. Dispatching a synthetic scroll event on the
255-
* .files-list element triggers the recalculation without changing scroll position.
256-
*/
248+
/** Fixes empty file list when switching between grid and list view. */
257249
function setupGridViewScrollFix(): void {
258250
let filesListEl: Element | null = null
259251
let classObserver: MutationObserver | null = null
260252

261-
/**
262-
* Forces the virtual scroll to recalculate after a view switch.
263-
*
264-
* The actual scroll container is the .files-list element itself (scrollTop > 0
265-
* when scrolled, confirmed via DOM inspection). We dispatch a scroll event on it
266-
* so the virtual scroll recalculates visible rows at the current scroll position.
267-
* setTimeout ensures CSS has fully reflowed before the event fires.
268-
* @param scrollContainer The .files-list element to dispatch the scroll event on.
269-
*/
270-
function forceVirtualScrollUpdate(scrollContainer: Element): void {
271-
setTimeout(() => {
272-
scrollContainer.dispatchEvent(new Event('scroll', { bubbles: true }))
273-
}, 0)
274-
}
253+
const domObserver = new MutationObserver(() => {
254+
const el = document.querySelector('.files-list')
255+
if (!el || el === filesListEl) return
256+
filesListEl = el
275257

276-
/**
277-
* Attaches a class mutation observer to the files list element.
278-
* @param el The files list element to observe.
279-
*/
280-
function attachClassObserver(el: Element): void {
281258
let prevIsGrid = el.classList.contains('files-list--grid')
282259
classObserver?.disconnect()
283260
classObserver = new MutationObserver(() => {
284261
const isGrid = el.classList.contains('files-list--grid')
285262
if (isGrid === prevIsGrid) return
286263
prevIsGrid = isGrid
287-
288-
// Wait one frame for Vue to finish applying the new layout
289-
requestAnimationFrame(() => forceVirtualScrollUpdate(el))
264+
setTimeout(() => el.dispatchEvent(new Event('scroll', { bubbles: true })), 0)
290265
})
291266
classObserver.observe(el, { attributes: true, attributeFilter: ['class'] })
292-
}
293-
294-
const domObserver = new MutationObserver(() => {
295-
const el = document.querySelector('.files-list')
296-
if (el && el !== filesListEl) {
297-
filesListEl = el
298-
attachClassObserver(el)
299-
}
300267
})
301268

302269
domObserver.observe(document.body, { childList: true, subtree: true })

0 commit comments

Comments
 (0)