From 41877d10d81e8b141723a05e7225bccf639038d1 Mon Sep 17 00:00:00 2001 From: Psychotoxical <171614930+Psychotoxical@users.noreply.github.com> Date: Tue, 30 Jun 2026 18:28:54 +0200 Subject: [PATCH] refactor(ui): move generic presentational primitives into ui/ (CoverLightbox, StarRating, LongPressWaveOverlay, icons, VirtualCardGrid) --- src/components/AboutPsysonicLol.tsx | 2 +- src/components/contextMenu/AlbumContextItems.tsx | 2 +- src/components/contextMenu/ArtistContextItems.tsx | 2 +- src/components/contextMenu/QueueItemContextItems.tsx | 2 +- src/components/contextMenu/SongContextItems.tsx | 2 +- src/components/playerBar/PlayerTrackInfo.tsx | 2 +- src/components/settings/musicNetwork/presetIcon.tsx | 2 +- src/cover/lightbox.test.tsx | 2 +- src/cover/lightbox.tsx | 2 +- src/features/album/components/AlbumCard.tsx | 2 +- src/features/album/components/AlbumHeader.test.tsx | 2 +- src/features/album/components/AlbumHeader.tsx | 2 +- src/features/album/components/TrackRow.tsx | 2 +- src/features/album/pages/AlbumDetail.tsx | 2 +- src/features/album/pages/Albums.tsx | 2 +- src/features/album/pages/LabelAlbums.tsx | 2 +- src/features/album/pages/LosslessAlbums.tsx | 2 +- src/features/album/pages/MostPlayed.tsx | 2 +- src/features/album/pages/NewReleases.tsx | 2 +- src/features/album/pages/RandomAlbums.tsx | 2 +- src/features/album/utils/exportAlbumCard.ts | 2 +- src/features/artist/components/ArtistDetailHero.tsx | 6 +++--- src/features/artist/components/ArtistsGridView.tsx | 2 +- src/features/artist/pages/ArtistDetail.tsx | 2 +- src/features/composers/pages/ComposerDetail.tsx | 4 ++-- src/features/composers/pages/Composers.tsx | 2 +- src/features/favorites/components/FavoriteSongRow.tsx | 2 +- src/features/genre/pages/GenreDetail.tsx | 4 ++-- src/features/home/components/BecauseYouLikeRail.tsx | 2 +- src/features/home/components/Hero.tsx | 2 +- src/features/offline/pages/OfflineLibrary.tsx | 2 +- .../playlist/components/PlaylistFolderSection.tsx | 2 +- src/features/playlist/components/PlaylistRow.tsx | 2 +- .../playlist/components/PlaylistSuggestions.tsx | 2 +- .../playlist/components/PlaylistsSmartEditor.tsx | 2 +- src/features/playlist/pages/Playlists.tsx | 2 +- src/features/radio/pages/InternetRadio.tsx | 2 +- src/features/settings/components/LibraryTab.tsx | 2 +- .../settings/components/PlayerBarLayoutCustomizer.tsx | 2 +- src/features/settings/components/ThemeStoreSection.tsx | 2 +- src/features/sidebar/components/Sidebar.tsx | 4 ++-- src/{components => ui}/CoverLightbox.test.tsx | 2 +- src/{components => ui}/CoverLightbox.tsx | 0 src/{components => ui}/LastfmIcon.tsx | 0 src/{components => ui}/LongPressWaveOverlay.tsx | 0 src/{components => ui}/PSmallLogo.tsx | 0 src/{components => ui}/PsysonicLogo.tsx | 0 src/{components => ui}/StarRating.tsx | 0 src/{components => ui}/VirtualCardGrid.tsx | 10 +++++----- src/{components => ui}/WikipediaIcon.tsx | 0 50 files changed, 52 insertions(+), 52 deletions(-) rename src/{components => ui}/CoverLightbox.test.tsx (97%) rename src/{components => ui}/CoverLightbox.tsx (100%) rename src/{components => ui}/LastfmIcon.tsx (100%) rename src/{components => ui}/LongPressWaveOverlay.tsx (100%) rename src/{components => ui}/PSmallLogo.tsx (100%) rename src/{components => ui}/PsysonicLogo.tsx (100%) rename src/{components => ui}/StarRating.tsx (100%) rename src/{components => ui}/VirtualCardGrid.tsx (94%) rename src/{components => ui}/WikipediaIcon.tsx (100%) diff --git a/src/components/AboutPsysonicLol.tsx b/src/components/AboutPsysonicLol.tsx index 0e981106..09ef7720 100644 --- a/src/components/AboutPsysonicLol.tsx +++ b/src/components/AboutPsysonicLol.tsx @@ -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; diff --git a/src/components/contextMenu/AlbumContextItems.tsx b/src/components/contextMenu/AlbumContextItems.tsx index 1456b77d..3a7f8a03 100644 --- a/src/components/contextMenu/AlbumContextItems.tsx +++ b/src/components/contextMenu/AlbumContextItems.tsx @@ -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'; diff --git a/src/components/contextMenu/ArtistContextItems.tsx b/src/components/contextMenu/ArtistContextItems.tsx index 0143e5b7..da423e8d 100644 --- a/src/components/contextMenu/ArtistContextItems.tsx +++ b/src/components/contextMenu/ArtistContextItems.tsx @@ -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'; diff --git a/src/components/contextMenu/QueueItemContextItems.tsx b/src/components/contextMenu/QueueItemContextItems.tsx index 1d7f2805..4786a421 100644 --- a/src/components/contextMenu/QueueItemContextItems.tsx +++ b/src/components/contextMenu/QueueItemContextItems.tsx @@ -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'; diff --git a/src/components/contextMenu/SongContextItems.tsx b/src/components/contextMenu/SongContextItems.tsx index 32e3d521..cdb30463 100644 --- a/src/components/contextMenu/SongContextItems.tsx +++ b/src/components/contextMenu/SongContextItems.tsx @@ -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'; diff --git a/src/components/playerBar/PlayerTrackInfo.tsx b/src/components/playerBar/PlayerTrackInfo.tsx index b3727f5f..b9a9c8e8 100644 --- a/src/components/playerBar/PlayerTrackInfo.tsx +++ b/src/components/playerBar/PlayerTrackInfo.tsx @@ -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'; diff --git a/src/components/settings/musicNetwork/presetIcon.tsx b/src/components/settings/musicNetwork/presetIcon.tsx index ef771ca8..dbd69542 100644 --- a/src/components/settings/musicNetwork/presetIcon.tsx +++ b/src/components/settings/musicNetwork/presetIcon.tsx @@ -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'; /** diff --git a/src/cover/lightbox.test.tsx b/src/cover/lightbox.test.tsx index 6b1d341a..daaa0129 100644 --- a/src/cover/lightbox.test.tsx +++ b/src/cover/lightbox.test.tsx @@ -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'; diff --git a/src/cover/lightbox.tsx b/src/cover/lightbox.tsx index 97784754..2e905212 100644 --- a/src/cover/lightbox.tsx +++ b/src/cover/lightbox.tsx @@ -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'; diff --git a/src/features/album/components/AlbumCard.tsx b/src/features/album/components/AlbumCard.tsx index 2eb4ab39..7b03d3c4 100644 --- a/src/features/album/components/AlbumCard.tsx +++ b/src/features/album/components/AlbumCard.tsx @@ -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'; diff --git a/src/features/album/components/AlbumHeader.test.tsx b/src/features/album/components/AlbumHeader.test.tsx index fd5572e4..a4f3598e 100644 --- a/src/features/album/components/AlbumHeader.test.tsx +++ b/src/features/album/components/AlbumHeader.test.tsx @@ -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 })); diff --git a/src/features/album/components/AlbumHeader.tsx b/src/features/album/components/AlbumHeader.tsx index 7d4a4c40..47d1fd8b 100644 --- a/src/features/album/components/AlbumHeader.tsx +++ b/src/features/album/components/AlbumHeader.tsx @@ -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'; diff --git a/src/features/album/components/TrackRow.tsx b/src/features/album/components/TrackRow.tsx index 358b4060..42ea0fe7 100644 --- a/src/features/album/components/TrackRow.tsx +++ b/src/features/album/components/TrackRow.tsx @@ -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'; diff --git a/src/features/album/pages/AlbumDetail.tsx b/src/features/album/pages/AlbumDetail.tsx index bdb402a0..730be3cf 100644 --- a/src/features/album/pages/AlbumDetail.tsx +++ b/src/features/album/pages/AlbumDetail.tsx @@ -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'; diff --git a/src/features/album/pages/Albums.tsx b/src/features/album/pages/Albums.tsx index fc9077eb..901291b0 100644 --- a/src/features/album/pages/Albums.tsx +++ b/src/features/album/pages/Albums.tsx @@ -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'; diff --git a/src/features/album/pages/LabelAlbums.tsx b/src/features/album/pages/LabelAlbums.tsx index cf62b5cd..c278eded 100644 --- a/src/features/album/pages/LabelAlbums.tsx +++ b/src/features/album/pages/LabelAlbums.tsx @@ -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(); diff --git a/src/features/album/pages/LosslessAlbums.tsx b/src/features/album/pages/LosslessAlbums.tsx index 817a2b1f..c91436bf 100644 --- a/src/features/album/pages/LosslessAlbums.tsx +++ b/src/features/album/pages/LosslessAlbums.tsx @@ -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'; diff --git a/src/features/album/pages/MostPlayed.tsx b/src/features/album/pages/MostPlayed.tsx index 30d155db..16b65901 100644 --- a/src/features/album/pages/MostPlayed.tsx +++ b/src/features/album/pages/MostPlayed.tsx @@ -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'; diff --git a/src/features/album/pages/NewReleases.tsx b/src/features/album/pages/NewReleases.tsx index c6f13dcc..036d3f56 100644 --- a/src/features/album/pages/NewReleases.tsx +++ b/src/features/album/pages/NewReleases.tsx @@ -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'; diff --git a/src/features/album/pages/RandomAlbums.tsx b/src/features/album/pages/RandomAlbums.tsx index 5e18d071..d10967ce 100644 --- a/src/features/album/pages/RandomAlbums.tsx +++ b/src/features/album/pages/RandomAlbums.tsx @@ -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'; diff --git a/src/features/album/utils/exportAlbumCard.ts b/src/features/album/utils/exportAlbumCard.ts index 87ca9661..3b02ea8e 100644 --- a/src/features/album/utils/exportAlbumCard.ts +++ b/src/features/album/utils/exportAlbumCard.ts @@ -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; diff --git a/src/features/artist/components/ArtistDetailHero.tsx b/src/features/artist/components/ArtistDetailHero.tsx index 040d4ca9..c18aeb61 100644 --- a/src/features/artist/components/ArtistDetailHero.tsx +++ b/src/features/artist/components/ArtistDetailHero.tsx @@ -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'; diff --git a/src/features/artist/components/ArtistsGridView.tsx b/src/features/artist/components/ArtistsGridView.tsx index 21bcd7c9..0e5cc8f3 100644 --- a/src/features/artist/components/ArtistsGridView.tsx +++ b/src/features/artist/components/ArtistsGridView.tsx @@ -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 { diff --git a/src/features/artist/pages/ArtistDetail.tsx b/src/features/artist/pages/ArtistDetail.tsx index 1dde0a26..bae9d483 100644 --- a/src/features/artist/pages/ArtistDetail.tsx +++ b/src/features/artist/pages/ArtistDetail.tsx @@ -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'; diff --git a/src/features/composers/pages/ComposerDetail.tsx b/src/features/composers/pages/ComposerDetail.tsx index 967430ec..18246212 100644 --- a/src/features/composers/pages/ComposerDetail.tsx +++ b/src/features/composers/pages/ComposerDetail.tsx @@ -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(); diff --git a/src/features/composers/pages/Composers.tsx b/src/features/composers/pages/Composers.tsx index 99d52100..0e98ca1a 100644 --- a/src/features/composers/pages/Composers.tsx +++ b/src/features/composers/pages/Composers.tsx @@ -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'; diff --git a/src/features/favorites/components/FavoriteSongRow.tsx b/src/features/favorites/components/FavoriteSongRow.tsx index 87e9c2a7..e8a25cbd 100644 --- a/src/features/favorites/components/FavoriteSongRow.tsx +++ b/src/features/favorites/components/FavoriteSongRow.tsx @@ -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'; diff --git a/src/features/genre/pages/GenreDetail.tsx b/src/features/genre/pages/GenreDetail.tsx index d1e54576..335d79c5 100644 --- a/src/features/genre/pages/GenreDetail.tsx +++ b/src/features/genre/pages/GenreDetail.tsx @@ -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'; diff --git a/src/features/home/components/BecauseYouLikeRail.tsx b/src/features/home/components/BecauseYouLikeRail.tsx index 2988ec45..b8af25f2 100644 --- a/src/features/home/components/BecauseYouLikeRail.tsx +++ b/src/features/home/components/BecauseYouLikeRail.tsx @@ -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'; diff --git a/src/features/home/components/Hero.tsx b/src/features/home/components/Hero.tsx index 157b6ed0..6d0ceca2 100644 --- a/src/features/home/components/Hero.tsx +++ b/src/features/home/components/Hero.tsx @@ -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; diff --git a/src/features/offline/pages/OfflineLibrary.tsx b/src/features/offline/pages/OfflineLibrary.tsx index 1514a275..886206ff 100644 --- a/src/features/offline/pages/OfflineLibrary.tsx +++ b/src/features/offline/pages/OfflineLibrary.tsx @@ -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, diff --git a/src/features/playlist/components/PlaylistFolderSection.tsx b/src/features/playlist/components/PlaylistFolderSection.tsx index ebf1fbec..dc00536c 100644 --- a/src/features/playlist/components/PlaylistFolderSection.tsx +++ b/src/features/playlist/components/PlaylistFolderSection.tsx @@ -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; diff --git a/src/features/playlist/components/PlaylistRow.tsx b/src/features/playlist/components/PlaylistRow.tsx index 1403eacd..5d58151c 100644 --- a/src/features/playlist/components/PlaylistRow.tsx +++ b/src/features/playlist/components/PlaylistRow.tsx @@ -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 { diff --git a/src/features/playlist/components/PlaylistSuggestions.tsx b/src/features/playlist/components/PlaylistSuggestions.tsx index c1ad0630..afa901ec 100644 --- a/src/features/playlist/components/PlaylistSuggestions.tsx +++ b/src/features/playlist/components/PlaylistSuggestions.tsx @@ -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'; diff --git a/src/features/playlist/components/PlaylistsSmartEditor.tsx b/src/features/playlist/components/PlaylistsSmartEditor.tsx index a8198d7c..9fdfd1d1 100644 --- a/src/features/playlist/components/PlaylistsSmartEditor.tsx +++ b/src/features/playlist/components/PlaylistsSmartEditor.tsx @@ -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, diff --git a/src/features/playlist/pages/Playlists.tsx b/src/features/playlist/pages/Playlists.tsx index 372cab4d..6f48b1ac 100644 --- a/src/features/playlist/pages/Playlists.tsx +++ b/src/features/playlist/pages/Playlists.tsx @@ -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'; diff --git a/src/features/radio/pages/InternetRadio.tsx b/src/features/radio/pages/InternetRadio.tsx index 49947c51..6ad1e26a 100644 --- a/src/features/radio/pages/InternetRadio.tsx +++ b/src/features/radio/pages/InternetRadio.tsx @@ -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() { diff --git a/src/features/settings/components/LibraryTab.tsx b/src/features/settings/components/LibraryTab.tsx index 9d543b80..2b4df1df 100644 --- a/src/features/settings/components/LibraryTab.tsx +++ b/src/features/settings/components/LibraryTab.tsx @@ -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']; diff --git a/src/features/settings/components/PlayerBarLayoutCustomizer.tsx b/src/features/settings/components/PlayerBarLayoutCustomizer.tsx index 5e323ae5..4fce161a 100644 --- a/src/features/settings/components/PlayerBarLayoutCustomizer.tsx +++ b/src/features/settings/components/PlayerBarLayoutCustomizer.tsx @@ -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, diff --git a/src/features/settings/components/ThemeStoreSection.tsx b/src/features/settings/components/ThemeStoreSection.tsx index 8aa55cbf..8b80d296 100644 --- a/src/features/settings/components/ThemeStoreSection.tsx +++ b/src/features/settings/components/ThemeStoreSection.tsx @@ -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'; diff --git a/src/features/sidebar/components/Sidebar.tsx b/src/features/sidebar/components/Sidebar.tsx index 8fef119f..4172d2c6 100644 --- a/src/features/sidebar/components/Sidebar.tsx +++ b/src/features/sidebar/components/Sidebar.tsx @@ -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 { diff --git a/src/components/CoverLightbox.test.tsx b/src/ui/CoverLightbox.test.tsx similarity index 97% rename from src/components/CoverLightbox.test.tsx rename to src/ui/CoverLightbox.test.tsx index 5a0d88d2..3128c6cf 100644 --- a/src/components/CoverLightbox.test.tsx +++ b/src/ui/CoverLightbox.test.tsx @@ -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', () => { diff --git a/src/components/CoverLightbox.tsx b/src/ui/CoverLightbox.tsx similarity index 100% rename from src/components/CoverLightbox.tsx rename to src/ui/CoverLightbox.tsx diff --git a/src/components/LastfmIcon.tsx b/src/ui/LastfmIcon.tsx similarity index 100% rename from src/components/LastfmIcon.tsx rename to src/ui/LastfmIcon.tsx diff --git a/src/components/LongPressWaveOverlay.tsx b/src/ui/LongPressWaveOverlay.tsx similarity index 100% rename from src/components/LongPressWaveOverlay.tsx rename to src/ui/LongPressWaveOverlay.tsx diff --git a/src/components/PSmallLogo.tsx b/src/ui/PSmallLogo.tsx similarity index 100% rename from src/components/PSmallLogo.tsx rename to src/ui/PSmallLogo.tsx diff --git a/src/components/PsysonicLogo.tsx b/src/ui/PsysonicLogo.tsx similarity index 100% rename from src/components/PsysonicLogo.tsx rename to src/ui/PsysonicLogo.tsx diff --git a/src/components/StarRating.tsx b/src/ui/StarRating.tsx similarity index 100% rename from src/components/StarRating.tsx rename to src/ui/StarRating.tsx diff --git a/src/components/VirtualCardGrid.tsx b/src/ui/VirtualCardGrid.tsx similarity index 94% rename from src/components/VirtualCardGrid.tsx rename to src/ui/VirtualCardGrid.tsx index 1dda46d9..41cce935 100644 --- a/src/components/VirtualCardGrid.tsx +++ b/src/ui/VirtualCardGrid.tsx @@ -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 = { items: readonly T[]; diff --git a/src/components/WikipediaIcon.tsx b/src/ui/WikipediaIcon.tsx similarity index 100% rename from src/components/WikipediaIcon.tsx rename to src/ui/WikipediaIcon.tsx