mirror of
https://github.com/GiriNeko/YesPlayMusic.git
synced 2025-12-17 05:38:04 +00:00
feat: updates (#1530)
* feat: 支持repeat mode切换 * feat: 歌单页面的播放按钮可以暂停 * fix: 专辑页面播放按钮 考虑私人FM的情况 解决按钮闪烁问题 * fix: SvgName报错 * update
This commit is contained in:
parent
13281d3f08
commit
24af937e70
5 changed files with 96 additions and 30 deletions
|
|
@ -10,6 +10,7 @@ import { resizeImage } from '@/renderer/utils/common'
|
||||||
import {
|
import {
|
||||||
State as PlayerState,
|
State as PlayerState,
|
||||||
Mode as PlayerMode,
|
Mode as PlayerMode,
|
||||||
|
RepeatMode as PlayerRepeatMode,
|
||||||
} from '@/renderer/utils/player'
|
} from '@/renderer/utils/player'
|
||||||
|
|
||||||
const PlayingTrack = () => {
|
const PlayingTrack = () => {
|
||||||
|
|
@ -130,25 +131,45 @@ const MediaControls = () => {
|
||||||
|
|
||||||
const Others = () => {
|
const Others = () => {
|
||||||
const playerSnapshot = useSnapshot(player)
|
const playerSnapshot = useSnapshot(player)
|
||||||
const mode = useMemo(() => playerSnapshot.mode, [playerSnapshot.mode])
|
|
||||||
|
const switchRepeatMode = () => {
|
||||||
|
if (playerSnapshot.repeatMode === PlayerRepeatMode.OFF) {
|
||||||
|
player.repeatMode = PlayerRepeatMode.ON
|
||||||
|
} else if (playerSnapshot.repeatMode === PlayerRepeatMode.ON) {
|
||||||
|
player.repeatMode = PlayerRepeatMode.ONE
|
||||||
|
} else {
|
||||||
|
player.repeatMode = PlayerRepeatMode.OFF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex items-center justify-end gap-2 pr-2 text-black dark:text-white'>
|
<div className='flex items-center justify-end gap-2 pr-2 text-black dark:text-white'>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => toast('Work in progress')}
|
onClick={() => toast('Work in progress')}
|
||||||
disabled={mode === PlayerMode.FM}
|
disabled={playerSnapshot.mode === PlayerMode.FM}
|
||||||
>
|
>
|
||||||
<SvgIcon className='h-6 w-6' name='playlist' />
|
<SvgIcon className='h-6 w-6' name='playlist' />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => toast('施工中...')}
|
onClick={switchRepeatMode}
|
||||||
disabled={mode === PlayerMode.FM}
|
disabled={playerSnapshot.mode === PlayerMode.FM}
|
||||||
>
|
>
|
||||||
<SvgIcon className='h-6 w-6' name='repeat' />
|
<SvgIcon
|
||||||
|
className={classNames(
|
||||||
|
'h-6 w-6',
|
||||||
|
playerSnapshot.repeatMode !== PlayerRepeatMode.OFF &&
|
||||||
|
'text-brand-500'
|
||||||
|
)}
|
||||||
|
name={
|
||||||
|
playerSnapshot.repeatMode === PlayerRepeatMode.ONE
|
||||||
|
? 'repeat-1'
|
||||||
|
: 'repeat'
|
||||||
|
}
|
||||||
|
/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => toast('施工中...')}
|
onClick={() => toast('施工中...')}
|
||||||
disabled={mode === PlayerMode.FM}
|
disabled={playerSnapshot.mode === PlayerMode.FM}
|
||||||
>
|
>
|
||||||
<SvgIcon className='h-6 w-6' name='shuffle' />
|
<SvgIcon className='h-6 w-6' name='shuffle' />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
type SvgName =
|
export type SvgName =
|
||||||
| 'back'
|
| 'back'
|
||||||
| 'dislike'
|
| 'dislike'
|
||||||
| 'dj'
|
| 'dj'
|
||||||
|
|
@ -35,6 +35,7 @@ type SvgName =
|
||||||
| 'volume-mute'
|
| 'volume-mute'
|
||||||
| 'volume'
|
| 'volume'
|
||||||
| 'windows-close'
|
| 'windows-close'
|
||||||
|
| 'windows-minimize'
|
||||||
| 'windows-maximize'
|
| 'windows-maximize'
|
||||||
| 'windows-un-maximize'
|
| 'windows-un-maximize'
|
||||||
| 'x'
|
| 'x'
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,11 @@ import TracksAlbum from '@/renderer/components/TracksAlbum'
|
||||||
import useAlbum from '@/renderer/hooks/useAlbum'
|
import useAlbum from '@/renderer/hooks/useAlbum'
|
||||||
import useArtistAlbums from '@/renderer/hooks/useArtistAlbums'
|
import useArtistAlbums from '@/renderer/hooks/useArtistAlbums'
|
||||||
import { player } from '@/renderer/store'
|
import { player } from '@/renderer/store'
|
||||||
import { State as PlayerState } from '@/renderer/utils/player'
|
import {
|
||||||
|
Mode as PlayerMode,
|
||||||
|
State as PlayerState,
|
||||||
|
TrackListSourceType,
|
||||||
|
} from '@/renderer/utils/player'
|
||||||
import {
|
import {
|
||||||
formatDate,
|
formatDate,
|
||||||
formatDuration,
|
formatDuration,
|
||||||
|
|
@ -27,40 +31,37 @@ const PlayButton = ({
|
||||||
isLoading,
|
isLoading,
|
||||||
}: {
|
}: {
|
||||||
album: Album | undefined
|
album: Album | undefined
|
||||||
isLoading: boolean
|
|
||||||
handlePlay: () => void
|
handlePlay: () => void
|
||||||
|
isLoading: boolean
|
||||||
}) => {
|
}) => {
|
||||||
const playerSnapshot = useSnapshot(player)
|
const playerSnapshot = useSnapshot(player)
|
||||||
const isPlaying = useMemo(
|
|
||||||
() => playerSnapshot.state === PlayerState.PLAYING,
|
|
||||||
[playerSnapshot.state]
|
|
||||||
)
|
|
||||||
const isThisAlbumPlaying = useMemo(
|
const isThisAlbumPlaying = useMemo(
|
||||||
() =>
|
() =>
|
||||||
playerSnapshot.trackListSource?.type === 'album' &&
|
playerSnapshot.mode === PlayerMode.PLAYLIST &&
|
||||||
|
playerSnapshot.trackListSource?.type === TrackListSourceType.ALBUM &&
|
||||||
playerSnapshot.trackListSource?.id === album?.id,
|
playerSnapshot.trackListSource?.id === album?.id,
|
||||||
[playerSnapshot.trackListSource, album?.id]
|
[playerSnapshot.trackListSource, album?.id]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const isPlaying =
|
||||||
|
isThisAlbumPlaying &&
|
||||||
|
[PlayerState.PLAYING, PlayerState.LOADING].includes(playerSnapshot.state)
|
||||||
|
|
||||||
const wrappedHandlePlay = () => {
|
const wrappedHandlePlay = () => {
|
||||||
if (isPlaying && isThisAlbumPlaying) {
|
if (isThisAlbumPlaying) {
|
||||||
player.pause()
|
player.playOrPause()
|
||||||
return
|
} else {
|
||||||
|
handlePlay()
|
||||||
}
|
}
|
||||||
if (!isPlaying && isThisAlbumPlaying) {
|
|
||||||
player.play()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
handlePlay()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button onClick={wrappedHandlePlay} isSkelton={isLoading}>
|
<Button onClick={wrappedHandlePlay} isSkelton={isLoading}>
|
||||||
<SvgIcon
|
<SvgIcon
|
||||||
name={isPlaying && isThisAlbumPlaying ? 'pause' : 'play'}
|
name={isPlaying ? 'pause' : 'play'}
|
||||||
className='mr-1 -ml-1 h-6 w-6'
|
className='mr-1 -ml-1 h-6 w-6'
|
||||||
/>
|
/>
|
||||||
{isPlaying && isThisAlbumPlaying ? '暂停' : '播放'}
|
{isPlaying ? '暂停' : '播放'}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import CoverRow, { Subtitle } from '@/renderer/components/CoverRow'
|
import CoverRow, { Subtitle } from '@/renderer/components/CoverRow'
|
||||||
import SvgIcon from '@/renderer/components/SvgIcon'
|
import SvgIcon, { SvgName } from '@/renderer/components/SvgIcon'
|
||||||
import useUserAlbums from '@/renderer/hooks/useUserAlbums'
|
import useUserAlbums from '@/renderer/hooks/useUserAlbums'
|
||||||
import useLyric from '@/renderer/hooks/useLyric'
|
import useLyric from '@/renderer/hooks/useLyric'
|
||||||
import usePlaylist from '@/renderer/hooks/usePlaylist'
|
import usePlaylist from '@/renderer/hooks/usePlaylist'
|
||||||
|
|
@ -105,7 +105,7 @@ const OtherCard = ({
|
||||||
className,
|
className,
|
||||||
}: {
|
}: {
|
||||||
name: string
|
name: string
|
||||||
icon: string
|
icon: SvgName
|
||||||
className?: string
|
className?: string
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,55 @@ import useUserPlaylists, {
|
||||||
useMutationLikeAPlaylist,
|
useMutationLikeAPlaylist,
|
||||||
} from '@/renderer/hooks/useUserPlaylists'
|
} from '@/renderer/hooks/useUserPlaylists'
|
||||||
import useUser from '@/renderer/hooks/useUser'
|
import useUser from '@/renderer/hooks/useUser'
|
||||||
|
import {
|
||||||
|
Mode as PlayerMode,
|
||||||
|
TrackListSourceType,
|
||||||
|
State as PlayerState,
|
||||||
|
} from '@/renderer/utils/player'
|
||||||
|
|
||||||
const enableRenderLog = true
|
const enableRenderLog = true
|
||||||
|
|
||||||
|
const PlayButton = ({
|
||||||
|
playlist,
|
||||||
|
handlePlay,
|
||||||
|
isLoading,
|
||||||
|
}: {
|
||||||
|
playlist: Playlist | undefined
|
||||||
|
handlePlay: () => void
|
||||||
|
isLoading: boolean
|
||||||
|
}) => {
|
||||||
|
const playerSnapshot = useSnapshot(player)
|
||||||
|
const isThisPlaylistPlaying = useMemo(
|
||||||
|
() =>
|
||||||
|
playerSnapshot.mode === PlayerMode.PLAYLIST &&
|
||||||
|
playerSnapshot.trackListSource?.type === TrackListSourceType.PLAYLIST &&
|
||||||
|
playerSnapshot.trackListSource?.id === playlist?.id,
|
||||||
|
[playerSnapshot.trackListSource, playlist?.id]
|
||||||
|
)
|
||||||
|
|
||||||
|
const wrappedHandlePlay = () => {
|
||||||
|
if (isThisPlaylistPlaying) {
|
||||||
|
player.playOrPause()
|
||||||
|
} else {
|
||||||
|
handlePlay()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const isPlaying =
|
||||||
|
isThisPlaylistPlaying &&
|
||||||
|
[PlayerState.PLAYING, PlayerState.LOADING].includes(playerSnapshot.state)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button onClick={wrappedHandlePlay} isSkelton={isLoading}>
|
||||||
|
<SvgIcon
|
||||||
|
name={isPlaying ? 'pause' : 'play'}
|
||||||
|
className='-ml-1 mr-1 h-6 w-6'
|
||||||
|
/>
|
||||||
|
{isPlaying ? '暂停' : '播放'}
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const Header = memo(
|
const Header = memo(
|
||||||
({
|
({
|
||||||
playlist,
|
playlist,
|
||||||
|
|
@ -127,10 +173,7 @@ const Header = memo(
|
||||||
|
|
||||||
{/* <!-- Buttons --> */}
|
{/* <!-- Buttons --> */}
|
||||||
<div className='mt-5 flex gap-4'>
|
<div className='mt-5 flex gap-4'>
|
||||||
<Button onClick={() => handlePlay()} isSkelton={isLoading}>
|
<PlayButton {...{ playlist, handlePlay, isLoading }} />
|
||||||
<SvgIcon name='play' className='-ml-1 mr-1 h-6 w-6' />
|
|
||||||
播放
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
{!isThisPlaylistCreatedByCurrentUser && (
|
{!isThisPlaylistCreatedByCurrentUser && (
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue