Migrate to Mantine v8 and Design Changes (#961)

* mantine v8 migration

* various design changes and improvements
This commit is contained in:
Jeff 2025-06-24 00:04:36 -07:00 committed by GitHub
parent bea55d48a8
commit c1330d92b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
473 changed files with 12469 additions and 11607 deletions

View file

@ -4,22 +4,9 @@ import formatDuration from 'format-duration';
import isElectron from 'is-electron';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { BsDice3 } from 'react-icons/bs';
import { IoIosPause } from 'react-icons/io';
import {
RiPlayFill,
RiRepeat2Line,
RiRepeatOneLine,
RiRewindFill,
RiShuffleFill,
RiSkipBackFill,
RiSkipForwardFill,
RiSpeedFill,
RiStopFill,
} from 'react-icons/ri';
import styled from 'styled-components';
import { Text } from '/@/renderer/components';
import styles from './center-controls.module.css';
import { PlayerButton } from '/@/renderer/features/player/components/player-button';
import { PlayerbarSlider } from '/@/renderer/features/player/components/playerbar-slider';
import { openShuffleAllModal } from '/@/renderer/features/player/components/shuffle-all-modal';
@ -39,60 +26,14 @@ import {
usePlaybackType,
useSettingsStore,
} from '/@/renderer/store/settings.store';
import { Icon } from '/@/shared/components/icon/icon';
import { Text } from '/@/shared/components/text/text';
import { PlaybackType, PlayerRepeat, PlayerShuffle, PlayerStatus } from '/@/shared/types/types';
interface CenterControlsProps {
playersRef: any;
}
const ButtonsContainer = styled.div`
display: flex;
gap: 0.5rem;
align-items: center;
`;
const SliderContainer = styled.div`
display: flex;
width: 95%;
height: 20px;
`;
const SliderValueWrapper = styled.div<{ $position: 'left' | 'right' }>`
display: flex;
flex: 1;
align-self: center;
justify-content: center;
max-width: 50px;
@media (width <= 768px) {
display: none;
}
`;
const SliderWrapper = styled.div`
display: flex;
flex: 6;
align-items: center;
height: 100%;
`;
const ControlsContainer = styled.div`
display: flex;
align-items: center;
justify-content: center;
height: 35px;
@media (width <= 768px) {
${ButtonsContainer} {
gap: 0;
}
${SliderValueWrapper} {
display: none;
}
}
`;
export const CenterControls = ({ playersRef }: CenterControlsProps) => {
const { t } = useTranslation();
const queryClient = useQueryClient();
@ -171,10 +112,16 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => {
return (
<>
<ControlsContainer>
<ButtonsContainer>
<div className={styles.controlsContainer}>
<div className={styles.buttonsContainer}>
<PlayerButton
icon={<RiStopFill size={buttonSize} />}
icon={
<Icon
fill="default"
icon="mediaStop"
size={buttonSize}
/>
}
onClick={handleStop}
tooltip={{
label: t('player.stop', { postProcess: 'sentenceCase' }),
@ -182,8 +129,14 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => {
variant="tertiary"
/>
<PlayerButton
$isActive={shuffle !== PlayerShuffle.NONE}
icon={<RiShuffleFill size={buttonSize} />}
icon={
<Icon
fill={shuffle === PlayerShuffle.NONE ? 'default' : 'primary'}
icon="mediaShuffle"
size={buttonSize}
/>
}
isActive={shuffle !== PlayerShuffle.NONE}
onClick={handleToggleShuffle}
tooltip={{
label:
@ -197,7 +150,13 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => {
variant="tertiary"
/>
<PlayerButton
icon={<RiSkipBackFill size={buttonSize} />}
icon={
<Icon
fill="default"
icon="mediaPrevious"
size={buttonSize}
/>
}
onClick={handlePrevTrack}
tooltip={{
label: t('player.previous', { postProcess: 'sentenceCase' }),
@ -206,7 +165,13 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => {
/>
{skip?.enabled && (
<PlayerButton
icon={<RiRewindFill size={buttonSize} />}
icon={
<Icon
fill="default"
icon="mediaStepBackward"
size={buttonSize}
/>
}
onClick={() => handleSkipBackward(skip?.skipBackwardSeconds)}
tooltip={{
label: t('player.skip', {
@ -221,9 +186,15 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => {
disabled={currentSong?.id === undefined}
icon={
status === PlayerStatus.PAUSED ? (
<RiPlayFill size={buttonSize} />
<Icon
icon="mediaPlay"
size={buttonSize}
/>
) : (
<IoIosPause size={buttonSize} />
<Icon
icon="mediaPause"
size={buttonSize}
/>
)
}
onClick={handlePlayPause}
@ -237,7 +208,13 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => {
/>
{skip?.enabled && (
<PlayerButton
icon={<RiSpeedFill size={buttonSize} />}
icon={
<Icon
fill="default"
icon="mediaStepForward"
size={buttonSize}
/>
}
onClick={() => handleSkipForward(skip?.skipForwardSeconds)}
tooltip={{
label: t('player.skip', {
@ -249,7 +226,13 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => {
/>
)}
<PlayerButton
icon={<RiSkipForwardFill size={buttonSize} />}
icon={
<Icon
fill="default"
icon="mediaNext"
size={buttonSize}
/>
}
onClick={handleNextTrack}
tooltip={{
label: t('player.next', { postProcess: 'sentenceCase' }),
@ -257,14 +240,22 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => {
variant="secondary"
/>
<PlayerButton
$isActive={repeat !== PlayerRepeat.NONE}
icon={
repeat === PlayerRepeat.ONE ? (
<RiRepeatOneLine size={buttonSize} />
<Icon
fill="primary"
icon="mediaRepeatOne"
size={buttonSize}
/>
) : (
<RiRepeat2Line size={buttonSize} />
<Icon
fill={repeat === PlayerRepeat.NONE ? 'default' : 'primary'}
icon="mediaRepeat"
size={buttonSize}
/>
)
}
isActive={repeat !== PlayerRepeat.NONE}
onClick={handleToggleRepeat}
tooltip={{
label: `${
@ -288,7 +279,13 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => {
/>
<PlayerButton
icon={<BsDice3 size={buttonSize} />}
icon={
<Icon
fill="default"
icon="mediaRandom"
size={buttonSize}
/>
}
onClick={() =>
openShuffleAllModal({
handlePlayQueueAdd,
@ -300,20 +297,20 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => {
}}
variant="tertiary"
/>
</ButtonsContainer>
</ControlsContainer>
<SliderContainer>
<SliderValueWrapper $position="left">
</div>
</div>
<div className={styles.sliderContainer}>
<div className={styles.sliderValueWrapper}>
<Text
$noSelect
$secondary
fw={600}
isMuted
isNoSelect
size="xs"
weight={600}
>
{formattedTime}
</Text>
</SliderValueWrapper>
<SliderWrapper>
</div>
<div className={styles.sliderWrapper}>
<PlayerbarSlider
label={(value) => formatDuration(value * 1000)}
max={songDuration}
@ -335,18 +332,18 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => {
value={!isSeeking ? currentTime : seekValue}
w="100%"
/>
</SliderWrapper>
<SliderValueWrapper $position="right">
</div>
<div className={styles.sliderValueWrapper}>
<Text
$noSelect
$secondary
fw={600}
isMuted
isNoSelect
size="xs"
weight={600}
>
{duration}
</Text>
</SliderValueWrapper>
</SliderContainer>
</div>
</div>
</>
);
};