mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-10 04:30:25 +02:00
add missing releases from musicbrainz to artist page
This commit is contained in:
@@ -20,6 +20,11 @@
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container.external {
|
||||||
|
opacity: 0.6;
|
||||||
|
filter: grayscale(0.3) saturate(0.7);
|
||||||
|
}
|
||||||
|
|
||||||
.image-container {
|
.image-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
@@ -65,6 +70,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image-container.no-hover-overlay {
|
||||||
|
&:hover {
|
||||||
|
&::before {
|
||||||
|
opacity: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.favorite-badge {
|
.favorite-badge {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -50px;
|
top: -50px;
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import {
|
|||||||
Genre,
|
Genre,
|
||||||
LibraryItem,
|
LibraryItem,
|
||||||
Playlist,
|
Playlist,
|
||||||
|
ServerType,
|
||||||
Song,
|
Song,
|
||||||
} from '/@/shared/types/domain-types';
|
} from '/@/shared/types/domain-types';
|
||||||
import { DragOperation, DragTarget } from '/@/shared/types/drag-and-drop';
|
import { DragOperation, DragTarget } from '/@/shared/types/drag-and-drop';
|
||||||
@@ -339,9 +340,11 @@ const CompactItemCard = ({
|
|||||||
? (data as { userRating: null | number }).userRating
|
? (data as { userRating: null | number }).userRating
|
||||||
: null;
|
: null;
|
||||||
const hasRating = showRating && userRating !== null && userRating > 0;
|
const hasRating = showRating && userRating !== null && userRating > 0;
|
||||||
|
const isExternal = data._serverType === ServerType.EXTERNAL;
|
||||||
|
|
||||||
const imageContainerClassName = clsx(styles.imageContainer, {
|
const imageContainerClassName = clsx(styles.imageContainer, {
|
||||||
[styles.isRound]: isRound,
|
[styles.isRound]: isRound,
|
||||||
|
[styles.noHoverOverlay]: isExternal,
|
||||||
});
|
});
|
||||||
|
|
||||||
const imageContainerContent = (
|
const imageContainerContent = (
|
||||||
@@ -374,7 +377,7 @@ const CompactItemCard = ({
|
|||||||
{isFavorite && <div className={styles.favoriteBadge} />}
|
{isFavorite && <div className={styles.favoriteBadge} />}
|
||||||
{hasRating && <div className={styles.ratingBadge}>{userRating}</div>}
|
{hasRating && <div className={styles.ratingBadge}>{userRating}</div>}
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{withControls && showControls && data && (
|
{withControls && showControls && data && !isExternal && (
|
||||||
<ItemCardControls
|
<ItemCardControls
|
||||||
controls={controls}
|
controls={controls}
|
||||||
enableExpansion={enableExpansion}
|
enableExpansion={enableExpansion}
|
||||||
@@ -409,6 +412,7 @@ const CompactItemCard = ({
|
|||||||
<div
|
<div
|
||||||
className={clsx(styles.container, styles.compact, {
|
className={clsx(styles.container, styles.compact, {
|
||||||
[styles.dragging]: isDragging,
|
[styles.dragging]: isDragging,
|
||||||
|
[styles.external]: isExternal,
|
||||||
[styles.selected]: isSelected,
|
[styles.selected]: isSelected,
|
||||||
})}
|
})}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
@@ -570,10 +574,6 @@ const DefaultItemCard = ({
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|
||||||
const imageContainerClassName = clsx(styles.imageContainer, {
|
|
||||||
[styles.isRound]: isRound,
|
|
||||||
});
|
|
||||||
|
|
||||||
const isFavorite =
|
const isFavorite =
|
||||||
'userFavorite' in data && (data as { userFavorite: boolean }).userFavorite;
|
'userFavorite' in data && (data as { userFavorite: boolean }).userFavorite;
|
||||||
const userRating =
|
const userRating =
|
||||||
@@ -582,6 +582,12 @@ const DefaultItemCard = ({
|
|||||||
? (data as { userRating: null | number }).userRating
|
? (data as { userRating: null | number }).userRating
|
||||||
: null;
|
: null;
|
||||||
const hasRating = showRating && userRating !== null && userRating > 0;
|
const hasRating = showRating && userRating !== null && userRating > 0;
|
||||||
|
const isExternal = data._serverType === ServerType.EXTERNAL;
|
||||||
|
|
||||||
|
const imageContainerClassName = clsx(styles.imageContainer, {
|
||||||
|
[styles.isRound]: isRound,
|
||||||
|
[styles.noHoverOverlay]: isExternal,
|
||||||
|
});
|
||||||
|
|
||||||
const imageContainerContent = (
|
const imageContainerContent = (
|
||||||
<>
|
<>
|
||||||
@@ -611,7 +617,7 @@ const DefaultItemCard = ({
|
|||||||
{isFavorite && <div className={styles.favoriteBadge} />}
|
{isFavorite && <div className={styles.favoriteBadge} />}
|
||||||
{hasRating && <div className={styles.ratingBadge}>{userRating}</div>}
|
{hasRating && <div className={styles.ratingBadge}>{userRating}</div>}
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{withControls && showControls && (
|
{withControls && showControls && !isExternal && (
|
||||||
<ItemCardControls
|
<ItemCardControls
|
||||||
controls={controls}
|
controls={controls}
|
||||||
enableExpansion={enableExpansion}
|
enableExpansion={enableExpansion}
|
||||||
@@ -628,6 +634,7 @@ const DefaultItemCard = ({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(styles.container, {
|
className={clsx(styles.container, {
|
||||||
|
[styles.external]: isExternal,
|
||||||
[styles.selected]: isSelected,
|
[styles.selected]: isSelected,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
@@ -870,10 +877,6 @@ const PosterItemCard = ({
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|
||||||
const imageContainerClassName = clsx(styles.imageContainer, {
|
|
||||||
[styles.isRound]: isRound,
|
|
||||||
});
|
|
||||||
|
|
||||||
const isFavorite =
|
const isFavorite =
|
||||||
'userFavorite' in data && (data as { userFavorite: boolean }).userFavorite;
|
'userFavorite' in data && (data as { userFavorite: boolean }).userFavorite;
|
||||||
const userRating =
|
const userRating =
|
||||||
@@ -882,6 +885,12 @@ const PosterItemCard = ({
|
|||||||
? (data as { userRating: null | number }).userRating
|
? (data as { userRating: null | number }).userRating
|
||||||
: null;
|
: null;
|
||||||
const hasRating = showRating && userRating !== null && userRating > 0;
|
const hasRating = showRating && userRating !== null && userRating > 0;
|
||||||
|
const isExternal = data._serverType === ServerType.EXTERNAL;
|
||||||
|
|
||||||
|
const imageContainerClassName = clsx(styles.imageContainer, {
|
||||||
|
[styles.isRound]: isRound,
|
||||||
|
[styles.noHoverOverlay]: isExternal,
|
||||||
|
});
|
||||||
|
|
||||||
const imageContainerContent = (
|
const imageContainerContent = (
|
||||||
<>
|
<>
|
||||||
@@ -911,7 +920,7 @@ const PosterItemCard = ({
|
|||||||
{isFavorite && <div className={styles.favoriteBadge} />}
|
{isFavorite && <div className={styles.favoriteBadge} />}
|
||||||
{hasRating && <div className={styles.ratingBadge}>{userRating}</div>}
|
{hasRating && <div className={styles.ratingBadge}>{userRating}</div>}
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{withControls && showControls && data && (
|
{withControls && showControls && data && !isExternal && (
|
||||||
<ItemCardControls
|
<ItemCardControls
|
||||||
controls={controls}
|
controls={controls}
|
||||||
enableExpansion={enableExpansion}
|
enableExpansion={enableExpansion}
|
||||||
@@ -930,6 +939,7 @@ const PosterItemCard = ({
|
|||||||
<div
|
<div
|
||||||
className={clsx(styles.container, styles.poster, {
|
className={clsx(styles.container, styles.poster, {
|
||||||
[styles.dragging]: isDragging,
|
[styles.dragging]: isDragging,
|
||||||
|
[styles.external]: isExternal,
|
||||||
[styles.selected]: isSelected,
|
[styles.selected]: isSelected,
|
||||||
})}
|
})}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { ItemTableListColumn } from '/@/renderer/components/item-list/item-table
|
|||||||
import { ItemControls } from '/@/renderer/components/item-list/types';
|
import { ItemControls } from '/@/renderer/components/item-list/types';
|
||||||
import { artistsQueries } from '/@/renderer/features/artists/api/artists-api';
|
import { artistsQueries } from '/@/renderer/features/artists/api/artists-api';
|
||||||
import { AlbumArtistGridCarousel } from '/@/renderer/features/artists/components/album-artist-grid-carousel';
|
import { AlbumArtistGridCarousel } from '/@/renderer/features/artists/components/album-artist-grid-carousel';
|
||||||
|
import { musicbrainzQueries } from '/@/renderer/features/musicbrainz/api/musicbrainz-api';
|
||||||
import { useIsPlayerFetching, usePlayer } from '/@/renderer/features/player/context/player-context';
|
import { useIsPlayerFetching, usePlayer } from '/@/renderer/features/player/context/player-context';
|
||||||
import { ListConfigMenu } from '/@/renderer/features/shared/components/list-config-menu';
|
import { ListConfigMenu } from '/@/renderer/features/shared/components/list-config-menu';
|
||||||
import {
|
import {
|
||||||
@@ -1364,16 +1365,44 @@ const ArtistAlbums = ({ albumsQuery }: ArtistAlbumsProps) => {
|
|||||||
albumArtistId?: string;
|
albumArtistId?: string;
|
||||||
artistId?: string;
|
artistId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const serverId = useCurrentServerId();
|
||||||
const routeId = (artistId || albumArtistId) as string;
|
const routeId = (artistId || albumArtistId) as string;
|
||||||
|
|
||||||
|
const detailQuery = useSuspenseQuery(
|
||||||
|
artistsQueries.albumArtistDetail({
|
||||||
|
query: { id: routeId },
|
||||||
|
serverId: serverId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const musicbrainzArtistQuery = useQuery({
|
||||||
|
...musicbrainzQueries.artist({ mbzArtistId: detailQuery.data?.mbz as string }),
|
||||||
|
meta: {
|
||||||
|
albumArtist: detailQuery.data,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const musicbrainzAlbums = useMemo(() => {
|
||||||
|
return musicbrainzArtistQuery.data || [];
|
||||||
|
}, [musicbrainzArtistQuery.data]);
|
||||||
|
|
||||||
const rows = useGridRows(LibraryItem.ALBUM, ItemListKey.ALBUM);
|
const rows = useGridRows(LibraryItem.ALBUM, ItemListKey.ALBUM);
|
||||||
const controls = useDefaultItemListControls();
|
const controls = useDefaultItemListControls();
|
||||||
|
|
||||||
const filteredAndSortedAlbums = useMemo(() => {
|
const filteredAndSortedAlbums = useMemo(() => {
|
||||||
const albums = albumsQuery.data?.items || [];
|
const existingReleaseIds = new Set(
|
||||||
|
albumsQuery.data?.items?.map((item) => item.mbzId) || [],
|
||||||
|
);
|
||||||
|
|
||||||
|
const newMusicbrainzAlbums = musicbrainzAlbums.filter(
|
||||||
|
(album) => !existingReleaseIds.has(album.mbzId),
|
||||||
|
);
|
||||||
|
|
||||||
|
const albums = [...(albumsQuery.data?.items || []), ...newMusicbrainzAlbums];
|
||||||
const searched = searchLibraryItems(albums, debouncedSearchTerm, LibraryItem.ALBUM);
|
const searched = searchLibraryItems(albums, debouncedSearchTerm, LibraryItem.ALBUM);
|
||||||
return sortAlbumList(searched, sortBy, sortOrder);
|
return sortAlbumList(searched, sortBy, sortOrder);
|
||||||
}, [albumsQuery.data?.items, debouncedSearchTerm, sortBy, sortOrder]);
|
}, [albumsQuery.data?.items, debouncedSearchTerm, musicbrainzAlbums, sortBy, sortOrder]);
|
||||||
|
|
||||||
const albumsByReleaseType = useMemo(() => {
|
const albumsByReleaseType = useMemo(() => {
|
||||||
return groupAlbumsByReleaseType(filteredAndSortedAlbums, routeId, groupingType);
|
return groupAlbumsByReleaseType(filteredAndSortedAlbums, routeId, groupingType);
|
||||||
|
|||||||
Reference in New Issue
Block a user