@@ -245,6 +245,69 @@ 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+ */
257+ function setupGridViewScrollFix ( ) : void {
258+ let filesListEl : Element | null = null
259+ let classObserver : MutationObserver | null = null
260+
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+ }
275+
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 {
281+ let prevIsGrid = el . classList . contains ( 'files-list--grid' )
282+ classObserver ?. disconnect ( )
283+ classObserver = new MutationObserver ( ( ) => {
284+ const isGrid = el . classList . contains ( 'files-list--grid' )
285+ if ( isGrid === prevIsGrid ) return
286+ prevIsGrid = isGrid
287+
288+ // Wait one frame for Vue to finish applying the new layout
289+ requestAnimationFrame ( ( ) => forceVirtualScrollUpdate ( el ) )
290+ } )
291+ 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+ }
300+ } )
301+
302+ domObserver . observe ( document . body , { childList : true , subtree : true } )
303+ }
304+
305+ if ( document . readyState === 'loading' ) {
306+ document . addEventListener ( 'DOMContentLoaded' , setupGridViewScrollFix )
307+ } else {
308+ setupGridViewScrollFix ( )
309+ }
310+
248311window . addEventListener ( 'DOMContentLoaded' , function ( ) {
249312 const breadcrumb = document . querySelector ( '.breadcrumb' )
250313 const empty = document . querySelector ( '.files-list__empty' )
0 commit comments