mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-04 20:43:04 +00:00
fix playing tracks on album page
This commit is contained in:
committed by
Mungai Njoroge
parent
977d9282cb
commit
6adf5df4c6
@@ -2,7 +2,7 @@
|
|||||||
<QueueActions />
|
<QueueActions />
|
||||||
<div
|
<div
|
||||||
ref="scrollable"
|
ref="scrollable"
|
||||||
class="scrollable-r"
|
id="queue-scrollable"
|
||||||
v-bind="containerProps"
|
v-bind="containerProps"
|
||||||
style="height: 100%"
|
style="height: 100%"
|
||||||
@mouseover="mouseover = true"
|
@mouseover="mouseover = true"
|
||||||
@@ -36,44 +36,37 @@ import QueueActions from "./Queue/QueueActions.vue";
|
|||||||
const queue = useQStore();
|
const queue = useQStore();
|
||||||
const mouseover = ref(false);
|
const mouseover = ref(false);
|
||||||
const scrollable = ref<HTMLElement>();
|
const scrollable = ref<HTMLElement>();
|
||||||
|
const sourceTrackList = computed(() => queue.tracklist);
|
||||||
|
const {
|
||||||
|
list: tracks,
|
||||||
|
containerProps,
|
||||||
|
wrapperProps,
|
||||||
|
} = useVirtualList(sourceTrackList, {
|
||||||
|
itemHeight: 64,
|
||||||
|
});
|
||||||
|
|
||||||
function playFromQueue(index: number) {
|
function playFromQueue(index: number) {
|
||||||
queue.play(index);
|
queue.play(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
const source = computed(() => queue.tracklist);
|
function scrollToCurrent() {
|
||||||
|
const elem = document.getElementById("queue-scrollable") as HTMLElement;
|
||||||
|
const itemHeight = 64;
|
||||||
|
|
||||||
const {
|
const top = queue.currentindex * itemHeight - itemHeight;
|
||||||
list: tracks,
|
elem.scroll({
|
||||||
containerProps,
|
top,
|
||||||
wrapperProps,
|
behavior: "smooth",
|
||||||
scrollTo,
|
});
|
||||||
} = useVirtualList(source, {
|
}
|
||||||
itemHeight: 64,
|
|
||||||
});
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// scrollTo(queue.currentindex);
|
|
||||||
queue.setScrollFunction(scrollToCurrent, mouseover);
|
queue.setScrollFunction(scrollToCurrent, mouseover);
|
||||||
});
|
});
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
queue.setScrollFunction(() => {}, null);
|
queue.setScrollFunction(() => {}, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: Handle focusing current track on song end
|
|
||||||
|
|
||||||
|
|
||||||
function scrollToCurrent() {
|
|
||||||
const elem = document.getElementsByClassName('scrollable-r')[0] as HTMLElement;
|
|
||||||
const itemHeight = 64;
|
|
||||||
|
|
||||||
const top = queue.currentindex * itemHeight - itemHeight;
|
|
||||||
elem.scroll({
|
|
||||||
top,
|
|
||||||
behavior: "smooth",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="morexx">
|
<div class="morexx">
|
||||||
<button class="btn" @click="loader">
|
<button class="btn" @click.prevent="loader()">
|
||||||
<div class="text">Load More</div>
|
<div class="text">Load More</div>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -20,7 +20,12 @@
|
|||||||
ref="header"
|
ref="header"
|
||||||
class="header rounded"
|
class="header rounded"
|
||||||
v-if="!no_header"
|
v-if="!no_header"
|
||||||
:style="{ height: headerHeight + (on_album_page ? 0 : 24) + 'px' }"
|
:style="{
|
||||||
|
height:
|
||||||
|
headerHeight +
|
||||||
|
(on_album_page && album.query.length === 0 ? 0 : 24) +
|
||||||
|
'px',
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<div ref="header_content" class="header-content">
|
<div ref="header_content" class="header-content">
|
||||||
<slot name="header"></slot>
|
<slot name="header"></slot>
|
||||||
@@ -50,7 +55,11 @@
|
|||||||
queue.currentid === t.data.trackid && queue.playing
|
queue.currentid === t.data.trackid && queue.playing
|
||||||
"
|
"
|
||||||
@playThis="
|
@playThis="
|
||||||
updateQueue(t.data.index !== undefined ? t.data.index : t.index)
|
updateQueue(
|
||||||
|
t.data.index !== undefined
|
||||||
|
? t.data.index - (on_album_page ? t.data.disc : 0)
|
||||||
|
: t.index
|
||||||
|
)
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -62,13 +71,15 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useElementSize, useVirtualList } from "@vueuse/core";
|
import { useElementSize, useVirtualList } from "@vueuse/core";
|
||||||
import { computed, onMounted, onUpdated, ref, watch } from "vue";
|
import { computed, onMounted, ref, watch } from "vue";
|
||||||
|
|
||||||
import { Track } from "@/interfaces";
|
import { Track } from "@/interfaces";
|
||||||
import useQStore from "@/stores/queue";
|
import useQStore from "@/stores/queue";
|
||||||
|
import useAlbumStore from "@/stores/pages/album";
|
||||||
|
|
||||||
import SongItem from "@/components/shared/SongItem.vue";
|
import SongItem from "@/components/shared/SongItem.vue";
|
||||||
import AlbumDiscBar from "@/components/AlbumView/AlbumDiscBar.vue";
|
import AlbumDiscBar from "@/components/AlbumView/AlbumDiscBar.vue";
|
||||||
|
|
||||||
// EMITS & PROPS
|
// EMITS & PROPS
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: "playFromPage", index: number): void;
|
(e: "playFromPage", index: number): void;
|
||||||
@@ -80,13 +91,13 @@ const props = defineProps<{
|
|||||||
no_header?: boolean;
|
no_header?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// QUEUE
|
|
||||||
const queue = useQStore();
|
const queue = useQStore();
|
||||||
|
const album = useAlbumStore();
|
||||||
|
|
||||||
function updateQueue(index: number) {
|
function updateQueue(index: number) {
|
||||||
emit("playFromPage", index);
|
emit("playFromPage", index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SCROLLABLE AREA
|
|
||||||
let scrollable: HTMLElement;
|
let scrollable: HTMLElement;
|
||||||
const v_list = ref<HTMLElement>();
|
const v_list = ref<HTMLElement>();
|
||||||
const header_content = ref<HTMLElement>();
|
const header_content = ref<HTMLElement>();
|
||||||
|
|||||||
+33
-15
@@ -9,7 +9,11 @@ import { getAlbumTracks } from "../../composables/fetch/album";
|
|||||||
import { AlbumInfo, Artist, FuseResult, Track } from "../../interfaces";
|
import { AlbumInfo, Artist, FuseResult, Track } from "../../interfaces";
|
||||||
import { useNotifStore } from "../notification";
|
import { useNotifStore } from "../notification";
|
||||||
|
|
||||||
function sortTracks(tracks: Track[]) {
|
interface Disc {
|
||||||
|
[key: string]: Track[];
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortByTrackNumber(tracks: Track[]) {
|
||||||
return tracks.sort((a, b) => {
|
return tracks.sort((a, b) => {
|
||||||
if (a.track && b.track) {
|
if (a.track && b.track) {
|
||||||
return a.track - b.track;
|
return a.track - b.track;
|
||||||
@@ -19,24 +23,31 @@ function sortTracks(tracks: Track[]) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Discs {
|
function albumHasNoDiscs(album: AlbumInfo) {
|
||||||
[key: string]: Track[];
|
if (album.is_single) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createDiscs(tracks: Track[]): Discs {
|
/**
|
||||||
|
*
|
||||||
|
* @param tracks The raw tracklist from the server
|
||||||
|
* @returns A list of `Disc` objects
|
||||||
|
*/
|
||||||
|
function createDiscs(tracks: Track[]) {
|
||||||
return tracks.reduce((group, track) => {
|
return tracks.reduce((group, track) => {
|
||||||
const { disc } = track;
|
const { disc } = track;
|
||||||
group[disc] = group[disc] ?? [];
|
group[disc] = group[disc] ?? [];
|
||||||
group[disc].push(track);
|
group[disc].push(track);
|
||||||
return group;
|
return group;
|
||||||
}, {} as Discs);
|
}, {} as Disc);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineStore("album", {
|
export default defineStore("album", {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
query: "",
|
query: "",
|
||||||
info: <AlbumInfo>{},
|
info: <AlbumInfo>{},
|
||||||
allTracks: <Track[]>[],
|
rawTracks: <Track[]>[],
|
||||||
artists: <Artist[]>[],
|
artists: <Artist[]>[],
|
||||||
bio: null,
|
bio: null,
|
||||||
}),
|
}),
|
||||||
@@ -47,14 +58,8 @@ export default defineStore("album", {
|
|||||||
* @param hash title of the album
|
* @param hash title of the album
|
||||||
*/
|
*/
|
||||||
async fetchTracksAndArtists(hash: string) {
|
async fetchTracksAndArtists(hash: string) {
|
||||||
this.allTracks = [];
|
|
||||||
const album = await getAlbumTracks(hash, useNotifStore);
|
const album = await getAlbumTracks(hash, useNotifStore);
|
||||||
|
this.rawTracks = album.tracks;
|
||||||
const discs = createDiscs(sortTracks(album.tracks));
|
|
||||||
Object.keys(discs).forEach((disc) => {
|
|
||||||
this.allTracks.push(...discs[disc]);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.info = album.info;
|
this.info = album.info;
|
||||||
},
|
},
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
@@ -62,15 +67,26 @@ export default defineStore("album", {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
|
discs(): Disc {
|
||||||
|
return createDiscs(sortByTrackNumber(this.rawTracks));
|
||||||
|
},
|
||||||
|
allTracks(): Track[] {
|
||||||
|
return Object.keys(this.discs).reduce((tracks: Track[], disc) => {
|
||||||
|
const disc_tracks = this.discs[disc];
|
||||||
|
|
||||||
|
return [...tracks, ...disc_tracks];
|
||||||
|
}, []);
|
||||||
|
},
|
||||||
filteredTracks(): ComputedRef<FuseResult[]> {
|
filteredTracks(): ComputedRef<FuseResult[]> {
|
||||||
const discs = createDiscs(this.allTracks);
|
const discs = this.discs;
|
||||||
let tracks: (Track[] | AlbumDisc[]) = [];
|
let tracks: Track[] | AlbumDisc[] = [];
|
||||||
|
|
||||||
Object.keys(discs).forEach((disc) => {
|
Object.keys(discs).forEach((disc) => {
|
||||||
const discHeader = {
|
const discHeader = {
|
||||||
is_album_disc_number: true,
|
is_album_disc_number: true,
|
||||||
album_page_disc_number: parseInt(disc),
|
album_page_disc_number: parseInt(disc),
|
||||||
} as AlbumDisc;
|
} as AlbumDisc;
|
||||||
|
|
||||||
tracks = [...tracks, discHeader, ...discs[disc]];
|
tracks = [...tracks, discHeader, ...discs[disc]];
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -90,3 +106,5 @@ export default defineStore("album", {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: Implement Disc interface using a class
|
||||||
|
|||||||
Reference in New Issue
Block a user