mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-03 20:13:02 +00:00
extract queue songlist into a reusable component
~ getting ready to implement "see all" in favorite page
This commit is contained in:
committed by
Mungai Njoroge
parent
b95603c51e
commit
108182ab01
@@ -1,188 +0,0 @@
|
||||
<template>
|
||||
<div
|
||||
class="table"
|
||||
v-if="tracks.length"
|
||||
ref="tracklistElem"
|
||||
:class="{
|
||||
isSmall: isSmall,
|
||||
isMedium: isMedium,
|
||||
}"
|
||||
>
|
||||
<div class="header">
|
||||
<div class="disc-number" v-if="disc">Disc {{ disc }}</div>
|
||||
<div class="disc-number" v-if="$route.name === Routes.folder">
|
||||
In this folder
|
||||
</div>
|
||||
</div>
|
||||
<div class="songlist">
|
||||
<SongItem
|
||||
v-for="(track, index) in tracks"
|
||||
:key="track.id"
|
||||
:track="track"
|
||||
:index="
|
||||
on_album_page
|
||||
? track.track
|
||||
: track.index !== undefined
|
||||
? track.index + 1
|
||||
: index + 1
|
||||
"
|
||||
@playThis="updateQueue(track.index !== undefined ? track.index : index)"
|
||||
/>
|
||||
</div>
|
||||
<div class="copyright" v-if="copyright && copyright">
|
||||
{{ copyright }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="tracks.length === 0">
|
||||
<div class="no-results">
|
||||
<div class="text">No tracks here</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from "@vue/reactivity";
|
||||
import { useElementSize } from "@vueuse/core";
|
||||
import { ref } from "vue";
|
||||
|
||||
import SongItem from "../shared/SongItem.vue";
|
||||
|
||||
import { Track } from "@/interfaces";
|
||||
import { Routes } from "@/router/routes";
|
||||
import useQStore from "@/stores/queue";
|
||||
|
||||
const queue = useQStore();
|
||||
|
||||
const props = defineProps<{
|
||||
tracks: Track[];
|
||||
path?: string;
|
||||
pname?: string;
|
||||
id?: string;
|
||||
on_album_page?: boolean;
|
||||
disc?: string | number;
|
||||
copyright?: string | null;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "playFromPage", index: number): void;
|
||||
}>();
|
||||
|
||||
const tracklistElem = ref<HTMLElement | null>(null);
|
||||
const { width } = useElementSize(tracklistElem);
|
||||
|
||||
const brk = {
|
||||
sm: 500,
|
||||
md: 800,
|
||||
};
|
||||
|
||||
const isSmall = computed(() => width.value < brk.sm);
|
||||
const isMedium = computed(() => width.value > brk.sm && width.value < brk.md);
|
||||
|
||||
function updateQueue(index: number) {
|
||||
emit("playFromPage", index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to show handle track indexes.
|
||||
*/
|
||||
function getTrackList() {
|
||||
if (props.on_album_page) {
|
||||
const tracks = props.tracks.map((track) => {
|
||||
track.index = track.track;
|
||||
return track;
|
||||
});
|
||||
|
||||
return tracks;
|
||||
}
|
||||
|
||||
return props.tracks;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.no-results {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.copyright {
|
||||
font-size: 0.8rem;
|
||||
margin-top: 1rem;
|
||||
text-align: center;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.table {
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
padding: $small 0;
|
||||
|
||||
.header {
|
||||
margin: $small;
|
||||
|
||||
.disc-number {
|
||||
font-size: small;
|
||||
font-weight: bold;
|
||||
margin: $small 1.5rem;
|
||||
color: $gray1;
|
||||
}
|
||||
}
|
||||
|
||||
.current {
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
color: $red;
|
||||
}
|
||||
|
||||
.current:hover {
|
||||
* {
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
}
|
||||
|
||||
.songlist {
|
||||
scrollbar-width: none;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.contexton {
|
||||
background-color: $gray4;
|
||||
color: $white !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table.isSmall {
|
||||
.songlist-item {
|
||||
grid-template-columns: 1.5rem 2fr 2rem 2.5rem;
|
||||
}
|
||||
|
||||
.song-artists,
|
||||
.song-album {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.isSmallArtists {
|
||||
display: unset !important;
|
||||
font-size: small;
|
||||
color: $white;
|
||||
opacity: 0.67;
|
||||
}
|
||||
}
|
||||
|
||||
.table.isMedium {
|
||||
.songlist-item {
|
||||
grid-template-columns: 1.5rem 2fr 1fr 2rem 2.5rem;
|
||||
}
|
||||
|
||||
.song-album {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<div
|
||||
class="queue-view-virtual-scroller v-scroll-page"
|
||||
:class="{ isSmall, isMedium }"
|
||||
style="height: 100%"
|
||||
>
|
||||
<RecycleScroller
|
||||
class="scroller"
|
||||
id="songlist-scroller"
|
||||
style="height: 100%"
|
||||
:items="tracks.map((track) => ({ track, id: Math.random() }))"
|
||||
:item-size="itemHeight"
|
||||
key-field="id"
|
||||
v-slot="{ item, index }"
|
||||
>
|
||||
<SongItem
|
||||
:track="item.track"
|
||||
:index="index + 1"
|
||||
@playThis="handlePlay(index)"
|
||||
/>
|
||||
</RecycleScroller>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import SongItem from "@/components/shared/SongItem.vue";
|
||||
import { isMedium, isSmall } from "@/stores/content-width";
|
||||
import { Track } from "@/interfaces";
|
||||
|
||||
defineProps<{
|
||||
tracks: Track[];
|
||||
handlePlay: (index: number) => void;
|
||||
}>();
|
||||
|
||||
const itemHeight = 64;
|
||||
</script>
|
||||
+4
-39
@@ -1,54 +1,19 @@
|
||||
<template>
|
||||
<div
|
||||
class="queue-view-virtual-scroller v-scroll-page"
|
||||
:class="{ isSmall, isMedium }"
|
||||
style="height: 100%"
|
||||
>
|
||||
<RecycleScroller
|
||||
class="scroller"
|
||||
id="queue-page-scrollable"
|
||||
style="height: 100%"
|
||||
:items="scrollerItems"
|
||||
:item-size="itemHeight"
|
||||
key-field="id"
|
||||
v-slot="{ item, index }"
|
||||
>
|
||||
<SongItem
|
||||
:track="item.track"
|
||||
:index="index + 1"
|
||||
@playThis="playFromQueue(index)"
|
||||
/>
|
||||
</RecycleScroller>
|
||||
</div>
|
||||
<SongList :tracks="queue.tracklist" :handlePlay="playFromQueue" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted } from "vue";
|
||||
|
||||
import SongItem from "@/components/shared/SongItem.vue";
|
||||
import { isMedium, isSmall } from "@/stores/content-width";
|
||||
import { onMounted } from "vue";
|
||||
import useQStore from "@/stores/queue";
|
||||
import { createTrackProps } from "@/utils";
|
||||
import SongList from "@/components/shared/SongList.vue";
|
||||
|
||||
const itemHeight = 64;
|
||||
const queue = useQStore();
|
||||
|
||||
const scrollerItems = computed(() => {
|
||||
return queue.tracklist.map((track) => {
|
||||
return {
|
||||
track,
|
||||
id: Math.random(),
|
||||
props: createTrackProps(track),
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
function playFromQueue(index: number) {
|
||||
queue.play(index);
|
||||
}
|
||||
|
||||
function scrollToCurrent() {
|
||||
const scrollable = document.getElementById("queue-page-scrollable");
|
||||
const scrollable = document.getElementById("songlist-scroller");
|
||||
const itemHeight = 64;
|
||||
const top = (queue.currentindex - 1) * itemHeight;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user