gitextract_6koal0cm/ ├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── 01-feature_request.yml │ │ ├── 02-bug_report.yml │ │ └── config.yml │ ├── config.yml │ ├── stale.yml │ └── workflows/ │ ├── publish-alpha.yml │ ├── publish-beta.yml │ ├── publish-docker-auto.yml │ ├── publish-docker.yml │ ├── publish-linux.yml │ ├── publish-macos.yml │ ├── publish-pr-comment.yml │ ├── publish-pr.yml │ ├── publish-windows.yml │ ├── publish-winget.yml │ ├── publish.yml │ ├── stale.yml │ └── test.yml ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc.yaml ├── .stylelintrc.json ├── .vscode/ │ ├── extensions.json │ ├── launch.json │ └── settings.json ├── CHANGELOG.md ├── Dockerfile ├── LICENSE ├── README.md ├── assets/ │ ├── assets.d.ts │ ├── entitlements.mac.plist │ └── icons/ │ └── icon.icns ├── dev-app-update.yml ├── docker-compose.yaml ├── docs/ │ └── ENV_SETTINGS.md ├── electron-builder-alpha.yml ├── electron-builder-beta.yml ├── electron-builder.yml ├── electron.vite.config.ts ├── eslint.config.mjs ├── feishin.desktop.tmpl ├── install-feishin-appimage ├── ng.conf.template ├── org.jeffvli.feishin.metainfo.xml ├── package.json ├── postcss.config.cjs ├── remote.vite.config.ts ├── scripts/ │ ├── after-all-artifact-build.mjs │ └── update-app-stream.mjs ├── settings.js.template ├── src/ │ ├── i18n/ │ │ ├── i18n.ts │ │ ├── i18next-parser.config.js │ │ └── locales/ │ │ ├── ar.json │ │ ├── ca.json │ │ ├── cs.json │ │ ├── da.json │ │ ├── de.json │ │ ├── en.json │ │ ├── es.json │ │ ├── eu.json │ │ ├── fa.json │ │ ├── fi.json │ │ ├── fr.json │ │ ├── hu.json │ │ ├── id.json │ │ ├── it.json │ │ ├── ja.json │ │ ├── ko.json │ │ ├── nb-NO.json │ │ ├── nl.json │ │ ├── pl.json │ │ ├── pt-BR.json │ │ ├── pt.json │ │ ├── ro.json │ │ ├── ru.json │ │ ├── sk.json │ │ ├── sl.json │ │ ├── sr.json │ │ ├── sv.json │ │ ├── ta.json │ │ ├── tr.json │ │ ├── uk.json │ │ ├── zh-Hans.json │ │ └── zh-Hant.json │ ├── main/ │ │ ├── features/ │ │ │ ├── core/ │ │ │ │ ├── autodiscover/ │ │ │ │ │ └── index.ts │ │ │ │ ├── discord-rpc/ │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── lyrics/ │ │ │ │ │ ├── genius.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── lrclib.ts │ │ │ │ │ ├── netease.ts │ │ │ │ │ ├── shared.ts │ │ │ │ │ └── simpmusic.ts │ │ │ │ ├── player/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── media-keys.ts │ │ │ │ ├── remote/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── manifest.json │ │ │ │ └── settings/ │ │ │ │ └── index.ts │ │ │ ├── darwin/ │ │ │ │ ├── dock-menu.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── linux/ │ │ │ │ ├── index.ts │ │ │ │ └── mpris.ts │ │ │ └── win32/ │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── menu.ts │ │ └── utils.ts │ ├── preload/ │ │ ├── autodiscover.ts │ │ ├── browser.ts │ │ ├── discord-rpc.ts │ │ ├── index.d.ts │ │ ├── index.ts │ │ ├── ipc.ts │ │ ├── local-settings.ts │ │ ├── lyrics.ts │ │ ├── mpris.ts │ │ ├── mpv-player.ts │ │ ├── remote.ts │ │ └── utils.ts │ ├── remote/ │ │ ├── app.tsx │ │ ├── components/ │ │ │ ├── buttons/ │ │ │ │ ├── image-button.tsx │ │ │ │ ├── reconnect-button.tsx │ │ │ │ └── theme-button.tsx │ │ │ ├── player-image.module.css │ │ │ ├── player-image.tsx │ │ │ ├── remote-container.module.css │ │ │ ├── remote-container.tsx │ │ │ ├── shell.tsx │ │ │ └── wrapped-slider.tsx │ │ ├── index.html │ │ ├── index.tsx │ │ ├── manifest.json │ │ ├── service-worker.ts │ │ ├── store/ │ │ │ └── index.ts │ │ └── worker.js │ ├── renderer/ │ │ ├── api/ │ │ │ ├── controller.ts │ │ │ ├── index.ts │ │ │ ├── jellyfin/ │ │ │ │ ├── jellyfin-api.ts │ │ │ │ └── jellyfin-controller.ts │ │ │ ├── navidrome/ │ │ │ │ ├── navidrome-api.ts │ │ │ │ └── navidrome-controller.ts │ │ │ ├── query-keys.ts │ │ │ ├── subsonic/ │ │ │ │ ├── subsonic-api.ts │ │ │ │ └── subsonic-controller.ts │ │ │ ├── utils-list-count.ts │ │ │ ├── utils-music-folder.ts │ │ │ └── utils.ts │ │ ├── app.tsx │ │ ├── assets/ │ │ │ ├── assets.d.ts │ │ │ ├── entitlements.mac.plist │ │ │ └── icons/ │ │ │ └── icon.icns │ │ ├── components/ │ │ │ ├── drag-preview/ │ │ │ │ ├── drag-preview.module.css │ │ │ │ └── drag-preview.tsx │ │ │ ├── export-import-settings-modal/ │ │ │ │ └── export-import-settings-modal.tsx │ │ │ ├── feature-carousel/ │ │ │ │ ├── feature-carousel.module.css │ │ │ │ ├── feature-carousel.tsx │ │ │ │ └── single-feature-carousel.tsx │ │ │ ├── grid-carousel/ │ │ │ │ ├── grid-carousel-v2.tsx │ │ │ │ └── grid-carousel.module.css │ │ │ ├── item-card/ │ │ │ │ ├── item-card-controls.module.css │ │ │ │ ├── item-card-controls.tsx │ │ │ │ ├── item-card.module.css │ │ │ │ └── item-card.tsx │ │ │ ├── item-image/ │ │ │ │ └── item-image.tsx │ │ │ ├── item-list/ │ │ │ │ ├── expanded-list-container.module.css │ │ │ │ ├── expanded-list-container.tsx │ │ │ │ ├── expanded-list-item.module.css │ │ │ │ ├── expanded-list-item.tsx │ │ │ │ ├── helpers/ │ │ │ │ │ ├── extract-row-id.ts │ │ │ │ │ ├── get-dragged-items.ts │ │ │ │ │ ├── get-title-path.ts │ │ │ │ │ ├── item-list-controls.ts │ │ │ │ │ ├── item-list-infinite-loader.ts │ │ │ │ │ ├── item-list-paginated-loader.ts │ │ │ │ │ ├── item-list-reducer-utils.ts │ │ │ │ │ ├── item-list-state.ts │ │ │ │ │ ├── parse-table-columns.ts │ │ │ │ │ ├── use-grid-rows.ts │ │ │ │ │ ├── use-is-fetching-item-list.ts │ │ │ │ │ ├── use-item-list-column-reorder.ts │ │ │ │ │ ├── use-item-list-column-resize.ts │ │ │ │ │ ├── use-item-list-scroll-persist.ts │ │ │ │ │ └── use-list-hotkeys.ts │ │ │ │ ├── item-detail-list/ │ │ │ │ │ ├── columns/ │ │ │ │ │ │ ├── actions-column.tsx │ │ │ │ │ │ ├── album-artist-column.tsx │ │ │ │ │ │ ├── album-column.tsx │ │ │ │ │ │ ├── artist-column.tsx │ │ │ │ │ │ ├── bit-depth-column.tsx │ │ │ │ │ │ ├── bit-rate-column.tsx │ │ │ │ │ │ ├── bpm-column.tsx │ │ │ │ │ │ ├── channels-column.tsx │ │ │ │ │ │ ├── codec-column.tsx │ │ │ │ │ │ ├── comment-column.tsx │ │ │ │ │ │ ├── composer-column.tsx │ │ │ │ │ │ ├── date-added-column.tsx │ │ │ │ │ │ ├── default-column.tsx │ │ │ │ │ │ ├── disc-number-column.tsx │ │ │ │ │ │ ├── duration-column.tsx │ │ │ │ │ │ ├── favorite-column.tsx │ │ │ │ │ │ ├── genre-badge-column.module.css │ │ │ │ │ │ ├── genre-badge-column.tsx │ │ │ │ │ │ ├── genre-column.tsx │ │ │ │ │ │ ├── image-column.module.css │ │ │ │ │ │ ├── image-column.tsx │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── last-played-column.tsx │ │ │ │ │ │ ├── path-column.tsx │ │ │ │ │ │ ├── play-count-column.tsx │ │ │ │ │ │ ├── rating-column.tsx │ │ │ │ │ │ ├── release-date-column.tsx │ │ │ │ │ │ ├── row-index-column.module.css │ │ │ │ │ │ ├── row-index-column.tsx │ │ │ │ │ │ ├── sample-rate-column.tsx │ │ │ │ │ │ ├── size-column.tsx │ │ │ │ │ │ ├── title-artist-column.tsx │ │ │ │ │ │ ├── title-column.module.css │ │ │ │ │ │ ├── title-column.tsx │ │ │ │ │ │ ├── title-combined-column.tsx │ │ │ │ │ │ ├── track-number-column.tsx │ │ │ │ │ │ ├── types.ts │ │ │ │ │ │ └── year-column.tsx │ │ │ │ │ ├── item-detail-list.module.css │ │ │ │ │ ├── item-detail-list.tsx │ │ │ │ │ └── utils.ts │ │ │ │ ├── item-grid-list/ │ │ │ │ │ ├── item-grid-list.module.css │ │ │ │ │ └── item-grid-list.tsx │ │ │ │ ├── item-list-pagination/ │ │ │ │ │ ├── item-list-pagination.module.css │ │ │ │ │ ├── item-list-pagination.tsx │ │ │ │ │ └── use-item-list-pagination.ts │ │ │ │ ├── item-table-list/ │ │ │ │ │ ├── album-group-header.module.css │ │ │ │ │ ├── album-group-header.tsx │ │ │ │ │ ├── cell-component-factory.tsx │ │ │ │ │ ├── columns/ │ │ │ │ │ │ ├── actions-column.tsx │ │ │ │ │ │ ├── album-artists-column.module.css │ │ │ │ │ │ ├── album-artists-column.tsx │ │ │ │ │ │ ├── album-column.module.css │ │ │ │ │ │ ├── album-column.tsx │ │ │ │ │ │ ├── album-group-column.tsx │ │ │ │ │ │ ├── artists-column.module.css │ │ │ │ │ │ ├── artists-column.tsx │ │ │ │ │ │ ├── composer-column.module.css │ │ │ │ │ │ ├── composer-column.tsx │ │ │ │ │ │ ├── count-column.tsx │ │ │ │ │ │ ├── date-column.tsx │ │ │ │ │ │ ├── default-column.tsx │ │ │ │ │ │ ├── duration-column.tsx │ │ │ │ │ │ ├── favorite-column.tsx │ │ │ │ │ │ ├── genre-badge-column.module.css │ │ │ │ │ │ ├── genre-badge-column.tsx │ │ │ │ │ │ ├── genre-column.module.css │ │ │ │ │ │ ├── genre-column.tsx │ │ │ │ │ │ ├── image-column.module.css │ │ │ │ │ │ ├── image-column.tsx │ │ │ │ │ │ ├── numeric-column.tsx │ │ │ │ │ │ ├── path-column.tsx │ │ │ │ │ │ ├── playlist-reorder-column.module.css │ │ │ │ │ │ ├── playlist-reorder-column.tsx │ │ │ │ │ │ ├── rating-column.tsx │ │ │ │ │ │ ├── row-index-column.module.css │ │ │ │ │ │ ├── row-index-column.tsx │ │ │ │ │ │ ├── size-column.tsx │ │ │ │ │ │ ├── text-column.module.css │ │ │ │ │ │ ├── text-column.tsx │ │ │ │ │ │ ├── title-artist-column.module.css │ │ │ │ │ │ ├── title-artist-column.tsx │ │ │ │ │ │ ├── title-column.module.css │ │ │ │ │ │ ├── title-column.tsx │ │ │ │ │ │ ├── title-combined-column.module.css │ │ │ │ │ │ ├── title-combined-column.tsx │ │ │ │ │ │ └── year-column.tsx │ │ │ │ │ ├── default-columns.ts │ │ │ │ │ ├── hooks/ │ │ │ │ │ │ ├── use-container-width-tracking.ts │ │ │ │ │ │ ├── use-item-drag-drop-state.tsx │ │ │ │ │ │ ├── use-row-interaction-delegate.ts │ │ │ │ │ │ ├── use-sticky-group-row-positioning.ts │ │ │ │ │ │ ├── use-sticky-header-positioning.ts │ │ │ │ │ │ ├── use-sticky-table-group-rows.tsx │ │ │ │ │ │ ├── use-sticky-table-header.tsx │ │ │ │ │ │ ├── use-table-column-model.ts │ │ │ │ │ │ ├── use-table-imperative-handle.ts │ │ │ │ │ │ ├── use-table-initial-scroll.ts │ │ │ │ │ │ ├── use-table-keyboard-navigation.ts │ │ │ │ │ │ ├── use-table-pane-sync.ts │ │ │ │ │ │ ├── use-table-row-model.ts │ │ │ │ │ │ └── use-table-scroll-to-index.ts │ │ │ │ │ ├── item-table-list-column.module.css │ │ │ │ │ ├── item-table-list-column.tsx │ │ │ │ │ ├── item-table-list-context.tsx │ │ │ │ │ ├── item-table-list.module.css │ │ │ │ │ ├── item-table-list.tsx │ │ │ │ │ └── memoized-cell-router.tsx │ │ │ │ ├── selection-dialog.module.css │ │ │ │ ├── selection-dialog.tsx │ │ │ │ └── types.ts │ │ │ ├── motion/ │ │ │ │ └── index.tsx │ │ │ ├── native-scroll-area/ │ │ │ │ ├── native-scroll-area.module.css │ │ │ │ └── native-scroll-area.tsx │ │ │ ├── page-header/ │ │ │ │ ├── page-header.module.css │ │ │ │ └── page-header.tsx │ │ │ ├── query-builder/ │ │ │ │ ├── index.tsx │ │ │ │ └── query-builder-option.tsx │ │ │ ├── select-with-invalid-data/ │ │ │ │ └── index.tsx │ │ │ ├── settings-diff-visualiser/ │ │ │ │ └── settings-diff-visualiser.tsx │ │ │ └── simple-item-table/ │ │ │ ├── simple-item-table.module.css │ │ │ └── simple-item-table.tsx │ │ ├── context/ │ │ │ └── list-context.tsx │ │ ├── env.d.ts │ │ ├── events/ │ │ │ ├── event-emitter.ts │ │ │ ├── events.ts │ │ │ └── types.ts │ │ ├── features/ │ │ │ ├── action-required/ │ │ │ │ ├── components/ │ │ │ │ │ ├── action-required-container.tsx │ │ │ │ │ ├── error-fallback.module.css │ │ │ │ │ ├── error-fallback.tsx │ │ │ │ │ ├── server-credential-required.tsx │ │ │ │ │ └── server-required.tsx │ │ │ │ ├── routes/ │ │ │ │ │ ├── action-required-route.tsx │ │ │ │ │ ├── invalid-route.tsx │ │ │ │ │ └── no-network-route.tsx │ │ │ │ └── utils/ │ │ │ │ └── window-properties.tsx │ │ │ ├── albums/ │ │ │ │ ├── api/ │ │ │ │ │ └── album-api.ts │ │ │ │ ├── components/ │ │ │ │ │ ├── album-detail-content.module.css │ │ │ │ │ ├── album-detail-content.tsx │ │ │ │ │ ├── album-detail-header.module.css │ │ │ │ │ ├── album-detail-header.tsx │ │ │ │ │ ├── album-grid-carousel.tsx │ │ │ │ │ ├── album-infinite-carousel.tsx │ │ │ │ │ ├── album-list-content.tsx │ │ │ │ │ ├── album-list-header-filters.tsx │ │ │ │ │ ├── album-list-header.tsx │ │ │ │ │ ├── album-list-infinite-detail.tsx │ │ │ │ │ ├── album-list-infinite-grid.tsx │ │ │ │ │ ├── album-list-infinite-table.tsx │ │ │ │ │ ├── album-list-paginated-detail.tsx │ │ │ │ │ ├── album-list-paginated-grid.tsx │ │ │ │ │ ├── album-list-paginated-table.tsx │ │ │ │ │ ├── expanded-album-list-item.module.css │ │ │ │ │ ├── expanded-album-list-item.tsx │ │ │ │ │ ├── jellyfin-album-filters.tsx │ │ │ │ │ ├── joined-artists.tsx │ │ │ │ │ ├── navidrome-album-filters.tsx │ │ │ │ │ └── subsonic-album-filters.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ └── use-album-list-filters.ts │ │ │ │ └── routes/ │ │ │ │ ├── album-detail-route.tsx │ │ │ │ ├── album-list-route.tsx │ │ │ │ ├── dummy-album-detail-route.module.css │ │ │ │ └── dummy-album-detail-route.tsx │ │ │ ├── analytics/ │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-analytics-disabled.ts │ │ │ │ │ ├── use-app-tracker.ts │ │ │ │ │ └── use-page-tracker.ts │ │ │ │ └── utils/ │ │ │ │ └── get-route-pattern.ts │ │ │ ├── artists/ │ │ │ │ ├── api/ │ │ │ │ │ └── artists-api.ts │ │ │ │ ├── components/ │ │ │ │ │ ├── album-artist-detail-content.module.css │ │ │ │ │ ├── album-artist-detail-content.tsx │ │ │ │ │ ├── album-artist-detail-discography-list.tsx │ │ │ │ │ ├── album-artist-detail-favorite-songs-list-header-filters.tsx │ │ │ │ │ ├── album-artist-detail-favorite-songs-list-header.tsx │ │ │ │ │ ├── album-artist-detail-header.module.css │ │ │ │ │ ├── album-artist-detail-header.tsx │ │ │ │ │ ├── album-artist-detail-top-songs-list-header.tsx │ │ │ │ │ ├── album-artist-grid-carousel.tsx │ │ │ │ │ ├── album-artist-infinite-carousel.tsx │ │ │ │ │ ├── album-artist-list-content.tsx │ │ │ │ │ ├── album-artist-list-header-filters.tsx │ │ │ │ │ ├── album-artist-list-header.tsx │ │ │ │ │ ├── album-artist-list-infinite-grid.tsx │ │ │ │ │ ├── album-artist-list-infinite-table.tsx │ │ │ │ │ ├── album-artist-list-paginated-grid.tsx │ │ │ │ │ ├── album-artist-list-paginated-table.tsx │ │ │ │ │ ├── artist-list-content.tsx │ │ │ │ │ ├── artist-list-header-filters.tsx │ │ │ │ │ ├── artist-list-header.tsx │ │ │ │ │ ├── artist-list-infinite-grid.tsx │ │ │ │ │ ├── artist-list-infinite-table.tsx │ │ │ │ │ ├── artist-list-paginated-grid.tsx │ │ │ │ │ └── artist-list-paginated-table.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-album-artist-list-filters.ts │ │ │ │ │ ├── use-artist-albums-grouped.ts │ │ │ │ │ └── use-artist-list-filters.ts │ │ │ │ └── routes/ │ │ │ │ ├── album-artist-detail-favorite-songs-list-route.tsx │ │ │ │ ├── album-artist-detail-route.tsx │ │ │ │ ├── album-artist-detail-top-songs-list-route.tsx │ │ │ │ ├── album-artist-list-route.tsx │ │ │ │ └── artist-list-route.tsx │ │ │ ├── context-menu/ │ │ │ │ ├── actions/ │ │ │ │ │ ├── add-to-playlist-action.tsx │ │ │ │ │ ├── delete-playlist-action.tsx │ │ │ │ │ ├── download-action.tsx │ │ │ │ │ ├── edit-playlist-action.tsx │ │ │ │ │ ├── get-info-action.tsx │ │ │ │ │ ├── go-to-action.tsx │ │ │ │ │ ├── move-queue-items-action.tsx │ │ │ │ │ ├── play-action.tsx │ │ │ │ │ ├── play-album-radio-action.tsx │ │ │ │ │ ├── play-artist-radio-action.tsx │ │ │ │ │ ├── play-track-radio-action.tsx │ │ │ │ │ ├── remove-from-playlist-action.tsx │ │ │ │ │ ├── remove-from-queue-action.tsx │ │ │ │ │ ├── set-favorite-action.tsx │ │ │ │ │ ├── set-rating-action.tsx │ │ │ │ │ ├── share-action.tsx │ │ │ │ │ ├── show-in-file-explorer-action.tsx │ │ │ │ │ └── shuffle-items-action.tsx │ │ │ │ ├── components/ │ │ │ │ │ ├── context-menu-preview.module.css │ │ │ │ │ └── context-menu-preview.tsx │ │ │ │ ├── context-menu-controller.tsx │ │ │ │ └── menus/ │ │ │ │ ├── album-artist-context-menu.tsx │ │ │ │ ├── album-context-menu.tsx │ │ │ │ ├── artist-context-menu.tsx │ │ │ │ ├── folder-context-menu.tsx │ │ │ │ ├── genre-context-menu.tsx │ │ │ │ ├── playlist-context-menu.tsx │ │ │ │ ├── playlist-song-context-menu.tsx │ │ │ │ ├── queue-context-menu.tsx │ │ │ │ └── song-context-menu.tsx │ │ │ ├── discord-rpc/ │ │ │ │ └── use-discord-rpc.ts │ │ │ ├── favorites/ │ │ │ │ ├── components/ │ │ │ │ │ ├── favorites-content.tsx │ │ │ │ │ └── favorites-header.tsx │ │ │ │ └── routes/ │ │ │ │ └── favorites-route.tsx │ │ │ ├── folders/ │ │ │ │ ├── api/ │ │ │ │ │ └── folder-api.ts │ │ │ │ ├── components/ │ │ │ │ │ ├── folder-list-content.tsx │ │ │ │ │ ├── folder-list-header-filters.tsx │ │ │ │ │ ├── folder-list-header.tsx │ │ │ │ │ ├── folder-tree-browser.module.css │ │ │ │ │ └── folder-tree-browser.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ └── use-folder-list-filters.ts │ │ │ │ └── routes/ │ │ │ │ └── folder-list-route.tsx │ │ │ ├── genres/ │ │ │ │ ├── api/ │ │ │ │ │ └── genres-api.ts │ │ │ │ ├── components/ │ │ │ │ │ ├── genre-detail-content.tsx │ │ │ │ │ ├── genre-detail-header.tsx │ │ │ │ │ ├── genre-list-content.tsx │ │ │ │ │ ├── genre-list-header-filters.tsx │ │ │ │ │ ├── genre-list-header.tsx │ │ │ │ │ ├── genre-list-infinite-grid.tsx │ │ │ │ │ ├── genre-list-infinite-table.tsx │ │ │ │ │ ├── genre-list-paginated-grid.tsx │ │ │ │ │ └── genre-list-paginated-table.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ └── use-genre-list-filters.ts │ │ │ │ └── routes/ │ │ │ │ ├── genre-detail-route.tsx │ │ │ │ └── genre-list-route.tsx │ │ │ ├── home/ │ │ │ │ ├── api/ │ │ │ │ │ └── home-api.ts │ │ │ │ ├── components/ │ │ │ │ │ ├── album-infinite-feature-carousel.tsx │ │ │ │ │ ├── album-infinite-single-feature-carousel.tsx │ │ │ │ │ ├── featured-genres.module.css │ │ │ │ │ └── featured-genres.tsx │ │ │ │ └── routes/ │ │ │ │ └── home-route.tsx │ │ │ ├── item-details/ │ │ │ │ └── components/ │ │ │ │ ├── item-details-modal.tsx │ │ │ │ └── song-path.tsx │ │ │ ├── login/ │ │ │ │ └── routes/ │ │ │ │ └── login-route.tsx │ │ │ ├── lyrics/ │ │ │ │ ├── api/ │ │ │ │ │ ├── lyric-translate.ts │ │ │ │ │ └── lyrics-api.ts │ │ │ │ ├── components/ │ │ │ │ │ ├── lyrics-export-form.tsx │ │ │ │ │ ├── lyrics-search-form.module.css │ │ │ │ │ ├── lyrics-search-form.tsx │ │ │ │ │ ├── lyrics-settings-form.tsx │ │ │ │ │ └── lyrics-settings-modal.tsx │ │ │ │ ├── lyric-line.module.css │ │ │ │ ├── lyric-line.tsx │ │ │ │ ├── lyrics-actions.tsx │ │ │ │ ├── lyrics.module.css │ │ │ │ ├── lyrics.tsx │ │ │ │ ├── synchronized-lyrics.module.css │ │ │ │ ├── synchronized-lyrics.tsx │ │ │ │ ├── unsynchronized-lyrics.module.css │ │ │ │ ├── unsynchronized-lyrics.tsx │ │ │ │ └── utils/ │ │ │ │ └── open-lyrics-settings-modal.ts │ │ │ ├── now-playing/ │ │ │ │ ├── components/ │ │ │ │ │ ├── drawer-play-queue.tsx │ │ │ │ │ ├── now-playing-header.tsx │ │ │ │ │ ├── play-queue-list-controls.tsx │ │ │ │ │ ├── play-queue.module.css │ │ │ │ │ ├── play-queue.tsx │ │ │ │ │ ├── popover-play-queue.tsx │ │ │ │ │ ├── sidebar-play-queue.module.css │ │ │ │ │ └── sidebar-play-queue.tsx │ │ │ │ └── routes/ │ │ │ │ └── now-playing-route.tsx │ │ │ ├── player/ │ │ │ │ ├── audio-player/ │ │ │ │ │ ├── engine/ │ │ │ │ │ │ ├── mpv-player-engine.tsx │ │ │ │ │ │ ├── wavesurfer-player-engine.tsx │ │ │ │ │ │ └── web-player-engine.tsx │ │ │ │ │ ├── hooks/ │ │ │ │ │ │ ├── use-main-player-listener.tsx │ │ │ │ │ │ ├── use-player-events.ts │ │ │ │ │ │ └── use-stream-url.tsx │ │ │ │ │ ├── mpv-player.tsx │ │ │ │ │ ├── types.ts │ │ │ │ │ ├── utils/ │ │ │ │ │ │ ├── list-handlers.ts │ │ │ │ │ │ └── player-utils.ts │ │ │ │ │ ├── wavesurfer-player.tsx │ │ │ │ │ └── web-player.tsx │ │ │ │ ├── components/ │ │ │ │ │ ├── audio-players.tsx │ │ │ │ │ ├── center-controls.module.css │ │ │ │ │ ├── center-controls.tsx │ │ │ │ │ ├── full-screen-player-image.module.css │ │ │ │ │ ├── full-screen-player-image.tsx │ │ │ │ │ ├── full-screen-player-queue.module.css │ │ │ │ │ ├── full-screen-player-queue.tsx │ │ │ │ │ ├── full-screen-player.module.css │ │ │ │ │ ├── full-screen-player.tsx │ │ │ │ │ ├── full-screen-similar-songs.tsx │ │ │ │ │ ├── full-screen-visualizer-song-info.tsx │ │ │ │ │ ├── full-screen-visualizer.module.css │ │ │ │ │ ├── full-screen-visualizer.tsx │ │ │ │ │ ├── left-controls.module.css │ │ │ │ │ ├── left-controls.tsx │ │ │ │ │ ├── mobile-fullscreen-player-album-art.tsx │ │ │ │ │ ├── mobile-fullscreen-player-bottom-controls.tsx │ │ │ │ │ ├── mobile-fullscreen-player-controls.tsx │ │ │ │ │ ├── mobile-fullscreen-player-header.tsx │ │ │ │ │ ├── mobile-fullscreen-player-metadata.tsx │ │ │ │ │ ├── mobile-fullscreen-player-progress.tsx │ │ │ │ │ ├── mobile-fullscreen-player.module.css │ │ │ │ │ ├── mobile-fullscreen-player.tsx │ │ │ │ │ ├── mobile-playerbar.module.css │ │ │ │ │ ├── mobile-playerbar.tsx │ │ │ │ │ ├── player-button.module.css │ │ │ │ │ ├── player-button.tsx │ │ │ │ │ ├── player-config.tsx │ │ │ │ │ ├── playerbar-seek-slider.tsx │ │ │ │ │ ├── playerbar-slider.module.css │ │ │ │ │ ├── playerbar-slider.tsx │ │ │ │ │ ├── playerbar-waveform.module.css │ │ │ │ │ ├── playerbar-waveform.tsx │ │ │ │ │ ├── playerbar.module.css │ │ │ │ │ ├── playerbar.tsx │ │ │ │ │ ├── radio-metadata-display.tsx │ │ │ │ │ ├── right-controls.tsx │ │ │ │ │ ├── shuffle-all-modal.tsx │ │ │ │ │ └── sleep-timer-button.tsx │ │ │ │ ├── context/ │ │ │ │ │ ├── player-context.tsx │ │ │ │ │ └── webaudio-context.ts │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-auto-dj.ts │ │ │ │ │ ├── use-autosave.ts │ │ │ │ │ ├── use-is-current-song.ts │ │ │ │ │ ├── use-media-session.ts │ │ │ │ │ ├── use-mpris.ts │ │ │ │ │ ├── use-playback-hotkeys.ts │ │ │ │ │ ├── use-power-save-blocker.ts │ │ │ │ │ ├── use-queue-restore.ts │ │ │ │ │ ├── use-scrobble.ts │ │ │ │ │ ├── use-update-current-song.ts │ │ │ │ │ └── use-webaudio.ts │ │ │ │ ├── mutations/ │ │ │ │ │ └── scrobble-mutation.ts │ │ │ │ ├── ref/ │ │ │ │ │ └── players-ref.tsx │ │ │ │ ├── update-remote-song.tsx │ │ │ │ ├── utils/ │ │ │ │ │ └── open-visualizer-settings-modal.ts │ │ │ │ └── utils.ts │ │ │ ├── playlists/ │ │ │ │ ├── api/ │ │ │ │ │ └── playlists-api.ts │ │ │ │ ├── components/ │ │ │ │ │ ├── add-to-playlist-context-modal.module.css │ │ │ │ │ ├── add-to-playlist-context-modal.tsx │ │ │ │ │ ├── client-side-song-filters.tsx │ │ │ │ │ ├── create-playlist-form.tsx │ │ │ │ │ ├── playlist-detail-album-view.tsx │ │ │ │ │ ├── playlist-detail-song-list-content.tsx │ │ │ │ │ ├── playlist-detail-song-list-grid.tsx │ │ │ │ │ ├── playlist-detail-song-list-header-filters.tsx │ │ │ │ │ ├── playlist-detail-song-list-header.tsx │ │ │ │ │ ├── playlist-detail-song-list-table.tsx │ │ │ │ │ ├── playlist-list-content.tsx │ │ │ │ │ ├── playlist-list-header-filters.tsx │ │ │ │ │ ├── playlist-list-header.tsx │ │ │ │ │ ├── playlist-list-infinite-grid.tsx │ │ │ │ │ ├── playlist-list-infinite-table.tsx │ │ │ │ │ ├── playlist-list-paginated-grid.tsx │ │ │ │ │ ├── playlist-list-paginated-table.tsx │ │ │ │ │ ├── playlist-query-builder.tsx │ │ │ │ │ ├── playlist-query-editor.tsx │ │ │ │ │ ├── save-and-replace-context-modal.tsx │ │ │ │ │ ├── save-as-playlist-form.tsx │ │ │ │ │ ├── update-playlist-form.tsx │ │ │ │ │ └── update-playlist-modal.ts │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-playlist-list-filters.ts │ │ │ │ │ ├── use-playlist-song-list-filters.ts │ │ │ │ │ ├── use-playlist-track-list.ts │ │ │ │ │ └── use-recent-playlists.ts │ │ │ │ ├── mutations/ │ │ │ │ │ ├── add-to-playlist-mutation.ts │ │ │ │ │ ├── create-playlist-mutation.ts │ │ │ │ │ ├── delete-playlist-mutation.ts │ │ │ │ │ ├── playlist-optimistic-updates.ts │ │ │ │ │ ├── remove-from-playlist-mutation.ts │ │ │ │ │ └── update-playlist-mutation.ts │ │ │ │ ├── routes/ │ │ │ │ │ ├── playlist-detail-song-list-route.tsx │ │ │ │ │ └── playlist-list-route.tsx │ │ │ │ └── utils.ts │ │ │ ├── radio/ │ │ │ │ ├── api/ │ │ │ │ │ └── radio-api.ts │ │ │ │ ├── components/ │ │ │ │ │ ├── create-radio-station-form.tsx │ │ │ │ │ ├── edit-radio-station-form.tsx │ │ │ │ │ ├── radio-list-content.tsx │ │ │ │ │ ├── radio-list-header-filters.tsx │ │ │ │ │ ├── radio-list-header.tsx │ │ │ │ │ ├── radio-list-items.module.css │ │ │ │ │ ├── radio-list-items.tsx │ │ │ │ │ └── radio-web-player.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ └── use-radio-player.ts │ │ │ │ ├── mutations/ │ │ │ │ │ ├── create-radio-station-mutation.ts │ │ │ │ │ ├── delete-radio-station-mutation.ts │ │ │ │ │ └── update-radio-station-mutation.ts │ │ │ │ ├── routes/ │ │ │ │ │ └── radio-list-route.tsx │ │ │ │ └── store/ │ │ │ │ └── radio-store.ts │ │ │ ├── remote/ │ │ │ │ └── hooks/ │ │ │ │ └── use-remote.tsx │ │ │ ├── search/ │ │ │ │ ├── api/ │ │ │ │ │ └── search-api.ts │ │ │ │ ├── components/ │ │ │ │ │ ├── collapsible-command-group.module.css │ │ │ │ │ ├── collapsible-command-group.tsx │ │ │ │ │ ├── command-item-selectable.tsx │ │ │ │ │ ├── command-palette.tsx │ │ │ │ │ ├── command.css │ │ │ │ │ ├── command.tsx │ │ │ │ │ ├── go-to-commands.tsx │ │ │ │ │ ├── home-commands.tsx │ │ │ │ │ ├── library-command-item.module.css │ │ │ │ │ ├── library-command-item.tsx │ │ │ │ │ ├── search-album-artists-section.tsx │ │ │ │ │ ├── search-albums-section.tsx │ │ │ │ │ ├── search-content.tsx │ │ │ │ │ ├── search-header.tsx │ │ │ │ │ ├── search-songs-section.tsx │ │ │ │ │ └── server-commands.tsx │ │ │ │ └── routes/ │ │ │ │ └── search-route.tsx │ │ │ ├── servers/ │ │ │ │ └── components/ │ │ │ │ ├── add-server-form.tsx │ │ │ │ ├── edit-server-form.tsx │ │ │ │ ├── ignore-cors-ssl-switches.tsx │ │ │ │ ├── server-list-item.tsx │ │ │ │ ├── server-list.tsx │ │ │ │ └── server-section.tsx │ │ │ ├── settings/ │ │ │ │ ├── components/ │ │ │ │ │ ├── advanced/ │ │ │ │ │ │ ├── advanced-tab.tsx │ │ │ │ │ │ ├── analytics-settings.tsx │ │ │ │ │ │ ├── export-import-settings.tsx │ │ │ │ │ │ ├── logger-settings.tsx │ │ │ │ │ │ └── styles-settings.tsx │ │ │ │ │ ├── general/ │ │ │ │ │ │ ├── application-settings.tsx │ │ │ │ │ │ ├── art-resolution-settings.tsx │ │ │ │ │ │ ├── artist-settings.tsx │ │ │ │ │ │ ├── control-settings.tsx │ │ │ │ │ │ ├── draggable-item.tsx │ │ │ │ │ │ ├── draggable-items.tsx │ │ │ │ │ │ ├── external-links-settings.tsx │ │ │ │ │ │ ├── fullscreen-player-settings.tsx │ │ │ │ │ │ ├── general-tab.tsx │ │ │ │ │ │ ├── home-settings.tsx │ │ │ │ │ │ ├── lyric-settings.tsx │ │ │ │ │ │ ├── path-settings.tsx │ │ │ │ │ │ ├── query-builder-settings.tsx │ │ │ │ │ │ ├── scrobble-settings.tsx │ │ │ │ │ │ ├── sidebar-reorder.tsx │ │ │ │ │ │ ├── sidebar-settings.tsx │ │ │ │ │ │ └── theme-settings.tsx │ │ │ │ │ ├── hotkeys/ │ │ │ │ │ │ ├── hotkey-manager-settings.tsx │ │ │ │ │ │ ├── hotkeys-manager-settings.module.css │ │ │ │ │ │ ├── hotkeys-tab.tsx │ │ │ │ │ │ ├── media-session-settings.tsx │ │ │ │ │ │ └── window-hotkey-settings.tsx │ │ │ │ │ ├── playback/ │ │ │ │ │ │ ├── audio-settings.tsx │ │ │ │ │ │ ├── auto-dj-settings.tsx │ │ │ │ │ │ ├── mpv-properties.ts │ │ │ │ │ │ ├── mpv-settings.tsx │ │ │ │ │ │ ├── playback-tab.tsx │ │ │ │ │ │ ├── player-filter-settings.tsx │ │ │ │ │ │ └── transcode-settings.tsx │ │ │ │ │ ├── settings-content.tsx │ │ │ │ │ ├── settings-header.tsx │ │ │ │ │ ├── settings-modal.tsx │ │ │ │ │ ├── settings-option.tsx │ │ │ │ │ ├── settings-section.tsx │ │ │ │ │ └── window/ │ │ │ │ │ ├── cache-settngs.tsx │ │ │ │ │ ├── discord-settings.tsx │ │ │ │ │ ├── password-settings.tsx │ │ │ │ │ ├── remote-settings.tsx │ │ │ │ │ ├── update-settings.tsx │ │ │ │ │ ├── window-settings.tsx │ │ │ │ │ └── window-tab.tsx │ │ │ │ ├── context/ │ │ │ │ │ └── search-context.tsx │ │ │ │ ├── restart-toast.ts │ │ │ │ ├── routes/ │ │ │ │ │ └── settings-route.tsx │ │ │ │ └── utils/ │ │ │ │ └── open-settings-modal.ts │ │ │ ├── shared/ │ │ │ │ ├── api/ │ │ │ │ │ └── shared-api.ts │ │ │ │ ├── components/ │ │ │ │ │ ├── animated-page.module.css │ │ │ │ │ ├── animated-page.tsx │ │ │ │ │ ├── component-error-boundary.tsx │ │ │ │ │ ├── display-type-toggle-button.tsx │ │ │ │ │ ├── filter-bar.module.css │ │ │ │ │ ├── filter-bar.tsx │ │ │ │ │ ├── filter-button.tsx │ │ │ │ │ ├── folder-button.tsx │ │ │ │ │ ├── grid-config.tsx │ │ │ │ │ ├── json-preview.module.css │ │ │ │ │ ├── json-preview.tsx │ │ │ │ │ ├── library-background-overlay.module.css │ │ │ │ │ ├── library-background-overlay.tsx │ │ │ │ │ ├── library-container.module.css │ │ │ │ │ ├── library-container.tsx │ │ │ │ │ ├── library-header-bar.module.css │ │ │ │ │ ├── library-header-bar.tsx │ │ │ │ │ ├── library-header.module.css │ │ │ │ │ ├── library-header.tsx │ │ │ │ │ ├── list-config-menu.tsx │ │ │ │ │ ├── list-display-type-toggle-button.tsx │ │ │ │ │ ├── list-filters.tsx │ │ │ │ │ ├── list-music-folder-dropdown.tsx │ │ │ │ │ ├── list-refresh-button.tsx │ │ │ │ │ ├── list-search-input.tsx │ │ │ │ │ ├── list-select-filter.tsx │ │ │ │ │ ├── list-sort-by-dropdown.tsx │ │ │ │ │ ├── list-sort-order-toggle-button.tsx │ │ │ │ │ ├── list-with-sidebar-container.module.css │ │ │ │ │ ├── list-with-sidebar-container.tsx │ │ │ │ │ ├── more-button.tsx │ │ │ │ │ ├── multi-select-rows.module.css │ │ │ │ │ ├── multi-select-rows.tsx │ │ │ │ │ ├── order-toggle-button.tsx │ │ │ │ │ ├── page-error-boundary.tsx │ │ │ │ │ ├── play-button-group.module.css │ │ │ │ │ ├── play-button-group.tsx │ │ │ │ │ ├── play-button.module.css │ │ │ │ │ ├── play-button.tsx │ │ │ │ │ ├── refresh-button.tsx │ │ │ │ │ ├── resize-handle.module.css │ │ │ │ │ ├── resize-handle.tsx │ │ │ │ │ ├── router-error-boundary.tsx │ │ │ │ │ ├── save-as-collection-button.module.css │ │ │ │ │ ├── save-as-collection-button.tsx │ │ │ │ │ ├── search-input.tsx │ │ │ │ │ ├── settings-button.tsx │ │ │ │ │ ├── table-config.module.css │ │ │ │ │ ├── table-config.tsx │ │ │ │ │ └── tag-filter.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-list-filter-persistence.ts │ │ │ │ │ ├── use-music-folder-id-filter.ts │ │ │ │ │ ├── use-play-button-click.ts │ │ │ │ │ ├── use-search-term-filter.ts │ │ │ │ │ ├── use-select-filter.ts │ │ │ │ │ ├── use-set-favorite.ts │ │ │ │ │ ├── use-set-rating.ts │ │ │ │ │ ├── use-sort-by-filter.ts │ │ │ │ │ └── use-sort-order-filter.ts │ │ │ │ ├── mutations/ │ │ │ │ │ ├── create-favorite-mutation.ts │ │ │ │ │ ├── delete-favorite-mutation.ts │ │ │ │ │ ├── favorite-optimistic-updates.ts │ │ │ │ │ ├── rating-optimistic-updates.ts │ │ │ │ │ └── set-rating-mutation.ts │ │ │ │ └── utils.ts │ │ │ ├── sharing/ │ │ │ │ ├── components/ │ │ │ │ │ └── share-item-context-modal.tsx │ │ │ │ └── mutations/ │ │ │ │ └── share-item-mutation.ts │ │ │ ├── sidebar/ │ │ │ │ └── components/ │ │ │ │ ├── action-bar.module.css │ │ │ │ ├── action-bar.tsx │ │ │ │ ├── collapsed-sidebar-button.module.css │ │ │ │ ├── collapsed-sidebar-button.tsx │ │ │ │ ├── collapsed-sidebar-item.module.css │ │ │ │ ├── collapsed-sidebar-item.tsx │ │ │ │ ├── collapsed-sidebar.module.css │ │ │ │ ├── collapsed-sidebar.tsx │ │ │ │ ├── mobile-sidebar.module.css │ │ │ │ ├── mobile-sidebar.tsx │ │ │ │ ├── server-selector-items.tsx │ │ │ │ ├── server-selector.module.css │ │ │ │ ├── server-selector.tsx │ │ │ │ ├── sidebar-collection-list.module.css │ │ │ │ ├── sidebar-collection-list.tsx │ │ │ │ ├── sidebar-icon.module.css │ │ │ │ ├── sidebar-icon.tsx │ │ │ │ ├── sidebar-item.module.css │ │ │ │ ├── sidebar-item.tsx │ │ │ │ ├── sidebar-playlist-list.module.css │ │ │ │ ├── sidebar-playlist-list.tsx │ │ │ │ ├── sidebar.module.css │ │ │ │ └── sidebar.tsx │ │ │ ├── similar-songs/ │ │ │ │ └── components/ │ │ │ │ └── similar-songs-list.tsx │ │ │ ├── songs/ │ │ │ │ ├── api/ │ │ │ │ │ └── songs-api.ts │ │ │ │ ├── components/ │ │ │ │ │ ├── jellyfin-song-filters.tsx │ │ │ │ │ ├── navidrome-song-filters.tsx │ │ │ │ │ ├── song-infinite-carousel.tsx │ │ │ │ │ ├── song-list-content.tsx │ │ │ │ │ ├── song-list-header-filters.tsx │ │ │ │ │ ├── song-list-header.tsx │ │ │ │ │ ├── song-list-infinite-grid.tsx │ │ │ │ │ ├── song-list-infinite-table.tsx │ │ │ │ │ ├── song-list-paginated-grid.tsx │ │ │ │ │ ├── song-list-paginated-table.tsx │ │ │ │ │ └── subsonic-song-filters.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ └── use-song-list-filters.ts │ │ │ │ └── routes/ │ │ │ │ └── song-list-route.tsx │ │ │ ├── titlebar/ │ │ │ │ └── components/ │ │ │ │ ├── app-menu.tsx │ │ │ │ ├── titlebar.module.css │ │ │ │ └── titlebar.tsx │ │ │ ├── visualizer/ │ │ │ │ └── components/ │ │ │ │ ├── audiomotionanalyzer/ │ │ │ │ │ ├── presets.ts │ │ │ │ │ ├── visualizer-settings-form.module.css │ │ │ │ │ ├── visualizer-settings-form.tsx │ │ │ │ │ ├── visualizer-settings-modal.tsx │ │ │ │ │ ├── visualizer.module.css │ │ │ │ │ └── visualizer.tsx │ │ │ │ └── butternchurn/ │ │ │ │ ├── butterchurn.d.ts │ │ │ │ ├── visualizer.module.css │ │ │ │ └── visualizer.tsx │ │ │ └── window-controls/ │ │ │ └── components/ │ │ │ ├── window-controls.module.css │ │ │ └── window-controls.tsx │ │ ├── global.d.ts │ │ ├── hooks/ │ │ │ ├── index.ts │ │ │ ├── use-app-focus.ts │ │ │ ├── use-check-for-updates.ts │ │ │ ├── use-container-query.ts │ │ │ ├── use-drag-drop.tsx │ │ │ ├── use-fast-average-color.tsx │ │ │ ├── use-garbage-collection.ts │ │ │ ├── use-genre-route.ts │ │ │ ├── use-hide-scrollbar.ts │ │ │ ├── use-is-mobile.ts │ │ │ ├── use-is-mounted.ts │ │ │ ├── use-server-authenticated.ts │ │ │ ├── use-should-pad-titlebar.tsx │ │ │ └── use-sync-settings-to-main.ts │ │ ├── index.html │ │ ├── layouts/ │ │ │ ├── auth-layout.module.css │ │ │ ├── auth-layout.tsx │ │ │ ├── authentication-outlet.tsx │ │ │ ├── default-layout/ │ │ │ │ ├── full-screen-overlay.tsx │ │ │ │ ├── full-screen-visualizer-overlay.tsx │ │ │ │ ├── left-sidebar.module.css │ │ │ │ ├── left-sidebar.tsx │ │ │ │ ├── main-content.module.css │ │ │ │ ├── main-content.tsx │ │ │ │ ├── player-bar.module.css │ │ │ │ ├── player-bar.tsx │ │ │ │ ├── right-sidebar.module.css │ │ │ │ ├── right-sidebar.tsx │ │ │ │ ├── side-drawer-queue.module.css │ │ │ │ └── side-drawer-queue.tsx │ │ │ ├── default-layout.module.css │ │ │ ├── default-layout.tsx │ │ │ ├── mobile-layout/ │ │ │ │ ├── mobile-layout.module.css │ │ │ │ └── mobile-layout.tsx │ │ │ ├── responsive-layout.tsx │ │ │ ├── window-bar.module.css │ │ │ └── window-bar.tsx │ │ ├── lib/ │ │ │ ├── react-query.ts │ │ │ └── zustand.ts │ │ ├── main.tsx │ │ ├── release-notes-modal.tsx │ │ ├── router/ │ │ │ ├── app-outlet.tsx │ │ │ ├── app-router.tsx │ │ │ ├── routes.ts │ │ │ ├── titlebar-outlet.module.css │ │ │ └── titlebar-outlet.tsx │ │ ├── store/ │ │ │ ├── app.store.ts │ │ │ ├── auth.store.ts │ │ │ ├── env-settings-overrides.ts │ │ │ ├── full-screen-player.store.ts │ │ │ ├── index.ts │ │ │ ├── player.store.ts │ │ │ ├── scroll.store.ts │ │ │ ├── settings.store.ts │ │ │ ├── sleep-timer.store.ts │ │ │ ├── timestamp.store.ts │ │ │ └── utils.ts │ │ ├── styles/ │ │ │ ├── helpers.ts │ │ │ └── overlayscrollbars.css │ │ ├── themes/ │ │ │ ├── mantine-theme.tsx │ │ │ └── use-app-theme.ts │ │ ├── types/ │ │ │ ├── emotion.d.ts │ │ │ └── fonts.ts │ │ ├── update-available-dialog.tsx │ │ └── utils/ │ │ ├── constrain-sidebar-width.ts │ │ ├── format.tsx │ │ ├── get-header-color.ts │ │ ├── index.ts │ │ ├── linkify.tsx │ │ ├── logger-message.ts │ │ ├── logger.ts │ │ ├── normalize-release-types.tsx │ │ ├── normalize-server-url.ts │ │ ├── parse-search-params.ts │ │ ├── query-params.ts │ │ ├── random-string.ts │ │ ├── rgb-to-rgba.ts │ │ ├── sanitize.ts │ │ ├── sentence-case.ts │ │ ├── set-local-storage-setttings.ts │ │ ├── shuffle.ts │ │ ├── title-case.ts │ │ └── truncate-middle.ts │ ├── shared/ │ │ ├── api/ │ │ │ ├── jellyfin/ │ │ │ │ ├── jellyfin-normalize.ts │ │ │ │ └── jellyfin-types.ts │ │ │ ├── navidrome/ │ │ │ │ ├── navidrome-normalize.ts │ │ │ │ └── navidrome-types.ts │ │ │ ├── subsonic/ │ │ │ │ ├── subsonic-normalize.ts │ │ │ │ └── subsonic-types.ts │ │ │ └── utils.ts │ │ ├── assets.d.ts │ │ ├── components/ │ │ │ ├── accordion/ │ │ │ │ ├── accordion.module.css │ │ │ │ └── accordion.tsx │ │ │ ├── action-icon/ │ │ │ │ ├── action-icon.module.css │ │ │ │ └── action-icon.tsx │ │ │ ├── angle-slider/ │ │ │ │ └── angle-slider.tsx │ │ │ ├── animations/ │ │ │ │ ├── animation-props.ts │ │ │ │ └── animation-variants.ts │ │ │ ├── badge/ │ │ │ │ ├── badge.module.css │ │ │ │ └── badge.tsx │ │ │ ├── box/ │ │ │ │ └── box.tsx │ │ │ ├── breadcrumb/ │ │ │ │ └── breadcrumb.tsx │ │ │ ├── button/ │ │ │ │ ├── button.module.css │ │ │ │ └── button.tsx │ │ │ ├── center/ │ │ │ │ └── center.tsx │ │ │ ├── checkbox/ │ │ │ │ ├── checkbox.module.css │ │ │ │ └── checkbox.tsx │ │ │ ├── checkbox-select/ │ │ │ │ ├── checkbox-select.module.css │ │ │ │ └── checkbox-select.tsx │ │ │ ├── code/ │ │ │ │ ├── code.module.css │ │ │ │ └── code.tsx │ │ │ ├── color-input/ │ │ │ │ ├── color-input.module.css │ │ │ │ └── color-input.tsx │ │ │ ├── context-menu/ │ │ │ │ ├── context-menu.module.css │ │ │ │ └── context-menu.tsx │ │ │ ├── copy-button/ │ │ │ │ └── copy-button.tsx │ │ │ ├── date-picker/ │ │ │ │ ├── date-picker.module.css │ │ │ │ └── date-picker.tsx │ │ │ ├── date-time-picker/ │ │ │ │ ├── date-time-picker.module.css │ │ │ │ └── date-time-picker.tsx │ │ │ ├── dialog/ │ │ │ │ ├── dialog.module.css │ │ │ │ └── dialog.tsx │ │ │ ├── divider/ │ │ │ │ ├── divider.module.css │ │ │ │ └── divider.tsx │ │ │ ├── drag-drop-zone/ │ │ │ │ └── drag-drop-zone.tsx │ │ │ ├── drawer/ │ │ │ │ └── drawer.tsx │ │ │ ├── dropdown-menu/ │ │ │ │ ├── dropdown-menu.module.css │ │ │ │ └── dropdown-menu.tsx │ │ │ ├── explicit-indicator/ │ │ │ │ ├── explicit-indicator.module.css │ │ │ │ └── explicit-indicator.tsx │ │ │ ├── fieldset/ │ │ │ │ ├── fieldset.module.css │ │ │ │ └── fieldset.tsx │ │ │ ├── file-input/ │ │ │ │ ├── file-input.module.css │ │ │ │ └── file-input.tsx │ │ │ ├── flex/ │ │ │ │ └── flex.tsx │ │ │ ├── grid/ │ │ │ │ └── grid.tsx │ │ │ ├── group/ │ │ │ │ └── group.tsx │ │ │ ├── hover-card/ │ │ │ │ ├── hover-card.module.css │ │ │ │ └── hover-card.tsx │ │ │ ├── icon/ │ │ │ │ ├── icon.module.css │ │ │ │ └── icon.tsx │ │ │ ├── image/ │ │ │ │ ├── image.module.css │ │ │ │ ├── image.tsx │ │ │ │ └── use-native-image.ts │ │ │ ├── json-input/ │ │ │ │ ├── json-input.module.css │ │ │ │ └── json-input.tsx │ │ │ ├── kbd/ │ │ │ │ └── kbd.tsx │ │ │ ├── loading-overlay/ │ │ │ │ └── loading-overlay.tsx │ │ │ ├── modal/ │ │ │ │ ├── modal.module.css │ │ │ │ ├── modal.tsx │ │ │ │ └── model-shared.tsx │ │ │ ├── multi-select/ │ │ │ │ ├── multi-select.module.css │ │ │ │ ├── multi-select.tsx │ │ │ │ ├── virtual-multi-select.module.css │ │ │ │ └── virtual-multi-select.tsx │ │ │ ├── number-input/ │ │ │ │ ├── number-input.module.css │ │ │ │ └── number-input.tsx │ │ │ ├── option/ │ │ │ │ ├── option.module.css │ │ │ │ └── option.tsx │ │ │ ├── pagination/ │ │ │ │ ├── pagination.module.css │ │ │ │ └── pagination.tsx │ │ │ ├── paper/ │ │ │ │ ├── paper.module.css │ │ │ │ └── paper.tsx │ │ │ ├── password-input/ │ │ │ │ ├── password-input.module.css │ │ │ │ └── password-input.tsx │ │ │ ├── pill/ │ │ │ │ ├── pill.module.css │ │ │ │ └── pill.tsx │ │ │ ├── popover/ │ │ │ │ ├── popover.module.css │ │ │ │ └── popover.tsx │ │ │ ├── portal/ │ │ │ │ └── portal.tsx │ │ │ ├── rating/ │ │ │ │ ├── rating.module.css │ │ │ │ └── rating.tsx │ │ │ ├── read-only-rating/ │ │ │ │ ├── read-only-rating.module.css │ │ │ │ └── read-only-rating.tsx │ │ │ ├── scroll-area/ │ │ │ │ ├── scroll-area.css │ │ │ │ ├── scroll-area.module.css │ │ │ │ └── scroll-area.tsx │ │ │ ├── segmented-control/ │ │ │ │ ├── segmented-control.module.css │ │ │ │ └── segmented-control.tsx │ │ │ ├── select/ │ │ │ │ ├── select.module.css │ │ │ │ └── select.tsx │ │ │ ├── separator/ │ │ │ │ ├── separator.module.css │ │ │ │ └── separator.tsx │ │ │ ├── skeleton/ │ │ │ │ ├── skeleton.module.css │ │ │ │ └── skeleton.tsx │ │ │ ├── slider/ │ │ │ │ ├── slider.module.css │ │ │ │ └── slider.tsx │ │ │ ├── spinner/ │ │ │ │ ├── spinner.module.css │ │ │ │ └── spinner.tsx │ │ │ ├── spoiler/ │ │ │ │ ├── spoiler.module.css │ │ │ │ └── spoiler.tsx │ │ │ ├── stack/ │ │ │ │ └── stack.tsx │ │ │ ├── switch/ │ │ │ │ ├── switch.module.css │ │ │ │ └── switch.tsx │ │ │ ├── table/ │ │ │ │ ├── table.module.css │ │ │ │ └── table.tsx │ │ │ ├── tabs/ │ │ │ │ ├── tabs.module.css │ │ │ │ └── tabs.tsx │ │ │ ├── text/ │ │ │ │ ├── text.module.css │ │ │ │ └── text.tsx │ │ │ ├── text-input/ │ │ │ │ ├── text-input.module.css │ │ │ │ └── text-input.tsx │ │ │ ├── text-title/ │ │ │ │ ├── text-title.module.css │ │ │ │ └── text-title.tsx │ │ │ ├── textarea/ │ │ │ │ ├── textarea.module.css │ │ │ │ └── textarea.tsx │ │ │ ├── toast/ │ │ │ │ ├── toast.module.css │ │ │ │ └── toast.tsx │ │ │ ├── tooltip/ │ │ │ │ ├── tooltip.module.css │ │ │ │ └── tooltip.tsx │ │ │ └── yes-no-select/ │ │ │ └── yes-no-select.tsx │ │ ├── constants/ │ │ │ └── playback-selectors.ts │ │ ├── hooks/ │ │ │ ├── use-click-outside.ts │ │ │ ├── use-container-query.ts │ │ │ ├── use-debounced-callback.ts │ │ │ ├── use-debounced-state.ts │ │ │ ├── use-debounced-value.ts │ │ │ ├── use-disclosure.ts │ │ │ ├── use-double-click.ts │ │ │ ├── use-element-size.ts │ │ │ ├── use-focus-trap.ts │ │ │ ├── use-focus-within.ts │ │ │ ├── use-form.ts │ │ │ ├── use-hotkeys.ts │ │ │ ├── use-in-viewport.ts │ │ │ ├── use-intersection.ts │ │ │ ├── use-is-overflow.ts │ │ │ ├── use-local-storage.ts │ │ │ ├── use-long-press.ts │ │ │ ├── use-media-query.ts │ │ │ ├── use-merged-ref.ts │ │ │ ├── use-session-storage.ts │ │ │ ├── use-set-state.ts │ │ │ ├── use-throttled-callback.ts │ │ │ ├── use-throttled-value.ts │ │ │ └── use-timeout.ts │ │ ├── styles/ │ │ │ ├── ag-grid.css │ │ │ └── global.css │ │ ├── themes/ │ │ │ ├── app-theme-types.ts │ │ │ ├── app-theme.ts │ │ │ ├── ayu-dark/ │ │ │ │ └── ayu-dark.ts │ │ │ ├── ayu-light/ │ │ │ │ └── ayu-light.ts │ │ │ ├── catppuccin-latte/ │ │ │ │ └── catppuccin-latte.ts │ │ │ ├── catppuccin-mocha/ │ │ │ │ └── catppuccin-mocha.ts │ │ │ ├── default-dark/ │ │ │ │ └── default-dark.ts │ │ │ ├── default-light/ │ │ │ │ └── default-light.ts │ │ │ ├── default.ts │ │ │ ├── dracula/ │ │ │ │ └── dracula.ts │ │ │ ├── github-dark/ │ │ │ │ └── github-dark.ts │ │ │ ├── github-light/ │ │ │ │ └── github-light.ts │ │ │ ├── glassy-dark/ │ │ │ │ ├── glassy-dark.ts │ │ │ │ └── glassy_overrides.css │ │ │ ├── gruvbox-dark/ │ │ │ │ └── gruvbox-dark.ts │ │ │ ├── gruvbox-light/ │ │ │ │ └── gruvbox-light.ts │ │ │ ├── high-contrast-dark/ │ │ │ │ └── high-contrast-dark.ts │ │ │ ├── high-contrast-light/ │ │ │ │ └── high-contrast-light.ts │ │ │ ├── material-dark/ │ │ │ │ └── material-dark.ts │ │ │ ├── material-light/ │ │ │ │ └── material-light.ts │ │ │ ├── monokai/ │ │ │ │ └── monokai.ts │ │ │ ├── night-owl/ │ │ │ │ └── night-owl.ts │ │ │ ├── nord/ │ │ │ │ └── nord.ts │ │ │ ├── one-dark/ │ │ │ │ └── one-dark.ts │ │ │ ├── rose-pine/ │ │ │ │ └── rose-pine.ts │ │ │ ├── rose-pine-dawn/ │ │ │ │ └── rose-pine-dawn.ts │ │ │ ├── rose-pine-moon/ │ │ │ │ └── rose-pine-moon.ts │ │ │ ├── shades-of-purple/ │ │ │ │ └── shades-of-purple.ts │ │ │ ├── solarized-dark/ │ │ │ │ └── solarized-dark.ts │ │ │ ├── solarized-light/ │ │ │ │ └── solarized-light.ts │ │ │ ├── tokyo-night/ │ │ │ │ └── tokyo-night.ts │ │ │ ├── vscode-dark-plus/ │ │ │ │ └── vscode-dark-plus.ts │ │ │ └── vscode-light-plus/ │ │ │ └── vscode-light-plus.ts │ │ ├── types/ │ │ │ ├── css-modules.d.ts │ │ │ ├── domain-types.ts │ │ │ ├── drag-and-drop.ts │ │ │ ├── features-types.ts │ │ │ ├── remote-types.ts │ │ │ └── types.ts │ │ └── utils/ │ │ ├── create-polymorphic-component.ts │ │ ├── create-use-external-events.ts │ │ ├── double-click-handler.ts │ │ ├── is-light-color.ts │ │ └── string-to-color.ts │ └── types/ │ ├── mantine.d.ts │ └── mpris-service.d.ts ├── tsconfig.json ├── tsconfig.node.json ├── tsconfig.web.json └── web.vite.config.ts