mirror of
https://github.com/GiriNeko/YesPlayMusic.git
synced 2025-12-16 21:28:06 +00:00
feat: updates
This commit is contained in:
parent
74dcb36e67
commit
b5f681631e
15 changed files with 320 additions and 99 deletions
|
|
@ -99,7 +99,6 @@ export function getCache(
|
|||
if (!isIDsValid) return
|
||||
|
||||
const idsQuery = ids.map(id => `id = ${id}`).join(' OR ')
|
||||
console.log(idsQuery)
|
||||
const tracksRaw = realm
|
||||
.objects(ModelNames.TRACK)
|
||||
.filtered(`(${idsQuery})`)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import './preload' // must be first
|
||||
import './sentry'
|
||||
import {
|
||||
BrowserWindow,
|
||||
BrowserWindowConstructorOptions,
|
||||
|
|
|
|||
14
packages/main/sentry.ts
Normal file
14
packages/main/sentry.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import * as Sentry from '@sentry/node'
|
||||
import * as Tracing from '@sentry/tracing'
|
||||
import pkg from '../../package.json'
|
||||
|
||||
Sentry.init({
|
||||
dsn: 'https://2aaaa67f1c3d4d6baefafa5d58fcf340@o436528.ingest.sentry.io/6274637',
|
||||
release: `yesplaymusic@${pkg.version}`,
|
||||
environment: import.meta.env.MODE,
|
||||
|
||||
// Set tracesSampleRate to 1.0 to capture 100%
|
||||
// of transactions for performance monitoring.
|
||||
// We recommend adjusting this value in production
|
||||
tracesSampleRate: 1.0,
|
||||
})
|
||||
|
|
@ -1,2 +1,4 @@
|
|||
<svg viewBox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M301.2 34.85c-11.5-5.19-25.02-3.122-34.44 5.253L131.8 160H48c-26.51 0-48 21.49-48 47.1v95.1c0 26.51 21.49 47.1 48 47.1h83.84l134.9 119.9c5.98 5.31 13.58 8.09 21.26 8.09 4.43 0 8.97-.94 13.17-2.85 11.5-5.16 18.82-16.56 18.82-29.16V63.99c-.89-12.59-7.29-24-18.79-29.15ZM513.9 255.1l47.03-47.03c9.375-9.375 9.375-24.56 0-33.94 -9.375-9.38-24.56-9.375-33.94 0L480 222.1 432.1 175c-9.375-9.375-24.56-9.375-33.94 0 -9.38 9.375-9.375 24.56 0 33.94l47.03 47.03L398.16 303c-9.375 9.375-9.375 24.56 0 33.94 9.37 9.37 24.56 9.38 33.94 0L480 289.9l47.03 47.03c9.37 9.37 24.56 9.38 33.94 0 9.375-9.375 9.375-24.56 0-33.94L513.9 255.1Z"/></svg>
|
||||
<svg viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"><path d="M412.6 181.9c-10.28-8.35-25.41-6.875-33.75 3.4 -8.41 10.25-6.91 25.37 3.375 33.78 11.27 9.31 17.77 22.714 17.77 36.91 0 14.19-6.5 27.62-17.81 36.87 -10.28 8.4-11.78 23.53-3.375 33.78 4.71 5.81 11.62 8.81 18.56 8.81 5.34 0 10.75-1.79 15.19-5.41 22.53-18.46 35.435-45.36 35.435-74.06 0-28.7-12.9-55.6-35.4-74.1ZM301.2 34.84c-11.5-5.19-25.01-3.12-34.43 5.25L131.8 159.99H48c-26.51 0-48 21.49-48 47.1v95.1c0 26.51 21.49 47.1 48 47.1h83.84l134.9 119.9c5.96 8 13.56 10.8 21.26 10.8 4.43 0 8.95-.94 13.16-2.84 11.54-5.17 18.84-16.57 18.84-29.17v-384c0-12.59-7.3-24.9-18.8-29.16Z"/></svg>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.4966 5.50774L10.4966 5.50774L6.61626 9H4.5C3.67157 9 3 9.67157 3 10.5V13.5C3 14.3284 3.67157 15 4.5 15H6.61626L10.4966 18.4923C11.4618 19.361 13 18.676 13 17.3773V6.62268C13 5.32402 11.4618 4.63899 10.4966 5.50774Z" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M16.5 9C16.5 9 17.5 10 17.5 12C17.5 14 16.5 15 16.5 15" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 525 B |
|
|
@ -1,4 +1,4 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3 10.5V13.5C3 14.3284 3.67157 15 4.5 15H6.61626L10.4966 18.4923C11.4618 19.361 13 18.676 13 17.3773V6.62268C13 5.32402 11.4618 4.63899 10.4966 5.50774L10.4966 5.50774L6.61626 9L4.5 9C3.67157 9 3 9.67157 3 10.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M16.5 9.5C16.5 9.5 17.5 10.5 17.5 12C17.5 13.5 16.5 14.5 16.5 14.5M19 7C19 7 21 9 21 12C21 15 19 17 19 17" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M10.4966 5.50774L10.4966 5.50774L6.61626 9H4.5C3.67157 9 3 9.67157 3 10.5V13.5C3 14.3284 3.67157 15 4.5 15H6.61626L10.4966 18.4923C11.4618 19.361 13 18.676 13 17.3773V6.62268C13 5.32402 11.4618 4.63899 10.4966 5.50774Z" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M16.5 9C16.5 9 17.5 10 17.5 12C17.5 14 16.5 15 16.5 15M19 6.5C19 6.5 21 9 21 12C21 15 19 17.5 19 17.5" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 569 B After Width: | Height: | Size: 572 B |
|
|
@ -1,3 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 6L18 18M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 354 B After Width: | Height: | Size: 222 B |
|
|
@ -29,17 +29,38 @@ const NavigationButtons = () => {
|
|||
}
|
||||
|
||||
const SearchBox = () => {
|
||||
const [keyword, setKeyword] = useState('')
|
||||
const navigate = useNavigate()
|
||||
const toSearch = (e: React.KeyboardEvent) => {
|
||||
if (!keyword) return
|
||||
if (e.key === 'Enter') {
|
||||
navigate(`/search/${keyword}`)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='app-region-no-drag group flex w-[16rem] cursor-text items-center rounded-full bg-gray-500 bg-opacity-5 px-3 transition duration-300 hover:bg-opacity-10 dark:bg-gray-300 dark:bg-opacity-5'>
|
||||
<div className='app-region-no-drag group flex w-[16rem] cursor-text items-center rounded-full bg-gray-500 bg-opacity-5 pl-2.5 pr-2 transition duration-300 hover:bg-opacity-10 dark:bg-gray-300 dark:bg-opacity-5'>
|
||||
<SvgIcon
|
||||
className='mr-2 h-5 w-5 text-gray-500 transition duration-300 group-hover:text-gray-600 dark:text-gray-400 dark:group-hover:text-gray-200'
|
||||
className='mr-2 h-4 w-4 text-gray-500 transition duration-300 group-hover:text-gray-600 dark:text-gray-400 dark:group-hover:text-gray-200'
|
||||
name='search'
|
||||
/>
|
||||
<input
|
||||
value={keyword}
|
||||
onChange={e => setKeyword(e.target.value)}
|
||||
onKeyDown={toSearch}
|
||||
type='text'
|
||||
className='w-full bg-transparent placeholder:text-gray-500 dark:text-white dark:placeholder:text-gray-400'
|
||||
className='flex-grow bg-transparent placeholder:text-gray-500 dark:text-white dark:placeholder:text-gray-400'
|
||||
placeholder='搜索'
|
||||
/>
|
||||
<div
|
||||
onClick={() => setKeyword('')}
|
||||
className={classNames(
|
||||
'cursor-default rounded-full p-1 transition after:bg-gray-300 hover:bg-white/20 dark:text-white/50',
|
||||
!keyword && 'hidden'
|
||||
)}
|
||||
>
|
||||
<SvgIcon className='h-4 w-4' name='x' />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -55,9 +76,12 @@ const Settings = () => {
|
|||
const Avatar = () => {
|
||||
const navigate = useNavigate()
|
||||
const { data: user } = useUser()
|
||||
|
||||
const avatarUrl = resizeImage(user?.profile?.avatarUrl ?? '', 'sm')
|
||||
|
||||
return (
|
||||
<img
|
||||
src={user?.profile?.avatarUrl}
|
||||
src={avatarUrl}
|
||||
onClick={() => navigate('/login')}
|
||||
className='app-region-no-drag h-9 w-9 rounded-full bg-gray-100 dark:bg-gray-700'
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,24 @@
|
|||
import { StrictMode } from 'react'
|
||||
import { render } from 'react-dom'
|
||||
import { BrowserRouter } from 'react-router-dom'
|
||||
import * as Sentry from '@sentry/react'
|
||||
import { BrowserTracing } from '@sentry/tracing'
|
||||
import 'virtual:svg-icons-register'
|
||||
import '@/styles/global.scss'
|
||||
import App from './App'
|
||||
import pkg from '../../../package.json'
|
||||
|
||||
Sentry.init({
|
||||
dsn: 'https://7cc7879b42ba4bed9f66fb6752558475@o436528.ingest.sentry.io/6274630',
|
||||
integrations: [new BrowserTracing()],
|
||||
release: `yesplaymusic@${pkg.version}`,
|
||||
environment: import.meta.env.MODE,
|
||||
|
||||
// Set tracesSampleRate to 1.0 to capture 100%
|
||||
// of transactions for performance monitoring.
|
||||
// We recommend adjusting this value in production
|
||||
tracesSampleRate: 1.0,
|
||||
})
|
||||
|
||||
render(
|
||||
<StrictMode>
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ const Header = ({
|
|||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
<div className='absolute top-0 h-full w-full bg-gradient-to-b from-white/75 to-white dark:from-black/50 dark:to-[#1d1d1d]'></div>
|
||||
<div className='absolute top-0 h-full w-full bg-gradient-to-b from-white/80 to-white dark:from-black/50 dark:to-[#1d1d1d]'></div>
|
||||
</div>
|
||||
|
||||
<div className='grid grid-cols-[17rem_auto] items-center gap-9'>
|
||||
|
|
@ -145,7 +145,7 @@ const Header = ({
|
|||
<Skeleton className='mt-5 w-64 text-lg'>PLACEHOLDER</Skeleton>
|
||||
) : (
|
||||
<div className='mt-5 text-lg font-medium text-gray-800 dark:text-gray-300'>
|
||||
Album by{' '}
|
||||
Album ·{' '}
|
||||
<NavLink
|
||||
to={`/artist/${album?.artist.id}`}
|
||||
className='cursor-default font-semibold hover:underline'
|
||||
|
|
@ -161,8 +161,14 @@ const Header = ({
|
|||
PLACEHOLDER
|
||||
</Skeleton>
|
||||
) : (
|
||||
<div className='text-sm text-gray-500 dark:text-gray-400'>
|
||||
{dayjs(album?.publishTime || 0).year()} · {album?.size} 首歌,{' '}
|
||||
<div className='flex items-center text-sm text-gray-500 dark:text-gray-400'>
|
||||
{album?.mark === 1056768 && (
|
||||
<SvgIcon
|
||||
name='explicit'
|
||||
className='mt-px mr-1 h-4 w-4 text-gray-400 dark:text-gray-500'
|
||||
/>
|
||||
)}
|
||||
{dayjs(album?.publishTime || 0).year()} · {album?.size} 首歌 ·{' '}
|
||||
{albumDuration}
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -11,22 +11,113 @@ import Skeleton from '@/components/Skeleton'
|
|||
import { Fragment } from 'react'
|
||||
import useTracks from '@/hooks/useTracks'
|
||||
|
||||
const Header = ({ artist }: { artist: Artist | undefined }) => {
|
||||
const coverImage = resizeImage(artist?.img1v1Url || '', 'md')
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div className='absolute top-0 left-0 z-0 h-[24rem] w-full overflow-hidden'>
|
||||
{coverImage && (
|
||||
<Fragment>
|
||||
<img
|
||||
src={coverImage}
|
||||
className='absolute -top-full w-full blur-[100px]'
|
||||
/>
|
||||
<img
|
||||
src={coverImage}
|
||||
className='absolute -top-full w-full blur-[100px]'
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
<div className='absolute top-0 h-full w-full bg-gradient-to-b from-white/80 to-white dark:from-black/50 dark:to-[#1d1d1d]'></div>
|
||||
</div>
|
||||
|
||||
<div className='relative mt-6 overflow-hidden rounded-2xl bg-gray-500/10 dark:bg-gray-800/20'>
|
||||
<div className='flex h-[26rem] justify-center overflow-hidden'>
|
||||
<img src={coverImage} className='aspect-square brightness-[.5]' />
|
||||
<img src={coverImage} className='aspect-square brightness-[.5]' />
|
||||
<img src={coverImage} />
|
||||
<img src={coverImage} className='aspect-square brightness-[.5]' />
|
||||
<img src={coverImage} className='aspect-square brightness-[.5]' />
|
||||
</div>
|
||||
|
||||
<div className='absolute right-0 left-0 top-[18rem] h-32 bg-gradient-to-t from-[#222]/60 to-transparent'></div>
|
||||
|
||||
<div className='absolute top-0 right-0 left-0 flex h-[26rem] items-end justify-between p-8 pb-6'>
|
||||
<div className='text-7xl font-bold text-white'>{artist?.name}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
const LatestRelease = ({
|
||||
album,
|
||||
isLoading,
|
||||
}: {
|
||||
album: Album | undefined
|
||||
isLoading: boolean
|
||||
}) => {
|
||||
return (
|
||||
<div>
|
||||
<div className='mb-6 text-2xl font-semibold text-gray-800 dark:text-white'>
|
||||
最新发行
|
||||
</div>
|
||||
<div className='flex-grow rounded-xl '>
|
||||
{isLoading ? (
|
||||
<Skeleton className='aspect-square w-full rounded-xl'></Skeleton>
|
||||
) : (
|
||||
<Cover imageUrl={album?.picUrl ?? ''} />
|
||||
)}
|
||||
<div className='line-clamp-2 line-clamp-1 mt-2 font-semibold leading-tight decoration-gray-600 decoration-2 hover:underline dark:text-white dark:decoration-gray-200'>
|
||||
{album?.name}
|
||||
</div>
|
||||
<div className='text-[12px] text-gray-500 dark:text-gray-400'>
|
||||
{album?.type} · {dayjs(album?.publishTime || 0).year()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const PopularTracks = ({
|
||||
tracks,
|
||||
isLoadingArtist,
|
||||
}: {
|
||||
tracks: Track[] | undefined
|
||||
isLoadingArtist: boolean
|
||||
}) => {
|
||||
const { data: tracksWithExtraInfo } = useTracks({
|
||||
ids: tracks?.slice(0, 10)?.map(t => t.id) ?? [],
|
||||
})
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='mb-6 text-2xl font-semibold text-gray-800 dark:text-white'>
|
||||
热门歌曲
|
||||
</div>
|
||||
<div className='rounded-xl'>
|
||||
<TracksGrid
|
||||
tracks={tracksWithExtraInfo?.songs ?? tracks?.slice(0, 10) ?? []}
|
||||
isSkeleton={isLoadingArtist}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Artist = () => {
|
||||
const params = useParams()
|
||||
|
||||
const { data: artist, isLoading } = useArtist({
|
||||
const { data: artist, isLoading: isLoadingArtist } = useArtist({
|
||||
id: Number(params.id) || 0,
|
||||
})
|
||||
|
||||
const { data: albumsRaw, isLoading: isLoadingAlbum } = useArtistAlbums({
|
||||
const { data: albumsRaw, isLoading: isLoadingAlbums } = useArtistAlbums({
|
||||
id: Number(params.id) || 0,
|
||||
limit: 1000,
|
||||
})
|
||||
|
||||
const { data: tracks, isLoading: isLoadingTracks } = useTracks({
|
||||
ids: artist?.hotSongs?.slice(0, 10)?.map(t => t.id) ?? [],
|
||||
})
|
||||
|
||||
const albums = useMemo(() => {
|
||||
if (!albumsRaw?.hotAlbums) return []
|
||||
const albums: Album[] = []
|
||||
|
|
@ -66,84 +157,20 @@ const Artist = () => {
|
|||
)
|
||||
}, [albums, albumsRaw?.hotAlbums])
|
||||
|
||||
const latestAlbum = useMemo(() => {
|
||||
if (!albumsRaw || !albumsRaw.hotAlbums) return
|
||||
return albumsRaw.hotAlbums[0]
|
||||
}, [albumsRaw])
|
||||
|
||||
const coverImage = resizeImage(artist?.artist?.img1v1Url || '', 'md')
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='absolute top-0 left-0 z-0 h-[24rem] w-full overflow-hidden'>
|
||||
{coverImage && (
|
||||
<Fragment>
|
||||
<img
|
||||
src={coverImage}
|
||||
className='absolute -top-full w-full blur-[100px]'
|
||||
/>
|
||||
<img
|
||||
src={coverImage}
|
||||
className='absolute -top-full w-full blur-[100px]'
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
<div className='absolute top-0 h-full w-full bg-gradient-to-b from-white/[.84] to-white dark:from-black/[.6] dark:to-[#1d1d1d]'></div>
|
||||
</div>
|
||||
|
||||
{/* Header */}
|
||||
<div className='relative mt-6 overflow-hidden rounded-2xl'>
|
||||
<div className='flex h-[26rem] justify-center overflow-hidden'>
|
||||
<img src={coverImage} className='aspect-square brightness-[.5]' />
|
||||
<img src={coverImage} className='aspect-square brightness-[.5]' />
|
||||
<img src={coverImage} />
|
||||
<img src={coverImage} className='aspect-square brightness-[.5]' />
|
||||
<img src={coverImage} className='aspect-square brightness-[.5]' />
|
||||
</div>
|
||||
|
||||
<div className='absolute right-0 left-0 top-[18rem] h-32 bg-gradient-to-t from-[#222]/60 to-transparent'></div>
|
||||
|
||||
<div className='absolute top-0 right-0 left-0 flex h-[26rem] items-end justify-between p-8 pb-6'>
|
||||
<div className='text-7xl font-bold text-white'>
|
||||
{artist?.artist.name}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Header artist={artist?.artist} />
|
||||
|
||||
<div className='mt-12 grid h-[20rem] grid-cols-[14rem,_auto] grid-rows-1 gap-16 px-2'>
|
||||
{/* Latest release */}
|
||||
<div>
|
||||
<div className='mb-6 text-2xl font-semibold text-gray-800 dark:text-white'>
|
||||
最新发行
|
||||
</div>
|
||||
<div className='flex-grow rounded-xl '>
|
||||
{isLoadingAlbum ? (
|
||||
<Skeleton className='aspect-square w-full rounded-xl'></Skeleton>
|
||||
) : (
|
||||
<Cover imageUrl={latestAlbum?.picUrl ?? ''} />
|
||||
)}
|
||||
<div className='line-clamp-2 line-clamp-1 mt-2 font-semibold leading-tight decoration-gray-600 decoration-2 hover:underline dark:text-white dark:decoration-gray-200'>
|
||||
{latestAlbum?.name}
|
||||
</div>
|
||||
<div className='text-[12px] text-gray-500 dark:text-gray-400'>
|
||||
{latestAlbum?.type} ·{' '}
|
||||
{dayjs(latestAlbum?.publishTime || 0).year()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<LatestRelease
|
||||
album={albumsRaw?.hotAlbums[0]}
|
||||
isLoading={isLoadingAlbums}
|
||||
/>
|
||||
|
||||
{/* Popular tracks */}
|
||||
<div>
|
||||
<div className='mb-6 text-2xl font-semibold text-gray-800 dark:text-white'>
|
||||
热门歌曲
|
||||
</div>
|
||||
<div className='rounded-xl'>
|
||||
<TracksGrid
|
||||
tracks={tracks?.songs ?? artist?.hotSongs.slice(0, 10) ?? []}
|
||||
isSkeleton={isLoading}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<PopularTracks
|
||||
tracks={artist?.hotSongs}
|
||||
isLoadingArtist={isLoadingArtist}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Albums */}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ const Header = memo(
|
|||
<div className='absolute top-0 left-0 z-0 h-[24rem] w-full overflow-hidden'>
|
||||
<img src={coverUrl} className='absolute top-0 w-full blur-[100px]' />
|
||||
<img src={coverUrl} className='absolute top-0 w-full blur-[100px]' />
|
||||
<div className='absolute top-0 h-full w-full bg-gradient-to-b from-white/[.84] to-white dark:from-black/[.5] dark:to-[#1d1d1d]'></div>
|
||||
<div className='absolute top-0 h-full w-full bg-gradient-to-b from-white/80 to-white dark:from-black/50 dark:to-[#1d1d1d]'></div>
|
||||
</div>
|
||||
|
||||
<div className='grid grid-cols-[17rem_auto] items-center gap-9'>
|
||||
|
|
@ -73,7 +73,7 @@ const Header = memo(
|
|||
{/* <!-- Playlist creator --> */}
|
||||
{!isLoading && (
|
||||
<div className='mt-5 text-lg font-medium text-gray-800 dark:text-gray-300'>
|
||||
Playlist by <span>{playlist?.creator?.nickname}</span>
|
||||
歌单 · <span>{playlist?.creator?.nickname}</span>
|
||||
</div>
|
||||
)}
|
||||
{isLoading && (
|
||||
|
|
|
|||
5
packages/renderer/src/pages/Search/Search.tsx
Normal file
5
packages/renderer/src/pages/Search/Search.tsx
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
const Search = () => {
|
||||
return <div></div>
|
||||
}
|
||||
|
||||
export default Search
|
||||
3
packages/renderer/src/pages/Search/index.ts
Normal file
3
packages/renderer/src/pages/Search/index.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import Search from './Search'
|
||||
|
||||
export default Search
|
||||
Loading…
Add table
Add a link
Reference in a new issue