Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add skeleton loaders to web UI

Add a set of skeleton components (AlbumCard, ArtistCard,
ArtistHeader, DetailHeader, FileList, TrackList, TrackRow) and a
useSkeletonColors hook, and integrate them into Album, Artist, Files,
Playlists and Tracks views. Use isLoading from queries and pass a
loading prop to show placeholders. Add react-content-loader to
package.json.

+316 -32
webui/rockbox/bun.lockb

This is a binary file and will not be displayed.

+1
webui/rockbox/package.json
··· 66 66 "jsdom": "^25.0.1", 67 67 "lodash": "^4.17.21", 68 68 "react": "^18.3.1", 69 + "react-content-loader": "^7.1.2", 69 70 "react-dom": "^18.3.1", 70 71 "react-hook-form": "^7.53.0", 71 72 "react-infinite-scroll-component": "^6.1.0",
+11 -2
webui/rockbox/src/Components/AlbumDetails/AlbumDetails.tsx
··· 31 31 import AlbumArt from "../../Assets/albumart.svg"; 32 32 import ContextMenu from "../ContextMenu"; 33 33 import _ from "lodash"; 34 + import DetailHeaderSkeleton from "../Skeletons/DetailHeaderSkeleton"; 35 + import TrackListSkeleton from "../Skeletons/TrackListSkeleton"; 34 36 35 37 const columnHelper = createColumnHelper<Track>(); 36 38 ··· 42 44 album?: Album | null; 43 45 volumes: Track[][]; 44 46 enableBlur?: boolean; 47 + loading?: boolean; 45 48 onPlayTrack: (position: number, disc: number) => void; 46 49 }; 47 50 ··· 150 153 <ArrowBack color={theme.colors.icon} /> 151 154 </div> 152 155 </BackButton> 153 - <div style={{ marginBottom: 100 }}> 156 + {props.loading && ( 157 + <div style={{ marginTop: 60, marginBottom: 100 }}> 158 + <DetailHeaderSkeleton /> 159 + <TrackListSkeleton /> 160 + </div> 161 + )} 162 + {!props.loading && <div style={{ marginBottom: 100 }}> 154 163 <Header> 155 164 <AlbumCover src={props.album?.albumArt || AlbumArt} /> 156 165 <AlbumInfos> ··· 205 214 ))} 206 215 </div> 207 216 )} 208 - </div> 217 + </div>} 209 218 </ContentWrapper> 210 219 </MainView> 211 220 </Container>
+2 -1
webui/rockbox/src/Components/AlbumDetails/AlbumDetailsWithData.tsx
··· 14 14 const { formatTime } = useTimeFormat(); 15 15 const navigate = useNavigate(); 16 16 const { id } = useParams<{ id: string }>(); 17 - const { data, refetch } = useGetAlbumQuery({ id: id! }); 17 + const { data, isLoading, refetch } = useGetAlbumQuery({ id: id! }); 18 18 const { mutate: playAlbum } = usePlayAlbumMutation(); 19 19 20 20 const album = useMemo( ··· 107 107 album={album as any} 108 108 volumes={volumes} 109 109 enableBlur={enableBlur} 110 + loading={isLoading} 110 111 onPlayTrack={onPlayTrack} 111 112 /> 112 113 );
+16
webui/rockbox/src/Components/Albums/Albums.tsx
··· 7 7 import { Container, FilterContainer, Scrollable, Title } from "./styles"; 8 8 import Filter from "../Filter"; 9 9 import Album from "../Album"; 10 + import AlbumCardSkeleton from "../Skeletons/AlbumCardSkeleton"; 10 11 11 12 export type AlbumsProps = { 12 13 albums: any[]; ··· 26 27 <ControlBar /> 27 28 <Scrollable> 28 29 <Title>Albums</Title> 30 + {props.loading && ( 31 + <div style={{ marginBottom: 100 }}> 32 + <Grid 33 + gridColumns={[2, 4, 5]} 34 + gridMargins={[20, 20, 20]} 35 + gridGutters={[25, 25, 25]} 36 + > 37 + {Array.from({ length: 10 }).map((_, i) => ( 38 + <Cell key={i}> 39 + <AlbumCardSkeleton /> 40 + </Cell> 41 + ))} 42 + </Grid> 43 + </div> 44 + )} 29 45 {(props.albums.length > 0 || props.keyword) && !props.loading && ( 30 46 <> 31 47 <FilterContainer>
+28 -2
webui/rockbox/src/Components/ArtistDetails/ArtistDetails.tsx
··· 33 33 import Album from "../Album"; 34 34 import TrackIcon from "../Icons/Track"; 35 35 import ArtistIcon from "../Icons/Artist"; 36 + import ArtistHeaderSkeleton from "../Skeletons/ArtistHeaderSkeleton"; 37 + import TrackListSkeleton from "../Skeletons/TrackListSkeleton"; 38 + import AlbumCardSkeleton from "../Skeletons/AlbumCardSkeleton"; 36 39 37 40 const columnHelper = createColumnHelper<Track>(); 38 41 ··· 41 44 image?: string; 42 45 tracks: Track[]; 43 46 albums: any[]; 47 + loading?: boolean; 44 48 onPlayAll: () => void; 45 49 onShuffleAll: () => void; 46 50 onPlayAlbum: (album: any) => void; ··· 53 57 }; 54 58 55 59 const ArtistDetails: FC<ArtistDetailsProps> = (props) => { 56 - const { image } = props; 60 + const { image, loading } = props; 57 61 const theme = useTheme(); 58 62 const columns = [ 59 63 columnHelper.accessor("albumArt", { ··· 193 197 <ArrowBack color={theme.colors.icon} /> 194 198 </div> 195 199 </BackButton> 196 - <ArtistHeader> 200 + {loading && ( 201 + <div style={{ marginTop: 20, marginBottom: 100 }}> 202 + <ArtistHeaderSkeleton /> 203 + <div style={{ marginTop: 40 }}> 204 + <TrackListSkeleton /> 205 + </div> 206 + <div style={{ marginTop: 40 }}> 207 + <Grid 208 + gridColumns={[2, 4, 5]} 209 + gridMargins={[0, 0, 0]} 210 + gridGutters={[20, 20, 20]} 211 + > 212 + {Array.from({ length: 5 }).map((_, i) => ( 213 + <Cell key={i}> 214 + <AlbumCardSkeleton /> 215 + </Cell> 216 + ))} 217 + </Grid> 218 + </div> 219 + </div> 220 + )} 221 + {!loading && <><ArtistHeader> 197 222 {image ? ( 198 223 <ArtistPicture src={image} alt={props.name} /> 199 224 ) : ( ··· 236 261 ))} 237 262 </Grid> 238 263 </div> 264 + </>} 239 265 </ContentWrapper> 240 266 </MainView> 241 267 </Container>
+2 -1
webui/rockbox/src/Components/ArtistDetails/ArtistDetailsWithData.tsx
··· 10 10 const ArtistDetailsWithData: FC = () => { 11 11 const navigate = useNavigate(); 12 12 const { id } = useParams<{ id: string }>(); 13 - const { data } = useGetArtistQuery({ id: id! }); 13 + const { data, isLoading } = useGetArtistQuery({ id: id! }); 14 14 const { mutate: playArtistTracks } = usePlayArtistTracksMutation(); 15 15 const { formatTime } = useTimeFormat(); 16 16 const tracks = ··· 41 41 <ArtistDetails 42 42 name={data?.artist?.name || ""} 43 43 image={data?.artist?.image ?? undefined} 44 + loading={isLoading} 44 45 // eslint-disable-next-line @typescript-eslint/no-explicit-any 45 46 tracks={(tracks as any) || []} 46 47 albums={albums || []}
+16
webui/rockbox/src/Components/Artists/Artists.tsx
··· 16 16 import Artist from "../Icons/Artist"; 17 17 import { Link } from "react-router-dom"; 18 18 import Filter from "../Filter"; 19 + import ArtistCardSkeleton from "../Skeletons/ArtistCardSkeleton"; 19 20 20 21 export type ArtistsProps = { 21 22 artists: any[]; ··· 34 35 <ControlBar /> 35 36 <Scrollable> 36 37 <Title>Artists</Title> 38 + {props.loading && ( 39 + <div style={{ marginBottom: 100 }}> 40 + <Grid 41 + gridColumns={[2, 3, 4]} 42 + gridMargins={[18, 18, 18]} 43 + gridGutters={[10, 10, 10]} 44 + > 45 + {Array.from({ length: 8 }).map((_, i) => ( 46 + <Cell key={i} align="center"> 47 + <ArtistCardSkeleton /> 48 + </Cell> 49 + ))} 50 + </Grid> 51 + </div> 52 + )} 37 53 {(props.artists.length > 0 || props.keyword) && !props.loading && ( 38 54 <> 39 55 <FilterContainer>
+2 -13
webui/rockbox/src/Components/Files/Files.tsx
··· 18 18 import Table from "../Table"; 19 19 import "./styles.css"; 20 20 import ArrowBack from "../Icons/ArrowBack"; 21 - import { Spinner } from "baseui/spinner"; 22 21 import MainView from "../MainView"; 23 22 import ContextMenu from "./ContextMenu"; 24 23 import Play from "../Icons/Play"; 24 + import FileListSkeleton from "../Skeletons/FileListSkeleton"; 25 25 26 26 const columnHelper = createColumnHelper<File>(); 27 27 ··· 139 139 {!props.refetching && ( 140 140 <Table columns={columns as any} tracks={props.files as any} /> 141 141 )} 142 - {props.refetching && ( 143 - <div 144 - style={{ 145 - display: "flex", 146 - alignItems: "center", 147 - justifyContent: "center", 148 - height: "calc(100vh - 200px)", 149 - }} 150 - > 151 - <Spinner $size={"30px"} $borderWidth={"4px"} /> 152 - </div> 153 - )} 142 + {props.refetching && <FileListSkeleton />} 154 143 </ContentWrapper> 155 144 </MainView> 156 145 </Container>
+2 -2
webui/rockbox/src/Components/Files/FilesWithData.tsx
··· 11 11 const [refetching, setRefetching] = useState(false); 12 12 const [params] = useSearchParams(); 13 13 const path = params.get("q"); 14 - const { data, refetch } = useGetEntriesQuery(path !== null ? { path } : undefined); 14 + const { data, isLoading, refetch } = useGetEntriesQuery(path !== null ? { path } : undefined); 15 15 const canGoBack = !!path; 16 16 const { mutate: playDirectory } = usePlayDirectoryMutation(); 17 17 ··· 45 45 files={files} 46 46 canGoBack={canGoBack} 47 47 onGoBack={onGoBack} 48 - refetching={refetching} 48 + refetching={isLoading || refetching} 49 49 onPlayDirectory={onPlayDirectory} 50 50 onPlayTrack={onPlayTrack} 51 51 />
+6
webui/rockbox/src/Components/Likes/Likes.tsx
··· 27 27 import Button from "../Button"; 28 28 import Play from "../Icons/Play"; 29 29 import Shuffle from "../Icons/Shuffle"; 30 + import TrackListSkeleton from "../Skeletons/TrackListSkeleton"; 30 31 31 32 const columnHelper = createColumnHelper<Track>(); 32 33 ··· 192 193 <ControlBar /> 193 194 <ContentWrapper ref={containerRef}> 194 195 <Title>Likes</Title> 196 + {props.loading && ( 197 + <div style={{ marginBottom: 60 }}> 198 + <TrackListSkeleton /> 199 + </div> 200 + )} 195 201 {(props.tracks.length > 0 || props.keyword) && !props.loading && ( 196 202 <> 197 203 <HeaderWrapper>
+12 -2
webui/rockbox/src/Components/PlaylistDetails/PlaylistDetails.tsx
··· 28 28 import { Track } from "../../Types/track"; 29 29 import ContextMenu from "../ContextMenu"; 30 30 import { Music } from "@styled-icons/boxicons-regular"; 31 + import DetailHeaderSkeleton from "../Skeletons/DetailHeaderSkeleton"; 32 + import TrackListSkeleton from "../Skeletons/TrackListSkeleton"; 31 33 32 34 const columnHelper = createColumnHelper<Track>(); 33 35 ··· 35 37 playlist?: any; 36 38 tracks: Track[]; 37 39 isSmart?: boolean; 40 + loading?: boolean; 38 41 onGoBack: () => void; 39 42 onPlayAll: () => void; 40 43 onShuffleAll: () => void; ··· 46 49 playlist, 47 50 tracks, 48 51 isSmart, 52 + loading, 49 53 onGoBack, 50 54 onPlayAll, 51 55 onShuffleAll, ··· 163 167 <ArrowBack color={theme.colors.icon} /> 164 168 </div> 165 169 </BackButton> 166 - <div style={{ marginBottom: 100 }}> 170 + {loading && ( 171 + <div style={{ marginTop: 60, marginBottom: 100 }}> 172 + <DetailHeaderSkeleton /> 173 + <TrackListSkeleton /> 174 + </div> 175 + )} 176 + {!loading && <div style={{ marginBottom: 100 }}> 167 177 <Header> 168 178 <CoverArt image={playlist?.image}> 169 179 {!playlist?.image && <Music size={64} color="#bbb" />} ··· 205 215 {tracks.length > 0 && ( 206 216 <Table columns={columns as any} tracks={tracks} /> 207 217 )} 208 - </div> 218 + </div>} 209 219 </ContentWrapper> 210 220 </MainView> 211 221 </Container>
+9 -4
webui/rockbox/src/Components/PlaylistDetails/PlaylistDetailsWithData.tsx
··· 24 24 const { formatTime } = useTimeFormat(); 25 25 const queryClient = useQueryClient(); 26 26 27 - const { data: savedPlaylistData } = useGetSavedPlaylistQuery( 27 + const { data: savedPlaylistData, isLoading: savedPlaylistLoading } = useGetSavedPlaylistQuery( 28 28 { id: id! }, 29 29 { enabled: !isSmart } 30 30 ); 31 - const { data: savedTracksData, refetch: refetchSavedTracks } = 31 + const { data: savedTracksData, isLoading: savedTracksLoading, refetch: refetchSavedTracks } = 32 32 useGetSavedPlaylistTracksQuery( 33 33 { playlistId: id! }, 34 34 { enabled: !isSmart } 35 35 ); 36 36 37 - const { data: smartPlaylistData } = useGetSmartPlaylistQuery( 37 + const { data: smartPlaylistData, isLoading: smartPlaylistLoading } = useGetSmartPlaylistQuery( 38 38 { id: id! }, 39 39 { enabled: isSmart } 40 40 ); 41 - const { data: smartTracksData } = useGetSmartPlaylistTracksQuery( 41 + const { data: smartTracksData, isLoading: smartTracksLoading } = useGetSmartPlaylistTracksQuery( 42 42 { id: id! }, 43 43 { enabled: isSmart } 44 44 ); 45 + 46 + const isLoading = isSmart 47 + ? smartPlaylistLoading || smartTracksLoading 48 + : savedPlaylistLoading || savedTracksLoading; 45 49 46 50 const { mutate: playSavedPlaylist } = usePlaySavedPlaylistMutation(); 47 51 const { mutate: playSmartPlaylist } = usePlaySmartPlaylistMutation(); ··· 112 116 playlist={playlist} 113 117 tracks={tracks} 114 118 isSmart={isSmart} 119 + loading={isLoading} 115 120 onGoBack={() => navigate(-1)} 116 121 onPlayAll={onPlayAll} 117 122 onShuffleAll={onShuffleAll}
+16 -3
webui/rockbox/src/Components/Playlists/Playlists.tsx
··· 22 22 import { Music } from "@styled-icons/boxicons-regular"; 23 23 import { Edit2, Trash2 } from "@styled-icons/feather"; 24 24 import PlaylistModal from "./PlaylistModal"; 25 + import AlbumCardSkeleton from "../Skeletons/AlbumCardSkeleton"; 25 26 26 27 export type PlaylistsProps = { 27 28 savedPlaylists: any[]; 28 29 smartPlaylists: any[]; 30 + loading?: boolean; 29 31 onPlay: (id: string, isSmart: boolean) => void; 30 32 onEdit: (playlist: any) => void; 31 33 onDelete: (id: string) => void; ··· 36 38 const Playlists: FC<PlaylistsProps> = ({ 37 39 savedPlaylists, 38 40 smartPlaylists, 41 + loading, 39 42 onPlay, 40 43 onDelete, 41 44 onCreate, ··· 78 81 </button> 79 82 </div> 80 83 81 - {savedPlaylists.length > 0 && ( 84 + {loading && ( 85 + <PlaylistGrid> 86 + {Array.from({ length: 8 }).map((_, i) => ( 87 + <div key={i}> 88 + <AlbumCardSkeleton /> 89 + </div> 90 + ))} 91 + </PlaylistGrid> 92 + )} 93 + 94 + {!loading && savedPlaylists.length > 0 && ( 82 95 <> 83 96 <SectionTitle>MY PLAYLISTS</SectionTitle> 84 97 <PlaylistGrid> ··· 114 127 </> 115 128 )} 116 129 117 - {smartPlaylists.length > 0 && ( 130 + {!loading && smartPlaylists.length > 0 && ( 118 131 <> 119 132 <SectionTitle>SMART PLAYLISTS</SectionTitle> 120 133 <PlaylistGrid> ··· 142 155 </> 143 156 )} 144 157 145 - {savedPlaylists.length === 0 && smartPlaylists.length === 0 && ( 158 + {!loading && savedPlaylists.length === 0 && smartPlaylists.length === 0 && ( 146 159 <div style={{ padding: "40px 20px", color: "#888", fontSize: 14 }}> 147 160 No playlists yet. Create one to get started. 148 161 </div>
+2 -1
webui/rockbox/src/Components/Playlists/PlaylistsWithData.tsx
··· 13 13 14 14 const PlaylistsWithData: FC = () => { 15 15 const queryClient = useQueryClient(); 16 - const { data: savedData } = useGetSavedPlaylistsQuery(); 16 + const { data: savedData, isLoading } = useGetSavedPlaylistsQuery(); 17 17 const { data: smartData } = useGetSmartPlaylistsQuery(); 18 18 const { mutateAsync: createSavedPlaylist } = useCreateSavedPlaylistMutation(); 19 19 const { mutateAsync: updateSavedPlaylist } = useUpdateSavedPlaylistMutation(); ··· 57 57 <Playlists 58 58 savedPlaylists={savedPlaylists} 59 59 smartPlaylists={smartPlaylists} 60 + loading={isLoading} 60 61 onPlay={onPlay} 61 62 onEdit={() => {}} 62 63 onDelete={onDelete}
+23
webui/rockbox/src/Components/Skeletons/AlbumCardSkeleton.tsx
··· 1 + import { FC } from "react"; 2 + import ContentLoader from "react-content-loader"; 3 + import useSkeletonColors from "./useSkeletonColors"; 4 + 5 + const AlbumCardSkeleton: FC = () => { 6 + const { backgroundColor, foregroundColor } = useSkeletonColors(); 7 + return ( 8 + <ContentLoader 9 + speed={2} 10 + width="100%" 11 + viewBox="0 0 200 260" 12 + backgroundColor={backgroundColor} 13 + foregroundColor={foregroundColor} 14 + > 15 + <rect x="0" y="0" rx="3" ry="3" width="200" height="200" /> 16 + <rect x="0" y="210" rx="3" ry="3" width="150" height="14" /> 17 + <rect x="0" y="230" rx="3" ry="3" width="110" height="12" /> 18 + <rect x="0" y="248" rx="3" ry="3" width="70" height="10" /> 19 + </ContentLoader> 20 + ); 21 + }; 22 + 23 + export default AlbumCardSkeleton;
+22
webui/rockbox/src/Components/Skeletons/ArtistCardSkeleton.tsx
··· 1 + import { FC } from "react"; 2 + import ContentLoader from "react-content-loader"; 3 + import useSkeletonColors from "./useSkeletonColors"; 4 + 5 + const ArtistCardSkeleton: FC = () => { 6 + const { backgroundColor, foregroundColor } = useSkeletonColors(); 7 + return ( 8 + <ContentLoader 9 + speed={2} 10 + width={194} 11 + height={230} 12 + viewBox="0 0 194 230" 13 + backgroundColor={backgroundColor} 14 + foregroundColor={foregroundColor} 15 + > 16 + <circle cx="97" cy="97" r="97" /> 17 + <rect x="22" y="208" rx="3" ry="3" width="150" height="14" /> 18 + </ContentLoader> 19 + ); 20 + }; 21 + 22 + export default ArtistCardSkeleton;
+24
webui/rockbox/src/Components/Skeletons/ArtistHeaderSkeleton.tsx
··· 1 + import { FC } from "react"; 2 + import ContentLoader from "react-content-loader"; 3 + import useSkeletonColors from "./useSkeletonColors"; 4 + 5 + const ArtistHeaderSkeleton: FC = () => { 6 + const { backgroundColor, foregroundColor } = useSkeletonColors(); 7 + return ( 8 + <ContentLoader 9 + speed={2} 10 + width="100%" 11 + height={200} 12 + viewBox="0 0 700 200" 13 + preserveAspectRatio="xMinYMid meet" 14 + backgroundColor={backgroundColor} 15 + foregroundColor={foregroundColor} 16 + > 17 + <circle cx="100" cy="100" r="100" /> 18 + <rect x="220" y="75" rx="3" ry="3" width="260" height="28" /> 19 + <rect x="220" y="115" rx="3" ry="3" width="180" height="16" /> 20 + </ContentLoader> 21 + ); 22 + }; 23 + 24 + export default ArtistHeaderSkeleton;
+28
webui/rockbox/src/Components/Skeletons/DetailHeaderSkeleton.tsx
··· 1 + import { FC } from "react"; 2 + import ContentLoader from "react-content-loader"; 3 + import useSkeletonColors from "./useSkeletonColors"; 4 + 5 + const DetailHeaderSkeleton: FC = () => { 6 + const { backgroundColor, foregroundColor } = useSkeletonColors(); 7 + return ( 8 + <ContentLoader 9 + speed={2} 10 + width="100%" 11 + height={260} 12 + viewBox="0 0 700 260" 13 + preserveAspectRatio="xMinYMid meet" 14 + backgroundColor={backgroundColor} 15 + foregroundColor={foregroundColor} 16 + > 17 + <rect x="0" y="10" rx="4" ry="4" width="240" height="240" /> 18 + <rect x="265" y="30" rx="3" ry="3" width="280" height="26" /> 19 + <rect x="265" y="68" rx="3" ry="3" width="190" height="18" /> 20 + <rect x="265" y="100" rx="3" ry="3" width="130" height="14" /> 21 + <rect x="265" y="124" rx="3" ry="3" width="90" height="12" /> 22 + <rect x="265" y="165" rx="6" ry="6" width="110" height="38" /> 23 + <rect x="385" y="165" rx="6" ry="6" width="120" height="38" /> 24 + </ContentLoader> 25 + ); 26 + }; 27 + 28 + export default DetailHeaderSkeleton;
+33
webui/rockbox/src/Components/Skeletons/FileListSkeleton.tsx
··· 1 + import { FC } from "react"; 2 + import ContentLoader from "react-content-loader"; 3 + import useSkeletonColors from "./useSkeletonColors"; 4 + 5 + const FileRowSkeleton: FC = () => { 6 + const { backgroundColor, foregroundColor } = useSkeletonColors(); 7 + return ( 8 + <ContentLoader 9 + speed={2} 10 + width="100%" 11 + height={48} 12 + viewBox="0 0 1000 48" 13 + preserveAspectRatio="none" 14 + backgroundColor={backgroundColor} 15 + foregroundColor={foregroundColor} 16 + > 17 + <rect x="20" y="14" rx="2" ry="2" width="20" height="20" /> 18 + <rect x="54" y="17" rx="2" ry="2" width="300" height="14" /> 19 + </ContentLoader> 20 + ); 21 + }; 22 + 23 + type Props = { rows?: number }; 24 + 25 + const FileListSkeleton: FC<Props> = ({ rows = 12 }) => ( 26 + <div> 27 + {Array.from({ length: rows }).map((_, i) => ( 28 + <FileRowSkeleton key={i} /> 29 + ))} 30 + </div> 31 + ); 32 + 33 + export default FileListSkeleton;
+14
webui/rockbox/src/Components/Skeletons/TrackListSkeleton.tsx
··· 1 + import { FC } from "react"; 2 + import TrackRowSkeleton from "./TrackRowSkeleton"; 3 + 4 + type Props = { rows?: number }; 5 + 6 + const TrackListSkeleton: FC<Props> = ({ rows = 10 }) => ( 7 + <div> 8 + {Array.from({ length: rows }).map((_, i) => ( 9 + <TrackRowSkeleton key={i} /> 10 + ))} 11 + </div> 12 + ); 13 + 14 + export default TrackListSkeleton;
+28
webui/rockbox/src/Components/Skeletons/TrackRowSkeleton.tsx
··· 1 + import { FC } from "react"; 2 + import ContentLoader from "react-content-loader"; 3 + import useSkeletonColors from "./useSkeletonColors"; 4 + 5 + const TrackRowSkeleton: FC = () => { 6 + const { backgroundColor, foregroundColor } = useSkeletonColors(); 7 + return ( 8 + <ContentLoader 9 + speed={2} 10 + width="100%" 11 + height={48} 12 + viewBox="0 0 1000 48" 13 + preserveAspectRatio="none" 14 + backgroundColor={backgroundColor} 15 + foregroundColor={foregroundColor} 16 + > 17 + <rect x="8" y="17" rx="2" ry="2" width="22" height="14" /> 18 + <rect x="44" y="4" rx="3" ry="3" width="40" height="40" /> 19 + <rect x="95" y="9" rx="2" ry="2" width="200" height="14" /> 20 + <rect x="95" y="28" rx="2" ry="2" width="130" height="10" /> 21 + <rect x="360" y="9" rx="2" ry="2" width="180" height="14" /> 22 + <rect x="600" y="9" rx="2" ry="2" width="170" height="14" /> 23 + <rect x="840" y="9" rx="2" ry="2" width="60" height="14" /> 24 + </ContentLoader> 25 + ); 26 + }; 27 + 28 + export default TrackRowSkeleton;
+12
webui/rockbox/src/Components/Skeletons/useSkeletonColors.ts
··· 1 + import { useTheme } from "@emotion/react"; 2 + 3 + const useSkeletonColors = () => { 4 + const theme = useTheme(); 5 + const isDark = theme.colors.text === "#e8e8e8"; 6 + return { 7 + backgroundColor: isDark ? "#1e1e24" : "#e0e0e0", 8 + foregroundColor: isDark ? "#2e2e3a" : "#ebebeb", 9 + }; 10 + }; 11 + 12 + export default useSkeletonColors;
+6
webui/rockbox/src/Components/Tracks/Tracks.tsx
··· 22 22 import { Play } from "@styled-icons/ionicons-sharp"; 23 23 import "./styles.css"; 24 24 import ContextMenu from "../ContextMenu"; 25 + import TrackListSkeleton from "../Skeletons/TrackListSkeleton"; 25 26 26 27 const columnHelper = createColumnHelper<Track>(); 27 28 ··· 184 185 <ControlBar /> 185 186 <ContentWrapper ref={containerRef}> 186 187 <Title>Songs</Title> 188 + {props.loading && ( 189 + <div style={{ marginBottom: 60 }}> 190 + <TrackListSkeleton /> 191 + </div> 192 + )} 187 193 {(props.tracks.length > 0 || props.keyword) && !props.loading && ( 188 194 <> 189 195 <FilterContainer>
+1 -1
webui/rockbox/tsconfig.app.tsbuildinfo
··· 1 - {"root":["./src/app.tsx","./src/theme.ts","./src/constants.ts","./src/emotion.d.ts","./src/main.tsx","./src/mocks.ts","./src/vite-env.d.ts","./src/components/album/album.stories.tsx","./src/components/album/album.test.tsx","./src/components/album/album.tsx","./src/components/album/albumwithdata.tsx","./src/components/album/index.tsx","./src/components/album/styles.tsx","./src/components/album/contextmenu/childmenu.tsx","./src/components/album/contextmenu/contextmenu.stories.tsx","./src/components/album/contextmenu/contextmenu.test.tsx","./src/components/album/contextmenu/contextmenu.tsx","./src/components/album/contextmenu/contextmenuwithdata.tsx","./src/components/album/contextmenu/index.tsx","./src/components/album/contextmenu/styles.tsx","./src/components/albumdetails/albumdetails.stories.tsx","./src/components/albumdetails/albumdetails.test.tsx","./src/components/albumdetails/albumdetails.tsx","./src/components/albumdetails/albumdetailswithdata.tsx","./src/components/albumdetails/index.tsx","./src/components/albumdetails/mocks.tsx","./src/components/albumdetails/styles.tsx","./src/components/albums/albums.stories.tsx","./src/components/albums/albums.test.tsx","./src/components/albums/albums.tsx","./src/components/albums/albumswithdata.tsx","./src/components/albums/index.tsx","./src/components/albums/mocks.tsx","./src/components/albums/styles.tsx","./src/components/artistdetails/artistdetails.stories.tsx","./src/components/artistdetails/artistdetails.test.tsx","./src/components/artistdetails/artistdetails.tsx","./src/components/artistdetails/artistdetailswithdata.tsx","./src/components/artistdetails/index.tsx","./src/components/artistdetails/mocks.tsx","./src/components/artistdetails/styles.tsx","./src/components/artists/artists.stories.tsx","./src/components/artists/artists.test.tsx","./src/components/artists/artists.tsx","./src/components/artists/artistswithdata.tsx","./src/components/artists/index.tsx","./src/components/artists/mocks.tsx","./src/components/artists/styles.tsx","./src/components/button/button.test.tsx","./src/components/button/button.tsx","./src/components/button/index.tsx","./src/components/contextmenu/childmenu.tsx","./src/components/contextmenu/contextmenu.stories.tsx","./src/components/contextmenu/contextmenu.test.tsx","./src/components/contextmenu/contextmenu.tsx","./src/components/contextmenu/contextmenuwithdata.tsx","./src/components/contextmenu/index.tsx","./src/components/contextmenu/styles.tsx","./src/components/controlbar/controlbar.stories.tsx","./src/components/controlbar/controlbar.test.tsx","./src/components/controlbar/controlbar.tsx","./src/components/controlbar/controlbarstate.tsx","./src/components/controlbar/controlbarwithdata.tsx","./src/components/controlbar/index.tsx","./src/components/controlbar/styles.tsx","./src/components/controlbar/currenttrack/currenttrack.tsx","./src/components/controlbar/currenttrack/index.tsx","./src/components/controlbar/currenttrack/styles.ts","./src/components/controlbar/devicelist/devicelist.tsx","./src/components/controlbar/devicelist/devicelistwithdata.tsx","./src/components/controlbar/devicelist/devicestate.tsx","./src/components/controlbar/devicelist/index.tsx","./src/components/controlbar/devicelist/styles.ts","./src/components/controlbar/playqueue/playqueue.stories.tsx","./src/components/controlbar/playqueue/playqueue.test.tsx","./src/components/controlbar/playqueue/playqueue.tsx","./src/components/controlbar/playqueue/playqueuewithdata.tsx","./src/components/controlbar/playqueue/index.tsx","./src/components/controlbar/playqueue/mocks.tsx","./src/components/controlbar/playqueue/styles.tsx","./src/components/controlbar/rightmenu/rightmenu.tsx","./src/components/controlbar/rightmenu/index.tsx","./src/components/controlbar/rightmenu/styles.tsx","./src/components/controlbar/rightmenu/volume/volume.stories.tsx","./src/components/controlbar/rightmenu/volume/volume.test.tsx","./src/components/controlbar/rightmenu/volume/volume.tsx","./src/components/controlbar/rightmenu/volume/volumewithdata.tsx","./src/components/controlbar/rightmenu/volume/index.tsx","./src/components/controlbar/rightmenu/volume/styles.tsx","./src/components/extensions/extensions.stories.tsx","./src/components/extensions/extensions.tsx","./src/components/extensions/index.tsx","./src/components/files/files.stories.tsx","./src/components/files/files.test.tsx","./src/components/files/files.tsx","./src/components/files/fileswithdata.tsx","./src/components/files/index.tsx","./src/components/files/mocks.tsx","./src/components/files/styles.tsx","./src/components/files/contextmenu/childmenu.tsx","./src/components/files/contextmenu/contextmenu.stories.tsx","./src/components/files/contextmenu/contextmenu.test.tsx","./src/components/files/contextmenu/contextmenu.tsx","./src/components/files/contextmenu/contextmenuwithdata.tsx","./src/components/files/contextmenu/index.tsx","./src/components/files/contextmenu/styles.tsx","./src/components/filter/filter.test.tsx","./src/components/filter/filter.tsx","./src/components/filter/filterstate.tsx","./src/components/filter/filterwithdata.tsx","./src/components/filter/index.tsx","./src/components/folder/folder.stories.tsx","./src/components/folder/folder.tsx","./src/components/folder/index.tsx","./src/components/icons/add.tsx","./src/components/icons/albumcover.tsx","./src/components/icons/arrowback.tsx","./src/components/icons/artist.tsx","./src/components/icons/heart.tsx","./src/components/icons/heartoutline.tsx","./src/components/icons/next.tsx","./src/components/icons/pause.tsx","./src/components/icons/play.tsx","./src/components/icons/previous.tsx","./src/components/icons/repeat.tsx","./src/components/icons/search.tsx","./src/components/icons/shuffle.tsx","./src/components/icons/speaker.tsx","./src/components/icons/track.tsx","./src/components/likes/likes.tsx","./src/components/likes/likesstate.ts","./src/components/likes/likeswithdata.tsx","./src/components/likes/index.tsx","./src/components/likes/styles.tsx","./src/components/mainview/mainview.tsx","./src/components/mainview/mainviewwithdata.tsx","./src/components/mainview/index.tsx","./src/components/mainview/styles.tsx","./src/components/playlistdetails/playlistdetails.stories.tsx","./src/components/playlistdetails/playlistdetails.tsx","./src/components/playlistdetails/playlistdetailswithdata.tsx","./src/components/playlistdetails/index.tsx","./src/components/playlistdetails/styles.tsx","./src/components/playlists/playlistmodal.tsx","./src/components/playlists/playlists.stories.tsx","./src/components/playlists/playlists.tsx","./src/components/playlists/playlistswithdata.tsx","./src/components/playlists/index.tsx","./src/components/playlists/styles.tsx","./src/components/settings/settings.tsx","./src/components/settings/settingsstate.ts","./src/components/settings/settingswithdata.tsx","./src/components/settings/index.tsx","./src/components/settings/styles.tsx","./src/components/settings/library/library.tsx","./src/components/settings/library/librarywithdata.tsx","./src/components/settings/library/index.tsx","./src/components/settings/library/styles.tsx","./src/components/settings/playback/playback.tsx","./src/components/settings/playback/playbackwithdata.tsx","./src/components/settings/playback/consts.ts","./src/components/settings/playback/index.tsx","./src/components/settings/playback/styles.tsx","./src/components/settings/sound/sound.tsx","./src/components/settings/sound/soundwithdata.tsx","./src/components/settings/sound/index.tsx","./src/components/settings/sound/styles.tsx","./src/components/settings/sound/equalizer/equalizer.tsx","./src/components/settings/sound/equalizer/equalizerwithdata.tsx","./src/components/settings/sound/equalizer/index.tsx","./src/components/settings/sound/equalizer/styles.tsx","./src/components/sidebar/sidebar.test.tsx","./src/components/sidebar/sidebar.tsx","./src/components/sidebar/sidebarwithdata.tsx","./src/components/sidebar/stidebar.stories.tsx","./src/components/sidebar/index.tsx","./src/components/sidebar/styles.tsx","./src/components/switch/switch.tsx","./src/components/switch/index.tsx","./src/components/table/table.tsx","./src/components/table/index.tsx","./src/components/tracks/tracks.stories.tsx","./src/components/tracks/tracks.test.tsx","./src/components/tracks/tracks.tsx","./src/components/tracks/trackswithdata.tsx","./src/components/tracks/index.tsx","./src/components/tracks/mocks.tsx","./src/components/tracks/styles.tsx","./src/components/virtualizedtable/virtualizedtable.tsx","./src/components/virtualizedtable/index.tsx","./src/containers/albumdetails/albumdetailspage.tsx","./src/containers/albumdetails/index.tsx","./src/containers/albums/albumspage.tsx","./src/containers/albums/index.tsx","./src/containers/artistdetails/artistdetailspage.tsx","./src/containers/artistdetails/index.tsx","./src/containers/artists/artistspage.tsx","./src/containers/artists/index.tsx","./src/containers/extensions/extensionspage.tsx","./src/containers/extensions/index.tsx","./src/containers/files/filespage.tsx","./src/containers/files/index.tsx","./src/containers/likes/likespage.tsx","./src/containers/likes/index.tsx","./src/containers/playlistdetails/smartplaylistdetailspage.tsx","./src/containers/playlistdetails/index.tsx","./src/containers/playlists/playlistspage.tsx","./src/containers/playlists/index.tsx","./src/containers/settings/settingspage.tsx","./src/containers/settings/index.tsx","./src/containers/tracks/trackspage.tsx","./src/containers/tracks/index.tsx","./src/graphql/browse/query.ts","./src/graphql/device/mutation.ts","./src/graphql/device/query.ts","./src/graphql/library/mutation.ts","./src/graphql/library/query.ts","./src/graphql/playback/mutation.ts","./src/graphql/playback/query.ts","./src/graphql/playback/subscription.ts","./src/graphql/playlist/mutation.ts","./src/graphql/playlist/query.ts","./src/graphql/playlist/subscription.ts","./src/graphql/savedplaylist/mutation.ts","./src/graphql/savedplaylist/query.ts","./src/graphql/settings/mutation.ts","./src/graphql/settings/query.ts","./src/graphql/smartplaylist/mutation.ts","./src/graphql/smartplaylist/query.ts","./src/graphql/sound/mutation.tsx","./src/graphql/system/query.ts","./src/hooks/graphql.tsx","./src/hooks/useformat.tsx","./src/hooks/useplayqueue.tsx","./src/hooks/useresumeplaylist.tsx","./src/hooks/usesettings.tsx","./src/providers/graphqlprovider.tsx","./src/providers/themeprovider.tsx","./src/providers/index.tsx","./src/types/file.ts","./src/types/playlist.ts","./src/types/track.ts","./src/lib/graphql-client.ts","./src/lib/subscription-client.ts","./src/stories/button.stories.ts","./src/stories/button.tsx","./src/stories/header.stories.ts","./src/stories/header.tsx","./src/stories/page.stories.ts","./src/stories/page.tsx"],"version":"5.6.2"} 1 + {"root":["./src/app.tsx","./src/theme.ts","./src/constants.ts","./src/emotion.d.ts","./src/main.tsx","./src/mocks.ts","./src/vite-env.d.ts","./src/components/album/album.stories.tsx","./src/components/album/album.test.tsx","./src/components/album/album.tsx","./src/components/album/albumwithdata.tsx","./src/components/album/index.tsx","./src/components/album/styles.tsx","./src/components/album/contextmenu/childmenu.tsx","./src/components/album/contextmenu/contextmenu.stories.tsx","./src/components/album/contextmenu/contextmenu.test.tsx","./src/components/album/contextmenu/contextmenu.tsx","./src/components/album/contextmenu/contextmenuwithdata.tsx","./src/components/album/contextmenu/index.tsx","./src/components/album/contextmenu/styles.tsx","./src/components/albumdetails/albumdetails.stories.tsx","./src/components/albumdetails/albumdetails.test.tsx","./src/components/albumdetails/albumdetails.tsx","./src/components/albumdetails/albumdetailswithdata.tsx","./src/components/albumdetails/index.tsx","./src/components/albumdetails/mocks.tsx","./src/components/albumdetails/styles.tsx","./src/components/albums/albums.stories.tsx","./src/components/albums/albums.test.tsx","./src/components/albums/albums.tsx","./src/components/albums/albumswithdata.tsx","./src/components/albums/index.tsx","./src/components/albums/mocks.tsx","./src/components/albums/styles.tsx","./src/components/artistdetails/artistdetails.stories.tsx","./src/components/artistdetails/artistdetails.test.tsx","./src/components/artistdetails/artistdetails.tsx","./src/components/artistdetails/artistdetailswithdata.tsx","./src/components/artistdetails/index.tsx","./src/components/artistdetails/mocks.tsx","./src/components/artistdetails/styles.tsx","./src/components/artists/artists.stories.tsx","./src/components/artists/artists.test.tsx","./src/components/artists/artists.tsx","./src/components/artists/artistswithdata.tsx","./src/components/artists/index.tsx","./src/components/artists/mocks.tsx","./src/components/artists/styles.tsx","./src/components/button/button.test.tsx","./src/components/button/button.tsx","./src/components/button/index.tsx","./src/components/contextmenu/childmenu.tsx","./src/components/contextmenu/contextmenu.stories.tsx","./src/components/contextmenu/contextmenu.test.tsx","./src/components/contextmenu/contextmenu.tsx","./src/components/contextmenu/contextmenuwithdata.tsx","./src/components/contextmenu/index.tsx","./src/components/contextmenu/styles.tsx","./src/components/controlbar/controlbar.stories.tsx","./src/components/controlbar/controlbar.test.tsx","./src/components/controlbar/controlbar.tsx","./src/components/controlbar/controlbarstate.tsx","./src/components/controlbar/controlbarwithdata.tsx","./src/components/controlbar/index.tsx","./src/components/controlbar/styles.tsx","./src/components/controlbar/currenttrack/currenttrack.tsx","./src/components/controlbar/currenttrack/index.tsx","./src/components/controlbar/currenttrack/styles.ts","./src/components/controlbar/devicelist/devicelist.tsx","./src/components/controlbar/devicelist/devicelistwithdata.tsx","./src/components/controlbar/devicelist/devicestate.tsx","./src/components/controlbar/devicelist/index.tsx","./src/components/controlbar/devicelist/styles.ts","./src/components/controlbar/playqueue/playqueue.stories.tsx","./src/components/controlbar/playqueue/playqueue.test.tsx","./src/components/controlbar/playqueue/playqueue.tsx","./src/components/controlbar/playqueue/playqueuewithdata.tsx","./src/components/controlbar/playqueue/index.tsx","./src/components/controlbar/playqueue/mocks.tsx","./src/components/controlbar/playqueue/styles.tsx","./src/components/controlbar/rightmenu/rightmenu.tsx","./src/components/controlbar/rightmenu/index.tsx","./src/components/controlbar/rightmenu/styles.tsx","./src/components/controlbar/rightmenu/volume/volume.stories.tsx","./src/components/controlbar/rightmenu/volume/volume.test.tsx","./src/components/controlbar/rightmenu/volume/volume.tsx","./src/components/controlbar/rightmenu/volume/volumewithdata.tsx","./src/components/controlbar/rightmenu/volume/index.tsx","./src/components/controlbar/rightmenu/volume/styles.tsx","./src/components/extensions/extensions.stories.tsx","./src/components/extensions/extensions.tsx","./src/components/extensions/index.tsx","./src/components/files/files.stories.tsx","./src/components/files/files.test.tsx","./src/components/files/files.tsx","./src/components/files/fileswithdata.tsx","./src/components/files/index.tsx","./src/components/files/mocks.tsx","./src/components/files/styles.tsx","./src/components/files/contextmenu/childmenu.tsx","./src/components/files/contextmenu/contextmenu.stories.tsx","./src/components/files/contextmenu/contextmenu.test.tsx","./src/components/files/contextmenu/contextmenu.tsx","./src/components/files/contextmenu/contextmenuwithdata.tsx","./src/components/files/contextmenu/index.tsx","./src/components/files/contextmenu/styles.tsx","./src/components/filter/filter.test.tsx","./src/components/filter/filter.tsx","./src/components/filter/filterstate.tsx","./src/components/filter/filterwithdata.tsx","./src/components/filter/index.tsx","./src/components/folder/folder.stories.tsx","./src/components/folder/folder.tsx","./src/components/folder/index.tsx","./src/components/icons/add.tsx","./src/components/icons/albumcover.tsx","./src/components/icons/arrowback.tsx","./src/components/icons/artist.tsx","./src/components/icons/heart.tsx","./src/components/icons/heartoutline.tsx","./src/components/icons/next.tsx","./src/components/icons/pause.tsx","./src/components/icons/play.tsx","./src/components/icons/previous.tsx","./src/components/icons/repeat.tsx","./src/components/icons/search.tsx","./src/components/icons/shuffle.tsx","./src/components/icons/speaker.tsx","./src/components/icons/track.tsx","./src/components/likes/likes.tsx","./src/components/likes/likesstate.ts","./src/components/likes/likeswithdata.tsx","./src/components/likes/index.tsx","./src/components/likes/styles.tsx","./src/components/mainview/mainview.tsx","./src/components/mainview/mainviewwithdata.tsx","./src/components/mainview/index.tsx","./src/components/mainview/styles.tsx","./src/components/playlistdetails/playlistdetails.stories.tsx","./src/components/playlistdetails/playlistdetails.tsx","./src/components/playlistdetails/playlistdetailswithdata.tsx","./src/components/playlistdetails/index.tsx","./src/components/playlistdetails/styles.tsx","./src/components/playlists/playlistmodal.tsx","./src/components/playlists/playlists.stories.tsx","./src/components/playlists/playlists.tsx","./src/components/playlists/playlistswithdata.tsx","./src/components/playlists/index.tsx","./src/components/playlists/styles.tsx","./src/components/settings/settings.tsx","./src/components/settings/settingsstate.ts","./src/components/settings/settingswithdata.tsx","./src/components/settings/index.tsx","./src/components/settings/styles.tsx","./src/components/settings/library/library.tsx","./src/components/settings/library/librarywithdata.tsx","./src/components/settings/library/index.tsx","./src/components/settings/library/styles.tsx","./src/components/settings/playback/playback.tsx","./src/components/settings/playback/playbackwithdata.tsx","./src/components/settings/playback/consts.ts","./src/components/settings/playback/index.tsx","./src/components/settings/playback/styles.tsx","./src/components/settings/sound/sound.tsx","./src/components/settings/sound/soundwithdata.tsx","./src/components/settings/sound/index.tsx","./src/components/settings/sound/styles.tsx","./src/components/settings/sound/equalizer/equalizer.tsx","./src/components/settings/sound/equalizer/equalizerwithdata.tsx","./src/components/settings/sound/equalizer/index.tsx","./src/components/settings/sound/equalizer/styles.tsx","./src/components/sidebar/sidebar.test.tsx","./src/components/sidebar/sidebar.tsx","./src/components/sidebar/sidebarwithdata.tsx","./src/components/sidebar/stidebar.stories.tsx","./src/components/sidebar/index.tsx","./src/components/sidebar/styles.tsx","./src/components/skeletons/albumcardskeleton.tsx","./src/components/skeletons/artistcardskeleton.tsx","./src/components/skeletons/artistheaderskeleton.tsx","./src/components/skeletons/detailheaderskeleton.tsx","./src/components/skeletons/filelistskeleton.tsx","./src/components/skeletons/tracklistskeleton.tsx","./src/components/skeletons/trackrowskeleton.tsx","./src/components/skeletons/useskeletoncolors.ts","./src/components/switch/switch.tsx","./src/components/switch/index.tsx","./src/components/table/table.tsx","./src/components/table/index.tsx","./src/components/tracks/tracks.stories.tsx","./src/components/tracks/tracks.test.tsx","./src/components/tracks/tracks.tsx","./src/components/tracks/trackswithdata.tsx","./src/components/tracks/index.tsx","./src/components/tracks/mocks.tsx","./src/components/tracks/styles.tsx","./src/components/virtualizedtable/virtualizedtable.tsx","./src/components/virtualizedtable/index.tsx","./src/containers/albumdetails/albumdetailspage.tsx","./src/containers/albumdetails/index.tsx","./src/containers/albums/albumspage.tsx","./src/containers/albums/index.tsx","./src/containers/artistdetails/artistdetailspage.tsx","./src/containers/artistdetails/index.tsx","./src/containers/artists/artistspage.tsx","./src/containers/artists/index.tsx","./src/containers/extensions/extensionspage.tsx","./src/containers/extensions/index.tsx","./src/containers/files/filespage.tsx","./src/containers/files/index.tsx","./src/containers/likes/likespage.tsx","./src/containers/likes/index.tsx","./src/containers/playlistdetails/smartplaylistdetailspage.tsx","./src/containers/playlistdetails/index.tsx","./src/containers/playlists/playlistspage.tsx","./src/containers/playlists/index.tsx","./src/containers/settings/settingspage.tsx","./src/containers/settings/index.tsx","./src/containers/tracks/trackspage.tsx","./src/containers/tracks/index.tsx","./src/graphql/browse/query.ts","./src/graphql/device/mutation.ts","./src/graphql/device/query.ts","./src/graphql/library/mutation.ts","./src/graphql/library/query.ts","./src/graphql/playback/mutation.ts","./src/graphql/playback/query.ts","./src/graphql/playback/subscription.ts","./src/graphql/playlist/mutation.ts","./src/graphql/playlist/query.ts","./src/graphql/playlist/subscription.ts","./src/graphql/savedplaylist/mutation.ts","./src/graphql/savedplaylist/query.ts","./src/graphql/settings/mutation.ts","./src/graphql/settings/query.ts","./src/graphql/smartplaylist/mutation.ts","./src/graphql/smartplaylist/query.ts","./src/graphql/sound/mutation.tsx","./src/graphql/system/query.ts","./src/hooks/graphql.tsx","./src/hooks/useformat.tsx","./src/hooks/useplayqueue.tsx","./src/hooks/useresumeplaylist.tsx","./src/hooks/usesettings.tsx","./src/providers/graphqlprovider.tsx","./src/providers/themeprovider.tsx","./src/providers/index.tsx","./src/types/file.ts","./src/types/playlist.ts","./src/types/track.ts","./src/lib/graphql-client.ts","./src/lib/subscription-client.ts","./src/stories/button.stories.ts","./src/stories/button.tsx","./src/stories/header.stories.ts","./src/stories/header.tsx","./src/stories/page.stories.ts","./src/stories/page.tsx"],"version":"5.6.2"}