remove div nesting on right sidebar

+ rewrite vTooltip to handle updates to tooltip text
This commit is contained in:
geoffrey45 2022-09-06 15:59:18 +03:00
parent 90514c8080
commit c9cd6a8067
8 changed files with 123 additions and 139 deletions

View File

@ -16,17 +16,17 @@
</div> </div>
<div class="songlist"> <div class="songlist">
<SongItem <SongItem
v-for="track in getTrackList()" v-for="(track, index) in getTrackList()"
:key="track.trackid" :key="track.trackid"
:track="track" :track="track"
:index="track.index" :index="track.index"
@updateQueue="updateQueue" @updateQueue="updateQueue(index)"
:isPlaying="queue.playing" :isPlaying="queue.playing"
:isCurrent="queue.currentid == track.trackid" :isCurrent="queue.currentid == track.trackid"
/> />
</div> </div>
<div class="copyright" v-if="copyright && copyright()"> <div class="copyright" v-if="copyright && copyright">
{{ copyright() }} {{ copyright }}
</div> </div>
</div> </div>
<div v-else-if="tracks.length === 0"> <div v-else-if="tracks.length === 0">
@ -38,19 +38,16 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from "vue"; import { ref } from "vue";
import { useRoute } from "vue-router";
import { useElementSize } from "@vueuse/core"; import { useElementSize } from "@vueuse/core";
import SongItem from "../shared/SongItem.vue"; import SongItem from "../shared/SongItem.vue";
import { Routes } from "@/composables/enums"; import { Routes } from "@/composables/enums";
import { Track } from "@/interfaces"; import { Track } from "@/interfaces";
import useAlbumStore from "@/stores/pages/album";
import useQStore from "@/stores/queue"; import useQStore from "@/stores/queue";
import { computed } from "@vue/reactivity"; import { computed } from "@vue/reactivity";
const queue = useQStore(); const queue = useQStore();
const album = useAlbumStore();
const props = defineProps<{ const props = defineProps<{
tracks: Track[]; tracks: Track[];
@ -59,14 +56,15 @@ const props = defineProps<{
playlistid?: string; playlistid?: string;
on_album_page?: boolean; on_album_page?: boolean;
disc?: string | number; disc?: string | number;
copyright?: (() => string) | null; copyright?: string | null;
}>(); }>();
const route = useRoute(); const emit = defineEmits<{
const routename = route.name as string; (e: "playFromPage", index: number): void;
}>();
const tracklistElem = ref<HTMLElement | null>(null); const tracklistElem = ref<HTMLElement | null>(null);
const { width, height } = useElementSize(tracklistElem); const { width } = useElementSize(tracklistElem);
const brk = { const brk = {
sm: 500, sm: 500,
@ -76,41 +74,8 @@ const brk = {
const isSmall = computed(() => width.value < brk.sm); const isSmall = computed(() => width.value < brk.sm);
const isMedium = computed(() => width.value > brk.sm && width.value < brk.md); const isMedium = computed(() => width.value > brk.sm && width.value < brk.md);
/** function updateQueue(index: number) {
* Plays a clicked track and updates the queue emit("playFromPage", index);
*
* @param track Track object
*/
function updateQueue(track: Track) {
const index = props.tracks.findIndex(
(t: Track) => t.trackid === track.trackid
);
switch (routename) {
case Routes.folder:
queue.playFromFolder(props.path || "", props.tracks);
queue.play(index);
break;
case Routes.album:
const tindex = album.tracks.findIndex((t) => t.trackid === track.trackid);
queue.playFromAlbum(
track.album || "",
track.albumartist || "",
track.albumhash || "",
album.tracks
);
queue.play(tindex);
break;
case Routes.playlist:
queue.playFromPlaylist(
props.pname || "",
props.playlistid || "",
props.tracks
);
queue.play(index);
break;
}
} }
/** /**

View File

@ -2,20 +2,18 @@
<div <div
class="r-sidebar rounded border" class="r-sidebar rounded border"
:style="{ :style="{
marginBottom: !settings.use_alt_np ? '-1rem' : '', marginBottom: !settings.show_alt_np ? '-1rem' : '',
}" }"
> >
<div class="grid"> <div class="r-content">
<div class="r-content"> <div class="r-dash" v-if="tabs.current === tabs.tabs.home">
<div class="r-dash" v-if="tabs.current === tabs.tabs.home"> <DashBoard />
<DashBoard /> </div>
</div> <div class="r-search" v-if="tabs.current === tabs.tabs.search">
<div class="r-search" v-if="tabs.current === tabs.tabs.search"> <Search />
<Search /> </div>
</div> <div class="r-queue" v-if="tabs.current === tabs.tabs.queue">
<div class="r-queue" v-if="tabs.current === tabs.tabs.queue"> <Queue />
<Queue />
</div>
</div> </div>
</div> </div>
</div> </div>
@ -35,28 +33,25 @@ const settings = useSettingsStore();
<style lang="scss"> <style lang="scss">
.r-sidebar { .r-sidebar {
width: 100%; width: 100%;
overflow: hidden;
.grid { .r-content {
display: flex; width: 100%;
position: relative;
height: 100%; height: 100%;
.r-content { .r-search {
grid-area: content; height: 100%;
}
.r-dash {
height: 100%;
}
.r-queue {
height: 100%;
overflow: hidden; overflow: hidden;
width: 100%; display: grid;
grid-template-rows: max-content 1fr;
.r-search {
height: 100%;
}
.r-dash {
height: 100%;
}
.r-queue {
height: 100%;
}
} }
} }
} }

View File

@ -1,20 +1,16 @@
<template> <template>
<div class="up-next"> <QueueActions />
<div class="r-grid"> <div class="scrollable-r">
<div class="scrollable-r rounded"> <div class="inner">
<QueueActions /> <TrackComponent
<div class="inner"> v-for="(t, index) in queue.tracklist"
<TrackComponent :key="index"
v-for="(t, index) in queue.tracklist" :track="t"
:key="index" :index="index + 1"
:track="t" :isPlaying="queue.playing"
:index="index + 1" :isHighlighted="false"
:isPlaying="queue.playing" :isCurrent="index === queue.currentindex"
:isHighlighted="false" />
:isCurrent="index === queue.currentindex"
/>
</div>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -58,32 +54,13 @@ onUpdated(() => {
</script> </script>
<style lang="scss"> <style lang="scss">
.up-next { .scrollable-r {
overflow: hidden;
height: 100%; height: 100%;
overflow: auto;
.heading { .inner {
position: relative; scrollbar-color: grey transparent;
margin: 0.5rem 0 1rem 0; margin: 1rem 0;
}
.r-grid {
position: relative;
height: 100%;
.scrollable-r {
height: 100%;
overflow: hidden;
display: grid;
grid-template-rows: max-content 1fr;
.inner {
overflow: scroll;
overflow-x: hidden;
scrollbar-color: grey transparent;
margin: 1rem 0;
}
}
} }
} }
</style> </style>

View File

@ -86,11 +86,11 @@ const props = defineProps<{
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
(e: "updateQueue", song: Track): void; (e: "updateQueue"): void;
}>(); }>();
function emitUpdate(track: Track) { function emitUpdate(track: Track) {
emit("updateQueue", track); emit("updateQueue");
} }
function showMenu(e: Event) { function showMenu(e: Event) {

View File

@ -11,13 +11,15 @@ function hideTooltip() {
tooltip.style.visibility = "hidden"; tooltip.style.visibility = "hidden";
} }
function handleHover(el: HTMLElement, text: string, isHovered: Ref<boolean>) { function handleHover(el: HTMLElement, text: string, handleOthers = true) {
let isHovered = false;
el.addEventListener("mouseover", () => { el.addEventListener("mouseover", () => {
isHovered.value = true; isHovered = true;
tooltip.innerText = text; tooltip.innerText = text;
setTimeout(() => { setTimeout(() => {
if (isHovered.value) { if (isHovered) {
tooltip.style.visibility = "visible"; tooltip.style.visibility = "visible";
createPopper(el, tooltip, { createPopper(el, tooltip, {
@ -37,28 +39,32 @@ function handleHover(el: HTMLElement, text: string, isHovered: Ref<boolean>) {
}); });
} }
}, 2000); }, 2000);
function handleHide() {
["mouseout", "click"].forEach((event) => {
el.addEventListener(event, () => {
isHovered = false;
hideTooltip();
});
});
}
handleOthers ? handleHide() : null;
}); });
} }
let isHovered = ref(false); let isHovered = ref(false);
export default { export default {
state: {},
mounted(el: HTMLElement, binding) { mounted(el: HTMLElement, binding) {
if (tooltip === undefined) { if (tooltip === undefined) {
tooltip = getTooltip(); tooltip = getTooltip();
} }
handleHover(el, binding.value, isHovered); handleHover(el, binding.value);
["mouseout", "click"].forEach((event) => {
el.addEventListener(event, () => {
isHovered.value = false;
hideTooltip();
});
});
}, },
updated(el, binding) { updated(el, binding) {
el.removeEventListener("mouseover", () => {}); el.removeEventListener("mouseover", () => {});
handleHover(el, binding.value, isHovered); handleHover(el, binding.value, false);
}, },
beforeUnmount(el: HTMLElement) { beforeUnmount(el: HTMLElement) {
hideTooltip(); hideTooltip();

View File

@ -12,8 +12,12 @@
loading="lazy" loading="lazy"
/> />
</div> </div>
<FolderList :folders="FStore.dirs" v-if="FStore.dirs.length" /> <FolderList :folders="folder.dirs" v-if="folder.dirs.length" />
<SongList :tracks="FStore.tracks" :path="FStore.path" /> <SongList
:tracks="folder.tracks"
:path="folder.path"
@playFromPage="playFromPage"
/>
</div> </div>
</div> </div>
</template> </template>
@ -26,12 +30,14 @@ import SongList from "@/components/FolderView/SongList.vue";
import FolderList from "@/components/FolderView/FolderList.vue"; import FolderList from "@/components/FolderView/FolderList.vue";
import FolderSvg from "@/assets/icons/folder.svg"; import FolderSvg from "@/assets/icons/folder.svg";
import useFStore from "../stores/pages/folder"; import useFolderStore from "@/stores/pages/folder";
import useLoaderStore from "../stores/loader"; import useQueueStore from "@/stores/queue";
import useLoaderStore from "@/stores/loader";
import { isSameRoute } from "@/composables/perks"; import { isSameRoute } from "@/composables/perks";
const loader = useLoaderStore(); const loader = useLoaderStore();
const FStore = useFStore(); const folder = useFolderStore();
const queue = useQueueStore();
const scrollable = ref<any>(null); const scrollable = ref<any>(null);
@ -40,11 +46,17 @@ function getFolderName(route: RouteLocationNormalized) {
return path.split("/").pop(); return path.split("/").pop();
} }
function playFromPage(index: number) {
queue.playFromFolder(folder.path, folder.tracks);
queue.play(index);
}
onBeforeRouteUpdate((to, from) => { onBeforeRouteUpdate((to, from) => {
if (isSameRoute(to, from)) return; if (isSameRoute(to, from)) return;
loader.startLoading(); loader.startLoading();
FStore.fetchAll(to.params.path as string) folder
.fetchAll(to.params.path as string)
.then(() => { .then(() => {
scrollable.value.scrollTop = 0; scrollable.value.scrollTop = 0;
@ -107,7 +119,7 @@ onBeforeRouteUpdate((to, from) => {
width: 100%; width: 100%;
object-fit: cover; object-fit: cover;
object-position: bottom right; object-position: bottom right;
transition: all .25s ease; transition: all 0.25s ease;
} }
} }

View File

@ -6,7 +6,8 @@
:tracks="disc" :tracks="disc"
:on_album_page="true" :on_album_page="true"
:disc="key" :disc="key"
:copyright="isLastDisc(key) ? () => copyright : null" :copyright="isLastDisc(key) ? copyright : null"
@playFromPage="playFromAlbumPage"
/> />
</div> </div>
</div> </div>
@ -15,6 +16,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { Track } from "@/interfaces"; import { Track } from "@/interfaces";
import SongList from "@/components/FolderView/SongList.vue"; import SongList from "@/components/FolderView/SongList.vue";
import useQueueStore from "@/stores/queue";
import useAlbumStore from "@/stores/pages/album";
const props = defineProps<{ const props = defineProps<{
discs: { discs: {
@ -23,11 +26,20 @@ const props = defineProps<{
copyright?: string; copyright?: string;
}>(); }>();
const queue = useQueueStore();
const album = useAlbumStore();
// check if the disc is the last disc // check if the disc is the last disc
const isLastDisc = (disc: string | number) => { const isLastDisc = (disc: string | number) => {
const discs = Object.keys(props.discs); const discs = Object.keys(props.discs);
return discs[discs.length - 1] === disc; return discs[discs.length - 1] === disc;
}; };
function playFromAlbumPage(index: number) {
const { title, artist, hash } = album.info;
queue.playFromAlbum(title, artist, hash, album.tracks);
queue.play(index);
}
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@ -1,7 +1,12 @@
<template> <template>
<div class="songlist rounded"> <div class="songlist rounded">
<div v-if="tracks.length"> <div v-if="tracks.length">
<SongList :tracks="tracks" :pname="name" :playlistid="playlistid"/> <SongList
:tracks="tracks"
:pname="name"
:playlistid="playlistid"
@playFromPage="playFromPlaylistPage"
/>
</div> </div>
<div v-else-if="tracks.length === 0 && count > 0"> <div v-else-if="tracks.length === 0 && count > 0">
<div class="no-results"> <div class="no-results">
@ -17,6 +22,9 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import useQueueStore from "@/stores/queue";
import usePlaylistStore from "@/stores/pages/playlist";
import SongList from "@/components/FolderView/SongList.vue"; import SongList from "@/components/FolderView/SongList.vue";
import { Track } from "@/interfaces"; import { Track } from "@/interfaces";
@ -26,4 +34,13 @@ defineProps<{
name: string; name: string;
playlistid: string; playlistid: string;
}>(); }>();
const queue = useQueueStore();
const playlist = usePlaylistStore();
function playFromPlaylistPage(index: number) {
const { name, playlistid } = playlist.info;
queue.playFromPlaylist(name, playlistid, playlist.tracks);
queue.play(index);
}
</script> </script>