mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-09 20:29:36 +02:00
Add configurable play button behavior
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
|||||||
LibraryItem,
|
LibraryItem,
|
||||||
CardRow,
|
CardRow,
|
||||||
CardRoute,
|
CardRoute,
|
||||||
|
Play,
|
||||||
} from '@/renderer/types';
|
} from '@/renderer/types';
|
||||||
|
|
||||||
initSimpleImg({ threshold: 0.5 }, true);
|
initSimpleImg({ threshold: 0.5 }, true);
|
||||||
@@ -133,6 +134,7 @@ interface BaseGridCardProps {
|
|||||||
cardRows: CardRow[];
|
cardRows: CardRow[];
|
||||||
handlePlayQueueAdd: (options: PlayQueueAddOptions) => void;
|
handlePlayQueueAdd: (options: PlayQueueAddOptions) => void;
|
||||||
itemType: LibraryItem;
|
itemType: LibraryItem;
|
||||||
|
playButtonBehavior: Play;
|
||||||
route: CardRoute;
|
route: CardRoute;
|
||||||
};
|
};
|
||||||
data: any;
|
data: any;
|
||||||
@@ -154,7 +156,7 @@ export const DefaultCard = ({
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { isScrolling, index } = listChildProps;
|
const { isScrolling, index } = listChildProps;
|
||||||
const { itemGap, itemHeight, itemWidth } = sizes;
|
const { itemGap, itemHeight, itemWidth } = sizes;
|
||||||
const { cardControls, handlePlayQueueAdd, itemType, cardRows, route } =
|
const { handlePlayQueueAdd, itemType, cardRows, route, playButtonBehavior } =
|
||||||
controls;
|
controls;
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
@@ -204,10 +206,10 @@ export const DefaultCard = ({
|
|||||||
<ControlsContainer>
|
<ControlsContainer>
|
||||||
{!isScrolling && (
|
{!isScrolling && (
|
||||||
<GridCardControls
|
<GridCardControls
|
||||||
cardControls={cardControls}
|
|
||||||
handlePlayQueueAdd={handlePlayQueueAdd}
|
handlePlayQueueAdd={handlePlayQueueAdd}
|
||||||
itemData={data}
|
itemData={data}
|
||||||
itemType={itemType}
|
itemType={itemType}
|
||||||
|
playButtonBehavior={playButtonBehavior}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</ControlsContainer>
|
</ControlsContainer>
|
||||||
@@ -224,6 +226,7 @@ export const DefaultCard = ({
|
|||||||
<React.Fragment key={`${data.id}-${item.id}`}>
|
<React.Fragment key={`${data.id}-${item.id}`}>
|
||||||
{itemIndex > 0 && (
|
{itemIndex > 0 && (
|
||||||
<Text
|
<Text
|
||||||
|
$noSelect
|
||||||
sx={{
|
sx={{
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
padding: '0 2px 0 1px',
|
padding: '0 2px 0 1px',
|
||||||
@@ -234,6 +237,7 @@ export const DefaultCard = ({
|
|||||||
)}{' '}
|
)}{' '}
|
||||||
<Text
|
<Text
|
||||||
$link
|
$link
|
||||||
|
$noSelect
|
||||||
$secondary={index > 0}
|
$secondary={index > 0}
|
||||||
component={Link}
|
component={Link}
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
@@ -262,6 +266,7 @@ export const DefaultCard = ({
|
|||||||
{data[row.property].map((item: any) => (
|
{data[row.property].map((item: any) => (
|
||||||
<Text
|
<Text
|
||||||
key={`${data.id}-${item.id}`}
|
key={`${data.id}-${item.id}`}
|
||||||
|
$noSelect
|
||||||
$secondary={index > 0}
|
$secondary={index > 0}
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
>
|
>
|
||||||
@@ -277,6 +282,7 @@ export const DefaultCard = ({
|
|||||||
{row.route ? (
|
{row.route ? (
|
||||||
<Text
|
<Text
|
||||||
$link
|
$link
|
||||||
|
$noSelect
|
||||||
component={Link}
|
component={Link}
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
to={generatePath(
|
to={generatePath(
|
||||||
@@ -293,7 +299,7 @@ export const DefaultCard = ({
|
|||||||
{data && data[row.property]}
|
{data && data[row.property]}
|
||||||
</Text>
|
</Text>
|
||||||
) : (
|
) : (
|
||||||
<Text $secondary={index > 0} overflow="hidden">
|
<Text $noSelect $secondary={index > 0} overflow="hidden">
|
||||||
{data && data[row.property]}
|
{data && data[row.property]}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { Button } from '@/renderer/components/button';
|
import { Button } from '@/renderer/components/button';
|
||||||
import { DropdownMenu } from '@/renderer/components/dropdown-menu';
|
import { DropdownMenu } from '@/renderer/components/dropdown-menu';
|
||||||
import { Play } from '@/renderer/types';
|
import { LibraryItem, Play, PlayQueueAddOptions } from '@/renderer/types';
|
||||||
|
|
||||||
type PlayButtonType = UnstyledButtonProps &
|
type PlayButtonType = UnstyledButtonProps &
|
||||||
React.ComponentPropsWithoutRef<'button'>;
|
React.ComponentPropsWithoutRef<'button'>;
|
||||||
@@ -74,11 +74,32 @@ const FavoriteWrapper = styled.span<{ isFavorite: boolean }>`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const PLAY_TYPES = [
|
||||||
|
{
|
||||||
|
label: 'Play',
|
||||||
|
play: Play.NOW,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Play last',
|
||||||
|
play: Play.LAST,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Play next',
|
||||||
|
play: Play.NEXT,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export const GridCardControls = ({
|
export const GridCardControls = ({
|
||||||
itemData,
|
itemData,
|
||||||
itemType,
|
itemType,
|
||||||
handlePlayQueueAdd,
|
handlePlayQueueAdd,
|
||||||
}: any) => {
|
playButtonBehavior,
|
||||||
|
}: {
|
||||||
|
handlePlayQueueAdd: (options: PlayQueueAddOptions) => void;
|
||||||
|
itemData: any;
|
||||||
|
itemType: LibraryItem;
|
||||||
|
playButtonBehavior: Play;
|
||||||
|
}) => {
|
||||||
return (
|
return (
|
||||||
<GridCardControlsContainer>
|
<GridCardControlsContainer>
|
||||||
<TopControls />
|
<TopControls />
|
||||||
@@ -96,7 +117,7 @@ export const GridCardControls = ({
|
|||||||
id: itemData.id,
|
id: itemData.id,
|
||||||
type: itemType,
|
type: itemType,
|
||||||
},
|
},
|
||||||
play: Play.NOW,
|
play: playButtonBehavior,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -126,36 +147,26 @@ export const GridCardControls = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</DropdownMenu.Target>
|
</DropdownMenu.Target>
|
||||||
<DropdownMenu.Dropdown>
|
<DropdownMenu.Dropdown>
|
||||||
<DropdownMenu.Item
|
{PLAY_TYPES.filter(
|
||||||
onClick={(e: MouseEvent) => {
|
(type) => type.play !== playButtonBehavior
|
||||||
e.preventDefault();
|
).map((type) => (
|
||||||
e.stopPropagation();
|
<DropdownMenu.Item
|
||||||
handlePlayQueueAdd({
|
key={`playtype-${type.play}`}
|
||||||
byItemType: {
|
onClick={(e: MouseEvent) => {
|
||||||
id: itemData.id,
|
e.preventDefault();
|
||||||
type: itemType,
|
e.stopPropagation();
|
||||||
},
|
handlePlayQueueAdd({
|
||||||
play: Play.LAST,
|
byItemType: {
|
||||||
});
|
id: itemData.id,
|
||||||
}}
|
type: itemType,
|
||||||
>
|
},
|
||||||
Play later
|
play: type.play,
|
||||||
</DropdownMenu.Item>
|
});
|
||||||
<DropdownMenu.Item
|
}}
|
||||||
onClick={(e: MouseEvent) => {
|
>
|
||||||
e.preventDefault();
|
{type.label}
|
||||||
e.stopPropagation();
|
</DropdownMenu.Item>
|
||||||
handlePlayQueueAdd({
|
))}
|
||||||
byItemType: {
|
|
||||||
id: itemData.id,
|
|
||||||
type: itemType,
|
|
||||||
},
|
|
||||||
play: Play.NEXT,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Play next
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
<DropdownMenu.Divider />
|
<DropdownMenu.Divider />
|
||||||
<DropdownMenu.Item disabled>Add to playlist</DropdownMenu.Item>
|
<DropdownMenu.Item disabled>Add to playlist</DropdownMenu.Item>
|
||||||
<DropdownMenu.Divider />
|
<DropdownMenu.Divider />
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export const GridCard = ({
|
|||||||
cardRows,
|
cardRows,
|
||||||
itemData,
|
itemData,
|
||||||
itemType,
|
itemType,
|
||||||
|
playButtonBehavior,
|
||||||
route,
|
route,
|
||||||
display,
|
display,
|
||||||
} = data as GridCardData;
|
} = data as GridCardData;
|
||||||
@@ -40,6 +41,7 @@ export const GridCard = ({
|
|||||||
cardRows,
|
cardRows,
|
||||||
handlePlayQueueAdd,
|
handlePlayQueueAdd,
|
||||||
itemType,
|
itemType,
|
||||||
|
playButtonBehavior,
|
||||||
route,
|
route,
|
||||||
}}
|
}}
|
||||||
data={itemData[i]}
|
data={itemData[i]}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
LibraryItem,
|
LibraryItem,
|
||||||
CardRow,
|
CardRow,
|
||||||
CardRoute,
|
CardRoute,
|
||||||
|
Play,
|
||||||
} from '@/renderer/types';
|
} from '@/renderer/types';
|
||||||
|
|
||||||
initSimpleImg({ threshold: 0.5 }, true);
|
initSimpleImg({ threshold: 0.5 }, true);
|
||||||
@@ -125,10 +126,10 @@ const Row = styled.div<{ $secondary?: boolean }>`
|
|||||||
interface BaseGridCardProps {
|
interface BaseGridCardProps {
|
||||||
columnIndex: number;
|
columnIndex: number;
|
||||||
controls: {
|
controls: {
|
||||||
cardControls: any[];
|
|
||||||
cardRows: CardRow[];
|
cardRows: CardRow[];
|
||||||
handlePlayQueueAdd: (options: PlayQueueAddOptions) => void;
|
handlePlayQueueAdd: (options: PlayQueueAddOptions) => void;
|
||||||
itemType: LibraryItem;
|
itemType: LibraryItem;
|
||||||
|
playButtonBehavior: Play;
|
||||||
route: CardRoute;
|
route: CardRoute;
|
||||||
};
|
};
|
||||||
data: any;
|
data: any;
|
||||||
@@ -149,7 +150,7 @@ export const PosterCard = ({
|
|||||||
}: BaseGridCardProps) => {
|
}: BaseGridCardProps) => {
|
||||||
const { isScrolling, index } = listChildProps;
|
const { isScrolling, index } = listChildProps;
|
||||||
const { itemGap, itemHeight, itemWidth } = sizes;
|
const { itemGap, itemHeight, itemWidth } = sizes;
|
||||||
const { cardControls, handlePlayQueueAdd, itemType, cardRows, route } =
|
const { handlePlayQueueAdd, itemType, cardRows, route, playButtonBehavior } =
|
||||||
controls;
|
controls;
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
@@ -196,10 +197,10 @@ export const PosterCard = ({
|
|||||||
<ControlsContainer>
|
<ControlsContainer>
|
||||||
{!isScrolling && (
|
{!isScrolling && (
|
||||||
<GridCardControls
|
<GridCardControls
|
||||||
cardControls={cardControls}
|
|
||||||
handlePlayQueueAdd={handlePlayQueueAdd}
|
handlePlayQueueAdd={handlePlayQueueAdd}
|
||||||
itemData={data}
|
itemData={data}
|
||||||
itemType={itemType}
|
itemType={itemType}
|
||||||
|
playButtonBehavior={playButtonBehavior}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</ControlsContainer>
|
</ControlsContainer>
|
||||||
@@ -217,6 +218,7 @@ export const PosterCard = ({
|
|||||||
<React.Fragment key={`${data.id}-${item.id}`}>
|
<React.Fragment key={`${data.id}-${item.id}`}>
|
||||||
{itemIndex > 0 && (
|
{itemIndex > 0 && (
|
||||||
<Text
|
<Text
|
||||||
|
$noSelect
|
||||||
sx={{
|
sx={{
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
padding: '0 2px 0 1px',
|
padding: '0 2px 0 1px',
|
||||||
@@ -227,6 +229,7 @@ export const PosterCard = ({
|
|||||||
)}{' '}
|
)}{' '}
|
||||||
<Text
|
<Text
|
||||||
$link
|
$link
|
||||||
|
$noSelect
|
||||||
$secondary={index > 0}
|
$secondary={index > 0}
|
||||||
component={Link}
|
component={Link}
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
@@ -254,6 +257,7 @@ export const PosterCard = ({
|
|||||||
{data[row.property].map((item: any) => (
|
{data[row.property].map((item: any) => (
|
||||||
<Text
|
<Text
|
||||||
key={`${data.id}-${item.id}`}
|
key={`${data.id}-${item.id}`}
|
||||||
|
$noSelect
|
||||||
$secondary={index > 0}
|
$secondary={index > 0}
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
>
|
>
|
||||||
@@ -269,6 +273,7 @@ export const PosterCard = ({
|
|||||||
{row.route ? (
|
{row.route ? (
|
||||||
<Text
|
<Text
|
||||||
$link
|
$link
|
||||||
|
$noSelect
|
||||||
component={Link}
|
component={Link}
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
to={generatePath(
|
to={generatePath(
|
||||||
@@ -284,7 +289,7 @@ export const PosterCard = ({
|
|||||||
{data && data[row.property]}
|
{data && data[row.property]}
|
||||||
</Text>
|
</Text>
|
||||||
) : (
|
) : (
|
||||||
<Text $secondary={index > 0} overflow="hidden">
|
<Text $noSelect $secondary={index > 0} overflow="hidden">
|
||||||
{data && data[row.property]}
|
{data && data[row.property]}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { FixedSizeList, FixedSizeListProps } from 'react-window';
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { GridCard } from '@/renderer/components/virtual-grid/grid-card';
|
import { GridCard } from '@/renderer/components/virtual-grid/grid-card';
|
||||||
import { usePlayQueueHandler } from '@/renderer/features/player/hooks/use-playqueue-handler';
|
import { usePlayQueueHandler } from '@/renderer/features/player/hooks/use-playqueue-handler';
|
||||||
|
import { useSettingsStore } from '@/renderer/store/settings.store';
|
||||||
import {
|
import {
|
||||||
CardRow,
|
CardRow,
|
||||||
LibraryItem,
|
LibraryItem,
|
||||||
@@ -38,26 +39,27 @@ export const VirtualGridWrapper = ({
|
|||||||
rowCount: number;
|
rowCount: number;
|
||||||
}) => {
|
}) => {
|
||||||
const handlePlayQueueAdd = usePlayQueueHandler();
|
const handlePlayQueueAdd = usePlayQueueHandler();
|
||||||
|
const { playButtonBehavior } = useSettingsStore((state) => state.player);
|
||||||
|
|
||||||
const memo = useMemo(
|
const memo = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
cardRows,
|
cardRows,
|
||||||
columnCount,
|
columnCount,
|
||||||
display,
|
display,
|
||||||
handlePlayQueueAdd,
|
|
||||||
itemCount,
|
itemCount,
|
||||||
itemData,
|
itemData,
|
||||||
itemGap,
|
itemGap,
|
||||||
itemHeight,
|
itemHeight,
|
||||||
itemType,
|
itemType,
|
||||||
itemWidth,
|
itemWidth,
|
||||||
|
playButtonBehavior,
|
||||||
route,
|
route,
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
cardRows,
|
cardRows,
|
||||||
itemType,
|
itemType,
|
||||||
columnCount,
|
columnCount,
|
||||||
handlePlayQueueAdd,
|
playButtonBehavior,
|
||||||
itemCount,
|
itemCount,
|
||||||
itemData,
|
itemData,
|
||||||
display,
|
display,
|
||||||
@@ -74,7 +76,7 @@ export const VirtualGridWrapper = ({
|
|||||||
{...rest}
|
{...rest}
|
||||||
useIsScrolling
|
useIsScrolling
|
||||||
itemCount={rowCount}
|
itemCount={rowCount}
|
||||||
itemData={memo}
|
itemData={{ ...memo, handlePlayQueueAdd }}
|
||||||
itemSize={itemHeight}
|
itemSize={itemHeight}
|
||||||
overscanCount={5}
|
overscanCount={5}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user