From 72ef719ba70eeca0fa4bae47df092706f6fbaeed Mon Sep 17 00:00:00 2001 From: Caleb Allen Date: Thu, 5 Mar 2026 08:46:01 -0500 Subject: [PATCH] fix(08-02): revert repeat() inside lit-virtualizer, restore .renderItem + .keyFunction repeat() as child content of lit-virtualizer bypasses virtualization, rendering ALL items instead of only visible ones. This caused 2+ minute loading times and UI freezing with large libraries. The correct approach: use lit-virtualizer's native .renderItem and .keyFunction properties which integrate with its scroll-based viewport management. --- .../components/artists-view/artists-view.ts | 9 +++---- .../src/components/cover-grid/cover-grid.ts | 25 +++++++------------ .../src/components/genres-view/genres-view.ts | 9 +++---- .../src/components/queue-panel/queue-panel.ts | 9 +++---- .../src/components/track-list/track-list.ts | 9 +++---- 5 files changed, 21 insertions(+), 40 deletions(-) diff --git a/frontend/src/components/artists-view/artists-view.ts b/frontend/src/components/artists-view/artists-view.ts index 24bc7de..1e53b3f 100644 --- a/frontend/src/components/artists-view/artists-view.ts +++ b/frontend/src/components/artists-view/artists-view.ts @@ -10,7 +10,6 @@ import type { VisibilityChangedEvent, } from '@lit-labs/virtualizer'; import { grid } from '@lit-labs/virtualizer/layouts/grid.js'; -import { repeat } from 'lit/directives/repeat.js'; import { GetAlbumsByArtist, GetAlbumTracks, @@ -1217,13 +1216,11 @@ export class ArtistsView > this.renderArtistCard(entry)} + .keyFunction=${(entry: ArtistEntry) => entry.artist.ID} .layout=${this.gridLayout} @visibilityChanged=${this.onVisibilityChanged} - >${repeat( - entries, - (entry) => entry.artist.ID, - (entry) => this.renderArtistCard(entry), - )} + > ${this.renderContextMenu()} `; diff --git a/frontend/src/components/cover-grid/cover-grid.ts b/frontend/src/components/cover-grid/cover-grid.ts index efbcb71..04d4a65 100644 --- a/frontend/src/components/cover-grid/cover-grid.ts +++ b/frontend/src/components/cover-grid/cover-grid.ts @@ -11,7 +11,6 @@ import type { VisibilityChangedEvent, } from '@lit-labs/virtualizer'; import { grid } from '@lit-labs/virtualizer/layouts/grid.js'; -import { repeat } from 'lit/directives/repeat.js'; import { GetAlbumTracks } from '@go/library/Library'; import { library } from '@go/models'; import { LibraryController } from '@store/controllers/library-controller'; @@ -1848,17 +1847,15 @@ export class CoverGrid entry.album.ID} .layout=${this.gridLayout} @click=${this.onGridAlbumClick} @dblclick=${this.onGridAlbumDblClick} @keydown=${this.onGridAlbumKeydown} @contextmenu=${this.onGridAlbumContextMenu} @visibilityChanged=${this.onVisibilityChanged} - >${repeat( - this.buildGridEntries(), - (entry) => entry.album.ID, - (entry) => this.renderGridEntry(entry), - )} + > `; } @@ -1877,17 +1874,15 @@ export class CoverGrid entry.album.ID} .layout=${this.gridLayout} @click=${this.onGridAlbumClick} @dblclick=${this.onGridAlbumDblClick} @keydown=${this.onGridAlbumKeydown} @contextmenu=${this.onGridAlbumContextMenu} @visibilityChanged=${this.onVisibilityChanged} - >${repeat( - this.getBeforeEntries(), - (entry) => entry.album.ID, - (entry) => this.renderGridEntry(entry), - )} + > entry.album.ID} .layout=${this.gridLayoutAfter} @click=${this.onGridAlbumClick} @dblclick=${this.onGridAlbumDblClick} @keydown=${this.onGridAlbumKeydown} @contextmenu=${this.onGridAlbumContextMenu} - >${repeat( - afterEntries, - (entry) => entry.album.ID, - (entry) => this.renderGridEntry(entry), - )} + > ` : nothing} `; diff --git a/frontend/src/components/genres-view/genres-view.ts b/frontend/src/components/genres-view/genres-view.ts index 5276d57..3b90315 100644 --- a/frontend/src/components/genres-view/genres-view.ts +++ b/frontend/src/components/genres-view/genres-view.ts @@ -10,7 +10,6 @@ import type { VisibilityChangedEvent, } from '@lit-labs/virtualizer'; import { grid } from '@lit-labs/virtualizer/layouts/grid.js'; -import { repeat } from 'lit/directives/repeat.js'; import { GetTracksByGenre } from '@go/library/Library'; import type { library } from '@go/models'; import { LibraryController } from '@store/controllers/library-controller'; @@ -1169,13 +1168,11 @@ export class GenresView > this.renderGenreCard(entry)} + .keyFunction=${(entry: GenreEntry) => entry.genre.name} .layout=${this.gridLayout} @visibilityChanged=${this.onVisibilityChanged} - >${repeat( - entries, - (entry) => entry.genre.name, - (entry) => this.renderGenreCard(entry), - )} + > ${this.renderContextMenu()} `; diff --git a/frontend/src/components/queue-panel/queue-panel.ts b/frontend/src/components/queue-panel/queue-panel.ts index 791acfd..dd5fd36 100644 --- a/frontend/src/components/queue-panel/queue-panel.ts +++ b/frontend/src/components/queue-panel/queue-panel.ts @@ -16,7 +16,6 @@ import type { PlaylistPicker } from '@components/playlist-picker/playlist-picker import '@lit-labs/virtualizer'; import type { LitVirtualizer } from '@lit-labs/virtualizer'; import { flow } from '@lit-labs/virtualizer/layouts/flow.js'; -import { repeat } from 'lit/directives/repeat.js'; import { classMap } from 'lit/directives/class-map.js'; import type { QueueTrack } from '@store/queue-store'; import { SelectionController } from '@utils/selection-controller'; @@ -1281,12 +1280,10 @@ export class QueuePanel track.id} .layout=${this.flowLayout} - >${repeat( - tracks, - (track) => track.id, - (track, index) => this.renderTrackItem(track, index), - )} + > `} diff --git a/frontend/src/components/track-list/track-list.ts b/frontend/src/components/track-list/track-list.ts index c3f9692..d9af0c9 100644 --- a/frontend/src/components/track-list/track-list.ts +++ b/frontend/src/components/track-list/track-list.ts @@ -26,7 +26,6 @@ import { DEFAULT_COLUMN_IDS, } from './columns'; import type { ColumnDef } from './columns'; -import { repeat } from 'lit/directives/repeat.js'; import { classMap } from 'lit/directives/class-map.js'; import { rankTracks, @@ -1738,12 +1737,10 @@ export class TrackList extends LitElement implements SelectionHost, ContextMenuH track.FilePath} .layout=${this.flowLayout} - >${repeat( - visibleTracks, - (track) => track.FilePath, - (track, index) => this.renderTrackRow(track, index), - )} + > `} ${this.searchCtrl.term && visibleTracks.length > 0