feat: 支持缓存歌词和一些小更新

This commit is contained in:
qier222 2022-04-05 23:02:59 +08:00
parent abedbe7531
commit 1eb38937fc
No known key found for this signature in database
GPG key ID: 9C85007ED905F14D
11 changed files with 44 additions and 18 deletions

View file

@ -80,6 +80,15 @@ export async function setCache(api: string, data: any, query: any) {
}) })
break break
} }
case 'lyric': {
if (!data.lrc) return
db.upsert(Tables.LYRIC, {
id: query.id,
json: JSON.stringify(data),
updatedAt: Date.now(),
})
break
}
} }
} }
@ -160,6 +169,12 @@ export function getCache(api: string, query: any): any {
) )
return artistAlbums return artistAlbums
} }
case 'lyric': {
if (isNaN(Number(query?.id))) return
const data = db.find(Tables.LYRIC, query.id)
if (data?.json) return JSON.parse(data.json)
break
}
} }
} }
@ -168,7 +183,7 @@ export async function getCacheForExpress(api: string, req: Request) {
if (api === 'song/detail') { if (api === 'song/detail') {
const cache = getCache(api, req.query) const cache = getCache(api, req.query)
if (cache) { if (cache) {
logger.info(`[cache] Cache hit for ${req.path}`) logger.debug(`[cache] Cache hit for ${req.path}`)
return cache return cache
} }
} }
@ -185,7 +200,7 @@ export async function getCacheForExpress(api: string, req: Request) {
) )
if (!isAudioFileExists) return if (!isAudioFileExists) return
logger.info(`[cache] Audio cache hit for ${req.path}`) logger.debug(`[cache] Audio cache hit for ${req.path}`)
return { return {
data: [ data: [

View file

@ -15,6 +15,7 @@ export enum Tables {
ARTIST = 'artist', ARTIST = 'artist',
PLAYLIST = 'playlist', PLAYLIST = 'playlist',
ARTIST_ALBUMS = 'artist_album', ARTIST_ALBUMS = 'artist_album',
LYRIC = 'lyric',
// Special tables // Special tables
ACCOUNT_DATA = 'account_data', ACCOUNT_DATA = 'account_data',
@ -123,6 +124,7 @@ if (process.env.NODE_ENV === 'development') {
Tables.ARTIST, Tables.ARTIST,
Tables.AUDIO, Tables.AUDIO,
Tables.ACCOUNT_DATA, Tables.ACCOUNT_DATA,
Tables.LYRIC,
] ]
tables.forEach(table => { tables.forEach(table => {
const data = db.findAll(table) const data = db.findAll(table)

View file

@ -1,12 +1,17 @@
import { app } from 'electron' /** By default, it writes logs to the following locations:
* on Linux: ~/.config/{app name}/logs/{process type}.log
* on macOS: ~/Library/Logs/{app name}/{process type}.log
* on Windows: %USERPROFILE%\AppData\Roaming\{app name}\logs\{process type}.log
* @see https://www.npmjs.com/package/electron-log
*/
import logger from 'electron-log' import logger from 'electron-log'
import pc from 'picocolors' import pc from 'picocolors'
Object.assign(console, logger.functions) Object.assign(console, logger.functions)
logger.transports.console.format = `${pc.dim('{h}:{i}:{s}{scope}')} {text}` logger.transports.console.format = `${pc.dim('{h}:{i}:{s}{scope}')} {text}`
logger.transports.file.level = 'info'
logger.transports.file.level = app.isPackaged ? 'info' : 'debug'
logger.info( logger.info(
`\n\n██╗ ██╗███████╗███████╗██████╗ ██╗ █████╗ ██╗ ██╗███╗ ███╗██╗ ██╗███████╗██╗ ██████╗ `\n\n██╗ ██╗███████╗███████╗██████╗ ██╗ █████╗ ██╗ ██╗███╗ ███╗██╗ ██╗███████╗██╗ ██████╗

View file

@ -1,7 +1,8 @@
CREATE TABLE "artist" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id)); CREATE TABLE "account_data" ("id" text NOT NULL,"json" text NOT NULL,"updateAt" int NOT NULL, PRIMARY KEY (id));
CREATE TABLE "album" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id)); CREATE TABLE "album" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id));
CREATE TABLE "artist_album" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id));
CREATE TABLE "artist" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id));
CREATE TABLE "audio" ("id" integer NOT NULL,"br" int NOT NULL,"type" text NOT NULL,"srouce" text NOT NULL,"updateAt" int NOT NULL, PRIMARY KEY (id));
CREATE TABLE "lyric" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" integer NOT NULL, PRIMARY KEY (id));
CREATE TABLE "playlist" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id)); CREATE TABLE "playlist" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id));
CREATE TABLE "track" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id)); CREATE TABLE "track" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id));
CREATE TABLE "artist_album" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id));
CREATE TABLE "audio" ("id" integer NOT NULL,"br" int NOT NULL,"type" text NOT NULL,"srouce" text NOT NULL,"updateAt" int NOT NULL, PRIMARY KEY (id));
CREATE TABLE "account_data" ("id" text NOT NULL,"json" text NOT NULL,"updateAt" int NOT NULL, PRIMARY KEY (id));

View file

@ -29,7 +29,7 @@ Object.entries(neteaseApi).forEach(([name, handler]) => {
name = pathCase(name) name = pathCase(name)
const wrappedHandler = async (req: Request, res: Response) => { const wrappedHandler = async (req: Request, res: Response) => {
logger.info(`[server] Handling request: ${req.path}`) logger.debug(`[server] Handling request: ${req.path}`)
// Get from cache // Get from cache
const cache = await getCacheForExpress(name, req) const cache = await getCacheForExpress(name, req)

View file

@ -10,6 +10,7 @@ export default function useUserAlbums(params: FetchUserAlbumsParams = {}) {
[UserApiNames.FETCH_USER_ALBUMS, user?.profile?.userId ?? 0], [UserApiNames.FETCH_USER_ALBUMS, user?.profile?.userId ?? 0],
() => fetchUserAlbums(params), () => fetchUserAlbums(params),
{ {
refetchOnWindowFocus: true,
placeholderData: (): FetchUserAlbumsResponse | undefined => placeholderData: (): FetchUserAlbumsResponse | undefined =>
window.ipcRenderer?.sendSync('getApiCacheSync', { window.ipcRenderer?.sendSync('getApiCacheSync', {
api: 'album/sublist', api: 'album/sublist',

View file

@ -3,6 +3,7 @@ import { UserApiNames, fetchUserArtists } from '@/api/user'
export default function useUserArtists() { export default function useUserArtists() {
return useQuery([UserApiNames.FETCH_USER_ARTIST], fetchUserArtists, { return useQuery([UserApiNames.FETCH_USER_ARTIST], fetchUserArtists, {
refetchOnWindowFocus: true,
placeholderData: (): FetchUserArtistsResponse => placeholderData: (): FetchUserArtistsResponse =>
window.ipcRenderer?.sendSync('getApiCacheSync', { window.ipcRenderer?.sendSync('getApiCacheSync', {
api: 'album/sublist', api: 'album/sublist',

View file

@ -29,6 +29,7 @@ export default function useUserPlaylists() {
params.uid !== 0 && params.uid !== 0 &&
params.offset !== undefined params.offset !== undefined
), ),
refetchOnWindowFocus: true,
placeholderData: (): FetchUserPlaylistsResponse => placeholderData: (): FetchUserPlaylistsResponse =>
window.ipcRenderer?.sendSync('getApiCacheSync', { window.ipcRenderer?.sendSync('getApiCacheSync', {
api: 'user/playlist', api: 'user/playlist',

View file

@ -64,7 +64,7 @@ const LatestRelease = ({
<Skeleton className='aspect-square w-full rounded-xl'></Skeleton> <Skeleton className='aspect-square w-full rounded-xl'></Skeleton>
) : ( ) : (
<Cover <Cover
imageUrl={album?.picUrl ?? ''} imageUrl={resizeImage(album?.picUrl ?? '', 'md')}
showPlayButton={true} showPlayButton={true}
onClick={toAlbum} onClick={toAlbum}
/> />

View file

@ -40,7 +40,7 @@ export default function Home() {
) )
const playlists = [ const playlists = [
...(dailyRecommendPlaylists?.recommend?.slice(1) ?? []), ...(dailyRecommendPlaylists?.recommend?.slice(1).slice(0, 8) ?? []),
...(recommendedPlaylists?.result ?? []), ...(recommendedPlaylists?.result ?? []),
] ]
.slice(0, 10) .slice(0, 10)

View file

@ -73,7 +73,7 @@ const LikedTracksCard = ({ className }: { className?: string }) => {
navigate(`/playlist/${likedSongsPlaylist.playlist.id}`) navigate(`/playlist/${likedSongsPlaylist.playlist.id}`)
} }
className={classNames( className={classNames(
'relative flex h-full w-full flex-col justify-between rounded-2xl bg-brand-50 py-5 px-6 text-brand-600 ', 'relative flex h-full w-full flex-col justify-between rounded-2xl bg-brand-50 py-5 px-6 text-brand-600 dark:bg-brand-800 dark:text-brand-50',
className className
)} )}
> >
@ -91,7 +91,7 @@ const LikedTracksCard = ({ className }: { className?: string }) => {
<button <button
onClick={handlePlay} onClick={handlePlay}
className='btn-pressed-animation absolute bottom-6 right-6 grid h-11 w-11 cursor-default place-content-center rounded-full bg-brand-600 text-brand-50 shadow-lg' className='btn-pressed-animation absolute bottom-6 right-6 grid h-11 w-11 cursor-default place-content-center rounded-full bg-brand-600 text-brand-50 shadow-lg dark:bg-white dark:text-brand-600'
> >
<SvgIcon name='play-fill' className='ml-0.5 h-6 w-6' /> <SvgIcon name='play-fill' className='ml-0.5 h-6 w-6' />
</button> </button>
@ -111,7 +111,7 @@ const OtherCard = ({
return ( return (
<div <div
className={classNames( className={classNames(
'flex h-full w-full flex-col justify-between rounded-2xl bg-gray-100 text-lg font-bold', 'flex h-full w-full flex-col justify-between rounded-2xl bg-gray-100 text-lg font-bold dark:bg-gray-800 dark:text-gray-200',
className className
)} )}
> >
@ -180,7 +180,7 @@ const TabHeader = ({
setActiveTab: (tab: keyof TabsType) => void setActiveTab: (tab: keyof TabsType) => void
}) => { }) => {
return ( return (
<div className='mt-10 flex text-lg'> <div className='mt-10 flex text-lg dark:text-white'>
{Object.entries(tabs).map(([id, name]) => ( {Object.entries(tabs).map(([id, name]) => (
<div <div
key={id} key={id}
@ -188,7 +188,7 @@ const TabHeader = ({
className={classNames( className={classNames(
'btn-pressed-animation mr-3 rounded-lg px-3.5 py-1.5 font-medium', 'btn-pressed-animation mr-3 rounded-lg px-3.5 py-1.5 font-medium',
activeTab === id activeTab === id
? 'bg-black/[.04]' ? 'bg-black/[.04] dark:bg-white/10'
: 'btn-hover-animation after:bg-black/[.04] dark:after:bg-white/10' : 'btn-hover-animation after:bg-black/[.04] dark:after:bg-white/10'
)} )}
> >
@ -238,7 +238,7 @@ const Library = () => {
return ( return (
<div className='mt-8'> <div className='mt-8'>
<div className='flex items-center text-[2.625rem] font-semibold'> <div className='flex items-center text-[2.625rem] font-semibold dark:text-white'>
<img src={avatarUrl} className='mr-3 mt-1 h-12 w-12 rounded-full' /> <img src={avatarUrl} className='mr-3 mt-1 h-12 w-12 rounded-full' />
{user?.profile?.nickname} {user?.profile?.nickname}
</div> </div>