mirror of
https://github.com/jeffvli/feishin.git
synced 2026-08-08 13:23:16 +02:00
Make ratings/favourites a bit more customizable (#2262)
* Replace show ratings toggle with favorite/rating controls setting Swap `genera.showRatings` (previously a simple bool) for a `favoriteRatingControls` enum, exposed via derived `useShowRatings` / `useShowFavorites` hooks. Settings switch becomes a select, with a migration to a new v32 schema mapping the old boolean forward with no user change. * Gate favorite controls on `favoriteRatingControls` setting Hide the playerbar and mobile fullscreen favorite buttons and the context-menu favorite action when the setting excludes favorites, mirroring how ratings are already gated. * Gate favorite controls on item cards and detail list Drill a `showFavorite` flag through the item-card tree (mirroring `showRating`), and gate the card/detail-list favorite badges and hover buttons on the `favoriteRatingControls` setting. * Gate favorite controls in detail headers and album group controls * Keep the original `showRatings` switch and add a `showFavorites` * Gate album header favorite hander at definition
This commit is contained in:
@@ -33,6 +33,7 @@ interface ItemCardControlsProps {
|
||||
internalState?: ItemListStateActions;
|
||||
item: Album | AlbumArtist | Artist | Genre | Playlist | Song | undefined;
|
||||
itemType: LibraryItem;
|
||||
showFavorite: boolean;
|
||||
showRating: boolean;
|
||||
type?: 'compact' | 'default' | 'poster';
|
||||
}
|
||||
@@ -205,6 +206,7 @@ export const ItemCardControls = ({
|
||||
internalState,
|
||||
item,
|
||||
itemType,
|
||||
showFavorite,
|
||||
showRating,
|
||||
type = 'default',
|
||||
}: ItemCardControlsProps) => {
|
||||
@@ -289,7 +291,7 @@ export const ItemCardControls = ({
|
||||
</PlayTooltip>
|
||||
</Tooltip.Group>
|
||||
)}
|
||||
{controls?.onFavorite && (
|
||||
{controls?.onFavorite && showFavorite && (
|
||||
<FavoriteButton isFavorite={isFavorite} onClick={favoriteHandler} />
|
||||
)}
|
||||
{controls?.onRating &&
|
||||
|
||||
@@ -19,7 +19,7 @@ import { ItemControls } from '/@/renderer/components/item-list/types';
|
||||
import { JoinedArtists } from '/@/renderer/features/albums/components/joined-artists';
|
||||
import { useDragDrop } from '/@/renderer/hooks/use-drag-drop';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { useShowRatings } from '/@/renderer/store';
|
||||
import { useShowFavorites, useShowRatings } from '/@/renderer/store';
|
||||
import {
|
||||
formatDateAbsolute,
|
||||
formatDateRelative,
|
||||
@@ -90,6 +90,7 @@ export const ItemCard = ({
|
||||
withControls,
|
||||
}: ItemCardProps) => {
|
||||
const showRatings = useShowRatings();
|
||||
const showFavorites = useShowFavorites();
|
||||
const imageUrl = getImageUrl(data);
|
||||
const rows = providedRows || [];
|
||||
|
||||
@@ -110,6 +111,7 @@ export const ItemCard = ({
|
||||
isRound={isRound}
|
||||
itemType={itemType}
|
||||
rows={rows}
|
||||
showFavorite={showFavorites}
|
||||
showRating={showRatings}
|
||||
withControls={withControls}
|
||||
/>
|
||||
@@ -130,6 +132,7 @@ export const ItemCard = ({
|
||||
isRound={isRound}
|
||||
itemType={itemType}
|
||||
rows={rows}
|
||||
showFavorite={showFavorites}
|
||||
showRating={showRatings}
|
||||
withControls={withControls}
|
||||
/>
|
||||
@@ -150,6 +153,7 @@ export const ItemCard = ({
|
||||
isRound={isRound}
|
||||
itemType={itemType}
|
||||
rows={rows}
|
||||
showFavorite={showFavorites}
|
||||
showRating={showRatings}
|
||||
withControls={withControls}
|
||||
/>
|
||||
@@ -166,6 +170,7 @@ export interface ItemCardDerivativeProps extends Omit<ItemCardProps, 'type'> {
|
||||
imageUrl: string | undefined;
|
||||
internalState?: ItemListStateActions;
|
||||
rows: DataRow[];
|
||||
showFavorite: boolean;
|
||||
showRating: boolean;
|
||||
}
|
||||
|
||||
@@ -186,6 +191,7 @@ const ItemCardStandardImageArea = memo(function ItemCardStandardImageArea({
|
||||
isRound,
|
||||
itemType,
|
||||
navigationPath,
|
||||
showFavorite,
|
||||
showRating,
|
||||
variant,
|
||||
withControls,
|
||||
@@ -204,6 +210,7 @@ const ItemCardStandardImageArea = memo(function ItemCardStandardImageArea({
|
||||
isRound?: boolean;
|
||||
itemType: LibraryItem;
|
||||
navigationPath: null | string;
|
||||
showFavorite: boolean;
|
||||
showRating: boolean;
|
||||
variant: 'default' | 'poster';
|
||||
withControls?: boolean;
|
||||
@@ -259,7 +266,7 @@ const ItemCardStandardImageArea = memo(function ItemCardStandardImageArea({
|
||||
type="itemCard"
|
||||
/>
|
||||
)}
|
||||
{isFavorite && <div className={styles.favoriteBadge} />}
|
||||
{showFavorite && isFavorite && <div className={styles.favoriteBadge} />}
|
||||
{hasRating && <div className={styles.ratingBadge}>{userRating}</div>}
|
||||
<AnimatePresence>
|
||||
{withControls && showControls && (
|
||||
@@ -269,6 +276,7 @@ const ItemCardStandardImageArea = memo(function ItemCardStandardImageArea({
|
||||
{...(variant === 'poster' ? { internalState } : {})}
|
||||
item={data}
|
||||
itemType={itemType}
|
||||
showFavorite={showFavorite}
|
||||
showRating={showRating}
|
||||
type={variant}
|
||||
/>
|
||||
@@ -321,6 +329,7 @@ const CompactItemCardImageArea = memo(function CompactItemCardImageArea({
|
||||
itemType,
|
||||
navigationPath,
|
||||
rows,
|
||||
showFavorite,
|
||||
showRating,
|
||||
withControls,
|
||||
}: {
|
||||
@@ -338,6 +347,7 @@ const CompactItemCardImageArea = memo(function CompactItemCardImageArea({
|
||||
itemType: LibraryItem;
|
||||
navigationPath: null | string;
|
||||
rows: DataRow[];
|
||||
showFavorite: boolean;
|
||||
showRating: boolean;
|
||||
withControls?: boolean;
|
||||
}) {
|
||||
@@ -393,7 +403,7 @@ const CompactItemCardImageArea = memo(function CompactItemCardImageArea({
|
||||
type="itemCard"
|
||||
/>
|
||||
)}
|
||||
{isFavorite && <div className={styles.favoriteBadge} />}
|
||||
{showFavorite && isFavorite && <div className={styles.favoriteBadge} />}
|
||||
{hasRating && <div className={styles.ratingBadge}>{userRating}</div>}
|
||||
<AnimatePresence>
|
||||
{withControls && showControls && data && (
|
||||
@@ -403,6 +413,7 @@ const CompactItemCardImageArea = memo(function CompactItemCardImageArea({
|
||||
internalState={internalState}
|
||||
item={data}
|
||||
itemType={itemType}
|
||||
showFavorite={showFavorite}
|
||||
showRating={showRating}
|
||||
type="compact"
|
||||
/>
|
||||
@@ -468,6 +479,7 @@ const CompactItemCard = ({
|
||||
isRound,
|
||||
itemType,
|
||||
rows,
|
||||
showFavorite,
|
||||
showRating,
|
||||
withControls,
|
||||
}: ItemCardDerivativeProps) => {
|
||||
@@ -634,6 +646,7 @@ const CompactItemCard = ({
|
||||
itemType={itemType}
|
||||
navigationPath={navigationPath}
|
||||
rows={rows}
|
||||
showFavorite={showFavorite}
|
||||
showRating={showRating}
|
||||
withControls={withControls}
|
||||
/>
|
||||
@@ -679,6 +692,7 @@ const DefaultItemCard = ({
|
||||
isRound,
|
||||
itemType,
|
||||
rows,
|
||||
showFavorite,
|
||||
showRating,
|
||||
withControls,
|
||||
}: ItemCardDerivativeProps) => {
|
||||
@@ -777,6 +791,7 @@ const DefaultItemCard = ({
|
||||
isRound={isRound}
|
||||
itemType={itemType}
|
||||
navigationPath={navigationPath}
|
||||
showFavorite={showFavorite}
|
||||
showRating={showRating}
|
||||
variant="default"
|
||||
withControls={withControls}
|
||||
@@ -840,6 +855,7 @@ const PosterItemCard = ({
|
||||
isRound,
|
||||
itemType,
|
||||
rows,
|
||||
showFavorite,
|
||||
showRating,
|
||||
withControls,
|
||||
}: ItemCardDerivativeProps) => {
|
||||
@@ -1005,6 +1021,7 @@ const PosterItemCard = ({
|
||||
isRound={isRound}
|
||||
itemType={itemType}
|
||||
navigationPath={navigationPath}
|
||||
showFavorite={showFavorite}
|
||||
showRating={showRating}
|
||||
variant="poster"
|
||||
withControls={withControls}
|
||||
|
||||
@@ -67,7 +67,7 @@ import { useIsMutatingDeleteFavorite } from '/@/renderer/features/shared/mutatio
|
||||
import { songsQueries } from '/@/renderer/features/songs/api/songs-api';
|
||||
import { useDragDrop } from '/@/renderer/hooks/use-drag-drop';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { useSettingsStore, useShowRatings } from '/@/renderer/store';
|
||||
import { useSettingsStore, useShowFavorites, useShowRatings } from '/@/renderer/store';
|
||||
import { formatDurationString, formatPartialIsoDateUTC } from '/@/renderer/utils';
|
||||
import { SEPARATOR_STRING } from '/@/shared/api/utils';
|
||||
import { ExplicitIndicator } from '/@/shared/components/explicit-indicator/explicit-indicator';
|
||||
@@ -426,6 +426,7 @@ const MetadataSection = memo(
|
||||
({ controls, internalState, item }: MetadataSectionProps) => {
|
||||
const { t } = useTranslation();
|
||||
const showRatings = useShowRatings();
|
||||
const showFavorites = useShowFavorites();
|
||||
const [isImageHovered, setIsImageHovered] = useState(false);
|
||||
const [isMetadataHovered, setIsMetadataHovered] = useState(false);
|
||||
|
||||
@@ -570,7 +571,7 @@ const MetadataSection = memo(
|
||||
serverId={item._serverId}
|
||||
type="itemCard"
|
||||
/>
|
||||
{isFavorite && <div className={styles.favoriteBadge} />}
|
||||
{showFavorites && isFavorite && <div className={styles.favoriteBadge} />}
|
||||
{hasRating && <div className={styles.ratingBadge}>{userRating}</div>}
|
||||
<AnimatePresence>
|
||||
{controls && isImageHovered && (
|
||||
@@ -580,6 +581,7 @@ const MetadataSection = memo(
|
||||
internalState={internalState}
|
||||
item={item}
|
||||
itemType={item._itemType}
|
||||
showFavorite={showFavorites}
|
||||
showRating={true}
|
||||
type="compact"
|
||||
/>
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useSetRating } from '/@/renderer/features/shared/hooks/use-set-rating';
|
||||
import { useIsMutatingCreateFavorite } from '/@/renderer/features/shared/mutations/create-favorite-mutation';
|
||||
import { useIsMutatingDeleteFavorite } from '/@/renderer/features/shared/mutations/delete-favorite-mutation';
|
||||
import { useIsMutatingRating } from '/@/renderer/features/shared/mutations/set-rating-mutation';
|
||||
import { useShowRatings } from '/@/renderer/store';
|
||||
import { useShowFavorites, useShowRatings } from '/@/renderer/store';
|
||||
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
||||
import { Rating } from '/@/shared/components/rating/rating';
|
||||
import { LibraryItem, ServerType } from '/@/shared/types/domain-types';
|
||||
@@ -35,6 +35,7 @@ interface AlbumGroupControlsProps {
|
||||
|
||||
export const AlbumGroupControls = ({ albumId, serverId, serverType }: AlbumGroupControlsProps) => {
|
||||
const showRatingsSetting = useShowRatings();
|
||||
const showFavorites = useShowFavorites();
|
||||
const detailQuery = useAlbumGroupAlbum(albumId, serverId);
|
||||
const setFavorite = useSetFavorite();
|
||||
const setRating = useSetRating();
|
||||
@@ -77,23 +78,25 @@ export const AlbumGroupControls = ({ albumId, serverId, serverType }: AlbumGroup
|
||||
|
||||
return (
|
||||
<div className={styles.controls}>
|
||||
<ActionIcon
|
||||
className={styles.favorite}
|
||||
disabled={isMutatingFavorite}
|
||||
icon="favorite"
|
||||
iconProps={{
|
||||
color: album.userFavorite ? 'primary' : 'muted',
|
||||
fill: album.userFavorite ? 'primary' : undefined,
|
||||
size: 'xs',
|
||||
}}
|
||||
onClick={handleFavorite}
|
||||
onDoubleClick={(event) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}}
|
||||
size="xs"
|
||||
variant="transparent"
|
||||
/>
|
||||
{showFavorites && (
|
||||
<ActionIcon
|
||||
className={styles.favorite}
|
||||
disabled={isMutatingFavorite}
|
||||
icon="favorite"
|
||||
iconProps={{
|
||||
color: album.userFavorite ? 'primary' : 'muted',
|
||||
fill: album.userFavorite ? 'primary' : undefined,
|
||||
size: 'xs',
|
||||
}}
|
||||
onClick={handleFavorite}
|
||||
onDoubleClick={(event) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}}
|
||||
size="xs"
|
||||
variant="transparent"
|
||||
/>
|
||||
)}
|
||||
{showRating && (
|
||||
<Rating
|
||||
className={styles.rating}
|
||||
|
||||
Reference in New Issue
Block a user