mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 06:25:41 +00:00
refactor(utils): group utils/ files into topic folders (Phase L, part 1) (#689)
111 of 122 top-level src/utils/ files move into 16 topic folders (audio, cache, cover, share, server, playback, playlist, deviceSync, waveform, mix, format, export, changelog, ui, perf, componentHelpers). True singletons with no cluster stay at the utils/ root. Pure file-move: a path-aware codemod rewrote 539 relative-import specifiers across 275 files; no logic touched. The hot-path coverage gate list (.github/frontend-hot-path-files.txt) is updated to the new paths for the 11 gated utils files — a mechanical consequence of the move, not a CI change. tsc is green.
This commit is contained in:
committed by
GitHub
parent
2409a1fec8
commit
7a7a9f5e6b
@@ -2,7 +2,7 @@ import { buildCoverArtUrl, coverArtCacheKey, buildDownloadUrl } from '../api/sub
|
||||
import { setRating, star, unstar } from '../api/subsonicStarRating';
|
||||
import { getArtistInfo } from '../api/subsonicArtists';
|
||||
import type { SubsonicSong } from '../api/subsonicTypes';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import React, { useEffect, useState, useCallback, useMemo } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
@@ -22,9 +22,9 @@ import AlbumTrackList from '../components/AlbumTrackList';
|
||||
import { AlbumDetailToolbar } from '../components/albumDetail/AlbumDetailToolbar';
|
||||
import { useCachedUrl } from '../components/CachedImage';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import { useSelectionStore } from '../store/selectionStore';
|
||||
import { sanitizeFilename } from '../utils/albumDetailHelpers';
|
||||
import { sanitizeFilename } from '../utils/componentHelpers/albumDetailHelpers';
|
||||
|
||||
export default function AlbumDetail() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -2,7 +2,7 @@ import { buildDownloadUrl } from '../api/subsonicStreamUrl';
|
||||
import { getAlbumsByGenre } from '../api/subsonicGenres';
|
||||
import { getAlbumList, getAlbum } from '../api/subsonicLibrary';
|
||||
import type { SubsonicAlbum } from '../api/subsonicTypes';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import React, { useState, useEffect, useRef, useCallback, useMemo, useLayoutEffect } from 'react';
|
||||
import AlbumCard from '../components/AlbumCard';
|
||||
import GenreFilterBar from '../components/GenreFilterBar';
|
||||
@@ -16,13 +16,13 @@ import { useDownloadModalStore } from '../store/downloadModalStore';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { join } from '@tauri-apps/api/path';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import { useZipDownloadStore } from '../store/zipDownloadStore';
|
||||
import { CheckSquare2, Download, HardDriveDownload, ListMusic, Disc3, ListPlus } from 'lucide-react';
|
||||
import { useVirtualizer } from '@tanstack/react-virtual';
|
||||
import { APP_MAIN_SCROLL_VIEWPORT_ID } from '../constants/appScroll';
|
||||
import { useElementClientHeightById } from '../hooks/useResizeClientHeight';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
||||
import { useRangeSelection } from '../hooks/useRangeSelection';
|
||||
|
||||
const ALBUM_GRID_GAP_PX = 16; // matches --space-4
|
||||
|
||||
@@ -3,7 +3,7 @@ import { buildCoverArtUrl, coverArtCacheKey } from '../api/subsonicStreamUrl';
|
||||
import { setRating, star, unstar } from '../api/subsonicStarRating';
|
||||
import { getAlbum } from '../api/subsonicLibrary';
|
||||
import type { SubsonicArtist, SubsonicAlbum, SubsonicSong, SubsonicArtistInfo } from '../api/subsonicTypes';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import { useEffect, useState, useRef, Fragment, useMemo } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import AlbumCard from '../components/AlbumCard';
|
||||
@@ -22,21 +22,21 @@ import { useTranslation } from 'react-i18next';
|
||||
import { lastfmIsConfigured } from '../api/lastfm';
|
||||
import LastfmIcon from '../components/LastfmIcon';
|
||||
import { invalidateCoverArt } from '../utils/imageCache';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { copyEntityShareLink } from '../utils/copyEntityShareLink';
|
||||
import { extractCoverColors } from '../utils/dynamicColors';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import { copyEntityShareLink } from '../utils/share/copyEntityShareLink';
|
||||
import { extractCoverColors } from '../utils/ui/dynamicColors';
|
||||
import StarRating from '../components/StarRating';
|
||||
import { useArtistLayoutStore, type ArtistSectionId } from '../store/artistLayoutStore';
|
||||
|
||||
import { sanitizeHtml } from '../utils/artistDetailHelpers';
|
||||
import { sanitizeHtml } from '../utils/componentHelpers/artistDetailHelpers';
|
||||
import { useArtistDetailData } from '../hooks/useArtistDetailData';
|
||||
import { useArtistSimilarArtists } from '../hooks/useArtistSimilarArtists';
|
||||
import {
|
||||
runArtistDetailPlayAll, runArtistDetailShuffle, runArtistDetailStartRadio,
|
||||
} from '../utils/runArtistDetailPlay';
|
||||
} from '../utils/componentHelpers/runArtistDetailPlay';
|
||||
import {
|
||||
runArtistEntityRating, runArtistToggleStar, runArtistShare, runArtistImageUpload,
|
||||
} from '../utils/runArtistDetailActions';
|
||||
} from '../utils/componentHelpers/runArtistDetailActions';
|
||||
import ArtistDetailHero from '../components/artistDetail/ArtistDetailHero';
|
||||
import ArtistDetailTopTracks from '../components/artistDetail/ArtistDetailTopTracks';
|
||||
import ArtistDetailSimilarArtists from '../components/artistDetail/ArtistDetailSimilarArtists';
|
||||
|
||||
@@ -10,14 +10,14 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useVirtualizer } from '@tanstack/react-virtual';
|
||||
import { APP_MAIN_SCROLL_VIEWPORT_ID } from '../constants/appScroll';
|
||||
import { useElementClientHeightById } from '../hooks/useResizeClientHeight';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
||||
import {
|
||||
ALL_SENTINEL,
|
||||
ALPHABET,
|
||||
ARTIST_LIST_LAST_IN_LETTER_EST,
|
||||
ARTIST_LIST_LETTER_ROW_EST,
|
||||
ARTIST_LIST_ROW_EST,
|
||||
} from '../utils/artistsHelpers';
|
||||
} from '../utils/componentHelpers/artistsHelpers';
|
||||
import { useArtistsFiltering } from '../hooks/useArtistsFiltering';
|
||||
import { useArtistsInfiniteScroll } from '../hooks/useArtistsInfiniteScroll';
|
||||
import { ArtistsGridView } from '../components/artists/ArtistsGridView';
|
||||
|
||||
@@ -13,8 +13,8 @@ import { open } from '@tauri-apps/plugin-shell';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { copyEntityShareLink } from '../utils/copyEntityShareLink';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { copyEntityShareLink } from '../utils/share/copyEntityShareLink';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
|
||||
/** Strip dangerous tags/attributes from server-provided HTML. Mirrors the
|
||||
* ArtistDetail sanitiser — kept inline because it's a 10-liner not worth a
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useVirtualizer } from '@tanstack/react-virtual';
|
||||
import { APP_MAIN_SCROLL_VIEWPORT_ID } from '../constants/appScroll';
|
||||
import { useElementClientHeightById } from '../hooks/useResizeClientHeight';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
||||
|
||||
const ALL_SENTINEL = 'ALL';
|
||||
const ALPHABET = [ALL_SENTINEL, '#', ...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')];
|
||||
|
||||
@@ -10,13 +10,13 @@ import CustomSelect from '../components/CustomSelect';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDeviceSyncStore, DeviceSyncSource } from '../store/deviceSyncStore';
|
||||
import { useDeviceSyncJobStore } from '../store/deviceSyncJobStore';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import { IS_WINDOWS } from '../utils/platform';
|
||||
|
||||
import {
|
||||
formatBytes,
|
||||
type SourceTab,
|
||||
} from '../utils/deviceSyncHelpers';
|
||||
} from '../utils/deviceSync/deviceSyncHelpers';
|
||||
import { useDeviceSyncDrives } from '../hooks/useDeviceSyncDrives';
|
||||
import { useDeviceSyncSourceStatuses } from '../hooks/useDeviceSyncSourceStatuses';
|
||||
import { useDeviceSyncBrowser } from '../hooks/useDeviceSyncBrowser';
|
||||
@@ -26,13 +26,13 @@ import {
|
||||
runDeviceSyncMigrationPreview,
|
||||
runDeviceSyncMigrationExecute,
|
||||
type MigrationPhase, type MigrationPair, type MigrationResult,
|
||||
} from '../utils/runDeviceSyncMigration';
|
||||
} from '../utils/deviceSync/runDeviceSyncMigration';
|
||||
import {
|
||||
runDeviceSyncSummaryPrompt,
|
||||
runDeviceSyncExecute,
|
||||
type SyncDelta,
|
||||
} from '../utils/runDeviceSyncExecution';
|
||||
import { runDeviceSyncChooseFolder } from '../utils/runDeviceSyncChooseFolder';
|
||||
} from '../utils/deviceSync/runDeviceSyncExecution';
|
||||
import { runDeviceSyncChooseFolder } from '../utils/deviceSync/runDeviceSyncChooseFolder';
|
||||
import DeviceSyncHeader from '../components/deviceSync/DeviceSyncHeader';
|
||||
import DeviceSyncPreSyncModal from '../components/deviceSync/DeviceSyncPreSyncModal';
|
||||
import DeviceSyncMigrationModal from '../components/deviceSync/DeviceSyncMigrationModal';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { setRating, unstar } from '../api/subsonicStarRating';
|
||||
import type { SubsonicAlbum, SubsonicArtist, SubsonicSong, InternetRadioStation } from '../api/subsonicTypes';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useTracklistColumns, type ColDef } from '../utils/useTracklistColumns';
|
||||
import { TopFavoriteArtistsRow } from '../components/favorites/TopFavoriteArtists';
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
entryToAlbumIfPresent, entryToTrack,
|
||||
type Column, type ColumnKind, type NavPos,
|
||||
} from '../utils/folderBrowserHelpers';
|
||||
} from '../utils/componentHelpers/folderBrowserHelpers';
|
||||
import FolderBrowserColumn from '../components/folderBrowser/FolderBrowserColumn';
|
||||
import { useFolderBrowserNowPlayingPath } from '../hooks/useFolderBrowserNowPlayingPath';
|
||||
import { useFolderBrowserScrolling } from '../hooks/useFolderBrowserScrolling';
|
||||
|
||||
+3
-3
@@ -12,9 +12,9 @@ import { NavLink, useNavigate } from 'react-router-dom';
|
||||
import { ChevronRight } from 'lucide-react';
|
||||
import { useHomeStore } from '../store/homeStore';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { filterAlbumsByMixRatings, getMixMinRatingsConfigFromAuth } from '../utils/mixRatingFilter';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
import { bumpPerfCounter } from '../utils/perfTelemetry';
|
||||
import { filterAlbumsByMixRatings, getMixMinRatingsConfigFromAuth } from '../utils/mix/mixRatingFilter';
|
||||
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
||||
import { bumpPerfCounter } from '../utils/perf/perfTelemetry';
|
||||
import { dedupeById } from '../utils/dedupeById';
|
||||
|
||||
/** Match Random Albums overshoot when mix filter uses album/artist axes so hero + discover row can still fill. */
|
||||
|
||||
@@ -11,7 +11,7 @@ import { invalidateCoverArt } from '../utils/imageCache';
|
||||
import CustomSelect from '../components/CustomSelect';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { open } from '@tauri-apps/plugin-shell';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import RadioToolbar, { type RadioSortBy } from '../components/internetRadio/RadioToolbar';
|
||||
import AlphabetFilterBar from '../components/internetRadio/AlphabetFilterBar';
|
||||
import RadioCard from '../components/internetRadio/RadioCard';
|
||||
|
||||
+2
-2
@@ -11,8 +11,8 @@ import {
|
||||
DECODED_PASSWORD_VISUAL_MASK,
|
||||
encodeServerMagicString,
|
||||
type ServerMagicPayload,
|
||||
} from '../utils/serverMagicString';
|
||||
import { shortHostFromServerUrl, serverListDisplayLabel } from '../utils/serverDisplayName';
|
||||
} from '../utils/server/serverMagicString';
|
||||
import { shortHostFromServerUrl, serverListDisplayLabel } from '../utils/server/serverDisplayName';
|
||||
|
||||
const PsysonicLogo = () => (
|
||||
<img src="/logo-psysonic.png" width="64" height="64" alt="Psysonic" style={{ borderRadius: 18 }} />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { buildDownloadUrl } from '../api/subsonicStreamUrl';
|
||||
import { getAlbum } from '../api/subsonicLibrary';
|
||||
import type { SubsonicAlbum } from '../api/subsonicTypes';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import AlbumCard from '../components/AlbumCard';
|
||||
import { ndListLosslessAlbumsPage } from '../api/navidromeBrowse';
|
||||
@@ -12,8 +12,8 @@ import { useDownloadModalStore } from '../store/downloadModalStore';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
import { useZipDownloadStore } from '../store/zipDownloadStore';
|
||||
import { useRangeSelection } from '../hooks/useRangeSelection';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { join } from '@tauri-apps/api/path';
|
||||
import { CheckSquare2, Download, HardDriveDownload, ListPlus } from 'lucide-react';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { buildAndPlayLuckyMix } from '../utils/luckyMix';
|
||||
import { buildAndPlayLuckyMix } from '../utils/mix/luckyMix';
|
||||
|
||||
export default function LuckyMixPage() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { buildCoverArtUrl, coverArtCacheKey } from '../api/subsonicStreamUrl';
|
||||
import { getAlbumList, getAlbum } from '../api/subsonicLibrary';
|
||||
import type { SubsonicAlbum } from '../api/subsonicTypes';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import React, { useEffect, useState, useCallback, useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { ArrowUpDown, ArrowDown, ArrowUp, TrendingUp, UsersRound, Play, ListPlus } from 'lucide-react';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
import CachedImage from '../components/CachedImage';
|
||||
import { playAlbum } from '../utils/playAlbum';
|
||||
import { playAlbum } from '../utils/playback/playAlbum';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const PAGE_SIZE = 50;
|
||||
|
||||
@@ -13,7 +13,7 @@ import { useDownloadModalStore } from '../store/downloadModalStore';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { join } from '@tauri-apps/api/path';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import { useZipDownloadStore } from '../store/zipDownloadStore';
|
||||
import { useRangeSelection } from '../hooks/useRangeSelection';
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { open as shellOpen } from '@tauri-apps/plugin-shell';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { useLyricsStore } from '../store/lyricsStore';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import { useCachedUrl } from '../components/CachedImage';
|
||||
import CachedImage from '../components/CachedImage';
|
||||
import { useRadioMetadata } from '../hooks/useRadioMetadata';
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
formatTime, formatCompact, isoToParts,
|
||||
buildContributorRows,
|
||||
type ContributorRow,
|
||||
} from '../utils/nowPlayingHelpers';
|
||||
} from '../utils/componentHelpers/nowPlayingHelpers';
|
||||
import NpCardWrap from '../components/nowPlaying/NpCardWrap';
|
||||
import NpColumnEl from '../components/nowPlaying/NpColumnEl';
|
||||
import RadioView from '../components/nowPlaying/RadioView';
|
||||
|
||||
@@ -26,9 +26,9 @@ import {
|
||||
isSmartPlaylistName,
|
||||
displayPlaylistName,
|
||||
codecLabel,
|
||||
} from '../utils/playlistDetailHelpers';
|
||||
import type { SpotifyCsvTrack } from '../utils/spotifyCsvImport';
|
||||
import { runPlaylistCsvImport } from '../utils/runPlaylistCsvImport';
|
||||
} from '../utils/componentHelpers/playlistDetailHelpers';
|
||||
import type { SpotifyCsvTrack } from '../utils/playlist/spotifyCsvImport';
|
||||
import { runPlaylistCsvImport } from '../utils/playlist/runPlaylistCsvImport';
|
||||
import PlaylistEditModal from '../components/playlist/PlaylistEditModal';
|
||||
import CsvImportReportModal from '../components/playlist/CsvImportReportModal';
|
||||
import PlaylistSongSearchPanel from '../components/playlist/PlaylistSongSearchPanel';
|
||||
@@ -36,11 +36,11 @@ import PlaylistSuggestions from '../components/playlist/PlaylistSuggestions';
|
||||
import PlaylistHero from '../components/playlist/PlaylistHero';
|
||||
import PlaylistTracklist from '../components/playlist/PlaylistTracklist';
|
||||
import PlaylistFilterToolbar from '../components/playlist/PlaylistFilterToolbar';
|
||||
import type { PlaylistSortKey, PlaylistSortDir } from '../utils/playlistDisplayedSongs';
|
||||
import { runPlaylistZipDownload } from '../utils/runPlaylistZipDownload';
|
||||
import { runPlaylistSaveMeta } from '../utils/runPlaylistSaveMeta';
|
||||
import { runPlaylistLoad } from '../utils/runPlaylistLoad';
|
||||
import { startPlaylistRowDrag } from '../utils/startPlaylistRowDrag';
|
||||
import type { PlaylistSortKey, PlaylistSortDir } from '../utils/playlist/playlistDisplayedSongs';
|
||||
import { runPlaylistZipDownload } from '../utils/playlist/runPlaylistZipDownload';
|
||||
import { runPlaylistSaveMeta } from '../utils/playlist/runPlaylistSaveMeta';
|
||||
import { runPlaylistLoad } from '../utils/playlist/runPlaylistLoad';
|
||||
import { startPlaylistRowDrag } from '../utils/playlist/startPlaylistRowDrag';
|
||||
import { usePlaylistCovers } from '../hooks/usePlaylistCovers';
|
||||
import { usePlaylistSelection } from '../hooks/usePlaylistSelection';
|
||||
import { usePlaylistSuggestions } from '../hooks/usePlaylistSuggestions';
|
||||
|
||||
@@ -2,7 +2,7 @@ import { getPlaylist } from '../api/subsonicPlaylists';
|
||||
import { getGenres } from '../api/subsonicGenres';
|
||||
import { filterSongsToActiveLibrary } from '../api/subsonicLibrary';
|
||||
import type { SubsonicPlaylist, SubsonicGenre } from '../api/subsonicTypes';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import React, { useEffect, useState, useRef, useCallback } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
@@ -11,19 +11,19 @@ import { useAuthStore } from '../store/authStore';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useRangeSelection } from '../hooks/useRangeSelection';
|
||||
|
||||
import { formatHumanHoursMinutes } from '../utils/formatHumanDuration';
|
||||
import { formatHumanHoursMinutes } from '../utils/format/formatHumanDuration';
|
||||
import {
|
||||
defaultSmartFilters, isSmartPlaylistName,
|
||||
type SmartFilters, type PendingSmartPlaylist,
|
||||
} from '../utils/playlistsSmart';
|
||||
} from '../utils/playlist/playlistsSmart';
|
||||
import { useSmartCoverCollage } from '../hooks/useSmartCoverCollage';
|
||||
import { usePlaylistsLibraryScopeCounts } from '../hooks/usePlaylistsLibraryScopeCounts';
|
||||
import { usePendingSmartPolling } from '../hooks/usePendingSmartPolling';
|
||||
import { runPlaylistsOpenSmartEditor } from '../utils/runPlaylistsOpenSmartEditor';
|
||||
import { runPlaylistsSaveSmart } from '../utils/runPlaylistsSaveSmart';
|
||||
import { runPlaylistsOpenSmartEditor } from '../utils/playlist/runPlaylistsOpenSmartEditor';
|
||||
import { runPlaylistsSaveSmart } from '../utils/playlist/runPlaylistsSaveSmart';
|
||||
import {
|
||||
runPlaylistDelete, runPlaylistDeleteSelected, runPlaylistMergeSelected,
|
||||
} from '../utils/runPlaylistsActions';
|
||||
} from '../utils/playlist/runPlaylistsActions';
|
||||
import PlaylistsSmartEditor from '../components/playlists/PlaylistsSmartEditor';
|
||||
import PlaylistsHeader from '../components/playlists/PlaylistsHeader';
|
||||
import PlaylistCard from '../components/playlists/PlaylistCard';
|
||||
|
||||
@@ -8,12 +8,12 @@ import AlbumCard from '../components/AlbumCard';
|
||||
import GenreFilterBar from '../components/GenreFilterBar';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { filterAlbumsByMixRatings, getMixMinRatingsConfigFromAuth } from '../utils/mixRatingFilter';
|
||||
import { filterAlbumsByMixRatings, getMixMinRatingsConfigFromAuth } from '../utils/mix/mixRatingFilter';
|
||||
import { useOfflineStore } from '../store/offlineStore';
|
||||
import { useDownloadModalStore } from '../store/downloadModalStore';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { join } from '@tauri-apps/api/path';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import { useZipDownloadStore } from '../store/zipDownloadStore';
|
||||
import { useRangeSelection } from '../hooks/useRangeSelection';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { star, unstar } from '../api/subsonicStarRating';
|
||||
import { getGenres } from '../api/subsonicGenres';
|
||||
import type { SubsonicSong, SubsonicGenre } from '../api/subsonicTypes';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
import { usePreviewStore } from '../store/previewStore';
|
||||
@@ -12,8 +12,8 @@ import { useOrbitSongRowBehavior } from '../hooks/useOrbitSongRowBehavior';
|
||||
import {
|
||||
fetchRandomMixSongsUntilFull,
|
||||
getMixMinRatingsConfigFromAuth,
|
||||
} from '../utils/mixRatingFilter';
|
||||
import { AUDIOBOOK_GENRES, filterRandomMixSongs, formatRandomMixDuration } from '../utils/randomMixHelpers';
|
||||
} from '../utils/mix/mixRatingFilter';
|
||||
import { AUDIOBOOK_GENRES, filterRandomMixSongs, formatRandomMixDuration } from '../utils/componentHelpers/randomMixHelpers';
|
||||
import RandomMixHeader from '../components/randomMix/RandomMixHeader';
|
||||
import RandomMixFiltersPanel from '../components/randomMix/RandomMixFiltersPanel';
|
||||
import RandomMixGenrePanel from '../components/randomMix/RandomMixGenrePanel';
|
||||
|
||||
@@ -19,7 +19,7 @@ import { SystemTab } from '../components/settings/SystemTab';
|
||||
import { SETTINGS_INDEX, type Tab, matchScore, resolveTab } from '../components/settings/settingsTabs';
|
||||
import { UserManagementSection } from '../components/settings/UserManagementSection';
|
||||
import { ndLogin } from '../api/navidromeAdmin';
|
||||
import { type ServerMagicPayload } from '../utils/serverMagicString';
|
||||
import { type ServerMagicPayload } from '../utils/server/serverMagicString';
|
||||
|
||||
|
||||
export default function Settings() {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { getAlbumList } from '../api/subsonicLibrary';
|
||||
import type { SubsonicAlbum, SubsonicGenre } from '../api/subsonicTypes';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Share2 } from 'lucide-react';
|
||||
import { formatHumanHoursMinutes } from '../utils/formatHumanDuration';
|
||||
import { formatHumanHoursMinutes } from '../utils/format/formatHumanDuration';
|
||||
import AlbumRow from '../components/AlbumRow';
|
||||
import StatsExportModal from '../components/StatsExportModal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { buildCoverArtUrl, coverArtCacheKey } from '../api/subsonicStreamUrl';
|
||||
import { getRandomSongs } from '../api/subsonicLibrary';
|
||||
import type { SubsonicSong } from '../api/subsonicTypes';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import React, { useEffect, useState, useCallback, useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Play, ListPlus, RefreshCw, Sparkles } from 'lucide-react';
|
||||
@@ -11,9 +11,9 @@ import { usePlayerStore } from '../store/playerStore';
|
||||
import CachedImage from '../components/CachedImage';
|
||||
import SongRail from '../components/SongRail';
|
||||
import VirtualSongList from '../components/VirtualSongList';
|
||||
import { playSongNow } from '../utils/playSong';
|
||||
import { playSongNow } from '../utils/playback/playSong';
|
||||
import { ndListSongs, ndInvalidateSongsCache } from '../api/navidromeBrowse';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
||||
|
||||
const RANDOM_RAIL_SIZE = 18;
|
||||
/** Over-fetch buffer so the client-side `userRating > 0` filter still leaves
|
||||
|
||||
@@ -4,8 +4,8 @@ import { useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { version } from '../../package.json';
|
||||
import changelogRaw from '../../CHANGELOG.md?raw';
|
||||
import { findChangelogReleaseEntry } from '../utils/changelogReleaseMatch';
|
||||
import { renderChangelogBody } from '../utils/changelogMarkdown';
|
||||
import { findChangelogReleaseEntry } from '../utils/changelog/changelogReleaseMatch';
|
||||
import { renderChangelogBody } from '../utils/changelog/changelogMarkdown';
|
||||
|
||||
export default function WhatsNew() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
Reference in New Issue
Block a user