[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 TrackInfo console errors

Kasper (Sep 17, 2024, 6:10 PM +0200) 88edbe1d 0f2c99d4

+167 -169
+4 -2
src/App.svelte
··· 5 5 import Player from './components/Player.svelte' 6 6 import Sidebar from './components/Sidebar.svelte' 7 7 import Queue from './components/Queue.svelte' 8 - import TrackInfo from './components/TrackInfo.svelte' 8 + import TrackInfo, { current_list } from './components/TrackInfo.svelte' 9 9 import PlaylistInfoModal from './components/PlaylistInfo.svelte' 10 10 import { queue_visible } from './lib/queue' 11 11 import { ipc_listen, ipc_renderer } from '@/lib/window' ··· 239 239 {/if} 240 240 </main> 241 241 242 - <TrackInfo /> 242 + {#if $current_list} 243 + <TrackInfo /> 244 + {/if} 243 245 {#if playlist_info} 244 246 <PlaylistInfoModal info={playlist_info} cancel={() => (playlist_info = null)} /> 245 247 {/if}
+163 -167
src/components/TrackInfo.svelte
··· 4 4 index: number 5 5 } 6 6 7 - const current_list = writable<TrackInfoList | null>(null) 7 + export const current_list = writable<TrackInfoList | null>(null) 8 8 9 9 export function open_track_info(ids: TrackID[], index: number) { 10 10 if (get(modal_count) === 0) { 11 11 current_list.set({ ids, index }) 12 12 } 13 13 } 14 + 15 + ipc_listen('context.Get Info', (_, ids: TrackID[], track_index: number) => { 16 + open_track_info(ids, track_index) 17 + }) 14 18 </script> 15 19 16 20 <script lang="ts"> ··· 23 27 import { onDestroy, tick } from 'svelte' 24 28 import { get, writable } from 'svelte/store' 25 29 import Modal, { modal_count } from './Modal.svelte' 26 - 27 - onDestroy( 28 - ipc_listen('context.Get Info', (_, ids: TrackID[], track_index: number) => { 29 - open_track_info(ids, track_index) 30 - }), 31 - ) 32 30 33 31 function cancel() { 34 32 current_list.set(null) ··· 319 317 320 318 <svelte:window on:keydown={keydown} /> 321 319 <svelte:body on:keydown|self={keydown_none_selected} on:paste={cover_paste} /> 322 - {#if $current_list} 323 - <Modal on_cancel={cancel} cancel_on_escape form={save}> 324 - <main class="modal"> 325 - <div class="header" class:has-subtitle={image && image.totalImages >= 2}> 320 + <Modal on_cancel={cancel} cancel_on_escape form={save}> 321 + <main class="modal"> 322 + <div class="header" class:has-subtitle={image && image.totalImages >= 2}> 323 + <div 324 + class="cover-area" 325 + class:droppable 326 + tabindex="0" 327 + on:keydown={cover_keydown} 328 + role="button" 329 + aria-label="Cover artwork" 330 + > 331 + <!-- svelte-ignore a11y-no-static-element-interactions --> 326 332 <div 327 - class="cover-area" 328 - class:droppable 329 - tabindex="0" 330 - on:keydown={cover_keydown} 331 - role="button" 332 - aria-label="Cover artwork" 333 + class="cover" 334 + on:dragenter={drag_enter_or_over} 335 + on:dragover={drag_enter_or_over} 336 + on:dragleave={drag_leave} 337 + on:drop={drop} 338 + on:dblclick={pick_cover} 333 339 > 334 - <!-- svelte-ignore a11y-no-static-element-interactions --> 335 - <div 336 - class="cover" 337 - on:dragenter={drag_enter_or_over} 338 - on:dragover={drag_enter_or_over} 339 - on:dragleave={drag_leave} 340 - on:drop={drop} 341 - on:dblclick={pick_cover} 342 - > 343 - {#if image} 344 - <img class="outline-element" alt="" src={image.objectUrl} /> 345 - {:else if image === null} 340 + {#if image} 341 + <img class="outline-element" alt="" src={image.objectUrl} /> 342 + {:else if image === null} 343 + <svg 344 + class="cover-svg outline-element" 345 + xmlns="http://www.w3.org/2000/svg" 346 + width="8" 347 + height="8" 348 + viewBox="0 0 24 24" 349 + > 350 + <path 351 + d="M23 0l-15.996 3.585v13.04c-2.979-.589-6.004 1.671-6.004 4.154 0 2.137 1.671 3.221 3.485 3.221 2.155 0 4.512-1.528 4.515-4.638v-10.9l12-2.459v8.624c-2.975-.587-6 1.664-6 4.141 0 2.143 1.715 3.232 3.521 3.232 2.14 0 4.476-1.526 4.479-4.636v-17.364z" 352 + /> 353 + </svg> 354 + {:else} 355 + <!-- empty when loading --> 356 + {/if} 357 + </div> 358 + {#if image && image.totalImages >= 2} 359 + {@const image_index = image.index} 360 + <div class="cover-subtitle"> 361 + <div class="arrow" class:unclickable={image_index <= 0}> 362 + <!-- svelte-ignore a11y-click-events-have-key-events --> 346 363 <svg 347 - class="cover-svg outline-element" 364 + on:click={prev_image} 365 + tabindex="-1" 366 + role="button" 367 + aria-label="Previous image" 368 + clip-rule="evenodd" 369 + fill-rule="evenodd" 370 + stroke-linejoin="round" 371 + stroke-miterlimit="2" 372 + width="18" 373 + height="18" 374 + fill="currentColor" 375 + viewBox="0 0 24 24" 348 376 xmlns="http://www.w3.org/2000/svg" 349 - width="8" 350 - height="8" 377 + ><path 378 + d="m13.789 7.155c.141-.108.3-.157.456-.157.389 0 .755.306.755.749v8.501c0 .445-.367.75-.755.75-.157 0-.316-.05-.457-.159-1.554-1.203-4.199-3.252-5.498-4.258-.184-.142-.29-.36-.29-.592 0-.23.107-.449.291-.591 1.299-1.002 3.945-3.044 5.498-4.243z" 379 + /></svg 380 + > 381 + </div> 382 + <div class="subtitle-text"> 383 + {image.index + 1} / {image.totalImages} 384 + </div> 385 + <div class="arrow" class:unclickable={image_index >= image.totalImages - 1}> 386 + <!-- svelte-ignore a11y-click-events-have-key-events --> 387 + <svg 388 + on:click={next_image} 389 + tabindex="-1" 390 + role="button" 391 + aria-label="Next image" 392 + clip-rule="evenodd" 393 + fill-rule="evenodd" 394 + stroke-linejoin="round" 395 + stroke-miterlimit="2" 396 + width="18" 397 + height="18" 398 + fill="currentColor" 351 399 viewBox="0 0 24 24" 400 + xmlns="http://www.w3.org/2000/svg" 401 + ><path 402 + d="m10.211 7.155c-.141-.108-.3-.157-.456-.157-.389 0-.755.306-.755.749v8.501c0 .445.367.75.755.75.157 0 .316-.05.457-.159 1.554-1.203 4.199-3.252 5.498-4.258.184-.142.29-.36.29-.592 0-.23-.107-.449-.291-.591-1.299-1.002-3.945-3.044-5.498-4.243z" 403 + /></svg 352 404 > 353 - <path 354 - d="M23 0l-15.996 3.585v13.04c-2.979-.589-6.004 1.671-6.004 4.154 0 2.137 1.671 3.221 3.485 3.221 2.155 0 4.512-1.528 4.515-4.638v-10.9l12-2.459v8.624c-2.975-.587-6 1.664-6 4.141 0 2.143 1.715 3.232 3.521 3.232 2.14 0 4.476-1.526 4.479-4.636v-17.364z" 355 - /> 356 - </svg> 357 - {:else} 358 - <!-- empty when loading --> 359 - {/if} 360 - </div> 361 - {#if image && image.totalImages >= 2} 362 - {@const image_index = image.index} 363 - <div class="cover-subtitle"> 364 - <div class="arrow" class:unclickable={image_index <= 0}> 365 - <!-- svelte-ignore a11y-click-events-have-key-events --> 366 - <svg 367 - on:click={prev_image} 368 - tabindex="-1" 369 - role="button" 370 - aria-label="Previous image" 371 - clip-rule="evenodd" 372 - fill-rule="evenodd" 373 - stroke-linejoin="round" 374 - stroke-miterlimit="2" 375 - width="18" 376 - height="18" 377 - fill="currentColor" 378 - viewBox="0 0 24 24" 379 - xmlns="http://www.w3.org/2000/svg" 380 - ><path 381 - d="m13.789 7.155c.141-.108.3-.157.456-.157.389 0 .755.306.755.749v8.501c0 .445-.367.75-.755.75-.157 0-.316-.05-.457-.159-1.554-1.203-4.199-3.252-5.498-4.258-.184-.142-.29-.36-.29-.592 0-.23.107-.449.291-.591 1.299-1.002 3.945-3.044 5.498-4.243z" 382 - /></svg 383 - > 384 - </div> 385 - <div class="subtitle-text"> 386 - {image.index + 1} / {image.totalImages} 387 - </div> 388 - <div class="arrow" class:unclickable={image_index >= image.totalImages - 1}> 389 - <!-- svelte-ignore a11y-click-events-have-key-events --> 390 - <svg 391 - on:click={next_image} 392 - tabindex="-1" 393 - role="button" 394 - aria-label="Next image" 395 - clip-rule="evenodd" 396 - fill-rule="evenodd" 397 - stroke-linejoin="round" 398 - stroke-miterlimit="2" 399 - width="18" 400 - height="18" 401 - fill="currentColor" 402 - viewBox="0 0 24 24" 403 - xmlns="http://www.w3.org/2000/svg" 404 - ><path 405 - d="m10.211 7.155c-.141-.108-.3-.157-.456-.157-.389 0-.755.306-.755.749v8.501c0 .445.367.75.755.75.157 0 .316-.05.457-.159 1.554-1.203 4.199-3.252 5.498-4.258.184-.142.29-.36.29-.592 0-.23-.107-.449-.291-.591-1.299-1.002-3.945-3.044-5.498-4.243z" 406 - /></svg 407 - > 408 - </div> 409 405 </div> 410 - {/if} 411 - </div> 412 - <div class="text"> 413 - <div class="name">{name}</div> 414 - <div class="artist">{artist}</div> 415 - </div> 406 + </div> 407 + {/if} 416 408 </div> 417 - <div class="spacer" /> 418 - <div class="row"> 419 - <div class="label">Title</div> 420 - <!-- svelte-ignore a11y-autofocus --> 421 - <input type="text" bind:value={name} autofocus /> 409 + <div class="text"> 410 + <div class="name">{name}</div> 411 + <div class="artist">{artist}</div> 422 412 </div> 423 - <div class="row"> 424 - <div class="label">Artist</div> 425 - <input type="text" bind:value={artist} /> 426 - </div> 427 - <div class="row"> 428 - <div class="label">Album</div> 429 - <input type="text" bind:value={album_name} /> 430 - </div> 431 - <div class="row"> 432 - <div class="label">Album artist</div> 433 - <input type="text" bind:value={album_artist} /> 434 - </div> 435 - <div class="row"> 436 - <div class="label">Composer</div> 437 - <input type="text" bind:value={composer} /> 438 - </div> 439 - <div class="row"> 440 - <div class="label">Grouping</div> 441 - <input type="text" bind:value={grouping} /> 442 - </div> 443 - <div class="row"> 444 - <div class="label">Genre</div> 445 - <input type="text" bind:value={genre} /> 446 - </div> 447 - <div class="row"> 448 - <div class="label">Year</div> 449 - <input class="medium" type="text" bind:value={year} /> 450 - </div> 451 - <div class="row num"> 452 - <div class="label">Track</div> 453 - <input class="num" type="text" bind:value={track_num} class:big={big(track_num)} /> 454 - <div class="midtext">of</div> 455 - <input class="num" type="text" bind:value={track_count} class:big={big(track_count)} /> 456 - </div> 457 - <div class="row num"> 458 - <div class="label">Disc number</div> 459 - <input class="num" type="text" bind:value={disc_num} class:big={big(disc_num)} /> 460 - <div class="midtext">of</div> 461 - <input class="num" type="text" bind:value={disc_count} class:big={big(disc_count)} /> 462 - </div> 463 - <div class="row"> 464 - <div class="label">Compilation</div> 465 - <p>{compilation ? 'Yes' : 'No'}</p> 466 - </div> 467 - <div class="row"> 468 - <div class="label">Rating</div> 469 - <p>{rating}, {liked ? 'Liked' : 'Not Liked'}</p> 470 - </div> 471 - <div class="row"> 472 - <div class="label">BPM</div> 473 - <input class="medium" type="text" bind:value={bpm} /> 474 - </div> 475 - <div class="row"> 476 - <div class="label">Play count</div> 477 - <p>{play_count}</p> 478 - </div> 479 - <div class="row"> 480 - <div class="label">Comments</div> 481 - <input type="text" bind:value={comments} /> 482 - </div> 483 - <div class="spacer" /> 484 - </main> 485 - <svelte:fragment slot="buttons"> 486 - <Button secondary on:click={cancel}>Cancel</Button> 487 - <Button type="submit" on:click={() => save()}>Save</Button> 488 - </svelte:fragment> 489 - </Modal> 490 - {/if} 413 + </div> 414 + <div class="spacer" /> 415 + <div class="row"> 416 + <div class="label">Title</div> 417 + <!-- svelte-ignore a11y-autofocus --> 418 + <input type="text" bind:value={name} autofocus /> 419 + </div> 420 + <div class="row"> 421 + <div class="label">Artist</div> 422 + <input type="text" bind:value={artist} /> 423 + </div> 424 + <div class="row"> 425 + <div class="label">Album</div> 426 + <input type="text" bind:value={album_name} /> 427 + </div> 428 + <div class="row"> 429 + <div class="label">Album artist</div> 430 + <input type="text" bind:value={album_artist} /> 431 + </div> 432 + <div class="row"> 433 + <div class="label">Composer</div> 434 + <input type="text" bind:value={composer} /> 435 + </div> 436 + <div class="row"> 437 + <div class="label">Grouping</div> 438 + <input type="text" bind:value={grouping} /> 439 + </div> 440 + <div class="row"> 441 + <div class="label">Genre</div> 442 + <input type="text" bind:value={genre} /> 443 + </div> 444 + <div class="row"> 445 + <div class="label">Year</div> 446 + <input class="medium" type="text" bind:value={year} /> 447 + </div> 448 + <div class="row num"> 449 + <div class="label">Track</div> 450 + <input class="num" type="text" bind:value={track_num} class:big={big(track_num)} /> 451 + <div class="midtext">of</div> 452 + <input class="num" type="text" bind:value={track_count} class:big={big(track_count)} /> 453 + </div> 454 + <div class="row num"> 455 + <div class="label">Disc number</div> 456 + <input class="num" type="text" bind:value={disc_num} class:big={big(disc_num)} /> 457 + <div class="midtext">of</div> 458 + <input class="num" type="text" bind:value={disc_count} class:big={big(disc_count)} /> 459 + </div> 460 + <div class="row"> 461 + <div class="label">Compilation</div> 462 + <p>{compilation ? 'Yes' : 'No'}</p> 463 + </div> 464 + <div class="row"> 465 + <div class="label">Rating</div> 466 + <p>{rating}, {liked ? 'Liked' : 'Not Liked'}</p> 467 + </div> 468 + <div class="row"> 469 + <div class="label">BPM</div> 470 + <input class="medium" type="text" bind:value={bpm} /> 471 + </div> 472 + <div class="row"> 473 + <div class="label">Play count</div> 474 + <p>{play_count}</p> 475 + </div> 476 + <div class="row"> 477 + <div class="label">Comments</div> 478 + <input type="text" bind:value={comments} /> 479 + </div> 480 + <div class="spacer" /> 481 + </main> 482 + <svelte:fragment slot="buttons"> 483 + <Button secondary on:click={cancel}>Cancel</Button> 484 + <Button type="submit" on:click={() => save()}>Save</Button> 485 + </svelte:fragment> 486 + </Modal> 491 487 492 488 <style lang="sass"> 493 489 $cover-size: 90px