Add Album Page

This commit is contained in:
Neshura 2024-05-02 03:53:28 +02:00
parent 19d35589be
commit 2af920a7ac
Signed by: Neshura
GPG key ID: B6983AAA6B9A7A6C
3 changed files with 194 additions and 0 deletions

View file

@ -1,5 +1,6 @@
import {Md5} from "ts-md5"; import {Md5} from "ts-md5";
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import {Disc} from "radix-icons-svelte";
function getIdent(): string { function getIdent(): string {
let cookie = Cookies.get("subsonicPlayerIdent"); let cookie = Cookies.get("subsonicPlayerIdent");
@ -242,6 +243,27 @@ export interface AlbumID3 {
discTitles?: Array<DiscTitle> 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 { interface RecordLabel {
name: string name: string
} }

View file

@ -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}

View file

@ -0,0 +1,7 @@
import type { RouteParams } from './$types';
export const load = ({ params }: { params: RouteParams }) => {
return {
albumId: params.albumId
}
}