mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 15:25:46 +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
@@ -24,19 +24,19 @@
|
||||
# - src/api/subsonic.ts (13 % — F3 covered the URL-builder + parser surface; async API endpoints need axios mocking, deferred)
|
||||
|
||||
# ── utils (already at or above threshold) ────────────────────────────
|
||||
src/utils/coverArtRegisteredSizes.ts
|
||||
src/utils/serverDisplayName.ts
|
||||
src/utils/serverMagicString.ts
|
||||
src/utils/shareLink.ts
|
||||
src/utils/dynamicColors.ts
|
||||
src/utils/resolvePlaybackUrl.ts
|
||||
src/utils/copyEntityShareLink.ts
|
||||
src/utils/cover/coverArtRegisteredSizes.ts
|
||||
src/utils/server/serverDisplayName.ts
|
||||
src/utils/server/serverMagicString.ts
|
||||
src/utils/share/shareLink.ts
|
||||
src/utils/ui/dynamicColors.ts
|
||||
src/utils/playback/resolvePlaybackUrl.ts
|
||||
src/utils/share/copyEntityShareLink.ts
|
||||
|
||||
# ── M0: pure helpers extracted from playerStore.ts (2026-05-12) ──────
|
||||
src/utils/shuffleArray.ts
|
||||
src/utils/resolveReplayGainDb.ts
|
||||
src/utils/songToTrack.ts
|
||||
src/utils/buildInfiniteQueueCandidates.ts
|
||||
src/utils/playback/shuffleArray.ts
|
||||
src/utils/audio/resolveReplayGainDb.ts
|
||||
src/utils/playback/songToTrack.ts
|
||||
src/utils/playback/buildInfiniteQueueCandidates.ts
|
||||
|
||||
# ── Phase B.1: pre-React bootstrap + window-kind detector (2026-05-12) ──
|
||||
src/app/windowKind.ts
|
||||
|
||||
+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;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user