feat: updates

This commit is contained in:
qier222 2023-01-24 16:29:33 +08:00
parent c6c59b2cd9
commit 7ce516877e
No known key found for this signature in database
63 changed files with 6591 additions and 1107 deletions

View file

@ -28,12 +28,7 @@ const ArtistInline = ({
if (!artists) return <div></div>
return (
<div
className={cx(
!className?.includes('line-clamp') && 'line-clamp-1',
className
)}
>
<div className={cx(!className?.includes('line-clamp') && 'line-clamp-1', className)}>
{artists.map((artist, index) => (
<span key={`${artist.id}-${artist.name}`}>
<span

View file

@ -6,7 +6,7 @@ import { prefetchAlbum } from '@/web/api/hooks/useAlbum'
import { prefetchPlaylist } from '@/web/api/hooks/usePlaylist'
import { memo, useCallback } from 'react'
import dayjs from 'dayjs'
import ArtistInline from './ArtistsInLine'
import ArtistInline from './ArtistsInline'
type ItemTitle = undefined | 'name'
type ItemSubTitle = undefined | 'artist' | 'year'
@ -56,15 +56,9 @@ const Album = ({
onMouseOver={prefetch}
/>
{title && (
<div className='line-clamp-2 mt-2 text-14 font-medium text-neutral-300'>
{title}
</div>
)}
{subtitle && (
<div className='mt-1 text-14 font-medium text-neutral-700'>
{subtitle}
</div>
<div className='line-clamp-2 mt-2 text-14 font-medium text-neutral-300'>{title}</div>
)}
{subtitle && <div className='mt-1 text-14 font-medium text-neutral-700'>{subtitle}</div>}
</div>
)
}
@ -107,21 +101,12 @@ const CoverRow = ({
return (
<div className={className}>
{/* Title */}
{title && (
<h4 className='mb-6 text-14 font-bold uppercase dark:text-neutral-300'>
{title}
</h4>
)}
{title && <h4 className='mb-6 text-14 font-bold uppercase dark:text-neutral-300'>{title}</h4>}
{/* Items */}
<div className='grid grid-cols-3 gap-4 lg:gap-6 xl:grid-cols-4 2xl:grid-cols-5'>
{albums?.map(album => (
<Album
key={album.id}
album={album}
itemTitle={itemTitle}
itemSubtitle={itemSubtitle}
/>
<Album key={album.id} album={album} itemTitle={itemTitle} itemSubtitle={itemSubtitle} />
))}
{playlists?.map(playlist => (
<Playlist key={playlist.id} playlist={playlist} />

View file

@ -2,7 +2,7 @@ import Main from '@/web/components/Main'
import Player from '@/web/components/Player'
import MenuBar from '@/web/components/MenuBar'
import Topbar from '@/web/components/Topbar/TopbarDesktop'
import { cx } from '@emotion/css'
import { css, cx } from '@emotion/css'
import player from '@/web/states/player'
import { useSnapshot } from 'valtio'
import Login from './Login'
@ -22,7 +22,10 @@ const Layout = () => {
id='layout'
className={cx(
'relative grid h-screen select-none overflow-hidden bg-white dark:bg-black',
window.env?.isElectron && !fullscreen && 'rounded-24'
window.env?.isElectron && !fullscreen && 'rounded-24',
css`
min-width: 720px;
`
)}
>
<BlurBackground />
@ -40,9 +43,7 @@ const Layout = () => {
{(window.env?.isWindows ||
window.env?.isLinux ||
window.localStorage.getItem('showWindowsTitleBar') === 'true') && (
<TitleBar />
)}
window.localStorage.getItem('showWindowsTitleBar') === 'true') && <TitleBar />}
<ContextMenus />

View file

@ -23,25 +23,19 @@ const LayoutMobile = () => {
<Router />
</main>
<div
className={cx(
'fixed bottom-0 left-0 right-0 z-20 pt-3 dark:bg-black',
css`
padding-bottom: calc(
className={cx('fixed bottom-0 left-0 right-0 z-20 pt-3 dark:bg-black')}
style={{
paddingBottom: `calc(
${isIosPwa ? '24px' : 'env(safe-area-inset-bottom)'} + 0.75rem
);
`
)}
)`,
}}
>
{showPlayer && (
<div
className={cx(
'absolute left-7 right-7 z-20',
css`
top: calc(
-100% - 6px + ${isIosPwa ? '24px' : 'env(safe-area-inset-bottom)'}
);
`
)}
className={cx('absolute left-7 right-7 z-20')}
style={{
top: `calc(-100% - 6px + ${isIosPwa ? '24px' : 'env(safe-area-inset-bottom)'})`,
}}
>
<Player />
</div>

View file

@ -11,13 +11,7 @@ import persistedUiStates from '@/web/states/persistedUiStates'
import useUser from '@/web/api/hooks/useUser'
import { useTranslation } from 'react-i18next'
const OR = ({
children,
onClick,
}: {
children: React.ReactNode
onClick: () => void
}) => {
const OR = ({ children, onClick }: { children: React.ReactNode; onClick: () => void }) => {
const { t } = useTranslation()
return (
@ -125,10 +119,9 @@ const Login = () => {
<motion.div
animate={animateCard}
className={cx(
'relative rounded-48 bg-white/10 p-9',
'relative h-fit rounded-48 bg-white/10 p-9',
css`
width: 392px;
height: fit-content;
`
)}
>
@ -136,9 +129,7 @@ const Login = () => {
{cardType === 'phone/email' && <LoginWithPhoneOrEmail />}
<OR onClick={handleSwitchCard}>
{cardType === 'qrCode'
? t`auth.use-phone-or-email`
: t`auth.scan-qr-code`}
{cardType === 'qrCode' ? t`auth.use-phone-or-email` : t`auth.scan-qr-code`}
</OR>
</motion.div>
</AnimatePresence>

View file

@ -1,6 +1,4 @@
import useUserLikedTracksIDs, {
useMutationLikeATrack,
} from '@/web/api/hooks/useUserLikedTracksIDs'
import useUserLikedTracksIDs, { useMutationLikeATrack } from '@/web/api/hooks/useUserLikedTracksIDs'
import player from '@/web/states/player'
import { resizeImage } from '@/web/utils/common'
@ -30,8 +28,7 @@ const PlayingTrack = () => {
[playerSnapshot.trackListSource]
)
const hasListSource =
playerSnapshot.mode !== PlayerMode.FM && trackListSource?.type
const hasListSource = playerSnapshot.mode !== PlayerMode.FM && trackListSource?.type
const toTrackListSource = () => {
if (!hasListSource) return
@ -76,16 +73,10 @@ const LikeButton = ({ track }: { track: Track | undefined | null }) => {
return (
<div className='mr-1 '>
<IconButton
onClick={() => track?.id && mutationLikeATrack.mutate(track.id)}
>
<IconButton onClick={() => track?.id && mutationLikeATrack.mutate(track.id)}>
<Icon
className='h-6 w-6 text-white'
name={
track?.id && userLikedSongs?.ids?.includes(track.id)
? 'heart'
: 'heart-outline'
}
name={track?.id && userLikedSongs?.ids?.includes(track.id) ? 'heart' : 'heart-outline'}
/>
</IconButton>
</div>
@ -101,10 +92,7 @@ const Controls = () => {
return (
<div className='flex items-center justify-center gap-2 text-white'>
{mode === PlayerMode.TrackList && (
<IconButton
onClick={() => track && player.prevTrack()}
disabled={!track}
>
<IconButton onClick={() => track && player.prevTrack()} disabled={!track}>
<Icon className='h-6 w-6' name='previous' />
</IconButton>
)}
@ -120,11 +108,7 @@ const Controls = () => {
>
<Icon
className='h-7 w-7'
name={
[PlayerState.Playing, PlayerState.Loading].includes(state)
? 'pause'
: 'play'
}
name={[PlayerState.Playing, PlayerState.Loading].includes(state) ? 'pause' : 'play'}
/>
</IconButton>
<IconButton onClick={() => track && player.nextTrack()} disabled={!track}>

View file

@ -2,7 +2,7 @@ import { css, cx } from '@emotion/css'
import player from '@/web/states/player'
import { useSnapshot } from 'valtio'
import { AnimatePresence, motion } from 'framer-motion'
import ArtistInline from '@/web/components/ArtistsInline'
import ArtistInline from '../ArtistsInline'
import persistedUiStates from '@/web/states/persistedUiStates'
import Controls from './Controls'
import Cover from './Cover'
@ -34,9 +34,7 @@ const NowPlaying = () => {
{/* Info & Controls */}
<div className='m-3 flex flex-col items-center rounded-20 bg-white/60 p-5 font-medium backdrop-blur-3xl dark:bg-black/70'>
{/* Track Info */}
<div className='line-clamp-1 text-lg text-black dark:text-white'>
{track?.name}
</div>
<div className='line-clamp-1 text-lg text-black dark:text-white'>{track?.name}</div>
<ArtistInline
artists={track?.ar || []}
className='text-black/30 dark:text-white/30'

View file

@ -5,6 +5,7 @@ const Tabs = ({
value,
onChange,
className,
style,
}: {
tabs: {
id: string
@ -13,9 +14,10 @@ const Tabs = ({
value: string
onChange: (id: string) => void
className?: string
style?: React.CSSProperties
}) => {
return (
<div className={cx('no-scrollbar flex overflow-y-auto', className)}>
<div className={cx('no-scrollbar flex overflow-y-auto', className)} style={style}>
{tabs.map(tab => (
<div
key={tab.id}

View file

@ -30,11 +30,9 @@ const Background = () => {
transition={{ ease }}
className={cx(
'absolute inset-0 z-0 bg-contain bg-repeat-x',
window.env?.isElectron && 'rounded-t-24',
css`
background-image: url(${topbarBackground});
`
window.env?.isElectron && 'rounded-t-24'
)}
style={{ backgroundImage: `url(${topbarBackground})` }}
></motion.div>
)}
</AnimatePresence>

View file

@ -67,14 +67,14 @@ const Info = ({
)}
{/* Description */}
{!isMobile && (
{!isMobile && description && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.3 }}
className='line-clamp-3 mt-6 whitespace-pre-wrap text-14 font-bold dark:text-white/40'
dangerouslySetInnerHTML={{
__html: description || '',
__html: description,
}}
></motion.div>
)}