mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-05 04:53:01 +00:00
use div scroll method to scroll to current song in queue
This commit is contained in:
committed by
Mungai Njoroge
parent
8e258eaf24
commit
278439eee8
@@ -4,7 +4,7 @@ input[type="range"] {
|
|||||||
width: calc(100% - 2px);
|
width: calc(100% - 2px);
|
||||||
height: 0.3rem;
|
height: 0.3rem;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background: $gray4 linear-gradient(90deg, $accent, $darkestblue) no-repeat;
|
background: $gray4 linear-gradient(90deg, $darkblue, $darkestblue) no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
|
|
||||||
&::-webkit-slider-thumb {
|
&::-webkit-slider-thumb {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tags">
|
<div class="tags">
|
||||||
<div class="title ellip">
|
<div v-tooltip class="title ellip">
|
||||||
{{ queue.currenttrack?.title || "Hello there" }}
|
{{ queue.currenttrack?.title || "Hello there" }}
|
||||||
</div>
|
</div>
|
||||||
<ArtistName
|
<ArtistName
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<QueueActions />
|
<QueueActions />
|
||||||
<div
|
<div
|
||||||
|
ref="scrollable"
|
||||||
class="scrollable-r"
|
class="scrollable-r"
|
||||||
v-bind="containerProps"
|
v-bind="containerProps"
|
||||||
style="height: 100%"
|
style="height: 100%"
|
||||||
@mouseover="mouseover = true"
|
@mouseover="mouseover = true"
|
||||||
@mouseout="mouseover = false"
|
@mouseout="mouseover = false"
|
||||||
>
|
>
|
||||||
<div class="inner" v-bind="wrapperProps" >
|
<div class="inner" v-bind="wrapperProps">
|
||||||
<TrackItem
|
<TrackItem
|
||||||
style="height: 64px"
|
style="height: 64px"
|
||||||
v-for="t in tracks"
|
v-for="t in tracks"
|
||||||
@@ -34,6 +35,7 @@ import QueueActions from "./Queue/QueueActions.vue";
|
|||||||
|
|
||||||
const queue = useQStore();
|
const queue = useQStore();
|
||||||
const mouseover = ref(false);
|
const mouseover = ref(false);
|
||||||
|
const scrollable = ref<HTMLElement>();
|
||||||
|
|
||||||
function playFromQueue(index: number) {
|
function playFromQueue(index: number) {
|
||||||
queue.play(index);
|
queue.play(index);
|
||||||
@@ -51,8 +53,8 @@ const {
|
|||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
scrollTo(queue.currentindex);
|
// scrollTo(queue.currentindex);
|
||||||
queue.setScrollFunction(scrollTo, mouseover);
|
queue.setScrollFunction(scrollToCurrent, mouseover);
|
||||||
});
|
});
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
@@ -60,6 +62,18 @@ onBeforeUnmount(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// TODO: Handle focusing current track on song end
|
// 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">
|
||||||
|
|||||||
@@ -14,9 +14,7 @@
|
|||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div v-auto-animate @click.pre@dblclick.prevent="emitUpdate" class="thumbnail">
|
<div v-auto-animate @click.pre@dblclick.prevent="emitUpdate" class="thumbnail">
|
||||||
<img
|
<img
|
||||||
loading="lazy"
|
|
||||||
:src="imguri + track.image"
|
:src="imguri + track.image"
|
||||||
alt=""
|
|
||||||
class="album-art image rounded-sm"
|
class="album-art image rounded-sm"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
<div class="album-art">
|
<div class="album-art">
|
||||||
<img
|
<img
|
||||||
:src="paths.images.thumb.small + track.image"
|
:src="paths.images.thumb.small + track.image"
|
||||||
alt=""
|
|
||||||
class="rounded-sm"
|
class="rounded-sm"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
// "local" | "remote"
|
// "local" | "remote"
|
||||||
let mode = "remote";
|
let mode = "local";
|
||||||
|
|
||||||
export interface D<T = string> {
|
export interface D<T = string> {
|
||||||
[key: string]: T;
|
[key: string]: T;
|
||||||
|
|||||||
@@ -2,26 +2,27 @@
|
|||||||
<!-- JUST A COMMENT: 64 is single item height, 24 is gap height -->
|
<!-- JUST A COMMENT: 64 is single item height, 24 is gap height -->
|
||||||
<div class="header-list-layout">
|
<div class="header-list-layout">
|
||||||
<div
|
<div
|
||||||
|
id="v-page-scrollable"
|
||||||
v-bind="containerProps"
|
v-bind="containerProps"
|
||||||
style="height: 100%"
|
style="height: 100%"
|
||||||
:style="{ paddingTop: !no_header ? headerHeight - 64 + 24 + 'px' : 0 }"
|
|
||||||
@scroll="handleScroll"
|
@scroll="handleScroll"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-bind="wrapperProps"
|
v-bind="wrapperProps"
|
||||||
class="scrollable"
|
class="v-list"
|
||||||
ref="scrollable"
|
ref="v_list"
|
||||||
:class="{
|
:class="{
|
||||||
isSmall: isSmall,
|
isSmall: isSmall,
|
||||||
isMedium: isMedium || on_album_page,
|
isMedium: isMedium || on_album_page,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div class="header rounded" style="height: 64px" v-if="!no_header">
|
|
||||||
<div
|
<div
|
||||||
ref="header"
|
ref="header"
|
||||||
:style="{ top: -headerHeight + 64 - 24 + 'px' }"
|
class="header rounded"
|
||||||
class="header-content"
|
v-if="!no_header"
|
||||||
|
:style="{ height: headerHeight + 24 + 'px' }"
|
||||||
>
|
>
|
||||||
|
<div ref="header_content" class="header-content">
|
||||||
<slot name="header"></slot>
|
<slot name="header"></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -54,7 +55,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useElementSize, useVirtualList } from "@vueuse/core";
|
import { useElementSize, useVirtualList } from "@vueuse/core";
|
||||||
import { computed, ref } from "vue";
|
import { computed, onMounted, onUpdated, ref, watch } from "vue";
|
||||||
|
|
||||||
import { Track } from "@/interfaces";
|
import { Track } from "@/interfaces";
|
||||||
import useQStore from "@/stores/queue";
|
import useQStore from "@/stores/queue";
|
||||||
@@ -79,8 +80,10 @@ function updateQueue(index: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SCROLLABLE AREA
|
// SCROLLABLE AREA
|
||||||
const scrollable = ref<HTMLElement>();
|
let scrollable: HTMLElement;
|
||||||
const { width } = useElementSize(scrollable);
|
const v_list = ref<HTMLElement>();
|
||||||
|
const header_content = ref<HTMLElement>();
|
||||||
|
const { width } = useElementSize(v_list);
|
||||||
|
|
||||||
const brk = {
|
const brk = {
|
||||||
sm: 500,
|
sm: 500,
|
||||||
@@ -92,28 +95,38 @@ const isMedium = computed(() => width.value > brk.sm && width.value < brk.md);
|
|||||||
|
|
||||||
// VIRTUAL LIST
|
// VIRTUAL LIST
|
||||||
const source = computed(() => props.tracks);
|
const source = computed(() => props.tracks);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
list: tracks,
|
list: tracks,
|
||||||
containerProps,
|
containerProps,
|
||||||
wrapperProps,
|
wrapperProps,
|
||||||
} = useVirtualList(source, {
|
} = useVirtualList(source, {
|
||||||
itemHeight: 60,
|
itemHeight: 60,
|
||||||
overscan: 15,
|
overscan: 20,
|
||||||
|
});
|
||||||
|
|
||||||
|
// watch source changes and scroll to top
|
||||||
|
watch(source, () => {
|
||||||
|
scrollable.scroll(0, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
// HEADER
|
// HEADER
|
||||||
const header = ref<HTMLElement>();
|
const header = ref<HTMLElement>();
|
||||||
const { height: headerHeight } = useElementSize(header);
|
const { height: headerHeight } = useElementSize(header_content);
|
||||||
|
|
||||||
function handleScroll(e: Event) {
|
function handleScroll(e: Event) {
|
||||||
const scrollTop = (e.target as HTMLElement).scrollTop;
|
const scrollTop = (e.target as HTMLElement).scrollTop;
|
||||||
|
|
||||||
if (scrollTop > headerHeight.value) {
|
if (scrollTop > (header.value?.offsetHeight || 0)) {
|
||||||
header.value ? (header.value.style.opacity = "0") : null;
|
header.value ? (header.value.style.opacity = "0") : null;
|
||||||
} else {
|
} else {
|
||||||
header.value ? (header.value.style.opacity = "1") : null;
|
header.value ? (header.value.style.opacity = "1") : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
scrollable = document.getElementById("v-page-scrollable") as HTMLElement;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@@ -121,7 +134,7 @@ function handleScroll(e: Event) {
|
|||||||
margin-right: -$medium;
|
margin-right: -$medium;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.scrollable {
|
.v-list {
|
||||||
padding-right: calc(1rem - $small + 2px);
|
padding-right: calc(1rem - $small + 2px);
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
|
|
||||||
@@ -134,7 +147,7 @@ function handleScroll(e: Event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollable.isSmall {
|
.v-list.isSmall {
|
||||||
// hide album and artists columns
|
// hide album and artists columns
|
||||||
.songlist-item {
|
.songlist-item {
|
||||||
grid-template-columns: 1.5rem 2fr 2.5rem 2.5rem;
|
grid-template-columns: 1.5rem 2fr 2.5rem 2.5rem;
|
||||||
@@ -153,7 +166,7 @@ function handleScroll(e: Event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollable.isMedium {
|
.v-list.isMedium {
|
||||||
// hide album column
|
// hide album column
|
||||||
.songlist-item {
|
.songlist-item {
|
||||||
grid-template-columns: 1.5rem 1.5fr 1fr 2.5rem 2.5rem;
|
grid-template-columns: 1.5rem 1.5fr 1fr 2.5rem 2.5rem;
|
||||||
@@ -163,14 +176,5 @@ function handleScroll(e: Event) {
|
|||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.header-content {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user