[+] Resume last
This commit is contained in:
@@ -2,6 +2,6 @@
|
|||||||
let { icon, ...rest } = $props();
|
let { icon, ...rest } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button class="cbox w-48px h-48px" {...rest}>
|
<button class="cbox size-48px" {...rest}>
|
||||||
<span class="h-24px w-24px {icon}"></span>
|
<span class="size-24px {icon}"></span>
|
||||||
</button>
|
</button>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { NeteaseSongBrief } from "../shared/songs";
|
||||||
|
|
||||||
|
let { info }: { info: NeteaseSongBrief } = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="hbox gap-16px">
|
||||||
|
<img class="rounded-16px size-68px" src={info.albumPic} alt="Album Art" />
|
||||||
|
<div class="vbox">
|
||||||
|
<div class="m3-font-title-large">{info.name}</div>
|
||||||
|
<div class="hbox w-full">
|
||||||
|
<div class="m3-font-body-medium m3-color-on-surface-variant">{info.artists.map(a => a.name).join(", ")} - {info.album}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import IconButton from "./IconButton.svelte";
|
||||||
|
|
||||||
|
let { title, ...rest } = $props()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="hbox h-full px-16px" {...rest}>
|
||||||
|
<div class="m3-font-title-large">{title}</div>
|
||||||
|
<IconButton icon="i-material-symbols:arrow-forward" />
|
||||||
|
</div>
|
||||||
@@ -19,4 +19,4 @@
|
|||||||
{#if settings}
|
{#if settings}
|
||||||
<IconButton icon="i-material-symbols:settings-rounded" onclick={settings} aria-label="Settings" />
|
<IconButton icon="i-material-symbols:settings-rounded" onclick={settings} aria-label="Settings" />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// import { log } from 'console';
|
||||||
|
import { getSongMeta, parseBrief } from '../shared/songs';
|
||||||
|
import type { PageServerLoad } from './$types';
|
||||||
|
|
||||||
|
export const load: PageServerLoad = async ({ params }) => {
|
||||||
|
let last = parseBrief(await getSongMeta(25723366))
|
||||||
|
return { last }
|
||||||
|
}
|
||||||
+24
-2
@@ -1,7 +1,29 @@
|
|||||||
<script>
|
<script lang="ts">
|
||||||
import { Button } from "m3-svelte"
|
|
||||||
import AppBar from "../components/appbar/AppBar.svelte";
|
import AppBar from "../components/appbar/AppBar.svelte";
|
||||||
|
import TitleHeader from "../components/TitleHeader.svelte";
|
||||||
|
import SongInfo from "../components/SongInfo.svelte";
|
||||||
|
import type { PageProps } from "./$types";
|
||||||
|
|
||||||
|
let { data }: PageProps = $props()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<AppBar account={() => alert('Account clicked')} settings={() => alert('Settings clicked')} />
|
<AppBar account={() => alert('Account clicked')} settings={() => alert('Settings clicked')} />
|
||||||
|
|
||||||
|
<div class="vbox gap-16px">
|
||||||
|
{#if data.last}
|
||||||
|
<div>
|
||||||
|
<TitleHeader title="从暂停的位置继续"/>
|
||||||
|
<div class="p-content">
|
||||||
|
<SongInfo info={data.last}></SongInfo>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<TitleHeader title="最近播放"/>
|
||||||
|
<div class="p-content">
|
||||||
|
最近播放的列表
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
+22
-1
@@ -4,4 +4,25 @@
|
|||||||
|
|
||||||
body
|
body
|
||||||
margin: 0
|
margin: 0
|
||||||
background: rgb(var(--m3-scheme-background))
|
background: rgb(var(--m3-scheme-background))
|
||||||
|
|
||||||
|
.hbox
|
||||||
|
display: flex
|
||||||
|
flex-direction: row
|
||||||
|
align-items: center
|
||||||
|
|
||||||
|
.vbox
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
|
||||||
|
.vcbox
|
||||||
|
@extend .vbox
|
||||||
|
align-items: center
|
||||||
|
|
||||||
|
.cbox
|
||||||
|
display: flex
|
||||||
|
justify-content: center
|
||||||
|
align-items: center
|
||||||
|
|
||||||
|
.p-content
|
||||||
|
padding: 0 16px
|
||||||
+19
-11
@@ -54,8 +54,14 @@ const getPlaylistRaw = cached(
|
|||||||
await fs.writeFile(p, JSON.stringify(track), 'utf-8')
|
await fs.writeFile(p, JSON.stringify(track), 'utf-8')
|
||||||
}
|
}
|
||||||
return pl
|
return pl
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
export const getSongMeta = cached(
|
||||||
|
async (songId: number) => path.join('data', 'songs', `${songId}`, 'meta.json'),
|
||||||
|
async (songId: number) => {
|
||||||
|
const detail = await ne.song_detail({ ids: songId.toString() })
|
||||||
|
return detail.body.songs[0]
|
||||||
|
})
|
||||||
|
|
||||||
export interface NeteaseSongBrief {
|
export interface NeteaseSongBrief {
|
||||||
id: number
|
id: number
|
||||||
@@ -66,20 +72,22 @@ export interface NeteaseSongBrief {
|
|||||||
artists: { id: number, name: string }[]
|
artists: { id: number, name: string }[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const parseBrief = (songData: any): NeteaseSongBrief => ({
|
||||||
|
id: songData.id,
|
||||||
|
name: songData.name,
|
||||||
|
album: songData.al.name,
|
||||||
|
albumId: songData.al.id,
|
||||||
|
albumPic: songData.al.picUrl,
|
||||||
|
artists: songData.ar.map((ar: any) => ({ id: ar.id, name: ar.name }))
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of songs from a playlist reference.
|
* Get a list of songs from a playlist reference.
|
||||||
*/
|
*/
|
||||||
export async function getSongsFromPlaylist(ref: string): Promise<any[]> {
|
export async function getSongsFromPlaylist(ref: string): Promise<any[]> {
|
||||||
const playlistId = parsePlaylistRef(ref)
|
const playlistId = parsePlaylistRef(ref)
|
||||||
const plData = await getPlaylistRaw({ id: playlistId })
|
const plData = await getPlaylistRaw({ id: playlistId })
|
||||||
return plData.playlist.tracks.map((track: any) => ({
|
return plData.playlist.tracks.map(parseBrief)
|
||||||
id: track.id,
|
|
||||||
name: track.name,
|
|
||||||
album: track.al.name,
|
|
||||||
albumId: track.al.id,
|
|
||||||
albumPic: track.al.picUrl,
|
|
||||||
artists: track.ar.map((ar: any) => ({ id: ar.id, name: ar.name }))
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NeteaseLyricsResponse { lrc: { lyric: string } }
|
interface NeteaseLyricsResponse { lrc: { lyric: string } }
|
||||||
@@ -98,4 +106,4 @@ export const getLyricsProcessed = cached(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// console.log((await getSongsFromPlaylist('580208139')).length)
|
// console.log((await getSongsFromPlaylist('580208139')).length)
|
||||||
console.log(await getLyricsProcessed(25723366))
|
// console.log(await getLyricsProcessed(25723366))
|
||||||
@@ -105,11 +105,6 @@ export default defineConfig({
|
|||||||
})]
|
})]
|
||||||
],
|
],
|
||||||
shortcuts: {
|
shortcuts: {
|
||||||
// Azalea's shortcuts
|
|
||||||
'hbox': 'flex flex-row items-center',
|
|
||||||
'vbox': 'flex flex-col items-center',
|
|
||||||
'cbox': 'flex justify-center items-center',
|
|
||||||
|
|
||||||
// Marina
|
// Marina
|
||||||
'form-error': 'text-3.5 font-medium text-destructive',
|
'form-error': 'text-3.5 font-medium text-destructive',
|
||||||
'form-warning': 'text-3.5 font-medium text-warning',
|
'form-warning': 'text-3.5 font-medium text-warning',
|
||||||
|
|||||||
Reference in New Issue
Block a user