From b607c57f5951bb8c1cd77b19233804fff5e83c20 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Mon, 3 Nov 2025 20:38:18 -0800 Subject: [PATCH] rename internal types in domain models --- src/main/features/core/remote/index.ts | 8 +- src/remote/components/remote-container.tsx | 2 +- .../components/album-detail-content.tsx | 4 +- .../albums/components/album-detail-header.tsx | 6 +- .../routes/dummy-album-detail-route.tsx | 4 +- .../components/album-artist-detail-header.tsx | 2 +- .../features/discord-rpc/use-discord-rpc.ts | 10 +- .../features/lyrics/api/lyrics-api.ts | 2 +- src/renderer/features/lyrics/lyrics.tsx | 12 +- .../now-playing/components/play-queue.tsx | 22 ++-- .../features/player/audio-player/index.tsx | 22 ++-- .../player/components/right-controls.tsx | 8 +- .../features/player/hooks/use-scrobble.ts | 14 +-- ...aylist-detail-song-list-header-filters.tsx | 2 +- .../playlist-detail-song-list-route.tsx | 6 +- .../shared/mutations/set-rating-mutation.ts | 6 +- .../components/similar-songs-list.tsx | 2 +- src/renderer/store/player.store.ts | 108 +++++++++--------- .../utils/set-transcoded-queue-data.ts | 2 +- src/shared/api/jellyfin/jellyfin-normalize.ts | 19 ++- .../api/navidrome/navidrome-normalize.ts | 21 ++-- src/shared/api/subsonic/subsonic-normalize.ts | 23 ++-- src/shared/types/domain-types.ts | 25 ++-- 23 files changed, 162 insertions(+), 168 deletions(-) diff --git a/src/main/features/core/remote/index.ts b/src/main/features/core/remote/index.ts index fe3f80684..75560620b 100644 --- a/src/main/features/core/remote/index.ts +++ b/src/main/features/core/remote/index.ts @@ -382,7 +382,7 @@ const enableServer = (config: RemoteConfig): Promise => { getMainWindow()?.webContents.send('request-favorite', { favorite, id, - serverId: currentState.song.serverId, + serverId: currentState.song._serverId, }); } break; @@ -443,7 +443,7 @@ const enableServer = (config: RemoteConfig): Promise => { getMainWindow()?.webContents.send('request-rating', { id, rating, - serverId: currentState.song.serverId, + serverId: currentState.song._serverId, }); } break; @@ -578,7 +578,7 @@ ipcMain.on('remote-username', (_event, username: string) => { }); ipcMain.on('update-favorite', (_event, favorite: boolean, serverId: string, ids: string[]) => { - if (currentState.song?.serverId !== serverId) return; + if (currentState.song?._serverId !== serverId) return; const id = currentState.song.id; @@ -592,7 +592,7 @@ ipcMain.on('update-favorite', (_event, favorite: boolean, serverId: string, ids: }); ipcMain.on('update-rating', (_event, rating: number, serverId: string, ids: string[]) => { - if (currentState.song?.serverId !== serverId) return; + if (currentState.song?._serverId !== serverId) return; const id = currentState.song.id; diff --git a/src/remote/components/remote-container.tsx b/src/remote/components/remote-container.tsx index 280186825..4566cd82e 100644 --- a/src/remote/components/remote-container.tsx +++ b/src/remote/components/remote-container.tsx @@ -96,7 +96,7 @@ export const RemoteContainer = () => { }} variant="transparent" /> - {(song?.serverType === 'navidrome' || song?.serverType === 'subsonic') && ( + {(song?._serverType === 'navidrome' || song?._serverType === 'subsonic') && (
{ try { if (wasFavorite) { await deleteFavoriteMutation.mutateAsync({ - apiClientProps: { serverId: detailQuery.data.serverId }, + apiClientProps: { serverId: detailQuery.data._serverId }, query: { id: [detailQuery.data.id], type: LibraryItem.SONG, @@ -77,7 +77,7 @@ const DummyAlbumDetailRoute = () => { }); } else { await createFavoriteMutation.mutateAsync({ - apiClientProps: { serverId: detailQuery.data.serverId }, + apiClientProps: { serverId: detailQuery.data._serverId }, query: { id: [detailQuery.data.id], type: LibraryItem.SONG, diff --git a/src/renderer/features/artists/components/album-artist-detail-header.tsx b/src/renderer/features/artists/components/album-artist-detail-header.tsx index f9634c64f..2ef933fdb 100644 --- a/src/renderer/features/artists/components/album-artist-detail-header.tsx +++ b/src/renderer/features/artists/components/album-artist-detail-header.tsx @@ -79,7 +79,7 @@ export const AlbumArtistDetailHeader = forwardRef( }); }; - const showRating = detailQuery?.data?.serverType === ServerType.NAVIDROME; + const showRating = detailQuery?.data?._serverType === ServerType.NAVIDROME; return ( { // Handle change detection const song = current[0]; - const trackChanged = lastUniqueId !== song.uniqueId; + const trackChanged = lastUniqueId !== song._uniqueId; /* 1. If the song has just started, update status @@ -51,7 +51,7 @@ export const useDiscordRpc = () => { current[2] !== previous[2] ) { if (trackChanged) { - setlastUniqueId(song.uniqueId); + setlastUniqueId(song._uniqueId); } const start = Math.round(Date.now() - current[1] * 1000); @@ -119,12 +119,12 @@ export const useDiscordRpc = () => { } if (discordSettings.showServerImage && song) { - if (song.serverType === ServerType.JELLYFIN && song.imageUrl) { + if (song._serverType === ServerType.JELLYFIN && song.imageUrl) { activity.largeImageKey = song.imageUrl; - } else if (song.serverType === ServerType.NAVIDROME) { + } else if (song._serverType === ServerType.NAVIDROME) { try { const info = await controller.getAlbumInfo({ - apiClientProps: { serverId: song.serverId }, + apiClientProps: { serverId: song._serverId }, query: { id: song.albumId }, }); diff --git a/src/renderer/features/lyrics/api/lyrics-api.ts b/src/renderer/features/lyrics/api/lyrics-api.ts index e49b4c5dd..a67bc6f21 100644 --- a/src/renderer/features/lyrics/api/lyrics-api.ts +++ b/src/renderer/features/lyrics/api/lyrics-api.ts @@ -99,7 +99,7 @@ export const lyricsQueries = { return queryOptions({ gcTime: Infinity, queryFn: async ({ signal }): Promise => { - const server = getServerById(song?.serverId); + const server = getServerById(song?._serverId); if (!server) throw new Error('Server not found'); if (!song) return null; diff --git a/src/renderer/features/lyrics/lyrics.tsx b/src/renderer/features/lyrics/lyrics.tsx index eec617230..1758becd1 100644 --- a/src/renderer/features/lyrics/lyrics.tsx +++ b/src/renderer/features/lyrics/lyrics.tsx @@ -45,7 +45,7 @@ export const Lyrics = () => { lyricsQueries.songLyrics( { query: { songId: currentSong?.id || '' }, - serverId: currentSong?.serverId || '', + serverId: currentSong?._serverId || '', }, currentSong, ), @@ -73,13 +73,13 @@ export const Lyrics = () => { const handleOnResetLyric = useCallback(() => { queryClient.invalidateQueries({ exact: true, - queryKey: queryKeys.songs.lyrics(currentSong?.serverId, { songId: currentSong?.id }), + queryKey: queryKeys.songs.lyrics(currentSong?._serverId, { songId: currentSong?.id }), }); - }, [currentSong?.id, currentSong?.serverId]); + }, [currentSong?.id, currentSong?._serverId]); const handleOnRemoveLyric = useCallback(() => { queryClient.setQueryData( - queryKeys.songs.lyrics(currentSong?.serverId, { songId: currentSong?.id }), + queryKeys.songs.lyrics(currentSong?._serverId, { songId: currentSong?.id }), (prev: FullLyricsMetadata | undefined) => { if (!prev) { return undefined; @@ -91,7 +91,7 @@ export const Lyrics = () => { }; }, ); - }, [currentSong?.id, currentSong?.serverId]); + }, [currentSong?.id, currentSong?._serverId]); const fetchTranslation = useCallback(async () => { if (!lyrics) return; @@ -126,7 +126,7 @@ export const Lyrics = () => { remoteSource: override?.source as LyricSource | undefined, song: currentSong, }, - serverId: currentSong?.serverId || '', + serverId: currentSong?._serverId || '', }), ); diff --git a/src/renderer/features/now-playing/components/play-queue.tsx b/src/renderer/features/now-playing/components/play-queue.tsx index 8f63455b4..1866bcdfa 100644 --- a/src/renderer/features/now-playing/components/play-queue.tsx +++ b/src/renderer/features/now-playing/components/play-queue.tsx @@ -122,7 +122,7 @@ export const PlayQueue = forwardRef(({ searchTerm, type }: QueueProps, ref: Ref< const handleDragEnd = (e: RowDragEvent) => { if (!e.nodes.length) return; const selectedUniqueIds = e.nodes - .map((node) => node.data?.uniqueId) + .map((node) => node.data?._uniqueId) .filter((e) => e !== undefined); // const playerData = reorderQueue(selectedUniqueIds as string[], e.overNode?.data?.uniqueId); @@ -143,8 +143,8 @@ export const PlayQueue = forwardRef(({ searchTerm, type }: QueueProps, ref: Ref< const handleGridReady = () => { const { api } = tableRef?.current || {}; - if (currentSong?.uniqueId) { - const currentNode = api?.getRowNode(currentSong?.uniqueId); + if (currentSong?._uniqueId) { + const currentNode = api?.getRowNode(currentSong?._uniqueId); if (!currentNode) return; api?.ensureNodeVisible(currentNode, 'middle'); @@ -196,10 +196,10 @@ export const PlayQueue = forwardRef(({ searchTerm, type }: QueueProps, ref: Ref< const rowClassRules = useMemo(() => { return { 'current-song': (params) => { - return params.data.uniqueId === currentSong?.uniqueId; + return params.data.uniqueId === currentSong?._uniqueId; }, }; - }, [currentSong?.uniqueId]); + }, [currentSong?._uniqueId]); const previousSongRef = useRef(undefined); @@ -217,11 +217,11 @@ export const PlayQueue = forwardRef(({ searchTerm, type }: QueueProps, ref: Ref< return; } - const currentNode = currentSong?.uniqueId - ? api.getRowNode(currentSong.uniqueId) + const currentNode = currentSong?._uniqueId + ? api.getRowNode(currentSong._uniqueId) : undefined; - const previousNode = previousSongRef.current?.uniqueId - ? api.getRowNode(previousSongRef.current?.uniqueId) + const previousNode = previousSongRef.current?._uniqueId + ? api.getRowNode(previousSongRef.current?._uniqueId) : undefined; const rowNodes = [currentNode, previousNode].filter( @@ -248,8 +248,8 @@ export const PlayQueue = forwardRef(({ searchTerm, type }: QueueProps, ref: Ref< return; } - const currentNode = currentSong?.uniqueId - ? api.getRowNode(currentSong.uniqueId) + const currentNode = currentSong?._uniqueId + ? api.getRowNode(currentSong._uniqueId) : undefined; if (currentNode) { diff --git a/src/renderer/features/player/audio-player/index.tsx b/src/renderer/features/player/audio-player/index.tsx index 6fddb0a14..0793fae0d 100644 --- a/src/renderer/features/player/audio-player/index.tsx +++ b/src/renderer/features/player/audio-player/index.tsx @@ -1,4 +1,4 @@ -import type { Song } from '/@/shared/types/domain-types'; +import type { QueueSong, Song } from '/@/shared/types/domain-types'; import type { CrossfadeStyle } from '/@/shared/types/types'; import type { ReactPlayerProps } from 'react-player'; @@ -18,7 +18,7 @@ import { api } from '/@/renderer/api'; import { crossfadeHandler, gaplessHandler, -} from '/@/renderer/components/audio-player/utils/list-handlers'; +} from '/@/renderer/features/player/audio-player/utils/list-handlers'; import { useWebAudio } from '/@/renderer/features/player/hooks/use-webaudio'; import { TranscodingConfig, @@ -62,26 +62,30 @@ const getDuration = (ref: any) => { const EMPTY_SOURCE = 'data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU2LjM2LjEwMAAAAAAAAAAAAAAA//OEAAAAAAAAAAAAAAAAAAAAAAAASW5mbwAAAA8AAAAEAAABIADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV6urq6urq6urq6urq6urq6urq6urq6urq6v////////////////////////////////8AAAAATGF2YzU2LjQxAAAAAAAAAAAAAAAAJAAAAAAAAAAAASDs90hvAAAAAAAAAAAAAAAAAAAA//MUZAAAAAGkAAAAAAAAA0gAAAAATEFN//MUZAMAAAGkAAAAAAAAA0gAAAAARTMu//MUZAYAAAGkAAAAAAAAA0gAAAAAOTku//MUZAkAAAGkAAAAAAAAA0gAAAAANVVV'; -const useSongUrl = (transcode: TranscodingConfig, current: boolean, song?: Song): null | string => { +const useSongUrl = ( + transcode: TranscodingConfig, + current: boolean, + song?: QueueSong, +): null | string => { const prior = useRef(['', '']); return useMemo(() => { - if (song?.serverId) { + if (song?._serverId) { // If we are the current track, we do not want a transcoding // reconfiguration to force a restart. - if (current && prior.current[0] === song.uniqueId) { + if (current && prior.current[0] === song._uniqueId) { return prior.current[1]; } if (!transcode.enabled) { // transcoding disabled; save the result - prior.current = [song.uniqueId, song.streamUrl]; + prior.current = [song._uniqueId, song.streamUrl]; return song.streamUrl; } const result = api.controller.getTranscodingUrl({ apiClientProps: { - serverId: song.serverId, + serverId: song._serverId, }, query: { base: song.streamUrl, @@ -90,14 +94,14 @@ const useSongUrl = (transcode: TranscodingConfig, current: boolean, song?: Song) })!; // transcoding enabled; save the updated result - prior.current = [song.uniqueId, result]; + prior.current = [song._uniqueId, result]; return result; } // no track; clear result prior.current = ['', '']; return null; - }, [current, song?.uniqueId, song?.serverId, song?.streamUrl, transcode]); + }, [current, song?._uniqueId, song?._serverId, song?.streamUrl, transcode]); }; export interface AudioPlayerRef { diff --git a/src/renderer/features/player/components/right-controls.tsx b/src/renderer/features/player/components/right-controls.tsx index 07639388a..7e9dbf490 100644 --- a/src/renderer/features/player/components/right-controls.tsx +++ b/src/renderer/features/player/components/right-controls.tsx @@ -71,7 +71,7 @@ export const RightControls = () => { if (!song?.id) return; addToFavoritesMutation.mutate({ - apiClientProps: { serverId: song?.serverId || '' }, + apiClientProps: { serverId: song?._serverId || '' }, query: { id: [song.id], type: LibraryItem.SONG, @@ -83,7 +83,7 @@ export const RightControls = () => { if (!currentSong) return; updateRatingMutation.mutate({ - apiClientProps: { serverId: currentSong?.serverId || '' }, + apiClientProps: { serverId: currentSong?._serverId || '' }, query: { item: [currentSong], rating, @@ -95,7 +95,7 @@ export const RightControls = () => { if (!song?.id) return; removeFromFavoritesMutation.mutate({ - apiClientProps: { serverId: song?.serverId || '' }, + apiClientProps: { serverId: song?._serverId || '' }, query: { id: [song.id], type: LibraryItem.SONG, @@ -188,7 +188,7 @@ export const RightControls = () => { { id, itemType: LibraryItem.SONG, - serverId, + _serverId, } as Song, // This is not a type-safe cast, but it works because those are all the prop ], rating, diff --git a/src/renderer/features/player/hooks/use-scrobble.ts b/src/renderer/features/player/hooks/use-scrobble.ts index 5c3ce5a36..a2b8b14c5 100644 --- a/src/renderer/features/player/hooks/use-scrobble.ts +++ b/src/renderer/features/player/hooks/use-scrobble.ts @@ -103,7 +103,7 @@ export const useScrobble = () => { // Only trigger if the song changed, or the player changed. This should be the case // anyways, but who knows if ( - currentSong.uniqueId !== previous[0]?.uniqueId || + currentSong._uniqueId !== previous[0]?._uniqueId || current[2] !== previous[2] ) { const artists = @@ -141,15 +141,15 @@ export const useScrobble = () => { if ( (!isCurrentSongScrobbled && shouldSubmitScrobble) || - previousSong?.serverType === ServerType.JELLYFIN + previousSong?._serverType === ServerType.JELLYFIN ) { const position = - previousSong?.serverType === ServerType.JELLYFIN + previousSong?._serverType === ServerType.JELLYFIN ? previousSongTimeSec * 1e7 : undefined; sendScrobble.mutate({ - apiClientProps: { serverId: previousSong?.serverId || '' }, + apiClientProps: { serverId: previousSong?._serverId || '' }, query: { id: previousSong.id, position, @@ -173,7 +173,7 @@ export const useScrobble = () => { // Send start scrobble when song changes and the new song is playing if (currentStatus === PlayerStatus.PLAYING && currentSong?.id) { sendScrobble.mutate({ - apiClientProps: { serverId: currentSong?.serverId || '' }, + apiClientProps: { serverId: currentSong?._serverId || '' }, query: { event: 'start', id: currentSong.id, @@ -182,7 +182,7 @@ export const useScrobble = () => { }, }); - if (currentSong?.serverType === ServerType.JELLYFIN) { + if (currentSong?._serverType === ServerType.JELLYFIN) { // It is possible that another function sets an interval. // We only want one running, so clear the existing interval if (progressIntervalId.current) { @@ -379,7 +379,7 @@ export const useScrobble = () => { // multiple times in a row and playback goes normally (no next/previous) equalityFn: (a, b) => // compute whether the song changed - a[0]?.uniqueId === b[0]?.uniqueId && + a[0]?._uniqueId === b[0]?._uniqueId && // compute whether the same player: relevant for repeat one and repeat all (one track) a[2] === b[2], }, diff --git a/src/renderer/features/playlists/components/playlist-detail-song-list-header-filters.tsx b/src/renderer/features/playlists/components/playlist-detail-song-list-header-filters.tsx index 6661ba1da..6c0c00e67 100644 --- a/src/renderer/features/playlists/components/playlist-detail-song-list-header-filters.tsx +++ b/src/renderer/features/playlists/components/playlist-detail-song-list-header-filters.tsx @@ -377,7 +377,7 @@ export const PlaylistDetailSongListHeaderFilters = ({ if (!detailQuery.data) return; deletePlaylistMutation?.mutate( { - apiClientProps: { serverId: detailQuery.data.serverId }, + apiClientProps: { serverId: detailQuery.data._serverId }, query: { id: detailQuery.data.id }, }, { diff --git a/src/renderer/features/playlists/routes/playlist-detail-song-list-route.tsx b/src/renderer/features/playlists/routes/playlist-detail-song-list-route.tsx index abe32d2d2..625add5d6 100644 --- a/src/renderer/features/playlists/routes/playlist-detail-song-list-route.tsx +++ b/src/renderer/features/playlists/routes/playlist-detail-song-list-route.tsx @@ -56,7 +56,7 @@ const PlaylistDetailSongListRoute = () => { createPlaylistMutation.mutate( { - apiClientProps: { serverId: detailQuery?.data?.serverId }, + apiClientProps: { serverId: detailQuery?.data?._serverId }, body: { _custom: { navidrome: { @@ -83,7 +83,7 @@ const PlaylistDetailSongListRoute = () => { }, ); deletePlaylistMutation.mutate({ - apiClientProps: { serverId: detailQuery?.data?.serverId }, + apiClientProps: { serverId: detailQuery?.data?._serverId }, query: { id: playlistId }, }); }, @@ -124,7 +124,7 @@ const PlaylistDetailSongListRoute = () => { }), ) } - serverId={detailQuery?.data?.serverId || ''} + serverId={detailQuery?.data?._serverId || ''} /> ), title: t('common.saveAs', { postProcess: 'sentenceCase' }), diff --git a/src/renderer/features/shared/mutations/set-rating-mutation.ts b/src/renderer/features/shared/mutations/set-rating-mutation.ts index 3a7fda56b..eeb004378 100644 --- a/src/renderer/features/shared/mutations/set-rating-mutation.ts +++ b/src/renderer/features/shared/mutations/set-rating-mutation.ts @@ -74,7 +74,7 @@ export const useSetRating = (args: MutationHookArgs) => { if (remote) { remote.updateRating( variables.query.rating, - variables.query.item[0].serverId, + variables.query.item[0]._serverId, songIds, ); } @@ -88,9 +88,9 @@ export const useSetRating = (args: MutationHookArgs) => { variables.query.item[0].itemType === LibraryItem.ALBUM; if (isAlbumDetailPage) { - const { id: albumId, serverId } = variables.query.item[0] as Album; + const { id: albumId, _serverId } = variables.query.item[0] as Album; - const queryKey = queryKeys.albums.detail(serverId || '', { id: albumId }); + const queryKey = queryKeys.albums.detail(_serverId || '', { id: albumId }); const previous = queryClient.getQueryData(queryKey); if (previous) { queryClient.setQueryData(queryKey, { diff --git a/src/renderer/features/similar-songs/components/similar-songs-list.tsx b/src/renderer/features/similar-songs/components/similar-songs-list.tsx index 258a20e74..596241271 100644 --- a/src/renderer/features/similar-songs/components/similar-songs-list.tsx +++ b/src/renderer/features/similar-songs/components/similar-songs-list.tsx @@ -34,7 +34,7 @@ export const SimilarSongsList = ({ count, fullScreen, song }: SimilarSongsListPr count, songId: song.id, }, - serverId: song?.serverId, + serverId: song?._serverId, }), ); diff --git a/src/renderer/store/player.store.ts b/src/renderer/store/player.store.ts index d32c55b42..cc1633c42 100644 --- a/src/renderer/store/player.store.ts +++ b/src/renderer/store/player.store.ts @@ -137,7 +137,7 @@ export const usePlayerStoreBase = create()( state.queue.shuffled[currentIndex], ...shuffleInPlace([ ...state.queue.shuffled.slice(currentIndex + 1), - ...newItems.map((item) => item.uniqueId), + ...newItems.map((item) => item._uniqueId), ]), ]; } @@ -160,7 +160,7 @@ export const usePlayerStoreBase = create()( state.queue.shuffled[currentIndex], ...shuffleInPlace([ ...state.queue.shuffled.slice(currentIndex + 1), - ...newItems.map((item) => item.uniqueId), + ...newItems.map((item) => item._uniqueId), ]), ]; } @@ -177,7 +177,7 @@ export const usePlayerStoreBase = create()( if (state.player.shuffle === PlayerShuffle.TRACK) { state.queue.shuffled = shuffleInPlace( - newItems.map((item) => item.uniqueId), + newItems.map((item) => item._uniqueId), ); } }); @@ -198,7 +198,7 @@ export const usePlayerStoreBase = create()( state.queue.shuffled = [ ...state.queue.shuffled, - ...newItems.map((item) => item.uniqueId), + ...newItems.map((item) => item._uniqueId), ]; }); break; @@ -227,7 +227,7 @@ export const usePlayerStoreBase = create()( state.queue.shuffled[currentIndex], ...shuffleInPlace([ ...state.queue.shuffled.slice(currentIndex + 1), - ...newItems.map((item) => item.uniqueId), + ...newItems.map((item) => item._uniqueId), ]), ]; }); @@ -252,7 +252,7 @@ export const usePlayerStoreBase = create()( state.player.index = 0; } else if (currentTrack) { const priorityIndex = state.queue.priority.findIndex( - (item) => item.uniqueId === currentTrack.uniqueId, + (item) => item._uniqueId === currentTrack._uniqueId, ); // If the current track is in the priority queue, add the first item after the current track @@ -294,7 +294,7 @@ export const usePlayerStoreBase = create()( if (state.player.shuffle === PlayerShuffle.TRACK) { state.queue.shuffled = shuffleInPlace( - newItems.map((item) => item.uniqueId), + newItems.map((item) => item._uniqueId), ); } }); @@ -312,7 +312,7 @@ export const usePlayerStoreBase = create()( set((state) => { if (queueType === PlayerQueueType.DEFAULT) { const index = state.queue.default.findIndex( - (item) => item.uniqueId === uniqueId, + (item) => item._uniqueId === uniqueId, ); const insertIndex = Math.max(0, edge === 'top' ? index : index + 1); @@ -333,7 +333,7 @@ export const usePlayerStoreBase = create()( state.queue.default = newQueue; } else { const priorityIndex = state.queue.priority.findIndex( - (item) => item.uniqueId === uniqueId, + (item) => item._uniqueId === uniqueId, ); if (priorityIndex !== -1) { @@ -349,7 +349,7 @@ export const usePlayerStoreBase = create()( ]; } else { const defaultIndex = state.queue.default.findIndex( - (item) => item.uniqueId === uniqueId, + (item) => item._uniqueId === uniqueId, ); if (defaultIndex !== -1) { @@ -374,7 +374,7 @@ export const usePlayerStoreBase = create()( state.queue.shuffled[currentIndex], ...shuffleInPlace([ ...state.queue.shuffled.slice(currentIndex + 1), - ...newItems.map((item) => item.uniqueId), + ...newItems.map((item) => item._uniqueId), ]), ]; } @@ -390,14 +390,14 @@ export const usePlayerStoreBase = create()( }, clearSelected: (items: QueueSong[]) => { set((state) => { - const uniqueIds = items.map((item) => item.uniqueId); + const uniqueIds = items.map((item) => item._uniqueId); state.queue.default = state.queue.default.filter( - (item) => !uniqueIds.includes(item.uniqueId), + (item) => !uniqueIds.includes(item._uniqueId), ); state.queue.priority = state.queue.priority.filter( - (item) => !uniqueIds.includes(item.uniqueId), + (item) => !uniqueIds.includes(item._uniqueId), ); const newQueue = [...state.queue.priority, ...state.queue.default]; @@ -546,7 +546,7 @@ export const usePlayerStoreBase = create()( if (id) { const queue = state.getQueue(); - const index = queue.items.findIndex((item) => item.uniqueId === id); + const index = queue.items.findIndex((item) => item._uniqueId === id); if (index !== -1) { state.player.index = index; @@ -618,12 +618,12 @@ export const usePlayerStoreBase = create()( const queueType = getQueueType(); set((state) => { - const uniqueIdMap = new Map(items.map((item) => [item.uniqueId, item])); + const uniqueIdMap = new Map(items.map((item) => [item._uniqueId, item])); if (queueType == PlayerQueueType.DEFAULT) { // Find the index of the drop target const index = state.queue.default.findIndex( - (item) => item.uniqueId === uniqueId, + (item) => item._uniqueId === uniqueId, ); // Get the new index based on the edge @@ -631,11 +631,11 @@ export const usePlayerStoreBase = create()( const itemsBefore = state.queue.default .slice(0, insertIndex) - .filter((item) => !uniqueIdMap.has(item.uniqueId)); + .filter((item) => !uniqueIdMap.has(item._uniqueId)); const itemsAfter = state.queue.default .slice(insertIndex) - .filter((item) => !uniqueIdMap.has(item.uniqueId)); + .filter((item) => !uniqueIdMap.has(item._uniqueId)); const newQueue = [...itemsBefore, ...items, ...itemsAfter]; @@ -643,7 +643,7 @@ export const usePlayerStoreBase = create()( state.queue.default = newQueue; } else { const priorityIndex = state.queue.priority.findIndex( - (item) => item.uniqueId === uniqueId, + (item) => item._uniqueId === uniqueId, ); // If the item is in the priority queue @@ -655,16 +655,16 @@ export const usePlayerStoreBase = create()( const itemsBefore = state.queue.priority .slice(0, newIndex) - .filter((item) => !uniqueIdMap.has(item.uniqueId)); + .filter((item) => !uniqueIdMap.has(item._uniqueId)); const itemsAfter = state.queue.priority .slice(newIndex) - .filter((item) => !uniqueIdMap.has(item.uniqueId)); + .filter((item) => !uniqueIdMap.has(item._uniqueId)); const newPriorityQueue = [...itemsBefore, ...items, ...itemsAfter]; const newDefaultQueue = state.queue.default.filter( - (item) => !uniqueIdMap.has(item.uniqueId), + (item) => !uniqueIdMap.has(item._uniqueId), ); recalculatePlayerIndex(state, newPriorityQueue); @@ -673,7 +673,7 @@ export const usePlayerStoreBase = create()( state.queue.default = newDefaultQueue; } else { const defaultIndex = state.queue.default.findIndex( - (item) => item.uniqueId === uniqueId, + (item) => item._uniqueId === uniqueId, ); if (defaultIndex !== -1) { @@ -684,11 +684,11 @@ export const usePlayerStoreBase = create()( const itemsBefore = state.queue.default .slice(0, newIndex) - .filter((item) => !uniqueIdMap.has(item.uniqueId)); + .filter((item) => !uniqueIdMap.has(item._uniqueId)); const itemsAfter = state.queue.default .slice(newIndex) - .filter((item) => !uniqueIdMap.has(item.uniqueId)); + .filter((item) => !uniqueIdMap.has(item._uniqueId)); const newDefaultQueue = [ ...itemsBefore, @@ -697,7 +697,7 @@ export const usePlayerStoreBase = create()( ]; const newPriorityQueue = state.queue.priority.filter( - (item) => !uniqueIdMap.has(item.uniqueId), + (item) => !uniqueIdMap.has(item._uniqueId), ); recalculatePlayerIndex(state, newDefaultQueue); @@ -711,17 +711,17 @@ export const usePlayerStoreBase = create()( }, moveSelectedToBottom: (items: QueueSong[]) => { set((state) => { - const uniqueIds = items.map((item) => item.uniqueId); + const uniqueIds = items.map((item) => item._uniqueId); if (state.player.queueType === PlayerQueueType.PRIORITY) { const priorityFiltered = state.queue.priority.filter( - (item) => !uniqueIds.includes(item.uniqueId), + (item) => !uniqueIds.includes(item._uniqueId), ); const newPriorityQueue = [...priorityFiltered, ...items]; const filtered = state.queue.default.filter( - (item) => !uniqueIds.includes(item.uniqueId), + (item) => !uniqueIds.includes(item._uniqueId), ); const newDefaultQueue = [...filtered]; @@ -732,7 +732,7 @@ export const usePlayerStoreBase = create()( state.queue.priority = newPriorityQueue; } else { const filtered = state.queue.default.filter( - (item) => !uniqueIds.includes(item.uniqueId), + (item) => !uniqueIds.includes(item._uniqueId), ); const newQueue = [...filtered, ...items]; @@ -750,14 +750,14 @@ export const usePlayerStoreBase = create()( const queue = state.getQueue(); const index = state.player.index; const currentTrack = queue.items[index]; - const uniqueId = currentTrack?.uniqueId; + const uniqueId = currentTrack?._uniqueId; - const uniqueIds = items.map((item) => item.uniqueId); + const uniqueIds = items.map((item) => item._uniqueId); if (queueType === PlayerQueueType.DEFAULT) { const currentIndex = state.player.index; const filtered = state.queue.default.filter( - (item) => !uniqueIds.includes(item.uniqueId), + (item) => !uniqueIds.includes(item._uniqueId), ); const newQueue = [ @@ -770,10 +770,12 @@ export const usePlayerStoreBase = create()( state.queue.default = newQueue; } else { const priorityIndex = state.queue.priority.findIndex( - (item) => item.uniqueId === uniqueId, + (item) => item._uniqueId === uniqueId, ); - const uniqueIdMap = new Map(items.map((item) => [item.uniqueId, item])); + const uniqueIdMap = new Map( + items.map((item) => [item._uniqueId, item]), + ); // If the item is in the priority queue if (priorityIndex !== -1) { @@ -781,16 +783,16 @@ export const usePlayerStoreBase = create()( const itemsBefore = state.queue.priority .slice(0, newIndex) - .filter((item) => !uniqueIdMap.has(item.uniqueId)); + .filter((item) => !uniqueIdMap.has(item._uniqueId)); const itemsAfter = state.queue.priority .slice(newIndex) - .filter((item) => !uniqueIdMap.has(item.uniqueId)); + .filter((item) => !uniqueIdMap.has(item._uniqueId)); const newPriorityQueue = [...itemsBefore, ...items, ...itemsAfter]; const newDefaultQueue = state.queue.default.filter( - (item) => !uniqueIdMap.has(item.uniqueId), + (item) => !uniqueIdMap.has(item._uniqueId), ); recalculatePlayerIndex(state, newPriorityQueue); @@ -799,7 +801,7 @@ export const usePlayerStoreBase = create()( state.queue.default = newDefaultQueue; } else { const defaultIndex = state.queue.default.findIndex( - (item) => item.uniqueId === uniqueId, + (item) => item._uniqueId === uniqueId, ); if (defaultIndex !== -1) { @@ -807,11 +809,11 @@ export const usePlayerStoreBase = create()( const itemsBefore = state.queue.default .slice(0, newIndex) - .filter((item) => !uniqueIdMap.has(item.uniqueId)); + .filter((item) => !uniqueIdMap.has(item._uniqueId)); const itemsAfter = state.queue.default .slice(newIndex) - .filter((item) => !uniqueIdMap.has(item.uniqueId)); + .filter((item) => !uniqueIdMap.has(item._uniqueId)); const newDefaultQueue = [ ...itemsBefore, @@ -820,7 +822,7 @@ export const usePlayerStoreBase = create()( ]; const newPriorityQueue = state.queue.priority.filter( - (item) => !uniqueIdMap.has(item.uniqueId), + (item) => !uniqueIdMap.has(item._uniqueId), ); recalculatePlayerIndex(state, newDefaultQueue); @@ -834,17 +836,17 @@ export const usePlayerStoreBase = create()( }, moveSelectedToTop: (items: QueueSong[]) => { set((state) => { - const uniqueIds = items.map((item) => item.uniqueId); + const uniqueIds = items.map((item) => item._uniqueId); if (state.player.queueType === PlayerQueueType.PRIORITY) { const priorityFiltered = state.queue.priority.filter( - (item) => !uniqueIds.includes(item.uniqueId), + (item) => !uniqueIds.includes(item._uniqueId), ); const newPriorityQueue = [...items, ...priorityFiltered]; const filtered = state.queue.default.filter( - (item) => !uniqueIds.includes(item.uniqueId), + (item) => !uniqueIds.includes(item._uniqueId), ); const newDefaultQueue = [...filtered]; @@ -855,7 +857,7 @@ export const usePlayerStoreBase = create()( state.queue.priority = newPriorityQueue; } else { const filtered = state.queue.default.filter( - (item) => !uniqueIds.includes(item.uniqueId), + (item) => !uniqueIds.includes(item._uniqueId), ); const newQueue = [...items, ...filtered]; @@ -926,7 +928,7 @@ export const usePlayerStoreBase = create()( set((state) => { state.player.shuffle = shuffle; const queue = state.queue.default; - state.queue.shuffled = shuffleInPlace(queue.map((item) => item.uniqueId)); + state.queue.shuffled = shuffleInPlace(queue.map((item) => item._uniqueId)); }); }, setSpeed: (speed: number) => { @@ -948,7 +950,7 @@ export const usePlayerStoreBase = create()( shuffle: () => { set((state) => { const queue = state.queue.default; - state.queue.shuffled = shuffleInPlace(queue.map((item) => item.uniqueId)); + state.queue.shuffled = shuffleInPlace(queue.map((item) => item._uniqueId)); }); }, shuffleAll: () => { @@ -960,7 +962,7 @@ export const usePlayerStoreBase = create()( shuffleSelected: (items: QueueSong[]) => { set((state) => { const indices = items.map((item) => - state.queue.default.findIndex((i) => i.uniqueId === item.uniqueId), + state.queue.default.findIndex((i) => i._uniqueId === item._uniqueId), ); const shuffledItems = shuffleInPlace(items); @@ -1143,7 +1145,7 @@ export const subscribeCurrentTrack = ( }, { equalityFn: (a, b) => { - return a.song?.uniqueId === b.song?.uniqueId; + return a.song?._uniqueId === b.song?._uniqueId; }, }, ); @@ -1377,14 +1379,14 @@ function recalculatePlayerIndex(state: any, queue: QueueSong[]) { return; } - const index = queue.findIndex((item) => item.uniqueId === currentTrack.uniqueId); + const index = queue.findIndex((item) => item._uniqueId === currentTrack._uniqueId); state.player.index = Math.max(0, index); } function toQueueSong(item: Song): QueueSong { return { ...item, - uniqueId: nanoid(), + _uniqueId: nanoid(), }; } diff --git a/src/renderer/utils/set-transcoded-queue-data.ts b/src/renderer/utils/set-transcoded-queue-data.ts index 6f7d69eed..0fe73aba4 100644 --- a/src/renderer/utils/set-transcoded-queue-data.ts +++ b/src/renderer/utils/set-transcoded-queue-data.ts @@ -12,7 +12,7 @@ const modifyUrl = (song: QueueSong): string => { if (transcode.enabled) { const streamUrl = api.controller.getTranscodingUrl({ apiClientProps: { - serverId: song.serverId, + serverId: song._serverId, }, query: { base: song.streamUrl, diff --git a/src/shared/api/jellyfin/jellyfin-normalize.ts b/src/shared/api/jellyfin/jellyfin-normalize.ts index 0fc1bf528..19f47302f 100644 --- a/src/shared/api/jellyfin/jellyfin-normalize.ts +++ b/src/shared/api/jellyfin/jellyfin-normalize.ts @@ -1,4 +1,3 @@ -import { nanoid } from 'nanoid'; import { z } from 'zod'; import { jfType } from '/@/shared/api/jellyfin/jellyfin-types'; @@ -228,6 +227,8 @@ const normalizeSong = ( } return { + _serverId: server?.id || '', + _serverType: ServerType.JELLYFIN, album: item.Album, albumArtists: item.AlbumArtists?.map((entry) => ({ id: entry.Id, @@ -290,13 +291,10 @@ const normalizeSong = ( : null, releaseYear: item.ProductionYear ? String(item.ProductionYear) : null, sampleRate, - serverId: server?.id || '', - serverType: ServerType.JELLYFIN, size, streamUrl, tags: getTags(item), trackNumber: item.IndexNumber, - uniqueId: nanoid(), updatedAt: item.DateCreated, userFavorite: (item.UserData && item.UserData.IsFavorite) || false, userRating: null, @@ -309,6 +307,8 @@ const normalizeAlbum = ( imageSize?: number, ): Album => { return { + _serverId: server?.id || '', + _serverType: ServerType.JELLYFIN, albumArtist: item.AlbumArtist, albumArtists: item.AlbumArtists.map((entry) => ({ @@ -351,13 +351,10 @@ const normalizeAlbum = ( releaseDate: item.PremiereDate?.split('T')[0] || null, releaseTypes: [], releaseYear: item.ProductionYear || null, - serverId: server?.id || '', - serverType: ServerType.JELLYFIN, size: null, songCount: item?.ChildCount || null, songs: item.Songs?.map((song) => normalizeSong(song, server, '', imageSize)), tags: getTags(item), - uniqueId: nanoid(), updatedAt: item?.DateLastMediaAdded || item.DateCreated, userFavorite: item.UserData?.IsFavorite || false, userRating: null, @@ -386,6 +383,8 @@ const normalizeAlbumArtist = ( ) || []; return { + _serverId: server?.id || '', + _serverType: ServerType.JELLYFIN, albumCount: item.AlbumCount ?? null, backgroundImageUrl: null, biography: item.Overview || null, @@ -407,8 +406,6 @@ const normalizeAlbumArtist = ( mbz: item.ProviderIds?.MusicBrainzArtist || null, name: item.Name, playCount: item.UserData?.PlayCount || 0, - serverId: server?.id || '', - serverType: ServerType.JELLYFIN, similarArtists, songCount: item.SongCount ?? null, userFavorite: item.UserData?.IsFavorite || false, @@ -430,6 +427,8 @@ const normalizePlaylist = ( const imagePlaceholderUrl = null; return { + _serverId: server?.id || '', + _serverType: ServerType.JELLYFIN, description: item.Overview || null, duration: item.RunTimeTicks / 10000, genres: item.GenreItems?.map((entry) => ({ @@ -447,8 +446,6 @@ const normalizePlaylist = ( ownerId: null, public: null, rules: null, - serverId: server?.id || '', - serverType: ServerType.JELLYFIN, size: null, songCount: item?.ChildCount || null, sync: null, diff --git a/src/shared/api/navidrome/navidrome-normalize.ts b/src/shared/api/navidrome/navidrome-normalize.ts index 602f56cd6..a35b91630 100644 --- a/src/shared/api/navidrome/navidrome-normalize.ts +++ b/src/shared/api/navidrome/navidrome-normalize.ts @@ -1,4 +1,3 @@ -import { nanoid } from 'nanoid'; import z from 'zod'; import { ndType } from '/@/shared/api/navidrome/navidrome-types'; @@ -152,6 +151,8 @@ const normalizeSong = ( album: item.album, albumId: item.albumId, ...getArtists(item), + _serverId: server?.id || 'unknown', + _serverType: ServerType.NAVIDROME, artistName: item.artist, bitDepth: item.bitDepth || null, bitRate: item.bitRate, @@ -204,13 +205,10 @@ const normalizeSong = ( ).toISOString(), releaseYear: String(item.year), sampleRate: item.sampleRate || null, - serverId: server?.id || 'unknown', - serverType: ServerType.NAVIDROME, size: item.size, streamUrl: `${server?.url}/rest/stream.view?id=${id}&v=1.13.0&c=Feishin&${server?.credential}`, tags: item.tags || null, trackNumber: item.trackNumber, - uniqueId: nanoid(), updatedAt: item.updatedAt, userFavorite: item.starred || false, userRating: item.rating || null, @@ -280,6 +278,8 @@ const normalizeAlbum = ( return { ...parseAlbumTags(item), ...getArtists(item), + _serverId: server?.id || 'unknown', + _serverType: ServerType.NAVIDROME, albumArtist: item.albumArtist, backdropImageUrl: imageBackdropUrl, comment: item.comment || null, @@ -301,9 +301,9 @@ const normalizeAlbum = ( imagePlaceholderUrl, imageUrl, isCompilation: item.compilation, + itemType: LibraryItem.ALBUM, lastPlayedAt: normalizePlayDate(item), - mbzId: item.mbzAlbumId || null, name: item.name, originalDate: item.originalDate @@ -317,12 +317,9 @@ const normalizeAlbum = ( : new Date(Date.UTC(item.minYear, 0, 1)) ).toISOString(), releaseYear: item.minYear, - serverId: server?.id || 'unknown', - serverType: ServerType.NAVIDROME, size: item.size, songCount: item.songCount, songs: item.songs ? item.songs.map((song) => normalizeSong(song, server)) : undefined, - uniqueId: nanoid(), updatedAt: item.updatedAt, userFavorite: item.starred, userRating: item.rating || null, @@ -365,6 +362,8 @@ const normalizeAlbumArtist = ( } return { + _serverId: server?.id || 'unknown', + _serverType: ServerType.NAVIDROME, albumCount, backgroundImageUrl: null, biography: item.biography || null, @@ -382,8 +381,6 @@ const normalizeAlbumArtist = ( mbz: item.mbzArtistId || null, name: item.name, playCount: item.playCount || 0, - serverId: server?.id || 'unknown', - serverType: ServerType.NAVIDROME, similarArtists: item.similarArtists?.map((artist) => ({ id: artist.id, @@ -412,6 +409,8 @@ const normalizePlaylist = ( const imagePlaceholderUrl = null; return { + _serverId: server?.id || 'unknown', + _serverType: ServerType.NAVIDROME, description: item.comment, duration: item.duration * 1000, genres: [], @@ -424,8 +423,6 @@ const normalizePlaylist = ( ownerId: item.ownerId, public: item.public, rules: item?.rules || null, - serverId: server?.id || 'unknown', - serverType: ServerType.NAVIDROME, size: item.size, songCount: item.songCount, sync: item.sync, diff --git a/src/shared/api/subsonic/subsonic-normalize.ts b/src/shared/api/subsonic/subsonic-normalize.ts index 58904124f..dc1f46900 100644 --- a/src/shared/api/subsonic/subsonic-normalize.ts +++ b/src/shared/api/subsonic/subsonic-normalize.ts @@ -1,4 +1,3 @@ -import { nanoid } from 'nanoid'; import { z } from 'zod'; import { ssType } from '/@/shared/api/subsonic/subsonic-types'; @@ -9,10 +8,10 @@ import { Genre, LibraryItem, Playlist, - QueueSong, RelatedArtist, ServerListItemWithCredential, ServerType, + Song, } from '/@/shared/types/domain-types'; const getCoverArtUrl = (args: { @@ -119,7 +118,7 @@ const normalizeSong = ( item: z.infer, server?: null | ServerListItemWithCredential, size?: number, -): QueueSong => { +): Song => { const imageUrl = getCoverArtUrl({ baseUrl: server?.url, @@ -131,6 +130,8 @@ const normalizeSong = ( const streamUrl = `${server?.url}/rest/stream.view?id=${item.id}&v=1.13.0&c=Feishin&${server?.credential}`; return { + _serverId: server?.id || 'unknown', + _serverType: ServerType.SUBSONIC, album: item.album || '', albumArtists: getArtistList(item.albumArtists, item.artistId, item.artist), albumId: item.albumId?.toString() || '', @@ -183,13 +184,10 @@ const normalizeSong = ( releaseDate: null, releaseYear: item.year ? String(item.year) : null, sampleRate: item.samplingRate || null, - serverId: server?.id || 'unknown', - serverType: ServerType.SUBSONIC, size: item.size, streamUrl, tags: null, trackNumber: item.track || 1, - uniqueId: nanoid(), updatedAt: '', userFavorite: item.starred || false, userRating: item.userRating || null, @@ -212,6 +210,8 @@ const normalizeAlbumArtist = ( }) || null; return { + _serverId: server?.id || 'unknown', + _serverType: ServerType.SUBSONIC, albumCount: item.albumCount ? Number(item.albumCount) : 0, backgroundImageUrl: null, biography: null, @@ -224,8 +224,6 @@ const normalizeAlbumArtist = ( mbz: null, name: item.name, playCount: null, - serverId: server?.id || 'unknown', - serverType: ServerType.SUBSONIC, similarArtists: [], songCount: null, userFavorite: false, @@ -247,6 +245,8 @@ const normalizeAlbum = ( }) || null; return { + _serverId: server?.id || 'unknown', + _serverType: ServerType.SUBSONIC, albumArtist: item.artist, albumArtists: getArtistList(item.artists, item.artistId, item.artist), artists: [], @@ -276,8 +276,6 @@ const normalizeAlbum = ( releaseDate: item.year ? new Date(Date.UTC(item.year, 0, 1)).toISOString() : null, releaseTypes: item.releaseTypes || [], releaseYear: item.year ? Number(item.year) : null, - serverId: server?.id || 'unknown', - serverType: ServerType.SUBSONIC, size: null, songCount: item.songCount, songs: @@ -285,7 +283,6 @@ const normalizeAlbum = ( normalizeSong(song, server), ) || [], tags: null, - uniqueId: nanoid(), updatedAt: item.created, userFavorite: item.starred || false, userRating: item.userRating || null, @@ -300,6 +297,8 @@ const normalizePlaylist = ( server?: null | ServerListItemWithCredential, ): Playlist => { return { + _serverId: server?.id || 'unknown', + _serverType: ServerType.SUBSONIC, description: item.comment || null, duration: item.duration * 1000, genres: [], @@ -316,8 +315,6 @@ const normalizePlaylist = ( owner: item.owner, ownerId: item.owner, public: item.public, - serverId: server?.id || 'unknown', - serverType: ServerType.SUBSONIC, size: null, songCount: item.songCount, }; diff --git a/src/shared/types/domain-types.ts b/src/shared/types/domain-types.ts index 3850e0761..a5e0c67b9 100644 --- a/src/shared/types/domain-types.ts +++ b/src/shared/types/domain-types.ts @@ -80,7 +80,7 @@ export interface QueueData { } export type QueueSong = Song & { - uniqueId: string; + _uniqueId: string; }; export type ServerListItem = { @@ -161,6 +161,8 @@ export enum ImageType { } export type Album = { + _serverId: string; + _serverType: ServerType; albumArtist: string; albumArtists: RelatedArtist[]; artists: RelatedArtist[]; @@ -185,13 +187,10 @@ export type Album = { releaseDate: null | string; releaseTypes: string[]; releaseYear: null | number; - serverId: string; - serverType: ServerType; size: null | number; songCount: null | number; songs?: Song[]; tags: null | Record; - uniqueId: string; updatedAt: string; userFavorite: boolean; userRating: null | number; @@ -199,6 +198,8 @@ export type Album = { } & { songs?: Song[] }; export type AlbumArtist = { + _serverId: string; + _serverType: ServerType; albumCount: null | number; backgroundImageUrl: null | string; biography: null | string; @@ -211,8 +212,6 @@ export type AlbumArtist = { mbz: null | string; name: string; playCount: null | number; - serverId: string; - serverType: ServerType; similarArtists: null | RelatedArtist[]; songCount: null | number; userFavorite: boolean; @@ -220,15 +219,14 @@ export type AlbumArtist = { }; export type Artist = { + _serverId: string; + _serverType: ServerType; biography: null | string; createdAt: string; id: string; itemType: LibraryItem.ARTIST; name: string; remoteCreatedAt: null | string; - serverFolderId: string; - serverId: string; - serverType: ServerType; updatedAt: string; }; @@ -297,6 +295,8 @@ export type MusicFolder = { export type MusicFoldersResponse = MusicFolder[]; export type Playlist = { + _serverId: string; + _serverType: ServerType; description: null | string; duration: null | number; genres: Genre[]; @@ -309,8 +309,6 @@ export type Playlist = { ownerId: null | string; public: boolean | null; rules?: null | Record; - serverId: string; - serverType: ServerType; size: null | number; songCount: null | number; sync?: boolean | null; @@ -328,6 +326,8 @@ export type RelatedArtist = { }; export type Song = { + _serverId: string; + _serverType: ServerType; album: null | string; albumArtists: RelatedArtist[]; albumId: string; @@ -364,13 +364,10 @@ export type Song = { releaseDate: null | string; releaseYear: null | string; sampleRate: null | number; - serverId: string; - serverType: ServerType; size: number; streamUrl: string; tags: null | Record; trackNumber: number; - uniqueId: string; updatedAt: string; userFavorite: boolean; userRating: null | number;