Add Album Page
This commit is contained in:
parent
19d35589be
commit
2af920a7ac
3 changed files with 194 additions and 0 deletions
|
@ -1,5 +1,6 @@
|
|||
import {Md5} from "ts-md5";
|
||||
import Cookies from 'js-cookie';
|
||||
import {Disc} from "radix-icons-svelte";
|
||||
|
||||
function getIdent(): string {
|
||||
let cookie = Cookies.get("subsonicPlayerIdent");
|
||||
|
@ -242,6 +243,27 @@ export interface AlbumID3 {
|
|||
discTitles?: Array<DiscTitle>
|
||||
}
|
||||
|
||||
export interface GetAlbumInfo2Response extends OpenSubsonicResponse {
|
||||
albumInfo: AlbumInfo
|
||||
}
|
||||
|
||||
export interface AlbumInfo {
|
||||
notes?: string,
|
||||
musicBrainzId?: string,
|
||||
lastFmUrl?: string,
|
||||
smallImageUrl?: string,
|
||||
mediumImageUrl?: string,
|
||||
largeImageUrl?: string,
|
||||
}
|
||||
|
||||
export interface GetAlbumResponse extends OpenSubsonicResponse{
|
||||
album: AlbumID3WithSongs
|
||||
}
|
||||
|
||||
export interface AlbumID3WithSongs extends AlbumID3 {
|
||||
song?: Array<Song>,
|
||||
}
|
||||
|
||||
interface RecordLabel {
|
||||
name: string
|
||||
}
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
<svelte:options runes={true} />
|
||||
|
||||
<script lang="ts">
|
||||
import {onMount} from "svelte";
|
||||
import {goto} from "$app/navigation";
|
||||
import {
|
||||
type AlbumID3WithSongs,
|
||||
type GetAlbumInfo2Response, type GetAlbumResponse,
|
||||
OpenSubsonic,
|
||||
type Parameter, type Song
|
||||
} from "$lib/opensubsonic";
|
||||
import {queueState} from "$lib/states/play-queue.svelte";
|
||||
import {playbackState, shuffle} from "$lib/states/playback-state.svelte";
|
||||
import {Button} from "$lib/components/ui/button";
|
||||
|
||||
class AlbumData {
|
||||
data: AlbumID3WithSongs = $state({})
|
||||
}
|
||||
|
||||
let { data } = $props();
|
||||
let albumId = $derived(data.albumId);
|
||||
let album = $state(new AlbumData());
|
||||
let loading = $state(true);
|
||||
console.log("album:", data.albumId)
|
||||
|
||||
async function fetchAlbumInfos(): Promise<void> {
|
||||
let parameters: Array<Parameter> = [
|
||||
{key: "id", value: albumId},
|
||||
];
|
||||
|
||||
const infoData: GetAlbumInfo2Response = await OpenSubsonic.get("getAlbumInfo2", parameters);
|
||||
if (infoData) {
|
||||
album.info = infoData.albumInfo;
|
||||
}
|
||||
|
||||
const albumResponse: GetAlbumResponse = await OpenSubsonic.get("getAlbum", parameters);
|
||||
if (albumResponse && albumResponse.album.song) {
|
||||
album.data = albumResponse.album;
|
||||
|
||||
}
|
||||
|
||||
loading = false;
|
||||
}
|
||||
|
||||
function getAlbumImage() {
|
||||
if (album.info.mediumImageUrl) {
|
||||
return album.info.mediumImageUrl;
|
||||
}
|
||||
else if (album.info.largeImageUrl) {
|
||||
return album.info.largeImageUrl;
|
||||
}
|
||||
else if (album.info.smallImageUrl) {
|
||||
return album.info.smallImageUrl;
|
||||
}
|
||||
else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let scrollY = $state(0);
|
||||
let scrollYMax = $state(1);
|
||||
|
||||
function updateScroll(self) {
|
||||
scrollY = self.scrollTop;
|
||||
scrollYMax = self.scrollTopMax;
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
if(scrollY/scrollYMax > 0.7 && albums.length === 100 && !albums.paginating) {
|
||||
console.log("triggered")
|
||||
}
|
||||
})
|
||||
|
||||
function selectAlbum(albumId) {
|
||||
goto(`/album/${albumId}`);
|
||||
console.log(albumId);
|
||||
}
|
||||
|
||||
function playSong( song: Song) {
|
||||
queueState.addSong(song);
|
||||
playbackState.pause();
|
||||
playbackState.newSong(queueState.getSong());
|
||||
playbackState.play();
|
||||
}
|
||||
|
||||
let playHover = $state(false);
|
||||
let shuffleHover = $state(false);
|
||||
|
||||
function playAlbum(addToQueue = false) {
|
||||
if (addToQueue) {
|
||||
const queuePosition = queueState.currentIndex;
|
||||
album.data.song.forEach((song) => {
|
||||
queueState.addSong(song);
|
||||
})
|
||||
queueState.setSong(queuePosition);
|
||||
}
|
||||
else {
|
||||
queueState.replaceQueue(album.data.song);
|
||||
console.log(queueState.queue);
|
||||
playbackState.pause();
|
||||
playbackState.newSong(queueState.getSong());
|
||||
playbackState.play();
|
||||
}
|
||||
}
|
||||
|
||||
function shuffleAlbum(addToQueue = false) {
|
||||
const shuffledAlbum = shuffle([...album.data.song])
|
||||
if (addToQueue) {
|
||||
const queuePosition = queueState.currentIndex;
|
||||
shuffledAlbum.forEach((song) => {
|
||||
queueState.addSong(song);
|
||||
})
|
||||
queueState.setSong(queuePosition);
|
||||
}
|
||||
else {
|
||||
queueState.replaceQueue(shuffledAlbum);
|
||||
console.log(queueState.queue);
|
||||
playbackState.pause();
|
||||
playbackState.newSong(queueState.getSong());
|
||||
playbackState.play();
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
fetchAlbumInfos();
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if loading}
|
||||
<p>Loading</p>
|
||||
{:else}
|
||||
<div class="flex flex-row gap-4">
|
||||
<img alt={album.data.name + " Album Cover"} src={getAlbumImage()} height="312px" width="312px" class="rounded-md" />
|
||||
<div>
|
||||
<h1>{album.data.name}</h1>
|
||||
<p>{album.info.notes}</p>
|
||||
<p>{album.info.lastFmUrl}</p>
|
||||
<p>{album.info.musicBrainzId}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="flex flex-col" onmouseover={() => playHover = true} onmouseleave={() => playHover = false}>
|
||||
<Button onclick={() => playAlbum()}>Play</Button>
|
||||
{#if playHover}
|
||||
<Button onclick={() => playAlbum(true)}>Add To Queue</Button>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="flex flex-col" onmouseover={() => shuffleHover = true} onmouseleave={() => shuffleHover = false}>
|
||||
<Button onclick={() => shuffleAlbum()}>Shuffle</Button>
|
||||
|
||||
{#if shuffleHover}
|
||||
<Button onclick={() => shuffleAlbum(true)}>Add To Queue</Button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="border border-2 p-2 rounded-md">
|
||||
{#each album.data.song as song}
|
||||
<p onclick={() => playSong(song)}>{song.title}</p>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
{/if}
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import type { RouteParams } from './$types';
|
||||
|
||||
export const load = ({ params }: { params: RouteParams }) => {
|
||||
return {
|
||||
albumId: params.albumId
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue