refactor(ui): move generic presentational primitives into ui/ (CoverLightbox, StarRating, LongPressWaveOverlay, icons, VirtualCardGrid)

This commit is contained in:
Psychotoxical
2026-06-30 18:28:54 +02:00
parent 8cd23e86db
commit 41877d10d8
50 changed files with 52 additions and 52 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useId, useState } from 'react';
import { createPortal } from 'react-dom';
import { X } from 'lucide-react';
import { open as openUrl } from '@tauri-apps/plugin-shell';
import PsysonicLogo from './PsysonicLogo';
import PsysonicLogo from '@/ui/PsysonicLogo';
const TAPS_TO_REVEAL_HINT = 10;
const TARGET_CLICKS_IN_WINDOW = 100;
@@ -5,7 +5,7 @@ import { resolveAlbum, resolveMediaServerId } from '@/features/offline';
import { star, unstar } from '@/lib/api/subsonicStarRating';
import type { SubsonicAlbum } from '@/lib/api/subsonicTypes';
import { songToTrack } from '@/lib/media/songToTrack';
import StarRating from '../StarRating';
import StarRating from '@/ui/StarRating';
import { AlbumToPlaylistSubmenu } from './AlbumArtistToPlaylistSubmenu';
import { MultiAlbumToPlaylistSubmenu } from './MultiAlbumToPlaylistSubmenu';
import type { ContextMenuItemsProps } from './contextMenuItemTypes';
@@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next';
import { Radio, Heart, ChevronRight, ListMusic, Star, Share2 } from 'lucide-react';
import { star, unstar } from '@/lib/api/subsonicStarRating';
import type { SubsonicArtist } from '@/lib/api/subsonicTypes';
import StarRating from '../StarRating';
import StarRating from '@/ui/StarRating';
import { ArtistToPlaylistSubmenu } from './AlbumArtistToPlaylistSubmenu';
import { MultiArtistToPlaylistSubmenu } from './MultiArtistToPlaylistSubmenu';
import type { ContextMenuItemsProps } from './contextMenuItemTypes';
@@ -5,7 +5,7 @@ import { getMusicNetworkRuntime, useEnrichmentPrimary } from '../../music-networ
import type { Track } from '@/lib/media/trackTypes';
import { useAuthStore } from '../../store/authStore';
import { renderPresetIcon } from '../settings/musicNetwork/presetIcon';
import StarRating from '../StarRating';
import StarRating from '@/ui/StarRating';
import { AddToPlaylistSubmenu } from './AddToPlaylistSubmenu';
import type { ContextMenuItemsProps } from './contextMenuItemTypes';
@@ -12,7 +12,7 @@ import { songToTrack } from '@/lib/media/songToTrack';
import { showToast } from '../../utils/ui/toast';
import { suggestOrbitTrack, hostEnqueueToOrbit, evaluateOrbitSuggestGate, OrbitSuggestBlockedError } from '@/features/orbit';
import { renderPresetIcon } from '../settings/musicNetwork/presetIcon';
import StarRating from '../StarRating';
import StarRating from '@/ui/StarRating';
import { AddToPlaylistSubmenu } from './AddToPlaylistSubmenu';
import type { ContextMenuItemsProps } from './contextMenuItemTypes';
+1 -1
View File
@@ -12,7 +12,7 @@ import { useAlbumCoverRef } from '../../cover/useLibraryCoverRef';
import { usePlaybackTrackCoverRef } from '../../cover/useLibraryCoverRef';
import MarqueeText from '@/ui/MarqueeText';
import { OpenArtistRefInline } from '@/features/artist';
import StarRating from '../StarRating';
import StarRating from '@/ui/StarRating';
import { PlaybackBufferingOverlay } from '../playback/PlaybackBufferingOverlay';
import { usePlayerStore } from '@/features/playback/store/playerStore';
import { useEnrichmentPrimaryLabel } from '../../hooks/useEnrichmentPrimaryLabel';
@@ -1,5 +1,5 @@
import { Globe, Radio, Server, Music2, Headphones } from 'lucide-react';
import LastfmIcon from '../../LastfmIcon';
import LastfmIcon from '@/ui/LastfmIcon';
import type { PresetIcon } from '../../../music-network';
/**
+1 -1
View File
@@ -6,7 +6,7 @@ vi.mock('./resolveDisk', () => ({ ensureCoverTierDiskSrc: vi.fn() }));
vi.mock('./diskSrcLookup', () => ({ getDiskSrcForGrid: vi.fn(() => '') }));
vi.mock('./fetchUrl', () => ({ buildCoverArtFetchUrl: vi.fn(() => 'net://2000') }));
vi.mock('./imgSrc', () => ({ coverImgSrc: (s: string) => s }));
vi.mock('../components/CoverLightbox', () => ({ default: () => null }));
vi.mock('@/ui/CoverLightbox', () => ({ default: () => null }));
import { useCoverLightboxSrc } from './lightbox';
import { ensureCoverTierDiskSrc } from './resolveDisk';
+1 -1
View File
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useState, type ReactNode } from 'react';
import CoverLightbox from '../components/CoverLightbox';
import CoverLightbox from '@/ui/CoverLightbox';
import { buildCoverArtFetchUrl } from './fetchUrl';
import { coverImgSrc } from './imgSrc';
import { getDiskSrcForGrid } from './diskSrcLookup';
+1 -1
View File
@@ -18,7 +18,7 @@ import { acquireUrl } from '@/utils/imageCache/urlPool';
import { OpenArtistRefInline } from '@/features/artist';
import { fetchAlbumTracks, playAlbum, playAlbumShuffled } from '@/features/playback/utils/playback/playAlbum';
import { useLongPressAction } from '@/lib/hooks/useLongPressAction';
import { LongPressWaveOverlay } from '@/components/LongPressWaveOverlay';
import { LongPressWaveOverlay } from '@/ui/LongPressWaveOverlay';
import { useDragDrop } from '@/lib/dnd/DragDropContext';
import { isAlbumRecentlyAdded } from '@/features/album/utils/albumRecency';
import { albumArtistDisplayName, deriveAlbumArtistRefs } from '@/features/album/utils/deriveAlbumHeaderArtistRefs';
@@ -18,7 +18,7 @@ vi.mock('@/cover/lightbox', () => ({ useCoverLightboxSrc: () => ({ open: vi.fn()
vi.mock('@/features/album/hooks/useAlbumDetailBack', () => ({ useAlbumDetailBack: () => vi.fn() }));
vi.mock('@/lib/hooks/useIsMobile', () => ({ useIsMobile: () => false }));
vi.mock('@/store/themeStore', () => ({ useThemeStore: () => false }));
vi.mock('@/components/StarRating', () => ({ default: () => null }));
vi.mock('@/ui/StarRating', () => ({ default: () => null }));
vi.mock('@/features/artist', () => ({ OpenArtistRefInline: () => null }));
vi.mock('@/cover/CoverArtImage', () => ({ CoverArtImage: () => null }));
@@ -10,7 +10,7 @@ import { useTranslation } from 'react-i18next';
import { useIsMobile } from '@/lib/hooks/useIsMobile';
import { useAlbumDetailBack } from '@/features/album/hooks/useAlbumDetailBack';
import { useThemeStore } from '@/store/themeStore';
import StarRating from '@/components/StarRating';
import StarRating from '@/ui/StarRating';
import { copyEntityShareLink } from '@/utils/share/copyEntityShareLink';
import { showToast } from '@/utils/ui/toast';
import { isAlbumRecentlyAdded } from '@/features/album/utils/albumRecency';
+1 -1
View File
@@ -9,7 +9,7 @@ import { songToTrack } from '@/lib/media/songToTrack';
import { useSelectionStore } from '@/store/selectionStore';
import { useThemeStore } from '@/store/themeStore';
import { previewInputFromSong, usePreviewStore } from '@/features/playback/store/previewStore';
import StarRating from '@/components/StarRating';
import StarRating from '@/ui/StarRating';
import { codecLabel, type ColKey } from '@/features/album/utils/albumTrackListHelpers';
import { formatLongDuration } from '@/lib/format/formatDuration';
import { formatLastSeen } from '@/utils/componentHelpers/userMgmtHelpers';
+1 -1
View File
@@ -41,7 +41,7 @@ import { sanitizeFilename } from '@/features/album/utils/albumDetailHelpers';
import { albumArtistDisplayName, deriveAlbumHeaderArtistRefs } from '@/features/album/utils/deriveAlbumHeaderArtistRefs';
import { usePerfProbeFlags } from '@/utils/perf/perfFlags';
import { albumGridWarmCovers } from '@/cover/layoutSizes';
import { VirtualCardGrid } from '@/components/VirtualCardGrid';
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
import LosslessModeBanner from '@/components/LosslessModeBanner';
import { isLosslessSuffix } from '@/lib/library/losslessFormats';
import { isLosslessMode } from '@/lib/library/losslessMode';
+1 -1
View File
@@ -30,7 +30,7 @@ import { useRangeSelection } from '@/lib/hooks/useRangeSelection';
import { useMainstageInpageHeaderTight } from '@/hooks/useMainstageInpageHeaderTight';
import { useInpageScrollViewport } from '@/hooks/useInpageScrollViewport';
import InpageScrollSentinel from '@/ui/InpageScrollSentinel';
import { VirtualCardGrid } from '@/components/VirtualCardGrid';
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
import OverlayScrollArea from '@/ui/OverlayScrollArea';
import { ALBUMS_INPAGE_SCROLL_VIEWPORT_ID } from '@/constants/appScroll';
import { useLibraryIndexStore } from '@/store/libraryIndexStore';
+1 -1
View File
@@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next';
import { useAuthStore } from '@/store/authStore';
import { usePerfProbeFlags } from '@/utils/perf/perfFlags';
import { albumGridWarmCovers } from '@/cover/layoutSizes';
import { VirtualCardGrid } from '@/components/VirtualCardGrid';
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
export default function LabelAlbums() {
const { t } = useTranslation();
+1 -1
View File
@@ -21,7 +21,7 @@ import { join } from '@tauri-apps/api/path';
import { Download, HardDriveDownload, ListPlus } from 'lucide-react';
import SelectionToggleButton from '@/ui/SelectionToggleButton';
import { albumGridWarmCovers } from '@/cover/layoutSizes';
import { VirtualCardGrid } from '@/components/VirtualCardGrid';
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
import OverlayScrollArea from '@/ui/OverlayScrollArea';
import { LOSSLESS_ALBUMS_INPAGE_SCROLL_VIEWPORT_ID } from '@/constants/appScroll';
import { useInpageScrollSentinel } from '@/hooks/useInpageScrollSentinel';
+1 -1
View File
@@ -11,7 +11,7 @@ import { AlbumCoverArtImage } from '@/cover/AlbumCoverArtImage';
import { ArtistCoverArtImage } from '@/cover/ArtistCoverArtImage';
import { playAlbum, playAlbumShuffled } from '@/features/playback/utils/playback/playAlbum';
import { useLongPressAction } from '@/lib/hooks/useLongPressAction';
import { LongPressWaveOverlay } from '@/components/LongPressWaveOverlay';
import { LongPressWaveOverlay } from '@/ui/LongPressWaveOverlay';
import { useTranslation } from 'react-i18next';
import { albumArtistDisplayName } from '@/features/album/utils/deriveAlbumHeaderArtistRefs';
+1 -1
View File
@@ -22,7 +22,7 @@ import { useRangeSelection } from '@/lib/hooks/useRangeSelection';
import { usePerfProbeFlags } from '@/utils/perf/perfFlags';
import { useMainstageInpageHeaderTight } from '@/hooks/useMainstageInpageHeaderTight';
import { albumGridWarmCovers } from '@/cover/layoutSizes';
import { VirtualCardGrid } from '@/components/VirtualCardGrid';
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
import OverlayScrollArea from '@/ui/OverlayScrollArea';
import { NEW_RELEASES_INPAGE_SCROLL_VIEWPORT_ID } from '@/constants/appScroll';
import { useAsyncInpagePagination } from '@/hooks/useAsyncInpagePagination';
+1 -1
View File
@@ -28,7 +28,7 @@ import { albumGridWarmCovers, COVER_DENSE_GRID_MIN_CELL_CSS_PX } from '@/cover/l
import {
primeAlbumCoversForDisplay,
} from '@/cover/warmDiskPeek';
import { VirtualCardGrid } from '@/components/VirtualCardGrid';
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
import OverlayScrollArea from '@/ui/OverlayScrollArea';
import { RANDOM_ALBUMS_INPAGE_SCROLL_VIEWPORT_ID } from '@/constants/appScroll';
import { useMainstageInpageHeaderTight } from '@/hooks/useMainstageInpageHeaderTight';
+1 -1
View File
@@ -3,7 +3,7 @@ import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { coverArtRef } from '@/cover/ref';
import { loadCoverBlobForExport } from '@/cover/integrations/export';
import PsysonicLogo from '@/components/PsysonicLogo';
import PsysonicLogo from '@/ui/PsysonicLogo';
export type ExportFormat = 'story' | 'square' | 'twitter';
export type ExportGridSize = 3 | 4 | 5;
@@ -18,9 +18,9 @@ import { usePlaybackCoverArt } from '@/cover/usePlaybackCoverArt';
import { useCachedUrl } from '@/ui/CachedImage';
import { useCoverLightboxSrc } from '@/cover/lightbox';
import type { CoverArtRef } from '@/cover/types';
import LastfmIcon from '@/components/LastfmIcon';
import WikipediaIcon from '@/components/WikipediaIcon';
import StarRating from '@/components/StarRating';
import LastfmIcon from '@/ui/LastfmIcon';
import WikipediaIcon from '@/ui/WikipediaIcon';
import StarRating from '@/ui/StarRating';
import { tooltipAttrs } from '@/ui/tooltipAttrs';
import { offlineActionPolicy, type OfflineActionPolicy } from '@/features/offline';
@@ -4,7 +4,7 @@ import type { TFunction } from 'i18next';
import type { SubsonicArtist } from '@/lib/api/subsonicTypes';
import type { PlayerState } from '@/features/playback/store/playerStoreTypes';
import { ARTISTS_INPAGE_SCROLL_VIEWPORT_ID } from '@/constants/appScroll';
import { VirtualCardGrid } from '@/components/VirtualCardGrid';
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
import { ArtistCardAvatar } from '@/features/artist/components/ArtistAvatars';
interface TileProps {
+1 -1
View File
@@ -35,7 +35,7 @@ import { albumGridWarmCovers, COVER_DENSE_GRID_MIN_CELL_CSS_PX, GRID_COVER_WARM_
import { artistDetailCoverWarmAlbums } from '@/features/artist/components/topSongAlbumForCover';
import { useLibraryCoverPrefetch } from '@/cover/useLibraryCoverPrefetch';
import { useWarmGridCovers } from '@/hooks/useWarmGridCovers';
import { VirtualCardGrid } from '@/components/VirtualCardGrid';
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
import { LOSSLESS_MODE_QUERY } from '@/lib/library/losslessMode';
import { sortArtistAlbumsByYear } from '@/features/artist/utils/sortArtistAlbums';
import { readDetailServerId } from '@/utils/navigation/detailServerScope';
@@ -9,7 +9,7 @@ import { ArtistHeroCover } from '@/cover/artistHero';
import { coverArtRef } from '@/cover/ref';
import { useCoverLightboxSrc } from '@/cover/lightbox';
import { ArrowLeft, Users, Heart, Feather, Share2 } from 'lucide-react';
import WikipediaIcon from '@/components/WikipediaIcon';
import WikipediaIcon from '@/ui/WikipediaIcon';
import { open } from '@tauri-apps/plugin-shell';
import { usePlayerStore } from '@/features/playback/store/playerStore';
import { useAuthStore } from '@/store/authStore';
@@ -19,7 +19,7 @@ import { showToast } from '@/utils/ui/toast';
import { sanitizeHtml } from '@/lib/util/sanitizeHtml';
import { usePerfProbeFlags } from '@/utils/perf/perfFlags';
import { albumGridWarmCovers } from '@/cover/layoutSizes';
import { VirtualCardGrid } from '@/components/VirtualCardGrid';
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
export default function ComposerDetail() {
const { t } = useTranslation();
+1 -1
View File
@@ -23,7 +23,7 @@ import { filterArtistsWithRoleAlbumCredits } from '@/lib/library/composerBrowse'
import { ALL_SENTINEL, artistLetterBucket } from '@/features/artist';
import { useLibraryIgnoredArticles } from '@/hooks/useLibraryIgnoredArticles';
import { usePerfProbeFlags } from '@/utils/perf/perfFlags';
import { VirtualCardGrid } from '@/components/VirtualCardGrid';
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
import OverlayScrollArea from '@/ui/OverlayScrollArea';
import { useVirtualizerScrollMargin } from '@/lib/hooks/useVirtualizerScrollMargin';
import { useClientSliceInfiniteScroll } from '@/hooks/useClientSliceInfiniteScroll';
@@ -7,7 +7,7 @@ import { codecLabel } from '@/utils/componentHelpers/playlistDetailHelpers';
import { formatLastSeen } from '@/utils/componentHelpers/userMgmtHelpers';
import i18n from '@/lib/i18n';
import { formatTrackTime } from '@/lib/format/formatDuration';
import StarRating from '@/components/StarRating';
import StarRating from '@/ui/StarRating';
import { OpenArtistRefInline } from '@/features/artist';
import { resolveTrackArtistRefs } from '@/features/playback/utils/playback/trackArtistRefs';
+2 -2
View File
@@ -3,10 +3,10 @@ import { useLocation, useNavigate, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { ArrowLeft, Disc3, Play, ListPlus, Loader2 } from 'lucide-react';
import { AlbumCard } from '@/features/album';
import { LongPressWaveOverlay } from '@/components/LongPressWaveOverlay';
import { LongPressWaveOverlay } from '@/ui/LongPressWaveOverlay';
import InpageScrollSentinel from '@/ui/InpageScrollSentinel';
import OverlayScrollArea from '@/ui/OverlayScrollArea';
import { VirtualCardGrid } from '@/components/VirtualCardGrid';
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
import { GENRE_DETAIL_INPAGE_SCROLL_VIEWPORT_ID } from '@/constants/appScroll';
import { albumGridWarmCovers } from '@/cover/layoutSizes';
import { useAlbumBrowseScrollSnapshotSync, type AlbumBrowseScrollSnapshot } from '@/features/album';
@@ -22,7 +22,7 @@ import { usePlayerStore } from '@/features/playback/store/playerStore';
import { useAuthStore } from '@/store/authStore';
import { playAlbum, playAlbumShuffled } from '@/features/playback/utils/playback/playAlbum';
import { useLongPressAction } from '@/lib/hooks/useLongPressAction';
import { LongPressWaveOverlay } from '@/components/LongPressWaveOverlay';
import { LongPressWaveOverlay } from '@/ui/LongPressWaveOverlay';
import { formatHumanHoursMinutes } from '@/lib/format/formatHumanDuration';
import { AlbumRow } from '@/features/album';
import { albumArtistDisplayName } from '@/features/album';
+1 -1
View File
@@ -21,7 +21,7 @@ import { filterAlbumsByMixRatings, getMixMinRatingsConfigFromAuth } from '@/util
import { usePerfProbeFlags } from '@/utils/perf/perfFlags';
import { playAlbum, playAlbumShuffled } from '@/features/playback/utils/playback/playAlbum';
import { useLongPressAction } from '@/lib/hooks/useLongPressAction';
import { LongPressWaveOverlay } from '@/components/LongPressWaveOverlay';
import { LongPressWaveOverlay } from '@/ui/LongPressWaveOverlay';
import { albumArtistDisplayName, deriveAlbumArtistRefs } from '@/features/album';
const INTERVAL_MS = 10000;
@@ -11,7 +11,7 @@ import { AlbumCoverArtImage } from '@/cover/AlbumCoverArtImage';
import { coverServerScopeForServerId } from '@/cover/serverScope';
import { usePerfProbeFlags } from '@/utils/perf/perfFlags';
import { GRID_COVER_WARM_LIMIT } from '@/cover/layoutSizes';
import { VirtualCardGrid } from '@/components/VirtualCardGrid';
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
import { OfflineLibraryDiskStat } from '@/features/offline/components/OfflineLibraryDiskStat';
import {
buildOfflineCacheQueueTracks,
@@ -5,7 +5,7 @@ import type { SubsonicPlaylist } from '@/lib/api/subsonicTypes';
import { usePlaylistFolderStore } from '@/features/playlist/store/playlistFolderStore';
import type { PlaylistFolder } from '@/features/playlist/utils/playlistFolders';
import { useDragDrop } from '@/lib/dnd/DragDropContext';
import { VirtualCardGrid } from '@/components/VirtualCardGrid';
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
interface Props {
serverId: string;
@@ -7,7 +7,7 @@ import { codecLabel } from '@/utils/componentHelpers/playlistDetailHelpers';
import { formatLastSeen } from '@/utils/componentHelpers/userMgmtHelpers';
import i18n from '@/lib/i18n';
import { formatTrackTime } from '@/lib/format/formatDuration';
import StarRating from '@/components/StarRating';
import StarRating from '@/ui/StarRating';
import { PlaylistArtistCell } from '@/features/playlist/components/PlaylistArtistCell';
export interface PlaylistRowCallbacks {
@@ -6,7 +6,7 @@ import type { ColDef } from '@/utils/useTracklistColumns';
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
import { usePlayerStore } from '@/features/playback/store/playerStore';
import { usePreviewStore } from '@/features/playback/store/previewStore';
import StarRating from '@/components/StarRating';
import StarRating from '@/ui/StarRating';
import { PlaylistArtistCell } from '@/features/playlist/components/PlaylistArtistCell';
import { useThemeStore } from '@/store/themeStore';
import { usePlaylistLayoutStore } from '@/features/playlist/store/playlistLayoutStore';
@@ -1,7 +1,7 @@
import React, { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { Plus } from 'lucide-react';
import StarRating from '@/components/StarRating';
import StarRating from '@/ui/StarRating';
import CustomSelect from '@/ui/CustomSelect';
import {
LIMIT_MAX, YEAR_MAX, YEAR_MIN, clampYear, defaultSmartFilters,
+1 -1
View File
@@ -26,7 +26,7 @@ import PlaylistsSmartEditor from '@/features/playlist/components/PlaylistsSmartE
import PlaylistsHeader from '@/features/playlist/components/PlaylistsHeader';
import PlaylistCard from '@/features/playlist/components/PlaylistCard';
import { usePerfProbeFlags } from '@/utils/perf/perfFlags';
import { VirtualCardGrid } from '@/components/VirtualCardGrid';
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
import { useOfflineBrowseContext } from '@/features/offline';
import { offlineActionPolicy } from '@/features/offline';
import { Info } from 'lucide-react';
+1 -1
View File
@@ -14,7 +14,7 @@ import RadioCard from '@/features/radio/components/RadioCard';
import RadioEditModal from '@/features/radio/components/RadioEditModal';
import RadioDirectoryModal from '@/features/radio/components/RadioDirectoryModal';
import { usePerfProbeFlags } from '@/utils/perf/perfFlags';
import { VirtualCardGrid } from '@/components/VirtualCardGrid';
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
import { useNavidromeAdminRole, canManageNavidromeRadio } from '@/hooks/useNavidromeAdminRole';
export default function InternetRadio() {
@@ -7,7 +7,7 @@ import SettingsSubSection from '@/features/settings/components/SettingsSubSectio
import { SettingsGroup } from '@/features/settings/components/SettingsGroup';
import { SettingsToggle } from '@/features/settings/components/SettingsToggle';
import { SettingsSubCard, SettingsField } from '@/features/settings/components/SettingsSubCard';
import StarRating from '@/components/StarRating';
import StarRating from '@/ui/StarRating';
import AnalyticsStrategySection from '@/features/settings/components/AnalyticsStrategySection';
const AUDIOBOOK_GENRES_DISPLAY = ['Hörbuch', 'Hoerbuch', 'Hörspiel', 'Hoerspiel', 'Audiobook', 'Audio Book', 'Spoken Word', 'Spokenword', 'Podcast', 'Kapitel', 'Thriller', 'Krimi', 'Speech', 'Fantasy', 'Comedy', 'Literature'];
@@ -1,7 +1,7 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Gauge, Heart, PictureInPicture2, SlidersVertical, Star } from 'lucide-react';
import LastfmIcon from '@/components/LastfmIcon';
import LastfmIcon from '@/ui/LastfmIcon';
import {
usePlayerBarLayoutStore,
type PlayerBarLayoutItemId,
@@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Check, ChevronLeft, ChevronRight, Download, RefreshCw, Trash2, WifiOff } from 'lucide-react';
import { open as openUrl } from '@tauri-apps/plugin-shell';
import CoverLightbox from '@/components/CoverLightbox';
import CoverLightbox from '@/ui/CoverLightbox';
import { useThemeAnimationRisk } from '@/hooks/useThemeAnimationRisk';
import { AnimatedThemeBadge } from '@/features/settings/components/AnimatedThemeBadge';
import CustomSelect from '@/ui/CustomSelect';
+2 -2
View File
@@ -9,8 +9,8 @@ import { useSidebarStore } from '@/features/sidebar/store/sidebarStore';
import { useLocation } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { PanelLeft, PanelLeftClose, Trash2 } from 'lucide-react';
import PsysonicLogo from '@/components/PsysonicLogo';
import PSmallLogo from '@/components/PSmallLogo';
import PsysonicLogo from '@/ui/PsysonicLogo';
import PSmallLogo from '@/ui/PSmallLogo';
import { usePlaylistStore } from '@/features/playlist';
import OverlayScrollArea from '@/ui/OverlayScrollArea';
import {
@@ -2,7 +2,7 @@ import { describe, it, expect, vi } from 'vitest';
import { screen, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { renderWithProviders } from '@/test/helpers/renderWithProviders';
import CoverLightbox from './CoverLightbox';
import CoverLightbox from '@/ui/CoverLightbox';
describe('CoverLightbox', () => {
it('renders the cover image with the supplied src and alt', () => {
@@ -1,13 +1,13 @@
import React, { useCallback, useMemo, useRef } from 'react';
import { GRID_COVER_WARM_LIMIT } from '../cover/layoutSizes';
import { useWarmGridCovers } from '../hooks/useWarmGridCovers';
import { GRID_COVER_WARM_LIMIT } from '@/cover/layoutSizes';
import { useWarmGridCovers } from '@/hooks/useWarmGridCovers';
import { useVirtualizer } from '@tanstack/react-virtual';
import { APP_MAIN_SCROLL_VIEWPORT_ID } from '../constants/appScroll';
import { APP_MAIN_SCROLL_VIEWPORT_ID } from '@/constants/appScroll';
import { useElementClientHeightById } from '@/lib/hooks/useResizeClientHeight';
import { useCardGridMetrics } from '../hooks/useCardGridMetrics';
import { useCardGridMetrics } from '@/hooks/useCardGridMetrics';
import { useRemeasureGridVirtualizer } from '@/lib/hooks/useRemeasureGridVirtualizer';
import { useVirtualizerScrollMargin } from '@/lib/hooks/useVirtualizerScrollMargin';
import type { CardGridRowHeightVariant } from '../utils/cardGridLayout';
import type { CardGridRowHeightVariant } from '@/utils/cardGridLayout';
export type VirtualCardGridProps<T> = {
items: readonly T[];