feat: updates

This commit is contained in:
qier222 2022-03-24 14:23:04 +08:00
parent 3b9d728410
commit 46349e8314
No known key found for this signature in database
GPG Key ID: 9C85007ED905F14D
10 changed files with 117 additions and 39 deletions

View File

@ -80,7 +80,7 @@ export function getCache(
break
}
case 'user/playlist': {
if (!query.uid) return
if (isNaN(Number(query.uid))) return
const userPlaylists = db.get(
ModelNames.USER_PLAYLISTS,
Number(query?.uid)
@ -90,7 +90,16 @@ export function getCache(
}
case 'song/detail': {
const ids: string[] = query?.ids.split(',')
if (ids.length === 0) return
let isIDsValid = true
ids.forEach(id => {
if (id === '' || isNaN(Number(id))) isIDsValid = false
})
if (!isIDsValid) return
const idsQuery = ids.map(id => `id = ${id}`).join(' OR ')
console.log(idsQuery)
const tracksRaw = realm
.objects(ModelNames.TRACK)
.filtered(`(${idsQuery})`)
@ -109,28 +118,28 @@ export function getCache(
}
}
case 'album': {
if (!query?.id) return
if (isNaN(Number(query?.id))) return
const album = db.get(ModelNames.ALBUM, Number(query?.id)) as any
if (checkIsExpired && isCacheExpired(album?.updateAt, 24 * 60)) return
if (album?.json) return JSON.parse(album.json)
break
}
case 'playlist/detail': {
if (!query?.id) return
if (isNaN(Number(query?.id))) return
const playlist = db.get(ModelNames.PLAYLIST, Number(query?.id)) as any
if (checkIsExpired && isCacheExpired(playlist?.updateAt, 10)) return
if (playlist?.json) return JSON.parse(playlist.json)
break
}
case 'artists': {
if (!query?.id) return
if (isNaN(Number(query?.id))) return
const artist = db.get(ModelNames.ARTIST, Number(query?.id)) as any
if (checkIsExpired && isCacheExpired(artist?.updateAt, 30)) return
if (artist?.json) return JSON.parse(artist.json)
break
}
case 'artist/album': {
if (!query?.id) return
if (isNaN(Number(query?.id))) return
const artistAlbums = db.get(
ModelNames.ARTIST_ALBUMS,
Number(query?.id)

View File

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 2C3.34315 2 2 3.34315 2 5V19C2 20.6569 3.34315 22 5 22H19C20.6569 22 22 20.6569 22 19V5C22 3.34315 20.6569 2 19 2H5ZM9 6C8.44772 6 8 6.44772 8 7V12V17C8 17.5523 8.44772 18 9 18H15C15.5523 18 16 17.5523 16 17C16 16.4477 15.5523 16 15 16H10V13H15C15.5523 13 16 12.5523 16 12C16 11.4477 15.5523 11 15 11H10V8H15C15.5523 8 16 7.55228 16 7C16 6.44772 15.5523 6 15 6H9Z" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 542 B

View File

@ -170,6 +170,16 @@ const CoverRow = ({
className='mr-1 mb-1 inline-block h-3 w-3 text-gray-300'
/>
)}
{/* Explicit icon */}
{(item as Album)?.mark === 1056768 && (
<SvgIcon
name='explicit'
className='float-right mt-[2px] h-4 w-4 text-gray-300'
/>
)}
{/* Name */}
<span
onClick={() => goTo(item.id)}
className='decoration-gray-600 decoration-2 hover:underline dark:text-white dark:decoration-gray-200'

View File

@ -16,17 +16,17 @@ interface PrimaryTab extends Tab {
const primaryTabs: PrimaryTab[] = [
{
name: 'Home',
name: '主页',
icon: 'home',
route: '/',
},
{
name: 'Podcast',
name: '播客',
icon: 'podcast',
route: '/podcast',
},
{
name: 'Library',
name: '音乐库',
icon: 'music-library',
route: '/library',
},

View File

@ -115,7 +115,15 @@ const Track = memo(
isHighlight ? 'text-brand-500' : 'text-black dark:text-white'
)}
>
<span>{track.name}</span>
<span className='flex items-center'>
{track.name}
{track.mark === 1318912 && (
<SvgIcon
name='explicit'
className='ml-1.5 mt-[2px] h-4 w-4 text-gray-300 dark:text-gray-500'
/>
)}
</span>
{subtitle && (
<span
title={subtitle}
@ -227,10 +235,10 @@ const TracksAlbum = ({
<div className='mx-4 mt-10 mb-2 grid grid-cols-12 border-b border-gray-100 py-2.5 text-sm text-gray-400 dark:border-gray-800 dark:text-gray-500'>
<div className='col-span-6 grid grid-cols-[2rem_auto]'>
<div>#</div>
<div>TITLE</div>
<div></div>
</div>
<div className='col-span-4'>ARTIST</div>
<div className='col-span-2 justify-self-end'>TIME</div>
<div className='col-span-4'></div>
<div className='col-span-2 justify-self-end'></div>
</div>
{/* Tracks */}

View File

@ -1,6 +1,8 @@
import ArtistInline from '@/components/ArtistsInline'
import Skeleton from '@/components/Skeleton'
import { resizeImage } from '@/utils/common'
import { Fragment } from 'react'
import SvgIcon from './SvgIcon'
const Track = ({
track,
@ -52,11 +54,18 @@ const Track = ({
)}
<div className='text-xs text-gray-500 dark:text-gray-400'>
{!isSkeleton && (
<ArtistInline artists={track.ar} disableLink={true} />
)}
{isSkeleton && (
{isSkeleton ? (
<Skeleton className='w-2/3 translate-y-px'>PLACE</Skeleton>
) : (
<span className='flex items-center'>
{track.mark === 1318912 && (
<SvgIcon
name='explicit'
className='mr-1 h-3 w-3 text-gray-300 dark:text-gray-500'
/>
)}
<ArtistInline artists={track.ar} disableLink={true} />
</span>
)}
</div>
</div>

View File

@ -87,7 +87,15 @@ const Track = memo(
{isSkeleton ? (
<Skeleton className='w-2/3 translate-y-px'>PLACE</Skeleton>
) : (
<ArtistInline artists={track.ar} />
<span className='inline-flex items-center'>
{track.mark === 1318912 && (
<SvgIcon
name='explicit'
className='mr-1 h-3.5 w-3.5 text-gray-300 dark:text-gray-500'
/>
)}
<ArtistInline artists={track.ar} />
</span>
)}
</div>
</div>
@ -191,10 +199,10 @@ const TracksList = memo(
<div className='ml-2 mr-4 mt-10 mb-2 grid grid-cols-12 border-b border-gray-100 py-2.5 text-sm text-gray-400 dark:border-gray-800 dark:text-gray-500'>
<div className='col-span-6 grid grid-cols-[4.2rem_auto]'>
<div></div>
<div>TITLE</div>
<div></div>
</div>
<div className='col-span-4'>ALBUM</div>
<div className='col-span-2 justify-self-end'>TIME</div>
<div className='col-span-4'></div>
<div className='col-span-2 justify-self-end'></div>
</div>
<div className='grid w-full'>

View File

@ -16,6 +16,7 @@ import {
resizeImage,
scrollToTop,
} from '@/utils/common'
import useTracks from '@/hooks/useTracks'
const PlayButton = ({
album,
@ -95,7 +96,7 @@ const Header = ({
/>
</Fragment>
)}
<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/75 to-white dark:from-black/50 dark:to-[#1d1d1d]'></div>
</div>
<div className='grid grid-cols-[17rem_auto] items-center gap-9'>
@ -285,6 +286,10 @@ const Album = () => {
id: Number(params.id) || 0,
})
const { data: tracks } = useTracks({
ids: album?.songs?.map(track => track.id) ?? [],
})
const handlePlay = async (trackID: number | null = null) => {
const realAlbum = album?.album
if (!realAlbum) {
@ -302,7 +307,7 @@ const Album = () => {
handlePlay={handlePlay}
/>
<TracksAlbum
tracks={album?.album.songs ?? []}
tracks={tracks?.songs ?? album?.album.songs ?? []}
onTrackDoubleClick={handlePlay}
isSkeleton={isLoading}
/>

View File

@ -9,6 +9,7 @@ import TracksGrid from '@/components/TracksGrid'
import CoverRow, { Subtitle } from '@/components/CoverRow'
import Skeleton from '@/components/Skeleton'
import { Fragment } from 'react'
import useTracks from '@/hooks/useTracks'
const Artist = () => {
const params = useParams()
@ -22,25 +23,48 @@ const Artist = () => {
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 []
return albumsRaw.hotAlbums.filter(
album =>
album.type === '专辑' &&
['混音版', '精选集', 'Remix'].includes(album.subType) === false &&
album.size > 1
)
const albums: Album[] = []
albumsRaw.hotAlbums.forEach(album => {
if (album.type !== '专辑') return false
if (['混音版', '精选集', 'Remix'].includes(album.subType)) return false
// No singles
if (album.size <= 1) return false
// No remixes
if (
/(\(|\[)(.*)(Remix|remix)(.*)(\)|\])/.test(
album.name.toLocaleLowerCase()
)
) {
return false
}
// If have same name album only keep the Explicit version
const sameNameAlbumIndex = albums.findIndex(a => a.name === album.name)
if (sameNameAlbumIndex !== -1) {
if (album.mark === 1056768) albums[sameNameAlbumIndex] = album
return
}
albums.push(album)
})
return albums
}, [albumsRaw?.hotAlbums])
const singles = useMemo(() => {
if (!albumsRaw?.hotAlbums) return []
const albumsIds = albums.map(album => album.id)
return albumsRaw.hotAlbums.filter(
album =>
album.type !== '专辑' ||
['混音版', '精选集', 'Remix'].includes(album.subType) ||
album.size === 1
album => albumsIds.includes(album.id) === false
)
}, [albumsRaw?.hotAlbums])
}, [albums, albumsRaw?.hotAlbums])
const latestAlbum = useMemo(() => {
if (!albumsRaw || !albumsRaw.hotAlbums) return
@ -89,7 +113,7 @@ const 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 dark:text-white'>
<div className='mb-6 text-2xl font-semibold text-gray-800 dark:text-white'>
</div>
<div className='flex-grow rounded-xl '>
@ -110,12 +134,12 @@ const Artist = () => {
{/* Popular tracks */}
<div>
<div className='mb-6 text-2xl font-semibold dark:text-white'>
<div className='mb-6 text-2xl font-semibold text-gray-800 dark:text-white'>
</div>
<div className='rounded-xl'>
<TracksGrid
tracks={artist?.hotSongs.slice(0, 10) ?? []}
tracks={tracks?.songs ?? artist?.hotSongs.slice(0, 10) ?? []}
isSkeleton={isLoading}
/>
</div>
@ -125,7 +149,7 @@ const Artist = () => {
{/* Albums */}
{albums.length !== 0 && (
<div className='mt-20 px-2'>
<div className='mb-6 text-2xl font-semibold dark:text-white'>
<div className='mb-6 text-2xl font-semibold text-gray-800 dark:text-white'>
</div>
<CoverRow
@ -137,7 +161,7 @@ const Artist = () => {
{/* Singles/EP */}
<div className='mt-16 px-2'>
<div className='mb-6 text-2xl font-semibold dark:text-white'>
<div className='mb-6 text-2xl font-semibold text-gray-800 dark:text-white'>
EP
</div>
<CoverRow

View File

@ -178,7 +178,9 @@ export class Player {
_howler = howler
this.play()
this.state = State.PLAYING
_howler.once('load', () => this._cacheAudio(this.trackID, audio))
const id = this.trackID
_howler.once('load', () => this._cacheAudio(id, audio))
if (!this._progressInterval) {
this._setupProgressInterval()