diff --git a/packages/web/components/New/LayoutMobile.tsx b/packages/web/components/New/LayoutMobile.tsx index 0a37eea..e98272c 100644 --- a/packages/web/components/New/LayoutMobile.tsx +++ b/packages/web/components/New/LayoutMobile.tsx @@ -6,7 +6,7 @@ import { useSnapshot } from 'valtio' import Router from '@/web/components/New/Router' import MenuBar from './MenuBar' import Topbar from './Topbar/TopbarMobile' -import { isIOS, isPWA, isSafari } from '@/web/utils/common' +import { isIOS, isIosPwa, isPWA, isSafari } from '@/web/utils/common' import Login from './Login' import { useLocation } from 'react-router-dom' import PlayingNext from './PlayingNextMobile' @@ -17,8 +17,8 @@ const LayoutMobile = () => { const location = useLocation() return ( -
-
+
+
{location.pathname === '/' && }
@@ -27,9 +27,7 @@ const LayoutMobile = () => { 'fixed bottom-0 left-0 right-0 z-20 pt-3 dark:bg-black', css` padding-bottom: calc( - ${isIOS && isSafari && isPWA - ? '24px' - : 'env(safe-area-inset-bottom)'} + 0.75rem + ${isIosPwa ? '24px' : 'env(safe-area-inset-bottom)'} + 0.75rem ); ` )} @@ -40,7 +38,7 @@ const LayoutMobile = () => { 'absolute left-7 right-7 z-20', css` top: calc( - -100% - 6px + ${isIOS && isSafari && isPWA ? '24px' : 'env(safe-area-inset-bottom)'} + -100% - 6px + ${isIosPwa ? '24px' : 'env(safe-area-inset-bottom)'} ); ` )} @@ -56,7 +54,7 @@ const LayoutMobile = () => { {/* Notch background */} - {isIOS && isSafari && isPWA && ( + {isIosPwa && (
{ const { track, progress } = useSnapshot(player) return ( -
+
{ onlyCallOnChangeAfterDragEnded={true} /> -
+
{formatDuration(progress * 1000, 'en', 'hh:mm:ss')} {formatDuration(track?.dt || 0, 'en', 'hh:mm:ss')}
@@ -83,7 +83,7 @@ const Cover = () => { ) } -const HeartButton = () => { +const LikeButton = () => { const { track } = useSnapshot(player) const { data: likedIDs } = useUserLikedTracksIDs() @@ -117,9 +117,9 @@ const NowPlaying = () => { {/* Info & Controls */} -
+
{/* Track Info */} -
+
{track?.name}
{ /> {/* Dividing line */} -
+
{/* Progress */} {/* Controls */} -
+
@@ -149,7 +149,7 @@ const NowPlaying = () => { disabled={!track} className='rounded-full bg-black/10 p-2.5 dark:bg-white/10' > - +
- +
diff --git a/packages/web/components/New/PlayerMobile.tsx b/packages/web/components/New/PlayerMobile.tsx index a870d22..c52573a 100644 --- a/packages/web/components/New/PlayerMobile.tsx +++ b/packages/web/components/New/PlayerMobile.tsx @@ -8,15 +8,38 @@ import { resizeImage } from '@/web/utils/common' import { motion, PanInfo, useMotionValue } from 'framer-motion' import { useLockBodyScroll } from 'react-use' import { useState } from 'react' +import useUserLikedTracksIDs, { + useMutationLikeATrack, +} from '@/web/api/hooks/useUserLikedTracksIDs' +import PlayingNextMobile from './PlayingNextMobile' + +const LikeButton = () => { + const { track } = useSnapshot(player) + const { data: likedIDs } = useUserLikedTracksIDs() + + const isLiked = !!likedIDs?.ids?.find(id => id === track?.id) + + const likeATrack = useMutationLikeATrack() + + return ( + + ) +} const PlayerMobile = () => { const { track, state } = useSnapshot(player) const bgColor = useCoverColor(track?.al?.picUrl ?? '') const [locked, setLocked] = useState(false) - useLockBodyScroll(locked) - const x = useMotionValue(0) const onDragEnd = ( event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo @@ -31,8 +54,6 @@ const PlayerMobile = () => { setLocked(false) } - const y = useMotionValue(0) - return (
{ ` )} > - {/* Indictor */} - -
-
- {/* Cover */} +
{/* Track info */} -
+
setLocked(true)} onDragEnd={onDragEnd} - className=' flex h-full flex-grow items-center ' + className='flex items-center flex-grow h-full ' >
-
+
{track?.name}
-
+
{track?.ar?.map(a => a.name).join(', ')}
-
+
{
{/* Like */} - + {/* Play or pause */}
diff --git a/packages/web/components/New/PlayingNext.tsx b/packages/web/components/New/PlayingNext.tsx index 94dc1f8..c7f005d 100644 --- a/packages/web/components/New/PlayingNext.tsx +++ b/packages/web/components/New/PlayingNext.tsx @@ -17,11 +17,11 @@ const Header = () => { return (
-
+
PLAYING NEXT
@@ -64,14 +64,14 @@ const Track = ({ {/* Cover */} Cover {/* Track info */} -
+
{track?.name}
-
+
{track?.ar.map(a => a.name).join(', ')}
@@ -91,7 +91,7 @@ const Track = ({ {playingTrackIndex === index ? ( ) : ( -
+
{String(index + 1).padStart(2, '0')}
)} @@ -163,7 +163,7 @@ const TrackList = ({ className }: { className?: string }) => { {/* 底部渐变遮罩 */}
diff --git a/packages/web/components/New/PlayingNextMobile.tsx b/packages/web/components/New/PlayingNextMobile.tsx index 29ccd22..673a22d 100644 --- a/packages/web/components/New/PlayingNextMobile.tsx +++ b/packages/web/components/New/PlayingNextMobile.tsx @@ -1,15 +1,82 @@ +import { css, cx } from '@emotion/css' +import { + motion, + useMotionValue, + useDragControls, + AnimatePresence, +} from 'framer-motion' +import { useEffect, useState } from 'react' import { useLockBodyScroll } from 'react-use' +import { isIosPwa } from '@/web/utils/common' import PlayingNext from './PlayingNext' +import { ease } from '@/web/utils/const' const PlayingNextMobile = () => { - useLockBodyScroll(true) + const [display, setDisplay] = useState(false) + const [isDragging, setIsDragging] = useState(false) + useLockBodyScroll(isDragging || display) + + const dragControls = useDragControls() + const y = useMotionValue('82%') return ( -
-
- -
-
+ + console.log(info.point.y)} + > + {/* Indictor */} + { + setIsDragging(true) + dragControls.start(e) + }} + onDragEnd={() => setIsDragging(false)} + dragConstraints={{ top: 0, bottom: 0 }} + className={cx( + 'mx-7 flex justify-center', + css` + --height: 30px; + bottom: calc( + 70px + 64px + + ${isIosPwa ? '24px' : 'env(safe-area-inset-bottom)'} + ); // 拖动条到导航栏的距离 + 导航栏高度 + safe-area-inset-bottom + height: var(--height); + ` + )} + layout + > + + + + {/* List */} +
+ +
+
+
) } diff --git a/packages/web/pages/New/Artist/Header/Header.tsx b/packages/web/pages/New/Artist/Header/Header.tsx index f8f1238..870846a 100644 --- a/packages/web/pages/New/Artist/Header/Header.tsx +++ b/packages/web/pages/New/Artist/Header/Header.tsx @@ -23,7 +23,7 @@ const Header = ({ artist }: { artist?: Artist }) => { > { { ` )} /> -
-
+
+
{album.name}
-
+
{album.type} {album.size > 1 ? `· ${album.size} Tracks` : ''}
@@ -69,8 +69,8 @@ const Video = () => { ` )} /> -
-
+
+
Swedish House Mafia & The Weeknd Live at C...
@@ -84,7 +84,7 @@ const Video = () => { const LatestRelease = () => { return (
-
+
Latest Releases
diff --git a/packages/web/utils/common.ts b/packages/web/utils/common.ts index c0daab0..374aa7a 100644 --- a/packages/web/utils/common.ts +++ b/packages/web/utils/common.ts @@ -166,3 +166,4 @@ export const isSafari = /^((?!chrome|android).)*safari/i.test( export const isPWA = (navigator as any).standalone || window.matchMedia('(display-mode: standalone)').matches +export const isIosPwa = isIOS && isPWA && isSafari