handle favorite/update in similarArtists

This commit is contained in:
jeffvli
2025-12-28 03:43:59 -08:00
parent 66699b9572
commit 1a930021b6
9 changed files with 124 additions and 15 deletions
@@ -279,11 +279,11 @@ export const SubsonicController: InternalControllerEndpoint = {
}
return {
...ssNormalize.albumArtist(artist, apiClientProps.server, 300),
...ssNormalize.albumArtist(artist, apiClientProps.server),
albums: artist.album?.map((album) => ssNormalize.album(album, apiClientProps.server)),
similarArtists:
artistInfo?.similarArtist?.map((artist) =>
ssNormalize.albumArtist(artist, apiClientProps.server, 300),
ssNormalize.albumArtist(artist, apiClientProps.server),
) || null,
};
},
@@ -303,7 +303,7 @@ export const SubsonicController: InternalControllerEndpoint = {
const artists = (res.body.artists?.index || []).flatMap((index) => index.artist);
let results = artists.map((artist) =>
ssNormalize.albumArtist(artist, apiClientProps.server, 300),
ssNormalize.albumArtist(artist, apiClientProps.server),
);
if (query.searchTerm) {
@@ -488,7 +488,7 @@ export const SubsonicController: InternalControllerEndpoint = {
return {
items:
res.body.albumList2.album?.map((album) =>
ssNormalize.album(album, apiClientProps.server, 300),
ssNormalize.album(album, apiClientProps.server),
) || [],
startIndex: query.startIndex,
totalRecordCount: null,
@@ -658,7 +658,7 @@ export const SubsonicController: InternalControllerEndpoint = {
}
let results = artists.map((artist) =>
ssNormalize.albumArtist(artist, apiClientProps.server, 300),
ssNormalize.albumArtist(artist, apiClientProps.server),
);
if (query.searchTerm) {
@@ -506,8 +506,8 @@ const AlbumArtistMetadataSimilarArtists = ({
playCount: null,
similarArtists: null,
songCount: null,
userFavorite: false,
userRating: null,
userFavorite: relatedArtist.userFavorite,
userRating: relatedArtist.userRating,
}),
);
}, [detailQuery.data?.similarArtists, server?.type, serverId]);
@@ -215,13 +215,36 @@ export const applyFavoriteOptimisticUpdates = (
queryClient.setQueryData(
queryKey,
(prev: AlbumArtistDetailResponse | undefined) => {
if (prev && itemIdSet.has(prev.id)) {
if (!prev) {
return prev;
}
// Update the main artist if it matches
if (itemIdSet.has(prev.id)) {
return {
...prev,
userFavorite: isFavorite,
};
}
// Update similar artists if any match
if (prev.similarArtists && prev.similarArtists.length > 0) {
const hasMatchingSimilarArtist = prev.similarArtists.some(
(artist) => itemIdSet.has(artist.id),
);
if (hasMatchingSimilarArtist) {
return {
...prev,
similarArtists: prev.similarArtists.map((artist) =>
itemIdSet.has(artist.id)
? { ...artist, userFavorite: isFavorite }
: artist,
),
};
}
}
return prev;
},
);
@@ -184,9 +184,33 @@ export const applyRatingOptimisticUpdates = (
queryClient.setQueryData(
queryKey,
(prev: AlbumArtistDetailResponse | undefined) => {
if (prev && itemIdSet.has(prev.id)) {
if (!prev) {
return prev;
}
// Update the main artist if it matches
if (itemIdSet.has(prev.id)) {
return { ...prev, userRating: rating };
}
// Update similar artists if any match
if (prev.similarArtists && prev.similarArtists.length > 0) {
const hasMatchingSimilarArtist = prev.similarArtists.some(
(artist) => itemIdSet.has(artist.id),
);
if (hasMatchingSimilarArtist) {
return {
...prev,
similarArtists: prev.similarArtists.map((artist) =>
itemIdSet.has(artist.id)
? { ...artist, userRating: rating }
: artist,
),
};
}
}
return prev;
},
);
@@ -37,6 +37,8 @@ const getPeople = (item: AlbumOrSong): null | Record<string, RelatedArtist[]> =>
imageId: null,
imageUrl: null,
name: person.Name,
userFavorite: false,
userRating: null,
};
if (key in participants) {
@@ -148,6 +150,8 @@ const normalizeSong = (
imageId: entry.Id,
imageUrl: null,
name: entry.Name,
userFavorite: false,
userRating: null,
})),
albumId: item.AlbumId || `dummy/${item.Id}`,
artistName: item?.ArtistItems?.[0]?.Name || item?.AlbumArtists?.[0]?.Name,
@@ -157,6 +161,8 @@ const normalizeSong = (
imageId: null,
imageUrl: null,
name: entry.Name,
userFavorite: false,
userRating: null,
}),
),
bitDepth: null,
@@ -232,6 +238,8 @@ const normalizeAlbum = (
imageId: entry.Id,
imageUrl: null,
name: entry.Name,
userFavorite: false,
userRating: null,
})) || [],
artists: (item.ArtistItems?.length ? item.ArtistItems : item.AlbumArtists)?.map(
(entry) => ({
@@ -239,6 +247,8 @@ const normalizeAlbum = (
imageId: entry.Id,
imageUrl: null,
name: entry.Name,
userFavorite: false,
userRating: null,
}),
),
comment: null,
@@ -295,6 +305,8 @@ const normalizeAlbumArtist = (
imageId: getAlbumArtistImageId(entry),
imageUrl: null,
name: entry.Name,
userFavorite: entry.UserData?.IsFavorite || false,
userRating: null,
}),
) || [];
@@ -51,6 +51,8 @@ const getArtists = (
imageId: null,
imageUrl: null,
name: item.name,
userFavorite: false,
userRating: null,
}));
if (role === 'albumartist') {
@@ -67,6 +69,8 @@ const getArtists = (
imageId: null,
imageUrl: null,
name: artist.name,
userFavorite: false,
userRating: null,
};
if (subRoles.has(artist.subRole)) {
@@ -89,12 +93,28 @@ const getArtists = (
if (albumArtists === undefined) {
albumArtists = [
{ id: item.albumArtistId, imageId: null, imageUrl: null, name: item.albumArtist },
{
id: item.albumArtistId,
imageId: null,
imageUrl: null,
name: item.albumArtist,
userFavorite: false,
userRating: null,
},
];
}
if (artists === undefined) {
artists = [{ id: item.artistId, imageId: null, imageUrl: null, name: item.artist }];
artists = [
{
id: item.artistId,
imageId: null,
imageUrl: null,
name: item.artist,
userFavorite: false,
userRating: null,
},
];
}
return { albumArtists, artists, participants };
@@ -304,6 +324,8 @@ const normalizeAlbumArtist = (
songCount = item.songCount;
}
console.log('similarArtists', item.similarArtists);
return {
_itemType: LibraryItem.ALBUM_ARTIST,
_serverId: server?.id || 'unknown',
@@ -335,7 +357,9 @@ const normalizeAlbumArtist = (
imageId: null,
imageUrl: artist?.artistImageUrl?.replace(/\?size=\d+/, '') || null,
name: artist.name,
})) || null,
userFavorite: Boolean(artist.starred) || false,
userRating: artist.userRating || null,
})) || [],
songCount,
userFavorite: item.starred || false,
userRating: item.rating || null,
+25 -3
View File
@@ -27,6 +27,8 @@ const getArtistList = (
imageId: null,
imageUrl: null,
name: item.name,
userFavorite: false,
userRating: null,
}))
: [
{
@@ -34,6 +36,8 @@ const getArtistList = (
imageId: null,
imageUrl: null,
name: artistName || '',
userFavorite: false,
userRating: null,
},
];
};
@@ -55,6 +59,8 @@ const getParticipants = (
imageId: null,
imageUrl: null,
name: contributor.artist.name || '',
userFavorite: false,
userRating: null,
};
const role = contributor.subRole
@@ -178,8 +184,16 @@ const normalizeSong = (
const normalizeAlbumArtist = (
item:
| z.infer<typeof ssType._response.albumArtist>
| z.infer<typeof ssType._response.artistListEntry>,
| (z.infer<typeof ssType._response.albumArtist> & {
similarArtists?: z.infer<
typeof ssType._response.artistInfo
>['artistInfo']['similarArtist'];
})
| (z.infer<typeof ssType._response.artistListEntry> & {
similarArtists?: z.infer<
typeof ssType._response.artistInfo
>['artistInfo']['similarArtist'];
}),
server?: null | ServerListItemWithCredential,
): AlbumArtist => {
return {
@@ -197,7 +211,15 @@ const normalizeAlbumArtist = (
mbz: null,
name: item.name,
playCount: null,
similarArtists: [],
similarArtists:
item.similarArtists?.map((artist) => ({
id: artist.id,
imageId: null,
imageUrl: null,
name: artist.name,
userFavorite: Boolean(artist.starred) || false,
userRating: artist.userRating || null,
})) || [],
songCount: null,
userFavorite: Boolean(item.starred) || false,
userRating: null,
@@ -236,6 +236,8 @@ const artistInfo = z.object({
coverArt: z.string().optional(),
id: z.string(),
name: z.string(),
starred: z.string().optional(),
userRating: z.number().optional(),
}),
),
smallImageUrl: z.string().optional(),
+2
View File
@@ -356,6 +356,8 @@ export type RelatedArtist = {
imageId: null | string;
imageUrl: null | string;
name: string;
userFavorite: boolean;
userRating: null | number;
};
export type Song = {