From cbab1a35bb7125f74fcebec3b8622719c794d6bc Mon Sep 17 00:00:00 2001 From: SimonShiki Date: Tue, 13 Aug 2024 10:15:07 +0800 Subject: [PATCH] :bug: fix: now-playing quit animation Signed-off-by: SimonShiki --- src-tauri/tauri.conf.json | 2 +- src/components/now-playing.tsx | 89 ++++++----------------------- src/components/playlist-tooltip.tsx | 45 +++++++++++++++ src/jotais/settings.ts | 5 ++ src/pages/local.tsx | 5 +- src/pages/song.tsx | 5 +- src/pages/songlist.tsx | 3 +- 7 files changed, 75 insertions(+), 79 deletions(-) create mode 100644 src/components/playlist-tooltip.tsx diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 7c06cd9..23ad97e 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -14,7 +14,7 @@ "title": "Cicadas", "width": 800, "height": 600, - "minWidth": 600, + "minWidth": 770, "minHeight": 540, "resizable": true, "fullscreen": false, diff --git a/src/components/now-playing.tsx b/src/components/now-playing.tsx index e20b60f..ff09811 100644 --- a/src/components/now-playing.tsx +++ b/src/components/now-playing.tsx @@ -5,14 +5,13 @@ import defaultCover from '../assets/default-cover.png'; import Button from './base/button'; import * as player from '../utils/player'; import Progress from './base/progress'; -import { useState, useCallback } from 'react'; +import { useState, useCallback, useEffect } from 'react'; import Slider from './base/slider'; import Tooltip from './base/tooltip'; -import { Virtuoso } from 'react-virtuoso'; import Lyrics from './lyrics'; import { focusAtom } from 'jotai-optics'; import { settingsJotai } from '../jotais/settings'; -import { FormattedMessage } from 'react-intl'; +import PlaylistTooltip from './playlist-tooltip'; const playModeIconMap: Record = { list: 'i-fluent:arrow-repeat-all-off-20-regular', @@ -34,29 +33,29 @@ function formatMilliseconds (ms: number): string { const streamingJotai = focusAtom(settingsJotai, (optic) => optic.prop('streaming')); export default function NowPlaying () { - const [fullscreen, setFullscreen] = useAtom(nowPlayingPageJotai); + const [globalFullscreen, setGlobalFullscreen] = useAtom(nowPlayingPageJotai); + const [localFullscreen, setLocalFullscreen] = useState(globalFullscreen); const [playing, setPlaying] = useAtom(playingJotai); const playMode = useAtomValue(playModeJotai); const [volume, setVolume] = useAtom(volumeJotai); - const playlist = useAtomValue(playlistJotai); const barOpen = useAtomValue(nowPlayingBarJotai); const song = useAtomValue(currentSongJotai); const progress = useAtomValue(progressJotai); const buffering = useAtomValue(bufferingJotai); const streaming = useAtomValue(streamingJotai); - + const [isAnimating, setIsAnimating] = useState(false); const handlePlayPause = useCallback(() => { setPlaying(playing => !playing); - }, [playing, setPlaying]); + }, [setPlaying]); - const toggleFullscreen = useCallback(() => { + useEffect(() => { setIsAnimating(true); - setFullscreen(!fullscreen); + setLocalFullscreen(globalFullscreen); // Reset animation state after animation completes setTimeout(() => setIsAnimating(false), 300); // 300ms matches the animation duration - }, [fullscreen, setFullscreen]); + }, [globalFullscreen]); const handleChangePlayProgress = useCallback(async (value: number) => { const actualElapsedSecs = value * song!.duration! / 100000; @@ -72,7 +71,9 @@ export default function NowPlaying () {
- {song.name} + {song.name} { + setGlobalFullscreen(true); + }} />
{song.name} {song.album} @@ -103,44 +104,14 @@ export default function NowPlaying () { > - - - - - { - const thatSong = playlist[index]; - return ( -
{ - player.setCurrentSong(thatSong); - }} className='flex gap-2 py-2 border-b-(1 solid outline-pri) hover:bg-bg-pri cursor-pointer transition-colors items-center' onDoubleClick={() => player.setCurrentSong(song)}> - {thatSong.name} -
- {thatSong.name} - {thatSong.album} -
-
- ); - }} - /> -
- )} - className='flex w-5 h-5' - placement='top-right' - trigger='click' - > - - +
- {(fullscreen || isAnimating) && ( + {(localFullscreen || isAnimating) && (
@@ -186,35 +157,7 @@ export default function NowPlaying () { > - - - - - { - const thatSong = playlist[index]; - return ( -
player.setCurrentSong(song)}> - {thatSong.name} -
- {thatSong.name} - {thatSong.album} -
-
- ); - }} - /> -
- )} - className='flex w-5 h-5' - trigger='click' - placement='top-right' - > - - +
diff --git a/src/components/playlist-tooltip.tsx b/src/components/playlist-tooltip.tsx new file mode 100644 index 0000000..5b9eee7 --- /dev/null +++ b/src/components/playlist-tooltip.tsx @@ -0,0 +1,45 @@ +import Tooltip from './base/tooltip'; +import { Virtuoso } from 'react-virtuoso'; +import { FormattedMessage } from 'react-intl'; +import defaultCover from '../assets/default-cover.png'; +import * as player from '../utils/player'; +import { useAtomValue } from 'jotai'; +import { currentSongJotai, playlistJotai } from '../jotais/play'; + +export default function PlaylistTooltip () { + const playlist = useAtomValue(playlistJotai); + const currentSong = useAtomValue(currentSongJotai); + return ( + + + + + { + const thatSong = playlist[index]; + return ( +
{ + player.setCurrentSong(thatSong); + }} className='flex gap-2 py-2 border-b-(1 solid outline-pri) hover:bg-bg-pri cursor-pointer transition-colors items-center'> + {thatSong.name} +
+ {thatSong.name} + {thatSong.album} +
+
+ ); + }} + /> + + )} + className='flex w-5 h-5' + placement='top-right' + trigger='click' + > + +
+ ); +} diff --git a/src/jotais/settings.ts b/src/jotais/settings.ts index 66e6a29..11ddeea 100644 --- a/src/jotais/settings.ts +++ b/src/jotais/settings.ts @@ -1,5 +1,6 @@ import { focusAtom } from 'jotai-optics'; import { atomWithStorage } from 'jotai/utils'; +import { SortOptions } from '../utils/sort'; export interface StorageConfig { identifer: Idenfiter; @@ -21,3 +22,7 @@ export const settingsJotai = atomWithStorage('settings', { export const localeJotai = focusAtom(settingsJotai, (optic) => optic.prop('locale')); export const storagesConfigJotai = focusAtom(settingsJotai, (optic) => optic.prop('storages')); + +export const sortOptionJotai = atomWithStorage('sortOption', 'a-z', undefined, { + getOnInit: true +}); diff --git a/src/pages/local.tsx b/src/pages/local.tsx index b48eab1..b62f67b 100644 --- a/src/pages/local.tsx +++ b/src/pages/local.tsx @@ -1,5 +1,5 @@ import { storagesJotai } from '../jotais/storage'; -import { useAtomValue } from 'jotai'; +import { useAtom, useAtomValue } from 'jotai'; import SongItem from '../components/song-item'; import Button from '../components/base/button'; import Select from '../components/base/select'; @@ -13,6 +13,7 @@ import { useCallback, useEffect, useState } from 'react'; import { filterSongList, SortOptions, sortSongList } from '../utils/sort'; import { nowPlayingBarJotai } from '../jotais/play'; import { FormattedMessage, useIntl } from 'react-intl'; +import { sortOptionJotai } from '../jotais/settings'; const localStorageJotai = focusAtom(storagesJotai, (optic) => optic.prop('local')); const songlistJotai = focusAtom(localStorageJotai, (optic) => optic.prop('songList')); @@ -24,7 +25,7 @@ export default function Local () { const barOpen = useAtomValue(nowPlayingBarJotai); const scanned = useAtomValue(scannedJotai); const [keyword, setKeyword] = useState(''); - const [sortBy, setSortBy] = useState('a-z'); + const [sortBy, setSortBy] = useAtom(sortOptionJotai); const intl = useIntl(); const sortOptions = [ { value: 'default', label: intl.formatMessage({ defaultMessage: 'Default'}) } as const, diff --git a/src/pages/song.tsx b/src/pages/song.tsx index eb98011..2841b3f 100644 --- a/src/pages/song.tsx +++ b/src/pages/song.tsx @@ -10,10 +10,11 @@ import { nowPlayingBarJotai } from '../jotais/play'; import * as player from '../utils/player'; import { scannedJotai } from '../jotais/storage'; import type { Song } from '../jotais/storage'; -import { SortOptions, filterSongList, sortSongList } from '../utils/sort'; +import { filterSongList, sortSongList } from '../utils/sort'; import { libraryJotai, songlistsJotai } from '../jotais/library'; import { FormattedMessage, useIntl } from 'react-intl'; import { Menu, MenuItem, PredefinedMenuItem, Submenu } from '@tauri-apps/api/menu'; +import { sortOptionJotai } from '../jotais/settings'; export default function SongPage () { const _list = useAtomValue(libraryJotai); @@ -25,7 +26,7 @@ export default function SongPage () { const [multiselect, setMultiselect] = useState(false); const [selected, setSelected] = useState<(number | string)[]>([]); const [keyword, setKeyword] = useState(''); - const [sortBy, setSortBy] = useState('a-z'); + const [sortBy, setSortBy] = useAtom(sortOptionJotai); const sortOptions = [ { value: 'default', label: intl.formatMessage({ defaultMessage: 'Default' }) } as const, { value: 'a-z', label: intl.formatMessage({ defaultMessage: 'A - Z' }) } as const, diff --git a/src/pages/songlist.tsx b/src/pages/songlist.tsx index 7db7f68..4d3b323 100644 --- a/src/pages/songlist.tsx +++ b/src/pages/songlist.tsx @@ -13,6 +13,7 @@ import Tooltip from '../components/base/tooltip'; import Input from '../components/base/input'; import { SortOptions, sortSongList } from '../utils/sort'; import Select from '../components/base/select'; +import { sortOptionJotai } from '../jotais/settings'; export default function SonglistPage () { const scanned = useAtomValue(scannedJotai); @@ -21,7 +22,7 @@ export default function SonglistPage () { const [songlistName, setSonglistName] = useState(''); const [_currentSonglist, _setCurrentSonglist] = useState(null); const [currentSonglist, setCurrentSonglist] = useState(null); - const [sortBy, setSortBy] = useState('a-z'); + const [sortBy, setSortBy] = useAtom(sortOptionJotai); const sortOptions = [ { value: 'default', label: intl.formatMessage({ defaultMessage: 'Default' }) } as const,