rename internal types in domain models

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