From a2f0ec5a2b0dd6935a8b9d113e870e514d9fd1a6 Mon Sep 17 00:00:00 2001 From: gumengyu <1415515984yuri@gmail.com> Date: Wed, 1 Nov 2023 17:52:17 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=AD=8C=E5=8D=95=E5=88=9B=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- electron/main/core/config/page.ts | 2 +- electron/main/core/menu.ts | 4 +- electron/main/core/util/store.ts | 2 +- electron/main/core/windowManager.ts | 4 +- src/components/nowPlaying/NowPlayingList.tsx | 34 ++++-- src/i18n/en-US.json | 1 + src/i18n/zh-CN.json | 1 + src/pages/Library.tsx | 117 ++++++++++++++++++- src/pages/detail/Playlist.tsx | 9 +- src/pages/layout/Header.tsx | 2 +- src/pages/layout/Main.tsx | 1 + src/pages/layout/SearchBar.tsx | 1 + src/pages/modal/Md3Dialog.tsx | 5 +- src/store/user.ts | 33 ++++-- 14 files changed, 179 insertions(+), 37 deletions(-) diff --git a/electron/main/core/config/page.ts b/electron/main/core/config/page.ts index 2e9f6e24..1b420353 100644 --- a/electron/main/core/config/page.ts +++ b/electron/main/core/config/page.ts @@ -21,7 +21,7 @@ let storeSize: { } = { width: 1099, - height: 740, + height: 700, } initWindowSize() function initWindowSize() { diff --git a/electron/main/core/menu.ts b/electron/main/core/menu.ts index 5573e8b0..5053005f 100644 --- a/electron/main/core/menu.ts +++ b/electron/main/core/menu.ts @@ -40,8 +40,8 @@ export function createElectronMenu(window: BrowserWindow) { { role: 'cut', label: '剪切' }, { role: 'copy', label: '复制' }, { role: 'paste', label: '粘贴' }, - // { role: 'delete', label: '删除' }, - // { role: 'selectAll', label: '全选' }, + { role: 'delete', label: '删除' }, + { role: 'selectAll', label: '全选' }, { label: '搜索', accelerator: 'CmdOrCtrl+F', diff --git a/electron/main/core/util/store.ts b/electron/main/core/util/store.ts index 42a7d4c1..38eb03d6 100644 --- a/electron/main/core/util/store.ts +++ b/electron/main/core/util/store.ts @@ -19,7 +19,7 @@ export interface StoreType { const store = new Store({ defaults: { windowSize: { - height: 740, + height: 700, width: 1099, }, windowPosition: null, diff --git a/electron/main/core/windowManager.ts b/electron/main/core/windowManager.ts index 9648fe8d..f6463330 100644 --- a/electron/main/core/windowManager.ts +++ b/electron/main/core/windowManager.ts @@ -13,7 +13,7 @@ import type { StoreType } from './util/store' import store from './util/store' export const WindowDefaultSize = { - height: 740, + height: 700, width: 1099, minWidth: 144, minHeight: 144, @@ -25,7 +25,7 @@ const defaultBrowserOptions: BrowserWindowConstructorOptions = { // show: false, frame: !(is.windows() || is.linux()), width: 1099, - height: 740, + height: 700, // vibrancy: 'ultra-dark', // visualEffectState: 'active', // transparent: true, diff --git a/src/components/nowPlaying/NowPlayingList.tsx b/src/components/nowPlaying/NowPlayingList.tsx index 3216f596..41aa3986 100644 --- a/src/components/nowPlaying/NowPlayingList.tsx +++ b/src/components/nowPlaying/NowPlayingList.tsx @@ -1,5 +1,5 @@ import Modal from '@mui/material/Modal' -import { Box, IconButton, Typography, useTheme } from '@mui/material' +import { Box, IconButton, Tooltip, Typography, useTheme } from '@mui/material' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { css, cx } from '@emotion/css' import type { VirtuosoHandle } from 'react-virtuoso' @@ -10,10 +10,11 @@ import Fade from '@mui/material/Fade' import { alpha } from '@mui/material/styles' import { useNavigate } from 'react-router-dom' import { useTranslation } from 'react-i18next' +import ClearAllIcon from '@mui/icons-material/ClearAll' import { useAppStore } from '@/store/app' import { playQueueStore } from '@/store/playQueue' import type { Track, TrackSource } from '@/types' -import { sizeOfImage } from '@/util/fn' +import { sizeOfImage, sleep } from '@/util/fn' import Wave from '@/components/Wave' import { usePlayer, usePlayerControl } from '@/hooks/usePlayer' import { Track as TrackType } from '@/types' @@ -276,16 +277,18 @@ function NowPlayingTrackList({ onClose }: { onClose: () => void }) { function NowPlayingList() { const { showNowPlayingList, toggleNowPlayingList } = useAppStore() + const { clearQueue } = playQueueStore() const theme = useTheme() + const { t } = useTranslation() const onClose = useCallback(() => { toggleNowPlayingList(false) }, []) - // useEffect(() => { - // if (showNowPlayingList) { - // console.log('open now playing list') - // } - // }, [showNowPlayingList]); + const onClear = useCallback(async () => { + clearQueue() + await sleep(200) + toggleNowPlayingList(false) + }, []) return (
- +
+ + + + + +
+
diff --git a/src/i18n/en-US.json b/src/i18n/en-US.json index 269ab607..e6b65711 100644 --- a/src/i18n/en-US.json +++ b/src/i18n/en-US.json @@ -200,6 +200,7 @@ "pause": "Pause", "reload": "Reload", "delete": "Delete", + "clear_queue": "Clear the queue", "open_search": "Open Search", "sign_in": "Sign In", "sign_out": "Sign Out", diff --git a/src/i18n/zh-CN.json b/src/i18n/zh-CN.json index 64bdf518..11024563 100644 --- a/src/i18n/zh-CN.json +++ b/src/i18n/zh-CN.json @@ -200,6 +200,7 @@ "add_all_to_playlist": "收藏全部", "pause": "暂停", "delete": "删除", + "clear_queue": "清空队列", "open_search": "打开搜索", "sign_in": "登录", "sign_out": "登出", diff --git a/src/pages/Library.tsx b/src/pages/Library.tsx index 166e0644..223ce0fa 100644 --- a/src/pages/Library.tsx +++ b/src/pages/Library.tsx @@ -1,5 +1,13 @@ -import { Box, Button, Card, Typography, useTheme } from '@mui/material' -import { memo, useEffect, useState } from 'react' +import { + Box, + Button, + Card, Checkbox, Dialog, + IconButton, TextField, + Tooltip, + Typography, + useTheme, +} from '@mui/material' +import { memo, useCallback, useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' import { sampleSize } from 'lodash' @@ -9,6 +17,10 @@ import HistoryIcon from '@mui/icons-material/History' import PodcastsIcon from '@mui/icons-material/Podcasts' import ThumbUpAltIcon from '@mui/icons-material/ThumbUpAlt' import { useTranslation } from 'react-i18next' +import { alpha } from '@mui/material/styles' +import AddCircleOutlineOutlinedIcon from '@mui/icons-material/AddCircleOutlineOutlined' +import PlaylistAddIcon from '@mui/icons-material/PlaylistAdd' +import { useSnackbar } from 'notistack' import MYTabs from '@/components/Tabs' import PageTransition from '@/components/PageTransition' import GridRow from '@/components/GridRow' @@ -27,6 +39,7 @@ import { getSongData } from '@/api/song' import { useReplacePlayQueue } from '@/hooks/usePlayQueue' import { getTrackList } from '@/api/music' import Col from '@/components/Col' +import { createPlaylist } from '@/api/playlist' const AlbumCovers = memo(({ tracks }: { tracks: Track[] }) => { const navigate = useNavigate() @@ -46,6 +59,104 @@ const AlbumCovers = memo(({ tracks }: { tracks: Track[] }) => { ) }) +function CreatePlaylist() { + const theme = useTheme() + const { t } = useTranslation() + const [open, setOpen] = useState(false) + const onClose = useCallback(() => { + setOpen(false) + }, []) + return <> + + setOpen(true)} + > + + + + + +} + +function CreateDialog({ open, onClose }: { open: boolean; onClose: () => void }) { + + const theme = useTheme() + const { refreshPlaylist } = useUserStore() + const { t } = useTranslation() + const { enqueueSnackbar } = useSnackbar() + const [playlist, setPlaylist] = useState({ + playlistName: '', + playlistPrivate: false, + }) + useEffect(() => { + if (!open) { + setPlaylist({ + playlistPrivate: false, + playlistName: '', + }) + } + return () => { + setPlaylist({ + playlistPrivate: false, + playlistName: '', + }) + } + }, [open]) + + async function createNewPlaylist() { + try { + await createPlaylist({ + name: playlist.playlistName, + privacy: playlist.playlistPrivate ? 10 : 0, + }) + enqueueSnackbar('创建成功', { variant: 'success' }) + refreshPlaylist() + onClose() + } + catch (e) { + enqueueSnackbar('something_wrong', { variant: 'error' }) + } + } + return + +
+ + 创建新歌单 +
+ +
+ { + setPlaylist(state => ({ + ...state, + playlistName: e.target.value, + })) + }} /> +
+
+ + {'私人歌单'} +
+
+ + +
+
+
+} + function ArtistPanel() { const { data } = useUserArtists() return @@ -58,7 +169,7 @@ function PlaylistPanel() { const { t } = useTranslation() const { createdPlaylist, subscribePlaylist } = useMyPlaylist() return
- + }> { createdPlaylist?.map(playlist => ()) diff --git a/src/pages/detail/Playlist.tsx b/src/pages/detail/Playlist.tsx index d7d9bd90..d4845460 100644 --- a/src/pages/detail/Playlist.tsx +++ b/src/pages/detail/Playlist.tsx @@ -37,6 +37,7 @@ import { sub } from '@/api/music' import { deletePlayList } from '@/api/playlist' import { PlayOutlinedIcon } from '@/components/icons/icons' import useVirtualListScroll from '@/hooks/useVirtualListScroll' +import { useUserStore } from '@/store/user' const PlayListHeader = memo(({ playlist, cover }: { playlist: Playlist | undefined; cover?: string }) => { const theme = useTheme() @@ -46,6 +47,7 @@ const PlayListHeader = memo(({ playlist, cover }: { playlist: Playlist | undefin const tracksDt = playlist?.tracks?.reduce((p, c: any) => p + c.dt, 0) const { openContextMenu } = useContextMenu() + const { refreshPlaylist } = useUserStore() const confirm = useConfirm() const { isCreatedPlaylist, isMyFavList } = useMyPlaylist() const { replaceQueueAndPlay } = useReplacePlayQueue() @@ -79,10 +81,11 @@ const PlayListHeader = memo(({ playlist, cover }: { playlist: Playlist | undefin dialogProps: { maxWidth: 'xs' }, }).then(async () => { const { code, message } = await deletePlayList(playlist.id) - if (code === 200) + if (code === 200) { enqueueSnackbar('已删除', { variant: 'success' }) - else - enqueueSnackbar(message, { variant: 'error' }) + refreshPlaylist() + } + else {enqueueSnackbar(message, { variant: 'error' })} }) } const handleMore = useCallback((e: React.MouseEvent) => { diff --git a/src/pages/layout/Header.tsx b/src/pages/layout/Header.tsx index fd6e18d8..dc870ba7 100644 --- a/src/pages/layout/Header.tsx +++ b/src/pages/layout/Header.tsx @@ -15,7 +15,7 @@ export default function Header() { height: 78, zIndex: 2, gridArea: 'main', - pr: 2, + pr: 1.5, position: 'relative', }} > diff --git a/src/pages/layout/Main.tsx b/src/pages/layout/Main.tsx index 51b9597c..a9b203ba 100644 --- a/src/pages/layout/Main.tsx +++ b/src/pages/layout/Main.tsx @@ -78,6 +78,7 @@ export default function Main({ diff --git a/src/pages/layout/SearchBar.tsx b/src/pages/layout/SearchBar.tsx index c905005d..687d82ba 100644 --- a/src/pages/layout/SearchBar.tsx +++ b/src/pages/layout/SearchBar.tsx @@ -21,6 +21,7 @@ export default function SearchBar() { sx={{ display: 'flex', alignItems: 'center', bgcolor: theme.palette.surfaceVariant.main, borderRadius: 16, width: 240, height: 42 }} > ({ '& .MuiPaper-root': { borderRadius: 24, @@ -12,3 +13,5 @@ export default function Md3Dialog(props: DialogProps) { {props.children} } + +export default memo(Md3Dialog) diff --git a/src/store/user.ts b/src/store/user.ts index 2cbb24a2..a845f6d2 100644 --- a/src/store/user.ts +++ b/src/store/user.ts @@ -15,6 +15,8 @@ interface userState { } interface userAction { refreshAccount: () => void + refreshPlaylist: () => void + refreshLikes: () => void fetchAccount: () => void favSong: (id: number, liked: boolean) => Promise getFavs: () => Playlist @@ -48,20 +50,27 @@ export const useUserStore = create(persist((set, get) => const uid = get().account?.profile?.userId const logged = !!uid if (logged) { - const [, likesRes, playlistRes] = await Promise.all([ - this.refreshAccount(), - getLikeList(), - getUserPlaylist({ - timestamp: new Date().getTime(), - uid, - }), - ]) - set({ - likes: likesRes.ids, - playlists: playlistRes.playlist, - }) + this.refreshAccount() + this.refreshPlaylist() + this.refreshLikes() } }, + async refreshPlaylist() { + const uid = get().account?.profile?.userId + const { playlist } = await getUserPlaylist({ + timestamp: new Date().getTime(), + uid, + }) + set({ + playlists: playlist, + }) + }, + async refreshLikes() { + const { ids } = await getLikeList() + set({ + likes: ids, + }) + }, async favSong(id: number, like: boolean) { let likes = get().likes try {