mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-03 20:13:02 +00:00
extract virtual scroller page into a layout
This commit is contained in:
committed by
Mungai Njoroge
parent
76a77823c8
commit
703ea71514
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="header-input-wrapper rounded-sm" :class="{ showInput: clicked }">
|
||||
<div class="search-svg" @click="clicked = !clicked">
|
||||
<div class="search-svg" @click="handleFocus">
|
||||
<SearchSvg />
|
||||
</div>
|
||||
<input
|
||||
@@ -8,8 +8,9 @@
|
||||
class="header-input rounded-sm pad-sm"
|
||||
:class="{ showInput: clicked }"
|
||||
placeholder="Search here"
|
||||
v-model.trim="source"
|
||||
v-model.trim="query"
|
||||
id="page-search"
|
||||
ref="inputRef"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -25,26 +26,44 @@ import useFolderStore from "@/stores/pages/folder";
|
||||
import { Routes } from "@/composables/enums";
|
||||
import SearchSvg from "@/assets/icons/search.svg";
|
||||
|
||||
const clicked = ref(false);
|
||||
const clicked = ref(true);
|
||||
const [playlist, album, folder] = [
|
||||
usePStore(),
|
||||
useAlbumStore(),
|
||||
useFolderStore(),
|
||||
];
|
||||
|
||||
const { query: playlistQuery } = storeToRefs(usePStore());
|
||||
const { query: folderQuery } = storeToRefs(useFolderStore());
|
||||
const { query: albumQuery } = storeToRefs(useAlbumStore());
|
||||
const { query: playlistQuery } = storeToRefs(playlist);
|
||||
const { query: folderQuery } = storeToRefs(folder);
|
||||
const { query: albumQuery } = storeToRefs(album);
|
||||
|
||||
const props = defineProps<{
|
||||
page: Routes | string;
|
||||
}>();
|
||||
const inputRef = ref<HTMLElement>();
|
||||
|
||||
function handleFocus() {
|
||||
// if input is not focused, focus it
|
||||
// if input is focused, blur it
|
||||
clicked.value = !clicked.value;
|
||||
if (clicked.value) {
|
||||
inputRef.value?.focus();
|
||||
} else {
|
||||
inputRef.value?.blur();
|
||||
resetQuery();
|
||||
}
|
||||
}
|
||||
|
||||
function getRef() {
|
||||
switch (props.page) {
|
||||
case Routes.playlist:
|
||||
return playlistQuery;
|
||||
return [playlistQuery, playlist.resetQuery];
|
||||
|
||||
case Routes.folder:
|
||||
return folderQuery;
|
||||
return [folderQuery, folder.resetQuery];
|
||||
|
||||
case Routes.album:
|
||||
return albumQuery;
|
||||
return [albumQuery, album.resetQuery];
|
||||
|
||||
default:
|
||||
return null;
|
||||
@@ -52,6 +71,13 @@ function getRef() {
|
||||
}
|
||||
|
||||
const source = getRef();
|
||||
let query: any;
|
||||
let resetQuery: any;
|
||||
|
||||
if (source) {
|
||||
query = source[0];
|
||||
resetQuery = source[1];
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@@ -66,7 +92,6 @@ const source = getRef();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.header-input {
|
||||
background-color: $gray3;
|
||||
outline: none;
|
||||
@@ -77,32 +102,28 @@ const source = getRef();
|
||||
transition: all 0.25s $overshoot;
|
||||
opacity: 0;
|
||||
transform: translateY(-1rem);
|
||||
|
||||
|
||||
&:focus {
|
||||
outline: solid;
|
||||
}
|
||||
|
||||
|
||||
&.showInput {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
transition-delay: .1s;
|
||||
transition-delay: 0.1s;
|
||||
}
|
||||
}
|
||||
|
||||
.search-svg {
|
||||
// outline: solid;
|
||||
margin-top: $smaller;
|
||||
cursor: pointer;
|
||||
// padding-left: ;
|
||||
width: 2.25rem;
|
||||
height: 2rem;
|
||||
// aspect-ratio: 1;
|
||||
z-index: 100;
|
||||
|
||||
svg {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
// outline: solid;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div class="header-list-layout">
|
||||
<div
|
||||
v-bind="containerProps"
|
||||
style="height: calc(100vh - 4.25rem)"
|
||||
:style="{ paddingTop: headerHeight - 64 + 16 + 'px' }"
|
||||
@scroll="handleScroll"
|
||||
>
|
||||
<div v-bind="wrapperProps">
|
||||
<div class="header rounded pad-sm" style="height: 64px">
|
||||
<div
|
||||
ref="header"
|
||||
:style="{ top: -headerHeight + 64 - 16 + 'px' }"
|
||||
class="header-content"
|
||||
>
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
</div>
|
||||
<SongItem
|
||||
style="height: 60px"
|
||||
v-for="(t, index) in tracks"
|
||||
:key="t.data.trackid"
|
||||
:track="t.data"
|
||||
:index="0"
|
||||
:isPlaying="queue.playing"
|
||||
:isCurrent="queue.currentid == t.data.trackid"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useElementSize, useVirtualList } from "@vueuse/core";
|
||||
import { computed, ref } from "vue";
|
||||
|
||||
import { Track } from "@/interfaces";
|
||||
import useQStore from "@/stores/queue";
|
||||
import SongItem from "@/components/shared/SongItem.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
tracks: Track[];
|
||||
}>();
|
||||
|
||||
const queue = useQStore();
|
||||
const header = ref<HTMLElement>();
|
||||
const source = computed(() => props.tracks);
|
||||
const { height: headerHeight } = useElementSize(header);
|
||||
|
||||
const {
|
||||
list: tracks,
|
||||
containerProps,
|
||||
wrapperProps,
|
||||
} = useVirtualList(source, {
|
||||
itemHeight: 60,
|
||||
overscan: 15,
|
||||
});
|
||||
|
||||
function handleScroll(e: Event) {
|
||||
const scrollTop = (e.target as HTMLElement).scrollTop;
|
||||
|
||||
if (scrollTop > headerHeight.value) {
|
||||
header.value ? (header.value.style.opacity = "0") : null;
|
||||
} else {
|
||||
header.value ? (header.value.style.opacity = "1") : null;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.header-list-layout {
|
||||
.header {
|
||||
position: relative;
|
||||
|
||||
.header-content {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+32
-109
@@ -1,133 +1,56 @@
|
||||
<template>
|
||||
<div class="queue-view">
|
||||
<div
|
||||
v-bind="containerProps"
|
||||
style="height: calc(100vh - 4.25rem)"
|
||||
:style="{ paddingTop: height - 64 + 16 + 'px' }"
|
||||
@scroll="handleScroll"
|
||||
>
|
||||
<div v-bind="wrapperProps">
|
||||
<div class="header rounded pad-sm" style="height: 64px">
|
||||
<div ref="header" :style="{ top: -height + 64 - 16 + 'px' }">
|
||||
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Culpa
|
||||
facere recusandae dolorem sunt blanditiis natus delectus alias
|
||||
soluta facilis? Asperiores praesentium repellat magni rerum? Ratione
|
||||
reiciendis ut magni laborum itaque! Lorem ipsum dolor sit amet
|
||||
consectetur adipisicing elit. Consequatur, ut. Iure ex nemo sunt.
|
||||
Nostrum, corporis! Asperiores omnis ducimus eum culpa quae nesciunt
|
||||
eius, soluta molestiae delectus quasi labore ipsum! Lorem ipsum
|
||||
dolor sit amet consectetur adipisicing elit. Alias et ducimus
|
||||
consequuntur doloremque voluptate laboriosam, obcaecati eligendi!
|
||||
Mollitia cum, sint fuga facere sit minus modi quaerat quia nisi,
|
||||
earum ut! Lorem ipsum dolor sit amet consectetur adipisicing elit.
|
||||
Alias aliquam, sit laboriosam quidem minus ipsam consequatur
|
||||
deleniti architecto accusamus distinctio earum in suscipit eveniet
|
||||
temporibus obcaecati voluptas odit tenetur adipisci?Lorem ipsum
|
||||
dolor sit amet consectetur, adipisicing elit. Culpa facere
|
||||
recusandae dolorem sunt blanditiis natus delectus alias soluta
|
||||
facilis? Asperiores praesentium repellat magni rerum? Ratione
|
||||
reiciendis ut magni laborum itaque! Lorem ipsum dolor sit amet
|
||||
consectetur adipisicing elit. Consequatur, ut. Iure ex nemo sunt.
|
||||
Nostrum, corporis! Asperiores omnis ducimus eum culpa quae nesciunt
|
||||
eius, soluta molestiae delectus quasi labore ipsum! Lorem ipsum
|
||||
dolor sit amet consectetur adipisicing elit. Alias et ducimus
|
||||
consequuntur doloremque voluptate laboriosam, obcaecati eligendi!
|
||||
Mollitia cum, sint fuga facere sit minus modi quaerat quia nisi,
|
||||
earum ut! Lorem ipsum dolor sit amet consectetur adipisicing elit.
|
||||
Alias aliquam, sit laboriosam quidem minus ipsam consequatur
|
||||
deleniti architecto accusamus distinctio earum in suscipit eveniet
|
||||
temporibus obcaecati voluptas odit tenetur adipisci?Lorem ipsum
|
||||
dolor sit amet consectetur, adipisicing elit. Culpa facere
|
||||
recusandae dolorem sunt blanditiis natus delectus alias soluta
|
||||
facilis? Asperiores praesentium repellat magni rerum? Ratione
|
||||
reiciendis ut magni laborum itaque! Lorem ipsum dolor sit amet
|
||||
consectetur adipisicing elit. Consequatur, ut. Iure ex nemo sunt.
|
||||
Nostrum, corporis! Asperiores omnis ducimus eum culpa quae nesciunt
|
||||
eius, soluta molestiae delectus quasi labore ipsum! Lorem ipsum
|
||||
dolor sit amet consectetur adipisicing elit. Alias et ducimus
|
||||
consequuntur doloremque voluptate laboriosam, obcaecati eligendi!
|
||||
Mollitia cum, sint fuga facere sit minus modi quaerat quia nisi,
|
||||
earum ut! Lorem ipsum dolor sit amet consectetur adipisicing elit.
|
||||
Alias aliquam, sit laboriosam quidem minus ipsam consequatur
|
||||
deleniti architecto accusamus distinctio earum in suscipit eveniet
|
||||
temporibus obcaecati voluptas odit tenetur adipisci?
|
||||
</div>
|
||||
<Layout :tracks="queue.tracklist">
|
||||
<template #header>
|
||||
<div>
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab doloremque
|
||||
doloribus nostrum voluptas? Nobis ipsa cupiditate perspiciatis earum
|
||||
explicabo hic accusamus assumenda commodi, veritatis, nostrum nisi
|
||||
quod sequi exercitationem ducimus.Lorem ipsum dolor sit amet
|
||||
consectetur, adipisicing elit. Culpa facere recusandae dolorem sunt
|
||||
blanditiis natus delectus alias soluta facilis? Asperiores praesentium
|
||||
repellat magni rerum? Ratione reiciendis ut magni laborum itaque!
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur,
|
||||
ut. Iure ex nemo sunt. Nostrum, corporis! Asperiores omnis ducimus eum
|
||||
culpa quae nesciunt eius, soluta molestiae delectus quasi labore
|
||||
ex
|
||||
nemo sunt. Nostrum, corporis! Asperiores omnis ducimus eum culpa quae
|
||||
nesciunt eius, soluta molestiae delectus quasi labore ipsum! Lorem
|
||||
ipsum dolor sit amet consectetur adipisicing elit. Alias et ducimus
|
||||
consequuntur doloremque voluptate laboriosam, obcaecati eligendi!
|
||||
Mollitia cum, sint fuga facere sit minus modi quaerat quia nisi, earum
|
||||
ut! Lorem ipsum dolor sit amet consectetur adipisicing elit. Alias
|
||||
aliquam, sit laboriosam quidem minus ipsam consequatur deleniti
|
||||
architecto accusamus distinctio earum in suscipit eveniet temporibus
|
||||
obcaecati voluptas odit tenetur adipisci?
|
||||
</div>
|
||||
<SongItem
|
||||
style="height: 60px"
|
||||
v-for="(t, index) in tracks"
|
||||
:key="t.data.trackid"
|
||||
:track="t.data"
|
||||
:index="0"
|
||||
:isPlaying="queue.playing"
|
||||
:isCurrent="queue.currentid == t.data.trackid"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Layout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from "vue";
|
||||
import { computed, onUpdated, ref } from "vue";
|
||||
|
||||
import useQStore from "@/stores/queue";
|
||||
import { focusElem } from "@/utils";
|
||||
import SongList from "@/components/FolderView/SongList.vue";
|
||||
import { onMounted } from "vue";
|
||||
import SongItem from "@/components/shared/SongItem.vue";
|
||||
import { useVirtualList } from "@vueuse/core";
|
||||
import Layout from "@/layouts/HeaderAndVList.vue";
|
||||
|
||||
const queue = useQStore();
|
||||
const height = ref(330);
|
||||
|
||||
function playFromQueuePage(index: number) {
|
||||
queue.play(index);
|
||||
}
|
||||
|
||||
const header = ref<HTMLElement>();
|
||||
onMounted(() => {
|
||||
height.value = header.value.offsetHeight;
|
||||
console.log(height.value);
|
||||
// height.value = 370;
|
||||
});
|
||||
const source = computed(() => queue.tracklist);
|
||||
function handleScroll(e: Event) {
|
||||
// check if header is visible
|
||||
const headerHeight = header.value?.offsetHeight || 0;
|
||||
const scrollTop = (e.target as HTMLElement).scrollTop;
|
||||
|
||||
if (scrollTop > headerHeight) {
|
||||
// console.log("header is not visible");
|
||||
header.value.style.opacity = "0";
|
||||
} else {
|
||||
// console.log("header is visible");
|
||||
header.value.style.opacity = "1";
|
||||
}
|
||||
}
|
||||
|
||||
const {
|
||||
list: tracks,
|
||||
containerProps,
|
||||
wrapperProps,
|
||||
scrollTo,
|
||||
} = useVirtualList(source, {
|
||||
itemHeight: 60,
|
||||
overscan: 15,
|
||||
});
|
||||
// function playFromQueuePage(index: number) {
|
||||
// queue.play(index);
|
||||
// }
|
||||
// import SongList from "@/components/FolderView/SongList.vue";
|
||||
// import { focusElem } from "@/utils";
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.queue-view {
|
||||
.header {
|
||||
// background-color: $gray3;
|
||||
// margin-bottom: 2rem;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
|
||||
div {
|
||||
position: absolute;
|
||||
top: -25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user