From 93ba99e36f0f9162ff638b21046b220a0d09d823 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sat, 29 Nov 2025 04:02:47 -0800 Subject: [PATCH] redesign PlayButtonGroup to match card styles --- .../player/components/shuffle-all-modal.tsx | 70 ++----------------- .../shared/components/library-header-bar.tsx | 13 ++-- .../shared/components/play-button-group.tsx | 62 ++++++++-------- .../shared/components/play-button.tsx | 28 +++++--- 4 files changed, 61 insertions(+), 112 deletions(-) diff --git a/src/renderer/features/player/components/shuffle-all-modal.tsx b/src/renderer/features/player/components/shuffle-all-modal.tsx index fe5b9abdb..4690f091c 100644 --- a/src/renderer/features/player/components/shuffle-all-modal.tsx +++ b/src/renderer/features/player/components/shuffle-all-modal.tsx @@ -12,7 +12,7 @@ import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; import { useGenreList } from '/@/renderer/features/genres/api/genres-api'; import { usePlayer } from '/@/renderer/features/player/context/player-context'; -import { PlayButton } from '/@/renderer/features/shared/components/play-button'; +import { PlayButtonGroup } from '/@/renderer/features/shared/components/play-button-group'; import { useCurrentServer } from '/@/renderer/store'; import { Checkbox } from '/@/shared/components/checkbox/checkbox'; import { Divider } from '/@/shared/components/divider/divider'; @@ -101,16 +101,6 @@ export const ShuffleAllContextModal = () => { closeAllModals(); }; - const isLoadingNext = - isFetching && - (fetchTypeRef.current === Play.NEXT || fetchTypeRef.current === Play.NEXT_SHUFFLE); - - const isLoadingLast = - isFetching && - (fetchTypeRef.current === Play.LAST || fetchTypeRef.current === Play.LAST_SHUFFLE); - - const isLoadingNow = isFetching && fetchTypeRef.current === Play.NOW; - return ( { /> )} - - handlePlay(Play.NEXT)} - onLongPress={() => handlePlay(Play.NEXT_SHUFFLE)} - /> - handlePlay(Play.NOW)} - onLongPress={() => handlePlay(Play.SHUFFLE)} - /> - handlePlay(Play.LAST)} - onLongPress={() => handlePlay(Play.LAST_SHUFFLE)} - /> - - {/* - - - - */} + ); }; diff --git a/src/renderer/features/shared/components/library-header-bar.tsx b/src/renderer/features/shared/components/library-header-bar.tsx index 844e50e45..82d40a6d0 100644 --- a/src/renderer/features/shared/components/library-header-bar.tsx +++ b/src/renderer/features/shared/components/library-header-bar.tsx @@ -1,6 +1,5 @@ import { closeAllModals, openModal } from '@mantine/modals'; import { CSSProperties, memo, ReactNode, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; import styles from './library-header-bar.module.css'; @@ -53,7 +52,6 @@ const HeaderPlayButton = ({ ...props }: HeaderPlayButtonProps) => { const serverId = useCurrentServerId(); - const { t } = useTranslation(); const player = usePlayer(); const handlePlay = useCallback( @@ -77,9 +75,16 @@ const HeaderPlayButton = ({ openModal({ children: , size: 'xs', - title: t('player.play', { postProcess: 'titleCase' }), + styles: { + body: { + padding: 'var(--theme-spacing-md)', + }, + header: { + display: 'none', + }, + }, }); - }, [serverId, handlePlay, t]); + }, [serverId, handlePlay]); return (
diff --git a/src/renderer/features/shared/components/play-button-group.tsx b/src/renderer/features/shared/components/play-button-group.tsx index 0d5258dab..9349e4528 100644 --- a/src/renderer/features/shared/components/play-button-group.tsx +++ b/src/renderer/features/shared/components/play-button-group.tsx @@ -1,58 +1,56 @@ import i18n from '/@/i18n/i18n'; -import { ActionIcon } from '/@/shared/components/action-icon/action-icon'; +import { PlayButton } from '/@/renderer/features/shared/components/play-button'; import { Group } from '/@/shared/components/group/group'; import { AppIconSelection } from '/@/shared/components/icon/icon'; +import { Tooltip } from '/@/shared/components/tooltip/tooltip'; import { Play } from '/@/shared/types/types'; -const playButtons: { icon: AppIconSelection; label: string; type: Play }[] = [ - { - icon: 'mediaPlay', - label: i18n.t('player.play', { postProcess: 'sentenceCase' }), - type: Play.NOW, - }, +const playButtons: { icon: AppIconSelection; label: string; secondary: boolean; type: Play }[] = [ { icon: 'mediaPlayNext', label: i18n.t('player.addNext', { postProcess: 'sentenceCase' }), + secondary: true, type: Play.NEXT, }, + { + icon: 'mediaPlay', + label: i18n.t('player.play', { postProcess: 'sentenceCase' }), + secondary: false, + type: Play.NOW, + }, { icon: 'mediaPlayLast', label: i18n.t('player.addLast', { postProcess: 'sentenceCase' }), + secondary: true, type: Play.LAST, }, - { - icon: 'mediaShuffle', - label: i18n.t('player.shuffle', { postProcess: 'sentenceCase' }), - type: Play.SHUFFLE, - }, ]; +const LONG_PRESS_PLAY_BEHAVIOR = { + [Play.LAST]: Play.LAST_SHUFFLE, + [Play.NEXT]: Play.NEXT_SHUFFLE, + [Play.NOW]: Play.SHUFFLE, +}; + interface PlayButtonGroupProps { + loading?: boolean | Play; onPlay: (type: Play) => void; } -export const PlayButtonGroup = ({ onPlay }: PlayButtonGroupProps) => { +export const PlayButtonGroup = ({ loading, onPlay }: PlayButtonGroupProps) => { return ( - + {playButtons.map((button) => ( - onPlay(button.type)} - styles={{ - root: { - padding: 'var(--mantine-spacing-lg)', - }, - }} - tooltip={{ - label: button.label, - openDelay: 0, - }} - variant="default" - /> + + onPlay(button.type)} + onLongPress={() => onPlay(LONG_PRESS_PLAY_BEHAVIOR[button.type])} + /> + ))} ); diff --git a/src/renderer/features/shared/components/play-button.tsx b/src/renderer/features/shared/components/play-button.tsx index edd966cad..41ad255b9 100644 --- a/src/renderer/features/shared/components/play-button.tsx +++ b/src/renderer/features/shared/components/play-button.tsx @@ -1,6 +1,6 @@ import clsx from 'clsx'; import { t } from 'i18next'; -import { memo } from 'react'; +import { forwardRef, memo } from 'react'; import styles from './play-button.module.css'; @@ -85,16 +85,19 @@ interface PlayButtonProps { onLongPress?: (e: React.MouseEvent) => void; } -export const PlayButton = memo( - ({ - classNames, - fill, - icon = 'mediaPlay', - isSecondary, - loading, - onClick, - onLongPress, - }: PlayButtonProps) => { +const PlayButtonBase = forwardRef( + ( + { + classNames, + fill, + icon = 'mediaPlay', + isSecondary, + loading, + onClick, + onLongPress, + }: PlayButtonProps, + ref, + ) => { const clickHandlers = usePlayButtonClick({ loading, onClick, @@ -107,6 +110,7 @@ export const PlayButton = memo( [styles.fill]: fill, [styles.secondary]: isSecondary, })} + ref={ref} {...clickHandlers.handlers} {...clickHandlers.props} > @@ -116,4 +120,6 @@ export const PlayButton = memo( }, ); +export const PlayButton = memo(PlayButtonBase); + PlayButton.displayName = 'PlayButton';