mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-21 22:15:40 +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
+1
-1
@@ -5,7 +5,7 @@ import {
|
||||
isNavidromeAudiomuseSoftwareEligible,
|
||||
type InstantMixProbeResult,
|
||||
type SubsonicServerIdentity,
|
||||
} from '../utils/subsonicServerIdentity';
|
||||
} from '../utils/server/subsonicServerIdentity';
|
||||
import {
|
||||
SUBSONIC_CLIENT,
|
||||
api,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { SubsonicServerIdentity } from '../utils/subsonicServerIdentity';
|
||||
import type { SubsonicServerIdentity } from '../utils/server/subsonicServerIdentity';
|
||||
|
||||
export interface SubsonicAlbum {
|
||||
id: string;
|
||||
|
||||
@@ -50,11 +50,11 @@ import { usePlayerStore } from '../store/playerStore';
|
||||
import { useThemeStore } from '../store/themeStore';
|
||||
import { useFontStore } from '../store/fontStore';
|
||||
import { useEqStore } from '../store/eqStore';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
||||
import {
|
||||
persistSidebarCollapsed,
|
||||
readInitialSidebarCollapsed,
|
||||
} from '../utils/appShellHelpers';
|
||||
} from '../utils/componentHelpers/appShellHelpers';
|
||||
|
||||
/**
|
||||
* The main webview's persistent layout: titlebar (Linux only) + sidebar +
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ import { initAudioListeners } from '../store/initAudioListeners';
|
||||
import { lazy, Suspense, useEffect, useState } from 'react';
|
||||
import { BrowserRouter, Route, Routes } from 'react-router-dom';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import { WindowVisibilityProvider } from '../hooks/useWindowVisibility';
|
||||
import { DragDropProvider } from '../contexts/DragDropContext';
|
||||
import PasteClipboardHandler from '../components/PasteClipboardHandler';
|
||||
@@ -69,7 +69,7 @@ export default function MainApp() {
|
||||
const handleExport = async (since: number) => {
|
||||
setExportPickerOpen(false);
|
||||
try {
|
||||
const { exportNewAlbumsImage } = await import('../utils/exportNewAlbums');
|
||||
const { exportNewAlbumsImage } = await import('../utils/export/exportNewAlbums');
|
||||
const result = await exportNewAlbumsImage(since);
|
||||
if (result) {
|
||||
const files = result.paths.length > 1 ? ` (${result.paths.length} Dateien)` : '';
|
||||
|
||||
@@ -22,7 +22,7 @@ vi.mock('../store/fontStore', () => ({
|
||||
vi.mock('../store/keybindingsStore', () => ({
|
||||
useKeybindingsStore: { persist: { rehydrate: keybindingsRehydrate } },
|
||||
}));
|
||||
vi.mock('../utils/perfFlags', () => ({
|
||||
vi.mock('../utils/perf/perfFlags', () => ({
|
||||
usePerfProbeFlags: () => ({ disableTooltipPortal: true }),
|
||||
}));
|
||||
vi.mock('../i18n', () => ({
|
||||
|
||||
@@ -7,7 +7,7 @@ import FpsOverlay from '../components/FpsOverlay';
|
||||
import { useThemeStore } from '../store/themeStore';
|
||||
import { useFontStore } from '../store/fontStore';
|
||||
import { useKeybindingsStore } from '../store/keybindingsStore';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
||||
import i18n from '../i18n';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { buildCoverArtUrl, coverArtCacheKey } 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, { memo, useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Play, ListPlus, HardDriveDownload, Check } from 'lucide-react';
|
||||
@@ -10,7 +10,7 @@ import { usePlayerStore } from '../store/playerStore';
|
||||
import { useOfflineStore } from '../store/offlineStore';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import CachedImage from './CachedImage';
|
||||
import { playAlbum } from '../utils/playAlbum';
|
||||
import { playAlbum } from '../utils/playback/playAlbum';
|
||||
import { useDragDrop } from '../contexts/DragDropContext';
|
||||
import { isAlbumRecentlyAdded } from '../utils/albumRecency';
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useIsMobile } from '../hooks/useIsMobile';
|
||||
import { useThemeStore } from '../store/themeStore';
|
||||
import StarRating from './StarRating';
|
||||
import { copyEntityShareLink } from '../utils/copyEntityShareLink';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { copyEntityShareLink } from '../utils/share/copyEntityShareLink';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import { isAlbumRecentlyAdded } from '../utils/albumRecency';
|
||||
|
||||
function formatDuration(seconds: number): string {
|
||||
|
||||
@@ -4,7 +4,7 @@ import AlbumCard from './AlbumCard';
|
||||
import { ChevronLeft, ChevronRight, ArrowRight } from 'lucide-react';
|
||||
import { NavLink, useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
||||
import { dedupeById } from '../utils/dedupeById';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -9,14 +9,14 @@ import { useSelectionStore } from '../store/selectionStore';
|
||||
import {
|
||||
COLUMNS,
|
||||
type SortKey,
|
||||
} from '../utils/albumTrackListHelpers';
|
||||
} from '../utils/componentHelpers/albumTrackListHelpers';
|
||||
import { useAlbumTrackListSelection } from '../hooks/useAlbumTrackListSelection';
|
||||
import { TrackRow } from './albumTrackList/TrackRow';
|
||||
import { AlbumTrackListMobile } from './albumTrackList/AlbumTrackListMobile';
|
||||
import { TracklistColumnPicker } from './albumTrackList/TracklistColumnPicker';
|
||||
import { TracklistHeaderRow } from './albumTrackList/TracklistHeaderRow';
|
||||
|
||||
export type { SortKey } from '../utils/albumTrackListHelpers';
|
||||
export type { SortKey } from '../utils/componentHelpers/albumTrackListHelpers';
|
||||
|
||||
interface AlbumTrackListProps {
|
||||
songs: SubsonicSong[];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import type { TFunction } from 'i18next';
|
||||
import { PanelRight, PanelRightClose } from 'lucide-react';
|
||||
import { shouldSuppressQueueResizerMouseDown } from '../utils/appShellHelpers';
|
||||
import { shouldSuppressQueueResizerMouseDown } from '../utils/componentHelpers/appShellHelpers';
|
||||
|
||||
interface Props {
|
||||
isQueueVisible: boolean;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { open } from '@tauri-apps/plugin-shell';
|
||||
import { ArrowUpCircle, CheckCircle2, ChevronDown, Download, FolderOpen, RefreshCw, ShieldCheck, X } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { version as currentVersion } from '../../package.json';
|
||||
import { fmtBytes } from '../utils/appUpdaterHelpers';
|
||||
import { fmtBytes } from '../utils/componentHelpers/appUpdaterHelpers';
|
||||
import { useAppUpdater } from '../hooks/useAppUpdater';
|
||||
import Changelog from './appUpdater/Changelog';
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { buildCoverArtUrl, coverArtCacheKey } from '../api/subsonicStreamUrl';
|
||||
import { getArtist, getArtistInfo } from '../api/subsonicArtists';
|
||||
import { getAlbum } from '../api/subsonicLibrary';
|
||||
import type { SubsonicAlbum } from '../api/subsonicTypes';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import React, { memo, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -10,7 +10,7 @@ import { Play, ListPlus, Music } from 'lucide-react';
|
||||
import CachedImage, { useCachedUrl } from './CachedImage';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { playAlbum } from '../utils/playAlbum';
|
||||
import { playAlbum } from '../utils/playback/playAlbum';
|
||||
import AlbumRow from './AlbumRow';
|
||||
|
||||
const ANCHOR_HISTORY_KEY_PREFIX = 'psysonic_because_anchor_history:';
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Sparkles } from 'lucide-react';
|
||||
import { version } from '../../package.json';
|
||||
import changelogRaw from '../../CHANGELOG.md?raw';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { findChangelogReleaseEntry } from '../utils/changelogReleaseMatch';
|
||||
import { findChangelogReleaseEntry } from '../utils/changelog/changelogReleaseMatch';
|
||||
|
||||
function renderInline(text: string): React.ReactNode[] {
|
||||
const parts = text.split(/(\*\*[^*]+\*\*|\*[^*]+\*|`[^`]+`)/g);
|
||||
|
||||
@@ -6,9 +6,9 @@ import { useNavigate } from 'react-router-dom';
|
||||
import { Check, ChevronDown } from 'lucide-react';
|
||||
import { ConnectionStatus } from '../hooks/useConnectionStatus';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { switchActiveServer } from '../utils/switchActiveServer';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { serverListDisplayLabel } from '../utils/serverDisplayName';
|
||||
import { switchActiveServer } from '../utils/server/switchActiveServer';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import { serverListDisplayLabel } from '../utils/server/serverDisplayName';
|
||||
|
||||
interface Props {
|
||||
status: ConnectionStatus;
|
||||
|
||||
@@ -5,14 +5,14 @@ import { usePlayerStore } from '../store/playerStore';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import type { EntityShareKind } from '../utils/shareLink';
|
||||
import type { EntityShareKind } from '../utils/share/shareLink';
|
||||
import { AddToPlaylistSubmenu } from './contextMenu/AddToPlaylistSubmenu';
|
||||
import {
|
||||
copyShareLink as copyShareLinkAction,
|
||||
downloadAlbum as downloadAlbumAction,
|
||||
startInstantMix as startInstantMixAction,
|
||||
startRadio as startRadioAction,
|
||||
} from '../utils/contextMenuActions';
|
||||
} from '../utils/componentHelpers/contextMenuActions';
|
||||
import { useContextMenuKeyboardNav } from '../hooks/useContextMenuKeyboardNav';
|
||||
import { useContextMenuRating } from '../hooks/useContextMenuRating';
|
||||
import ContextMenuItems from './contextMenu/ContextMenuItems';
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Save, Trash2, RotateCcw } from 'lucide-react';
|
||||
import CustomSelect from './CustomSelect';
|
||||
import { useEqStore, EQ_BANDS, BUILTIN_PRESETS } from '../store/eqStore';
|
||||
import { useThemeStore } from '../store/themeStore';
|
||||
import { drawCurve } from '../utils/eqCurve';
|
||||
import { drawCurve } from '../utils/audio/eqCurve';
|
||||
import VerticalFader from './equalizer/VerticalFader';
|
||||
import AutoEqSection from './equalizer/AutoEqSection';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { usePerfProbeFlag } from '../utils/perfFlags';
|
||||
import { usePerfProbeFlag } from '../utils/perf/perfFlags';
|
||||
|
||||
const SAMPLE_MS = 500;
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import { buildCoverArtUrl, coverArtCacheKey } from '../api/subsonicStreamUrl';
|
||||
import { getRandomAlbums, 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, useRef, useCallback, useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Play, ListPlus } from 'lucide-react';
|
||||
import CachedImage, { useCachedUrl } from './CachedImage';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { playAlbum } from '../utils/playAlbum';
|
||||
import { playAlbum } from '../utils/playback/playAlbum';
|
||||
import { useIsMobile } from '../hooks/useIsMobile';
|
||||
import { useWindowVisibility } from '../hooks/useWindowVisibility';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { useThemeStore } from '../store/themeStore';
|
||||
import { filterAlbumsByMixRatings, getMixMinRatingsConfigFromAuth } from '../utils/mixRatingFilter';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
import { filterAlbumsByMixRatings, getMixMinRatingsConfigFromAuth } from '../utils/mix/mixRatingFilter';
|
||||
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
||||
|
||||
const INTERVAL_MS = 10000;
|
||||
const HERO_ALBUM_COUNT = 8;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { buildCoverArtUrl, coverArtCacheKey } from '../api/subsonicStreamUrl';
|
||||
import { search } from '../api/subsonicSearch';
|
||||
import type { SearchResults, SubsonicArtist } from '../api/subsonicTypes';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Search, Disc3, Users, Music, TextSearch } from 'lucide-react';
|
||||
@@ -9,7 +9,7 @@ import { usePlayerStore } from '../store/playerStore';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import CachedImage, { FETCH_QUEUE_BIAS_SEARCH_ARTIST_OVER_ALBUM } from './CachedImage';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
|
||||
function debounce(fn: (q: string) => void, ms: number): (q: string) => void {
|
||||
let timer: ReturnType<typeof setTimeout>;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useLyrics, type WordLyricsLine } from '../hooks/useLyrics';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import type { Track } from '../store/playerStoreTypes';
|
||||
import { EaseScroller, targetForFraction } from '../utils/easeScroll';
|
||||
import { EaseScroller, targetForFraction } from '../utils/ui/easeScroll';
|
||||
import OverlayScrollArea from './OverlayScrollArea';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useRef, useState, useEffect, useCallback } from 'react';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
||||
|
||||
interface Props {
|
||||
text: string;
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
COLLAPSED_SIZE, EXPANDED_SIZE, COLLAPSED_MIN, EXPANDED_MIN,
|
||||
EXPANDED_H_KEY, QUEUE_OPEN_KEY,
|
||||
readStoredExpandedHeight, readQueueOpen, initialSnapshot,
|
||||
} from '../utils/miniPlayerHelpers';
|
||||
} from '../utils/componentHelpers/miniPlayerHelpers';
|
||||
import { MiniTitlebar } from './miniPlayer/MiniTitlebar';
|
||||
import { MiniMeta } from './miniPlayer/MiniMeta';
|
||||
import { MiniControls } from './miniPlayer/MiniControls';
|
||||
|
||||
@@ -16,7 +16,7 @@ import LyricsPane from './LyricsPane';
|
||||
import { usePlaybackDelayPress } from '../hooks/usePlaybackDelayPress';
|
||||
import PlaybackDelayModal from './PlaybackDelayModal';
|
||||
import PlaybackScheduleBadge from './PlaybackScheduleBadge';
|
||||
import { usePlaybackScheduleRemaining } from '../utils/playbackScheduleFormat';
|
||||
import { usePlaybackScheduleRemaining } from '../utils/format/playbackScheduleFormat';
|
||||
|
||||
// ── Color extraction ──────────────────────────────────────────────────────────
|
||||
// Samples a 16×16 canvas to find the most vibrant (highest-saturation,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { buildCoverArtUrl, coverArtCacheKey } from '../api/subsonicStreamUrl';
|
||||
import { search } from '../api/subsonicSearch';
|
||||
import type { SearchResults, SubsonicArtist } from '../api/subsonicTypes';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
@@ -10,7 +10,7 @@ import { usePlayerStore } from '../store/playerStore';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import CachedImage, { FETCH_QUEUE_BIAS_SEARCH_ARTIST_OVER_ALBUM } from './CachedImage';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
|
||||
const STORAGE_KEY = 'psysonic_recent_searches';
|
||||
const MAX_RECENT = 6;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Copy, Trash2 } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useOrbitStore } from '../store/orbitStore';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import { computeOrbitDriftMs } from '../utils/orbit';
|
||||
import {
|
||||
clearOrbitEvents,
|
||||
|
||||
@@ -9,9 +9,9 @@ import {
|
||||
readOrbitState,
|
||||
joinOrbitSession,
|
||||
} from '../utils/orbit';
|
||||
import { switchActiveServer } from '../utils/switchActiveServer';
|
||||
import { switchActiveServer } from '../utils/server/switchActiveServer';
|
||||
import { useOrbitAccountPickerStore } from '../store/orbitAccountPickerStore';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getSong } from '../api/subsonicLibrary';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { X, RefreshCw, Shuffle, Settings2, Share2, HelpCircle, Activity } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useOrbitStore } from '../store/orbitStore';
|
||||
import { updateOrbitSettings, triggerOrbitShuffleNow } from '../utils/orbit';
|
||||
import { ORBIT_DEFAULT_SETTINGS, ORBIT_SHUFFLE_INTERVAL_PRESETS_MIN, type OrbitShuffleIntervalMin } from '../api/orbit';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
|
||||
interface Props {
|
||||
anchorRef: React.RefObject<HTMLElement | null>;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
||||
import { computeOverlayScrollbarThumbMeta } from '../utils/overlayScrollbarMetrics';
|
||||
import { bindOverlayScrollbarThumbDrag } from '../utils/overlayScrollbarThumb';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
import { computeOverlayScrollbarThumbMeta } from '../utils/ui/overlayScrollbarMetrics';
|
||||
import { bindOverlayScrollbarThumbDrag } from '../utils/ui/overlayScrollbarThumb';
|
||||
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
||||
|
||||
export type OverlayScrollRailInset = 'none' | 'mini' | 'panel';
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@ import { useEffect, useRef, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { decodeSharePayloadFromText } from '../utils/shareLink';
|
||||
import { decodeServerMagicStringFromText } from '../utils/serverMagicString';
|
||||
import { applySharePastePayload } from '../utils/applySharePaste';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { decodeSharePayloadFromText } from '../utils/share/shareLink';
|
||||
import { decodeServerMagicStringFromText } from '../utils/server/serverMagicString';
|
||||
import { applySharePastePayload } from '../utils/share/applySharePaste';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import {
|
||||
parseOrbitShareLink,
|
||||
joinOrbitSession,
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
readOrbitState,
|
||||
OrbitJoinError,
|
||||
} from '../utils/orbit';
|
||||
import { switchActiveServer } from '../utils/switchActiveServer';
|
||||
import { switchActiveServer } from '../utils/server/switchActiveServer';
|
||||
import { useOrbitAccountPickerStore } from '../store/orbitAccountPickerStore';
|
||||
import ConfirmModal from './ConfirmModal';
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { usePlayerStore } from '../store/playerStore';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
|
||||
import type { TFunction } from 'i18next';
|
||||
import { formatPlaybackScheduleRemaining } from '../utils/playbackScheduleFormat';
|
||||
import { formatPlaybackScheduleRemaining } from '../utils/format/playbackScheduleFormat';
|
||||
|
||||
function formatClockTime(ts: number): string {
|
||||
const d = new Date(ts);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createPortal } from 'react-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { formatPlaybackScheduleRemaining } from '../utils/playbackScheduleFormat';
|
||||
import { formatPlaybackScheduleRemaining } from '../utils/format/playbackScheduleFormat';
|
||||
import { useWindowVisibility } from '../hooks/useWindowVisibility';
|
||||
|
||||
export interface PlaybackScheduleBadgeProps {
|
||||
|
||||
@@ -25,10 +25,10 @@ import { useRadioMetadata } from '../hooks/useRadioMetadata';
|
||||
import { usePlaybackDelayPress } from '../hooks/usePlaybackDelayPress';
|
||||
import PlaybackDelayModal from './PlaybackDelayModal';
|
||||
import PlaybackScheduleBadge from './PlaybackScheduleBadge';
|
||||
import { usePlaybackScheduleRemaining } from '../utils/playbackScheduleFormat';
|
||||
import { usePlaybackScheduleRemaining } from '../utils/format/playbackScheduleFormat';
|
||||
import { usePreviewStore } from '../store/previewStore';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
import { formatTime } from '../utils/playerBarHelpers';
|
||||
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
||||
import { formatTime } from '../utils/componentHelpers/playerBarHelpers';
|
||||
import { PlaybackTime, RemainingTime } from './playerBar/PlaybackClock';
|
||||
import { PlayerTrackInfo } from './playerBar/PlayerTrackInfo';
|
||||
import { PlayerTransportControls } from './playerBar/PlayerTransportControls';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getPlaylist, updatePlaylist } from '../api/subsonicPlaylists';
|
||||
import { buildCoverArtUrl, coverArtCacheKey } from '../api/subsonicStreamUrl';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import type { Track } from '../store/playerStoreTypes';
|
||||
import { useState, useRef, useMemo } from 'react';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
@@ -13,9 +13,9 @@ import { useCachedUrl } from './CachedImage';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { encodeSharePayload } from '../utils/shareLink';
|
||||
import { copyTextToClipboard } from '../utils/serverMagicString';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { encodeSharePayload } from '../utils/share/shareLink';
|
||||
import { copyTextToClipboard } from '../utils/server/serverMagicString';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import { useThemeStore } from '../store/themeStore';
|
||||
import { useLyricsStore } from '../store/lyricsStore';
|
||||
import LyricsPane from './LyricsPane';
|
||||
@@ -26,7 +26,7 @@ import { useQueueToolbarStore } from '../store/queueToolbarStore';
|
||||
import {
|
||||
DurationMode,
|
||||
formatTime,
|
||||
} from '../utils/queuePanelHelpers';
|
||||
} from '../utils/componentHelpers/queuePanelHelpers';
|
||||
import { SavePlaylistModal } from './queuePanel/SavePlaylistModal';
|
||||
import { LoadPlaylistModal } from './queuePanel/LoadPlaylistModal';
|
||||
import { QueueHeader } from './queuePanel/QueueHeader';
|
||||
|
||||
@@ -16,9 +16,9 @@ import OverlayScrollArea from './OverlayScrollArea';
|
||||
import {
|
||||
getLibraryItemsForReorder,
|
||||
getSystemItemsForReorder,
|
||||
} from '../utils/sidebarNavReorder';
|
||||
} from '../utils/componentHelpers/sidebarNavReorder';
|
||||
import { useLuckyMixAvailable } from '../hooks/useLuckyMixAvailable';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
||||
import { useSidebarNewReleasesUnread } from '../hooks/useSidebarNewReleasesUnread';
|
||||
import { useSidebarNavDnd } from '../hooks/useSidebarNavDnd';
|
||||
import { useSidebarLibraryDropdown } from '../hooks/useSidebarLibraryDropdown';
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { buildCoverArtUrl, coverArtCacheKey } from '../api/subsonicStreamUrl';
|
||||
import type { SubsonicSong } from '../api/subsonicTypes';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import React, { memo, useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Play, ListPlus, Star } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
import CachedImage from './CachedImage';
|
||||
import { enqueueAndPlay } from '../utils/playSong';
|
||||
import { enqueueAndPlay } from '../utils/playback/playSong';
|
||||
import { useDragDrop } from '../contexts/DragDropContext';
|
||||
import { useOrbitSongRowBehavior } from '../hooks/useOrbitSongRowBehavior';
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ import { useShallow } from 'zustand/react/shallow';
|
||||
import { ndGetSongPath } from '../api/navidromeAdmin';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { copyTextToClipboard } from '../utils/serverMagicString';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { copyTextToClipboard } from '../utils/server/serverMagicString';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
|
||||
function formatDuration(s: number): string {
|
||||
const m = Math.floor(s / 60);
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { SubsonicSong } from '../api/subsonicTypes';
|
||||
import React, { useRef, useState, useEffect, useMemo } from 'react';
|
||||
import { ChevronLeft, ChevronRight, RefreshCw } from 'lucide-react';
|
||||
import SongCard from './SongCard';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
||||
import { dedupeById } from '../utils/dedupeById';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { SubsonicSong } from '../api/subsonicTypes';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import React, { memo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Play, ListPlus } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
import { enqueueAndPlay } from '../utils/playSong';
|
||||
import { enqueueAndPlay } from '../utils/playback/playSong';
|
||||
import { useDragDrop } from '../contexts/DragDropContext';
|
||||
import { useOrbitSongRowBehavior } from '../hooks/useOrbitSongRowBehavior';
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ import { useTranslation } from 'react-i18next';
|
||||
import { X } from 'lucide-react';
|
||||
import { save } from '@tauri-apps/plugin-dialog';
|
||||
import { writeFile } from '@tauri-apps/plugin-fs';
|
||||
import { showToast } from '../utils/toast';
|
||||
import { showToast } from '../utils/ui/toast';
|
||||
import {
|
||||
exportAlbumCardBlob,
|
||||
renderAlbumCardCanvas,
|
||||
ExportFormat,
|
||||
ExportGridSize,
|
||||
} from '../utils/exportAlbumCard';
|
||||
} from '../utils/export/exportAlbumCard';
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
STATIC_REDRAW_FORCE_MS, STATIC_REDRAW_MIN_MS,
|
||||
fmt, invalidateColorCache, isBarQuantizedSeekStyle, makeAnimState,
|
||||
quantizeProgressByBars,
|
||||
} from '../utils/waveformSeekHelpers';
|
||||
import { drawSeekbar } from '../utils/waveformSeekRenderers';
|
||||
} from '../utils/waveform/waveformSeekHelpers';
|
||||
import { drawSeekbar } from '../utils/waveform/waveformSeekRenderers';
|
||||
import { useWaveformHeights } from '../hooks/useWaveformHeights';
|
||||
import { useWaveformInterpolation } from '../hooks/useWaveformInterpolation';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import type { SeekbarStyle } from '../store/authStoreTypes';
|
||||
import { makeAnimState, makeHeights } from '../utils/waveformSeekHelpers';
|
||||
import { drawSeekbar } from '../utils/waveformSeekRenderers';
|
||||
import { makeAnimState, makeHeights } from '../utils/waveform/waveformSeekHelpers';
|
||||
import { drawSeekbar } from '../utils/waveform/waveformSeekRenderers';
|
||||
|
||||
interface Props {
|
||||
style: SeekbarStyle;
|
||||
|
||||
@@ -2,8 +2,8 @@ import React from 'react';
|
||||
import { AudioLines } from 'lucide-react';
|
||||
import type { SubsonicSong } from '../../api/subsonicTypes';
|
||||
import type { Track } from '../../store/playerStoreTypes';
|
||||
import { songToTrack } from '../../utils/songToTrack';
|
||||
import { formatDuration } from '../../utils/albumTrackListHelpers';
|
||||
import { songToTrack } from '../../utils/playback/songToTrack';
|
||||
import { formatDuration } from '../../utils/componentHelpers/albumTrackListHelpers';
|
||||
|
||||
interface Props {
|
||||
discNums: number[];
|
||||
|
||||
@@ -5,12 +5,12 @@ import { useNavigate } from 'react-router-dom';
|
||||
import type { ColDef } from '../../utils/useTracklistColumns';
|
||||
import type { SubsonicSong } from '../../api/subsonicTypes';
|
||||
import type { Track } from '../../store/playerStoreTypes';
|
||||
import { songToTrack } from '../../utils/songToTrack';
|
||||
import { songToTrack } from '../../utils/playback/songToTrack';
|
||||
import { useSelectionStore } from '../../store/selectionStore';
|
||||
import { useThemeStore } from '../../store/themeStore';
|
||||
import { usePreviewStore } from '../../store/previewStore';
|
||||
import StarRating from '../StarRating';
|
||||
import { codecLabel, formatDuration, type ColKey } from '../../utils/albumTrackListHelpers';
|
||||
import { codecLabel, formatDuration, type ColKey } from '../../utils/componentHelpers/albumTrackListHelpers';
|
||||
|
||||
type ContextMenuFn = (
|
||||
x: number,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Check, ChevronDown, RotateCcw } from 'lucide-react';
|
||||
import type { TFunction } from 'i18next';
|
||||
import { COLUMNS } from '../../utils/albumTrackListHelpers';
|
||||
import { COLUMNS } from '../../utils/componentHelpers/albumTrackListHelpers';
|
||||
|
||||
interface Props {
|
||||
pickerRef: React.RefObject<HTMLDivElement | null>;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import type { TFunction } from 'i18next';
|
||||
import type { ColDef } from '../../utils/useTracklistColumns';
|
||||
import { CENTERED_COLS, isSortable, type ColKey, type SortKey } from '../../utils/albumTrackListHelpers';
|
||||
import { CENTERED_COLS, isSortable, type ColKey, type SortKey } from '../../utils/componentHelpers/albumTrackListHelpers';
|
||||
|
||||
interface Props {
|
||||
visibleCols: readonly ColDef[];
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useOfflineStore } from '../../store/offlineStore';
|
||||
import { useOfflineJobStore } from '../../store/offlineJobStore';
|
||||
import { useAuthStore } from '../../store/authStore';
|
||||
import { useIsMobile } from '../../hooks/useIsMobile';
|
||||
import { extractCoverColors } from '../../utils/dynamicColors';
|
||||
import { extractCoverColors } from '../../utils/ui/dynamicColors';
|
||||
import CachedImage from '../CachedImage';
|
||||
import CoverLightbox from '../CoverLightbox';
|
||||
import LastfmIcon from '../LastfmIcon';
|
||||
|
||||
@@ -5,8 +5,8 @@ import type { SubsonicSong } from '../../api/subsonicTypes';
|
||||
import { usePlayerStore } from '../../store/playerStore';
|
||||
import { usePreviewStore } from '../../store/previewStore';
|
||||
import { useOrbitSongRowBehavior } from '../../hooks/useOrbitSongRowBehavior';
|
||||
import { songToTrack } from '../../utils/songToTrack';
|
||||
import { formatDuration } from '../../utils/artistDetailHelpers';
|
||||
import { songToTrack } from '../../utils/playback/songToTrack';
|
||||
import { formatDuration } from '../../utils/componentHelpers/artistDetailHelpers';
|
||||
import ArtistSuggestionTrackCover from './ArtistSuggestionTrackCover';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useMemo } from 'react';
|
||||
import { buildCoverArtUrl, coverArtCacheKey } from '../../api/subsonicStreamUrl';
|
||||
import type { SubsonicArtist } from '../../api/subsonicTypes';
|
||||
import CachedImage from '../CachedImage';
|
||||
import { nameColor, nameInitial } from '../../utils/artistsHelpers';
|
||||
import { nameColor, nameInitial } from '../../utils/componentHelpers/artistsHelpers';
|
||||
|
||||
interface AvatarProps {
|
||||
artist: SubsonicArtist;
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { Virtualizer } from '@tanstack/react-virtual';
|
||||
import type { TFunction } from 'i18next';
|
||||
import type { SubsonicArtist } from '../../api/subsonicTypes';
|
||||
import type { PlayerState } from '../../store/playerStoreTypes';
|
||||
import type { ArtistListFlatRow } from '../../utils/artistsHelpers';
|
||||
import type { ArtistListFlatRow } from '../../utils/componentHelpers/artistsHelpers';
|
||||
import { ArtistRowAvatar } from './ArtistAvatars';
|
||||
|
||||
interface RowProps {
|
||||
|
||||
@@ -4,11 +4,11 @@ import { ListMusic, Plus } from 'lucide-react';
|
||||
import { getPlaylist, updatePlaylist } from '../../api/subsonicPlaylists';
|
||||
import type { SubsonicPlaylist } from '../../api/subsonicTypes';
|
||||
import { usePlaylistStore } from '../../store/playlistStore';
|
||||
import { showToast } from '../../utils/toast';
|
||||
import { showToast } from '../../utils/ui/toast';
|
||||
import {
|
||||
confirmAddAllDuplicates,
|
||||
isSmartPlaylistName,
|
||||
} from '../../utils/contextMenuHelpers';
|
||||
} from '../../utils/componentHelpers/contextMenuHelpers';
|
||||
|
||||
interface Props {
|
||||
songIds: string[];
|
||||
|
||||
@@ -5,7 +5,7 @@ import { getAlbum } from '../../api/subsonicLibrary';
|
||||
import { star, unstar } from '../../api/subsonicStarRating';
|
||||
import type { SubsonicAlbum } from '../../api/subsonicTypes';
|
||||
import { useAuthStore } from '../../store/authStore';
|
||||
import { songToTrack } from '../../utils/songToTrack';
|
||||
import { songToTrack } from '../../utils/playback/songToTrack';
|
||||
import StarRating from '../StarRating';
|
||||
import { AlbumToPlaylistSubmenu } from './AlbumArtistToPlaylistSubmenu';
|
||||
import { MultiAlbumToPlaylistSubmenu } from './MultiAlbumToPlaylistSubmenu';
|
||||
|
||||
@@ -4,11 +4,11 @@ import { ListMusic, Plus } from 'lucide-react';
|
||||
import { getAlbum } from '../../api/subsonicLibrary';
|
||||
import type { SubsonicPlaylist } from '../../api/subsonicTypes';
|
||||
import { usePlaylistStore } from '../../store/playlistStore';
|
||||
import { showToast } from '../../utils/toast';
|
||||
import { showToast } from '../../utils/ui/toast';
|
||||
import {
|
||||
confirmAddAllDuplicates,
|
||||
isSmartPlaylistName,
|
||||
} from '../../utils/contextMenuHelpers';
|
||||
} from '../../utils/componentHelpers/contextMenuHelpers';
|
||||
|
||||
interface Props {
|
||||
albumIds: string[];
|
||||
|
||||
@@ -6,11 +6,11 @@ import { getArtist } from '../../api/subsonicArtists';
|
||||
import { getPlaylists } from '../../api/subsonicPlaylists';
|
||||
import type { SubsonicPlaylist } from '../../api/subsonicTypes';
|
||||
import { usePlaylistStore } from '../../store/playlistStore';
|
||||
import { showToast } from '../../utils/toast';
|
||||
import { showToast } from '../../utils/ui/toast';
|
||||
import {
|
||||
confirmAddAllDuplicates,
|
||||
isSmartPlaylistName,
|
||||
} from '../../utils/contextMenuHelpers';
|
||||
} from '../../utils/componentHelpers/contextMenuHelpers';
|
||||
|
||||
interface Props {
|
||||
artistIds: string[];
|
||||
|
||||
@@ -46,7 +46,7 @@ export default function PlaylistContextItems(props: ContextMenuItemsProps) {
|
||||
</div>
|
||||
<div className="context-menu-divider" />
|
||||
<div className="context-menu-item" style={{ color: 'var(--danger)' }} onClick={() => handleAction(async () => {
|
||||
const { showToast } = await import('../../utils/toast');
|
||||
const { showToast } = await import('../../utils/ui/toast');
|
||||
const { deletePlaylist } = await import('../../api/subsonicPlaylists');
|
||||
const { removeId } = usePlaylistStore.getState();
|
||||
try {
|
||||
@@ -89,7 +89,7 @@ export default function PlaylistContextItems(props: ContextMenuItemsProps) {
|
||||
)}
|
||||
</div>
|
||||
<div className="context-menu-item" style={{ color: 'var(--danger)' }} onClick={() => handleAction(async () => {
|
||||
const { showToast } = await import('../../utils/toast');
|
||||
const { showToast } = await import('../../utils/ui/toast');
|
||||
const { deletePlaylist } = await import('../../api/subsonicPlaylists');
|
||||
const { removeId } = usePlaylistStore.getState();
|
||||
const deletedIds: string[] = [];
|
||||
|
||||
@@ -2,8 +2,8 @@ import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 're
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ListMusic, Plus } from 'lucide-react';
|
||||
import { usePlaylistStore } from '../../store/playlistStore';
|
||||
import { showToast } from '../../utils/toast';
|
||||
import { isSmartPlaylistName } from '../../utils/contextMenuHelpers';
|
||||
import { showToast } from '../../utils/ui/toast';
|
||||
import { isSmartPlaylistName } from '../../utils/componentHelpers/contextMenuHelpers';
|
||||
|
||||
interface SingleProps {
|
||||
playlist: { id: string; name: string };
|
||||
|
||||
@@ -7,8 +7,8 @@ import { lastfmLoveTrack, lastfmUnloveTrack } from '../../api/lastfm';
|
||||
import type { Track } from '../../store/playerStoreTypes';
|
||||
import { useAuthStore } from '../../store/authStore';
|
||||
import { usePlaylistStore } from '../../store/playlistStore';
|
||||
import { songToTrack } from '../../utils/songToTrack';
|
||||
import { showToast } from '../../utils/toast';
|
||||
import { songToTrack } from '../../utils/playback/songToTrack';
|
||||
import { showToast } from '../../utils/ui/toast';
|
||||
import { suggestOrbitTrack, hostEnqueueToOrbit, evaluateOrbitSuggestGate, OrbitSuggestBlockedError } from '../../utils/orbit';
|
||||
import LastfmIcon from '../LastfmIcon';
|
||||
import StarRating from '../StarRating';
|
||||
@@ -166,7 +166,7 @@ export default function SongContextItems(props: ContextMenuItemsProps) {
|
||||
{playlistId && playlistSongIndex !== undefined && (
|
||||
<div className="context-menu-item" style={{ color: 'var(--danger)' }} onClick={() => handleAction(async () => {
|
||||
const { getPlaylist, updatePlaylist } = await import('../../api/subsonicPlaylists');
|
||||
const { showToast } = await import('../../utils/toast');
|
||||
const { showToast } = await import('../../utils/ui/toast');
|
||||
const touchPlaylist = usePlaylistStore.getState().touchPlaylist;
|
||||
try {
|
||||
const { songs } = await getPlaylist(playlistId);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type React from 'react';
|
||||
import type { SubsonicAlbum, SubsonicArtist } from '../../api/subsonicTypes';
|
||||
import type { Track } from '../../store/playerStoreTypes';
|
||||
import type { EntityShareKind } from '../../utils/shareLink';
|
||||
import type { EntityShareKind } from '../../utils/share/shareLink';
|
||||
|
||||
export type RatingKind = 'song' | 'album' | 'artist';
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import type {
|
||||
SubsonicAlbum, SubsonicArtist, SubsonicPlaylist,
|
||||
} from '../../api/subsonicTypes';
|
||||
import type { DeviceSyncSource } from '../../store/deviceSyncStore';
|
||||
import type { SourceTab } from '../../utils/deviceSyncHelpers';
|
||||
import type { SourceTab } from '../../utils/deviceSync/deviceSyncHelpers';
|
||||
import BrowserRow from './BrowserRow';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
} from 'lucide-react';
|
||||
import { useDeviceSyncJobStore } from '../../store/deviceSyncJobStore';
|
||||
import type { DeviceSyncSource } from '../../store/deviceSyncStore';
|
||||
import type { SyncStatus } from '../../utils/deviceSyncHelpers';
|
||||
import type { SyncStatus } from '../../utils/deviceSync/deviceSyncHelpers';
|
||||
|
||||
interface Props {
|
||||
sources: DeviceSyncSource[];
|
||||
|
||||
@@ -4,8 +4,8 @@ import {
|
||||
AlertCircle, FolderOpen, HardDriveUpload, RefreshCw, Usb,
|
||||
} from 'lucide-react';
|
||||
import CustomSelect from '../CustomSelect';
|
||||
import type { RemovableDrive } from '../../utils/deviceSyncHelpers';
|
||||
import { formatBytes } from '../../utils/deviceSyncHelpers';
|
||||
import type { RemovableDrive } from '../../utils/deviceSync/deviceSyncHelpers';
|
||||
import { formatBytes } from '../../utils/deviceSync/deviceSyncHelpers';
|
||||
import type { DeviceSyncSource } from '../../store/deviceSyncStore';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { AlertCircle, CheckCircle2, Loader2 } from 'lucide-react';
|
||||
import type {
|
||||
MigrationPair, MigrationPhase, MigrationResult,
|
||||
} from '../../utils/runDeviceSyncMigration';
|
||||
} from '../../utils/deviceSync/runDeviceSyncMigration';
|
||||
|
||||
interface Props {
|
||||
migrationPhase: MigrationPhase;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { AlertCircle, Loader2 } from 'lucide-react';
|
||||
import type { SyncDelta } from '../../utils/runDeviceSyncExecution';
|
||||
import type { SyncDelta } from '../../utils/deviceSync/runDeviceSyncExecution';
|
||||
|
||||
interface Props {
|
||||
preSyncOpen: boolean;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { ListPlus, Play, SlidersHorizontal, X } from 'lucide-react';
|
||||
import type { SubsonicSong } from '../../api/subsonicTypes';
|
||||
import { usePlayerStore } from '../../store/playerStore';
|
||||
import { songToTrack } from '../../utils/songToTrack';
|
||||
import { songToTrack } from '../../utils/playback/songToTrack';
|
||||
import GenreFilterBar from '../GenreFilterBar';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -12,7 +12,7 @@ import { usePreviewStore } from '../../store/previewStore';
|
||||
import { useSelectionStore } from '../../store/selectionStore';
|
||||
import { useDragDrop } from '../../contexts/DragDropContext';
|
||||
import { useOrbitSongRowBehavior } from '../../hooks/useOrbitSongRowBehavior';
|
||||
import { songToTrack } from '../../utils/songToTrack';
|
||||
import { songToTrack } from '../../utils/playback/songToTrack';
|
||||
import { AddToPlaylistSubmenu } from '../ContextMenu';
|
||||
import StarRating from '../StarRating';
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { Track } from '../../store/playerStoreTypes';
|
||||
import {
|
||||
folderBrowserHasKeyModifiers, isFolderBrowserArrowKey,
|
||||
type Column,
|
||||
} from '../../utils/folderBrowserHelpers';
|
||||
} from '../../utils/componentHelpers/folderBrowserHelpers';
|
||||
|
||||
interface Props {
|
||||
col: Column;
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useWordLyricsSync } from '../../hooks/useWordLyricsSync';
|
||||
import { getPlaybackProgressSnapshot, subscribePlaybackProgress } from '../../store/playbackProgress';
|
||||
import type { LrcLine } from '../../api/lrclib';
|
||||
import type { Track } from '../../store/playerStoreTypes';
|
||||
import { EaseScroller, targetForFraction } from '../../utils/easeScroll';
|
||||
import { EaseScroller, targetForFraction } from '../../utils/ui/easeScroll';
|
||||
|
||||
// Apple Music-style fullscreen lyrics.
|
||||
// Full-screen scrollable list. Active line auto-scrolls to ~35% from top.
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Moon, Pause, Play, Sunrise } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { usePlayerStore } from '../../store/playerStore';
|
||||
import { usePlaybackDelayPress } from '../../hooks/usePlaybackDelayPress';
|
||||
import { usePlaybackScheduleRemaining } from '../../utils/playbackScheduleFormat';
|
||||
import { usePlaybackScheduleRemaining } from '../../utils/format/playbackScheduleFormat';
|
||||
import PlaybackDelayModal from '../PlaybackDelayModal';
|
||||
import PlaybackScheduleBadge from '../PlaybackScheduleBadge';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { memo, useCallback, useEffect, useRef } from 'react';
|
||||
import { usePlayerStore } from '../../store/playerStore';
|
||||
import { getPlaybackProgressSnapshot, subscribePlaybackProgress } from '../../store/playbackProgress';
|
||||
import { formatTime } from '../../utils/fullscreenPlayerHelpers';
|
||||
import { formatTime } from '../../utils/componentHelpers/fullscreenPlayerHelpers';
|
||||
|
||||
// Full-width seekbar — imperative DOM updates, zero React re-renders on tick.
|
||||
export const FsSeekbar = memo(function FsSeekbar({ duration }: { duration: number }) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
import {
|
||||
type InternetRadioStation, type RadioBrowserStation, RADIO_PAGE_SIZE,
|
||||
} from '../../api/subsonicTypes';
|
||||
import { showToast } from '../../utils/toast';
|
||||
import { showToast } from '../../utils/ui/toast';
|
||||
|
||||
interface RadioDirectoryModalProps {
|
||||
onClose: () => void;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Pause, Play, SkipBack, SkipForward } from 'lucide-react';
|
||||
import { fmt } from '../../utils/miniPlayerHelpers';
|
||||
import { fmt } from '../../utils/componentHelpers/miniPlayerHelpers';
|
||||
import type { MiniControlAction } from '../../utils/miniPlayerBridge';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { memo, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Disc3, ExternalLink, Star } from 'lucide-react';
|
||||
import type { SubsonicAlbum, SubsonicSong } from '../../api/subsonicTypes';
|
||||
import { formatTime, formatTotalDuration } from '../../utils/nowPlayingHelpers';
|
||||
import { formatTime, formatTotalDuration } from '../../utils/componentHelpers/nowPlayingHelpers';
|
||||
|
||||
interface AlbumCardProps {
|
||||
album: SubsonicAlbum | null;
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { memo, useEffect, useLayoutEffect, useMemo, useRef, useState } fr
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ExternalLink } from 'lucide-react';
|
||||
import type { SubsonicArtistInfo } from '../../api/subsonicTypes';
|
||||
import { isRealArtistImage, sanitizeHtml } from '../../utils/nowPlayingHelpers';
|
||||
import { isRealArtistImage, sanitizeHtml } from '../../utils/componentHelpers/nowPlayingHelpers';
|
||||
import CachedImage from '../CachedImage';
|
||||
|
||||
interface ArtistCardProps {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import type { ContributorRow } from '../../utils/nowPlayingHelpers';
|
||||
import type { ContributorRow } from '../../utils/componentHelpers/nowPlayingHelpers';
|
||||
|
||||
interface CreditsCardProps { rows: ContributorRow[]; }
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { Headphones, Heart, MicVocal, Music, Star } from 'lucide-react';
|
||||
import type { LastfmArtistStats, LastfmTrackInfo } from '../../api/lastfm';
|
||||
import LastfmIcon from '../LastfmIcon';
|
||||
import { formatTime } from '../../utils/nowPlayingHelpers';
|
||||
import { formatTime } from '../../utils/componentHelpers/nowPlayingHelpers';
|
||||
|
||||
interface HeroProps {
|
||||
track: { title: string; artist: string; album: string; year?: number;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { Cast, Clock, Radio, SkipForward, Users } from 'lucide-react';
|
||||
import type { useRadioMetadata } from '../../hooks/useRadioMetadata';
|
||||
import { usePlayerStore } from '../../store/playerStore';
|
||||
import { formatTime } from '../../utils/nowPlayingHelpers';
|
||||
import { formatTime } from '../../utils/componentHelpers/nowPlayingHelpers';
|
||||
|
||||
type NonNullStoreField<K extends keyof ReturnType<typeof usePlayerStore.getState>> =
|
||||
NonNullable<ReturnType<typeof usePlayerStore.getState>[K]>;
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ExternalLink, Play, TrendingUp } from 'lucide-react';
|
||||
import type { SubsonicSong } from '../../api/subsonicTypes';
|
||||
import { formatTime } from '../../utils/nowPlayingHelpers';
|
||||
import { formatTime } from '../../utils/componentHelpers/nowPlayingHelpers';
|
||||
|
||||
interface TopSongsCardProps {
|
||||
artistName: string;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { Calendar, Info } from 'lucide-react';
|
||||
import { open as shellOpen } from '@tauri-apps/plugin-shell';
|
||||
import type { BandsintownEvent } from '../../api/bandsintown';
|
||||
import { isoToParts } from '../../utils/nowPlayingHelpers';
|
||||
import { isoToParts } from '../../utils/componentHelpers/nowPlayingHelpers';
|
||||
|
||||
interface TourCardProps {
|
||||
artistName: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { memo, useEffect, useRef } from 'react';
|
||||
import { getPlaybackProgressSnapshot, subscribePlaybackProgress } from '../../store/playbackProgress';
|
||||
import { formatTime } from '../../utils/playerBarHelpers';
|
||||
import { formatTime } from '../../utils/componentHelpers/playerBarHelpers';
|
||||
|
||||
/** Renders the playback clock without ever causing PlayerBar to re-render.
|
||||
* Updates the DOM directly via an imperative store subscription. */
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ArrowLeftRight } from 'lucide-react';
|
||||
import type { TFunction } from 'i18next';
|
||||
import type { RadioMetadata } from '../../hooks/useRadioMetadata';
|
||||
import { useThemeStore } from '../../store/themeStore';
|
||||
import { formatTime } from '../../utils/playerBarHelpers';
|
||||
import { formatTime } from '../../utils/componentHelpers/playerBarHelpers';
|
||||
import WaveformSeek from '../WaveformSeek';
|
||||
import { PlaybackTime, RemainingTime } from './PlaybackClock';
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { PlayerState } from '../../store/playerStoreTypes';
|
||||
import { usePreviewStore } from '../../store/previewStore';
|
||||
import PlaybackScheduleBadge from '../PlaybackScheduleBadge';
|
||||
import { usePlaybackDelayPress } from '../../hooks/usePlaybackDelayPress';
|
||||
import { usePlaybackScheduleRemaining } from '../../utils/playbackScheduleFormat';
|
||||
import { usePlaybackScheduleRemaining } from '../../utils/format/playbackScheduleFormat';
|
||||
|
||||
type RepeatMode = PlayerState['repeatMode'];
|
||||
type PlayPauseBind = ReturnType<typeof usePlaybackDelayPress>['playPauseBind'];
|
||||
|
||||
@@ -2,8 +2,8 @@ import React from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Download, X } from 'lucide-react';
|
||||
import { showToast } from '../../utils/toast';
|
||||
import type { SpotifyCsvTrack } from '../../utils/spotifyCsvImport';
|
||||
import { showToast } from '../../utils/ui/toast';
|
||||
import type { SpotifyCsvTrack } from '../../utils/playlist/spotifyCsvImport';
|
||||
|
||||
interface CsvReportModalProps {
|
||||
report: {
|
||||
|
||||
@@ -10,7 +10,7 @@ import type { ZipDownload } from '../../store/zipDownloadStore';
|
||||
import { useThemeStore } from '../../store/themeStore';
|
||||
import {
|
||||
displayPlaylistName, formatSize, isSmartPlaylistName, totalDurationLabel,
|
||||
} from '../../utils/playlistDetailHelpers';
|
||||
} from '../../utils/componentHelpers/playlistDetailHelpers';
|
||||
import CachedImage from '../CachedImage';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -4,8 +4,8 @@ import { Check, ListPlus, X } from 'lucide-react';
|
||||
import { buildCoverArtUrl, coverArtCacheKey } from '../../api/subsonicStreamUrl';
|
||||
import type { SubsonicSong } from '../../api/subsonicTypes';
|
||||
import { usePlayerStore } from '../../store/playerStore';
|
||||
import { songToTrack } from '../../utils/songToTrack';
|
||||
import { formatDuration } from '../../utils/playlistDetailHelpers';
|
||||
import { songToTrack } from '../../utils/playback/songToTrack';
|
||||
import { formatDuration } from '../../utils/componentHelpers/playlistDetailHelpers';
|
||||
import CachedImage from '../CachedImage';
|
||||
import { AddToPlaylistSubmenu } from '../ContextMenu';
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ import type { SubsonicSong } from '../../api/subsonicTypes';
|
||||
import { usePlayerStore } from '../../store/playerStore';
|
||||
import { usePreviewStore } from '../../store/previewStore';
|
||||
import { useThemeStore } from '../../store/themeStore';
|
||||
import { songToTrack } from '../../utils/songToTrack';
|
||||
import { codecLabel, formatDuration } from '../../utils/playlistDetailHelpers';
|
||||
import { songToTrack } from '../../utils/playback/songToTrack';
|
||||
import { codecLabel, formatDuration } from '../../utils/componentHelpers/playlistDetailHelpers';
|
||||
|
||||
const PL_CENTERED = new Set(['favorite', 'rating', 'duration']);
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ import { usePreviewStore } from '../../store/previewStore';
|
||||
import { useThemeStore } from '../../store/themeStore';
|
||||
import { useDragDrop } from '../../contexts/DragDropContext';
|
||||
import { useOrbitSongRowBehavior } from '../../hooks/useOrbitSongRowBehavior';
|
||||
import { songToTrack } from '../../utils/songToTrack';
|
||||
import { codecLabel, formatDuration } from '../../utils/playlistDetailHelpers';
|
||||
import type { PlaylistSortKey, PlaylistSortDir } from '../../utils/playlistDisplayedSongs';
|
||||
import { songToTrack } from '../../utils/playback/songToTrack';
|
||||
import { codecLabel, formatDuration } from '../../utils/componentHelpers/playlistDetailHelpers';
|
||||
import type { PlaylistSortKey, PlaylistSortDir } from '../../utils/playlist/playlistDisplayedSongs';
|
||||
import StarRating from '../StarRating';
|
||||
import { AddToPlaylistSubmenu } from '../ContextMenu';
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ import type { SubsonicPlaylist } from '../../api/subsonicTypes';
|
||||
import { usePlayerStore } from '../../store/playerStore';
|
||||
import {
|
||||
displayPlaylistName, isSmartPlaylistName, type PendingSmartPlaylist,
|
||||
} from '../../utils/playlistsSmart';
|
||||
import { formatHumanHoursMinutes } from '../../utils/formatHumanDuration';
|
||||
} from '../../utils/playlist/playlistsSmart';
|
||||
import { formatHumanHoursMinutes } from '../../utils/format/formatHumanDuration';
|
||||
import { PlaylistCardMainCover, PlaylistSmartCoverCell } from './PlaylistCoverImages';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { CheckSquare2, Plus, Trash2 } from 'lucide-react';
|
||||
import type { SubsonicPlaylist } from '../../api/subsonicTypes';
|
||||
import {
|
||||
defaultSmartFilters, type SmartFilters,
|
||||
} from '../../utils/playlistsSmart';
|
||||
} from '../../utils/playlist/playlistsSmart';
|
||||
|
||||
interface Props {
|
||||
selectionMode: boolean;
|
||||
|
||||
@@ -5,7 +5,7 @@ import StarRating from '../StarRating';
|
||||
import {
|
||||
LIMIT_MAX, YEAR_MAX, YEAR_MIN, clampYear, defaultSmartFilters,
|
||||
type SmartFilters,
|
||||
} from '../../utils/playlistsSmart';
|
||||
} from '../../utils/playlist/playlistsSmart';
|
||||
|
||||
interface Props {
|
||||
smartFilters: SmartFilters;
|
||||
|
||||
@@ -3,13 +3,13 @@ import { ChevronDown, FolderOpen, HardDrive, Music, Waves } from 'lucide-react';
|
||||
import type { TFunction } from 'i18next';
|
||||
import type { Track } from '../../store/playerStoreTypes';
|
||||
import type { LoudnessLufsPreset, NormalizationEngine } from '../../store/authStoreTypes';
|
||||
import type { PlaybackSourceKind } from '../../utils/resolvePlaybackUrl';
|
||||
import type { PlaybackSourceKind } from '../../utils/playback/resolvePlaybackUrl';
|
||||
import {
|
||||
formatQueueReplayGainParts,
|
||||
renderStars,
|
||||
} from '../../utils/queuePanelHelpers';
|
||||
import { loudnessGainPlaceholderUntilCacheDb } from '../../utils/loudnessPlaceholder';
|
||||
import { effectiveLoudnessPreAnalysisAttenuationDb } from '../../utils/loudnessPreAnalysisSlider';
|
||||
} from '../../utils/componentHelpers/queuePanelHelpers';
|
||||
import { loudnessGainPlaceholderUntilCacheDb } from '../../utils/audio/loudnessPlaceholder';
|
||||
import { effectiveLoudnessPreAnalysisAttenuationDb } from '../../utils/audio/loudnessPreAnalysisSlider';
|
||||
import { QueueLufsTargetMenu } from './QueueLufsTargetMenu';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ChevronDown, ListMusic } from 'lucide-react';
|
||||
import type { TFunction } from 'i18next';
|
||||
import { usePlayerStore } from '../../store/playerStore';
|
||||
import type { Track } from '../../store/playerStoreTypes';
|
||||
import type { DurationMode } from '../../utils/queuePanelHelpers';
|
||||
import type { DurationMode } from '../../utils/componentHelpers/queuePanelHelpers';
|
||||
|
||||
interface Props {
|
||||
queue: Track[];
|
||||
|
||||
@@ -5,7 +5,7 @@ import OverlayScrollArea from '../OverlayScrollArea';
|
||||
import { usePlayerStore } from '../../store/playerStore';
|
||||
import { useLuckyMixStore } from '../../store/luckyMixStore';
|
||||
import type { Track, PlayerState } from '../../store/playerStoreTypes';
|
||||
import { formatTime } from '../../utils/queuePanelHelpers';
|
||||
import { formatTime } from '../../utils/componentHelpers/queuePanelHelpers';
|
||||
|
||||
type StartDrag = (
|
||||
payload: { data: string; label: string },
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { SubsonicSong } from '../../api/subsonicTypes';
|
||||
import type { Track } from '../../store/playerStoreTypes';
|
||||
import { usePreviewStore } from '../../store/previewStore';
|
||||
import { useDragDrop } from '../../contexts/DragDropContext';
|
||||
import { formatRandomMixDuration } from '../../utils/randomMixHelpers';
|
||||
import { formatRandomMixDuration } from '../../utils/componentHelpers/randomMixHelpers';
|
||||
|
||||
interface Props {
|
||||
song: SubsonicSong;
|
||||
|
||||
@@ -2,14 +2,14 @@ import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Eye, EyeOff } from 'lucide-react';
|
||||
import type { ServerProfile } from '../../store/authStoreTypes';
|
||||
import { showToast } from '../../utils/toast';
|
||||
import { showToast } from '../../utils/ui/toast';
|
||||
import {
|
||||
decodeServerMagicString,
|
||||
encodeServerMagicString,
|
||||
DECODED_PASSWORD_VISUAL_MASK,
|
||||
type ServerMagicPayload,
|
||||
} from '../../utils/serverMagicString';
|
||||
import { shortHostFromServerUrl } from '../../utils/serverDisplayName';
|
||||
} from '../../utils/server/serverMagicString';
|
||||
import { shortHostFromServerUrl } from '../../utils/server/serverDisplayName';
|
||||
|
||||
export function AddServerForm({
|
||||
onSave,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Music2, Sliders, Waves } from 'lucide-react';
|
||||
import { useAuthStore } from '../../store/authStore';
|
||||
import Equalizer from '../Equalizer';
|
||||
import SettingsSubSection from '../SettingsSubSection';
|
||||
import { effectiveLoudnessPreAnalysisAttenuationDb } from '../../utils/loudnessPreAnalysisSlider';
|
||||
import { effectiveLoudnessPreAnalysisAttenuationDb } from '../../utils/audio/loudnessPreAnalysisSlider';
|
||||
import { useAudioDevicesProbe } from '../../hooks/useAudioDevicesProbe';
|
||||
import { AudioOutputDeviceSection } from './audio/AudioOutputDeviceSection';
|
||||
import { NormalizationBlock } from './audio/NormalizationBlock';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Download, HardDrive, Upload } from 'lucide-react';
|
||||
import { exportBackup, importBackup } from '../../utils/backup';
|
||||
import { showToast } from '../../utils/toast';
|
||||
import { exportBackup, importBackup } from '../../utils/export/backup';
|
||||
import { showToast } from '../../utils/ui/toast';
|
||||
|
||||
export function BackupSection() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -7,10 +7,10 @@ import { useAuthStore } from '../../store/authStore';
|
||||
import type { ServerProfile } from '../../store/authStoreTypes';
|
||||
import { pingWithCredentials, scheduleInstantMixProbeForServer } from '../../api/subsonic';
|
||||
import { useDragDrop } from '../../contexts/DragDropContext';
|
||||
import { type ServerMagicPayload } from '../../utils/serverMagicString';
|
||||
import { showAudiomuseNavidromeServerSetting } from '../../utils/subsonicServerIdentity';
|
||||
import { serverListDisplayLabel } from '../../utils/serverDisplayName';
|
||||
import { switchActiveServer } from '../../utils/switchActiveServer';
|
||||
import { type ServerMagicPayload } from '../../utils/server/serverMagicString';
|
||||
import { showAudiomuseNavidromeServerSetting } from '../../utils/server/subsonicServerIdentity';
|
||||
import { serverListDisplayLabel } from '../../utils/server/serverDisplayName';
|
||||
import { switchActiveServer } from '../../utils/server/switchActiveServer';
|
||||
import { AddServerForm } from './AddServerForm';
|
||||
import { ServerGripHandle } from './ServerGripHandle';
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useAuthStore } from '../../store/authStore';
|
||||
import { useSidebarStore, SidebarItemConfig } from '../../store/sidebarStore';
|
||||
import { useLuckyMixAvailable } from '../../hooks/useLuckyMixAvailable';
|
||||
import { ALL_NAV_ITEMS } from '../../config/navItems';
|
||||
import { applySidebarDropReorder } from '../../utils/sidebarNavReorder';
|
||||
import { applySidebarDropReorder } from '../../utils/componentHelpers/sidebarNavReorder';
|
||||
|
||||
type DropTarget = { idx: number; before: boolean; section: 'library' | 'system' } | null;
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ import { useHotCacheStore } from '../../store/hotCacheStore';
|
||||
import { useOfflineStore } from '../../store/offlineStore';
|
||||
import { usePlayerStore } from '../../store/playerStore';
|
||||
import { clearImageCache, getImageCacheSize } from '../../utils/imageCache';
|
||||
import { formatBytes, snapHotCacheMb } from '../../utils/formatBytes';
|
||||
import { showToast } from '../../utils/toast';
|
||||
import { formatBytes, snapHotCacheMb } from '../../utils/format/formatBytes';
|
||||
import { showToast } from '../../utils/ui/toast';
|
||||
import SettingsSubSection from '../SettingsSubSection';
|
||||
|
||||
export function StorageTab() {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user