--- id: ML-169.5 title: "Fix: Display toggle (grid/list) triggers full DB reload" status: Done assignee: [] created_date: "2026-05-19 11:45" updated_date: "2026-05-19 15:13" labels: - perf - fix dependencies: [] references: - >- backlog/documents/doc-27 - Phase-4-Performance-Audit-Low-Hanging-Fruit-Findings.md modified_files: - lib/music_library_web/live_helpers/index_actions.ex - lib/music_library_web/live/collection_live/index.ex - lib/music_library_web/live/wishlist_live/index.ex parent_task_id: ML-169 priority: high ordinal: 26000 --- ## Description Fix performance issue where toggling between grid and list display views triggers a full FTS database reload. ## Problem `handle_set_display` in `index_actions.ex` calls `load_and_assign_records/2` which re-executes the full FTS search query (`search_records_count` + `search_records`). The toggle only changes a CSS layout class (`@display == :grid` vs `@display == :list`) — no data changes. ## Impact Every grid/list toggle wastes 2 FTS queries. This is a common user interaction (clicking the view switcher button). ## Files - `lib/music_library_web/live_helpers/index_actions.ex:136-143` — `handle_set_display/2` calls `load_and_assign_records` - `lib/music_library_web/live/collection_live/index.ex:336` — `handle_event("set_display")` - `lib/music_library_web/live/wishlist_live/index.ex:259` — `handle_event("set_display")` ## Fix Remove the `load_and_assign_records` call from `handle_set_display`. Only `assign(:display, mode)` is needed. The existing `:if={@display == :grid}` / `:if={@display == :list}` conditionals already handle showing/hiding the appropriate view. ## Acceptance Criteria - [ ] #1 Grid/list toggle no longer triggers DB queries (verified via QueryReporter) - [ ] #2 Grid view renders correctly after toggle - [ ] #3 List view renders correctly after toggle - [ ] #4 No regression in search/filter functionality after toggle ## Archive Reason Archived after validation showed the proposed optimization is not correct with the current LiveView stream rendering structure. Collection and wishlist render either `<.record_grid>` or `<.record_list>` behind mutually exclusive `:if` branches, and both components consume the same `@streams.records` stream. LiveView stream entries are consumed after render and the existing DOM holds the streamed children. When the display mode changes, the previously mounted stream container is removed and a different stream container is mounted. Without re-running `stream(:records, records, reset: true)`, the newly mounted container has no queued stream entries to insert, so only its static empty-state node remains and `only:block` displays “No records yet”. The DB reload avoided by this task is therefore also the step that rehydrates the stream for the newly mounted container. A future optimization would need a different rendering shape, such as keeping both containers mounted or avoiding conditional stream container replacement, before removing the reload. ## Final Summary Reverted the proposed `handle_set_display/2` change and archived this task as not actionable in the current UI structure. The reload is required because grid/list toggling replaces the mounted stream container.