[READ-ONLY] Mirror of https://github.com/probablykasper/ferrum. Music library app for Mac, Linux and Windows ferrum.kasper.space
electron linux macos music music-library music-player napi windows
0

Configure Feed

Select the types of activity you want to include in your feed.

Fix column size not updating when resizing window

Kasper (Jul 4, 2025, 8:01 AM +0200) eb52ea6b 7ea2a165

+45 -15
+3
CHANGELOG.md
··· 1 1 # Changelog 2 2 3 + ## Next 4 + - Fix column size not updating when resizing window 5 + 3 6 ## 0.19.8 - 2025 Jun 26 4 7 - Fix scrolling not happening when using arrow keys 5 8 - Fix up/down arrow keys selecting incorrectly after filtering
+4 -3
src/components/TrackList.svelte
··· 46 46 import { SvelteSelection } from '@/lib/selection' 47 47 import { get_flattened_tracklists, handle_selected_tracks_action } from '@/lib/menus' 48 48 import type { SelectedTracksAction } from '@/electron/typed_ipc' 49 - import { RefreshLevel, VirtualGrid, type Column } from '@/lib/virtual-grid' 49 + import { RefreshLevel, VirtualGrid, type Column } from '@/lib/virtual-grid.svelte' 50 50 51 51 let tracklist_element: HTMLDivElement 52 52 ··· 500 500 } 501 501 }, 502 502 row_render(row, item, i) { 503 + row.setAttribute('draggable', 'true') 503 504 row.classList.toggle('odd', i % 2 === 0) 504 505 row.classList.toggle('selected', $selection.has(item.item_id)) 505 506 row.classList.toggle('playing', !!$playing_id && $playing_id === item.track_id) 506 507 }, 507 508 }) 508 - $: grid_columns = virtual_grid.set_columns(columns) 509 + $: virtual_grid.set_columns(columns) 509 510 $: virtual_grid.set_source_items(tracks_page.itemIds) 510 511 $: $selection, $playing_id, virtual_grid.refresh(RefreshLevel.AllRows) 511 512 ··· 534 535 on:dragleave={() => (col_drag_to_index = null)} 535 536 bind:this={col_container} 536 537 > 537 - {#each grid_columns as column, i} 538 + {#each virtual_grid.columns as column, i} 538 539 <!-- svelte-ignore a11y-interactive-supports-focus --> 539 540 <!-- svelte-ignore a11y-click-events-have-key-events --> 540 541 <div
+38 -12
src/lib/virtual-grid.ts src/lib/virtual-grid.svelte.ts
··· 2 2 name: string 3 3 key: string 4 4 width: number 5 - is_pct?: true 5 + is_pct?: boolean 6 6 offset?: number 7 7 /** Handles both creation and updating of rows */ 8 8 cell_render?: (element: HTMLElement, value: unknown) => void ··· 40 40 public options: { 41 41 buffer?: number 42 42 row_prepare: (source_items: I, index: number) => R 43 - row_render: (element: HTMLElement, item: R, index: number) => void 43 + row_render?: (element: HTMLElement, item: R, index: number) => void 44 44 }, 45 45 ) {} 46 46 ··· 49 49 options: { 50 50 buffer?: number 51 51 row_prepare: (source_items: I, index: number) => R 52 - row_render: (element: HTMLElement, item: R, index: number) => void 52 + row_render?: (element: HTMLElement, item: R, index: number) => void 53 53 }, 54 54 ) { 55 55 return new VirtualGrid<I, R>(source_items, options) ··· 150 150 }) 151 151 } 152 152 153 - columns: Column[] = [] 153 + columns: Column[] = $state([]) 154 154 set_columns(columns: Column[]) { 155 155 const total_fixed_width = columns.reduce((sum, col) => sum + (col.is_pct ? 0 : col.width), 0) 156 156 const total_percent_pct = columns.reduce((sum, col) => sum + (col.is_pct ? col.width : 0), 0) 157 157 const container_width = this.viewport?.clientWidth ?? total_fixed_width 158 158 const total_percent_width = container_width - total_fixed_width 159 159 let offset = 0 160 - this.columns = columns.map((col) => { 160 + const new_columns = columns.map((col) => { 161 161 col = { ...col } 162 162 if (col.is_pct) { 163 163 const pct = col.width / total_percent_pct ··· 168 168 return col 169 169 }) 170 170 171 - // make all rows fully rerender 172 - for (const row of this.rows) { 173 - row.element?.remove() 171 + let resize_only = true 172 + if (this.columns.length !== new_columns.length) { 173 + resize_only = false 174 + } 175 + for (let i = 0; i < this.columns.length; i++) { 176 + if (new_columns[i].key !== this.columns[i].key) { 177 + resize_only = false 178 + break 179 + } 174 180 } 175 - this.rows = [] 176 181 177 - this.refresh(RefreshLevel.NewRows) 182 + this.columns = new_columns 183 + if (resize_only) { 184 + for (const row of this.rows) { 185 + if (!row.element) { 186 + throw new Error('Unexpected missing row element') 187 + } 188 + for (let ci = 0; ci < this.columns.length; ci++) { 189 + const column = this.columns[ci] 190 + const cell = row.element.children[ci] as HTMLElement 191 + cell.style.width = `${column.width}px` 192 + cell.style.translate = `${column.offset}px 0` 193 + } 194 + } 195 + } else { 196 + // make all rows fully rerender 197 + for (const row of this.rows) { 198 + row.element?.remove() 199 + } 200 + this.rows = [] 201 + 202 + this.refresh(RefreshLevel.NewRows) 203 + } 178 204 return this.columns 179 205 } 180 206 ··· 197 223 const row_element = document.createElement('div') 198 224 row_element.className = 'row' 199 225 row_element.setAttribute('role', 'row') 200 - row_element.setAttribute('draggable', 'true') 201 226 row.element = row_element 202 227 this.main_element?.appendChild(row_element) 203 228 ··· 234 259 cell.textContent = String(cell_value) 235 260 } 236 261 } 237 - this.options.row_render(row.element, row_item, row.index) 262 + this.options.row_render?.(row.element, row_item, row.index) 238 263 row.rendered = true 239 264 } 240 265 ··· 275 300 this.#update_viewport_size() 276 301 277 302 this.size_observer = new ResizeObserver(() => { 303 + this.set_columns(this.columns) 278 304 this.#update_viewport_size() 279 305 this.refresh(RefreshLevel.NewRows) 280 306 })