fix removing tracks from queue

This commit is contained in:
geoffrey45 2022-10-08 19:32:29 +03:00 committed by Mungai Njoroge
parent bb66ba70b3
commit a496d68439
9 changed files with 71 additions and 47 deletions

View File

@ -3,7 +3,6 @@
<div class="centered"> <div class="centered">
<div class="inner"> <div class="inner">
<div class="with-icons rounded-sm border"> <div class="with-icons rounded-sm border">
<!-- <button><PlusSvg /></button> -->
<RouterLink <RouterLink
title="go to album" title="go to album"
:to="{ :to="{
@ -26,7 +25,7 @@
<div class="with-title"> <div class="with-title">
<div class="time time-current"> <div class="time time-current">
<span> <span>
{{ formatSeconds(queue.duration?.current) }} {{ formatSeconds(queue.duration.current || 0) }}
</span> </span>
</div> </div>
<div class="tags"> <div class="tags">
@ -58,28 +57,26 @@
<HotKeys /> <HotKeys />
</div> </div>
</div> </div>
<div class=""></div> <div></div>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { paths } from "@/config"; import { paths } from "@/config";
import useQStore from "@/stores/queue";
import { formatSeconds } from "@/utils"; import { formatSeconds } from "@/utils";
import { Routes } from "@/composables/enums"; import { Routes } from "@/composables/enums";
import useSettingsStore from "@/stores/settings";
import useQStore from "@/stores/queue";
import ArtistName from "@/components/shared/ArtistName.vue";
import HotKeys from "@/components/LeftSidebar/NP/HotKeys.vue"; import HotKeys from "@/components/LeftSidebar/NP/HotKeys.vue";
import Progress from "@/components/LeftSidebar/NP/Progress.vue"; import Progress from "@/components/LeftSidebar/NP/Progress.vue";
import ArtistName from "@/components/shared/ArtistName.vue";
import HeartSvg from "@/assets/icons/heart.svg"; import HeartSvg from "@/assets/icons/heart.svg";
// import PlusSvg from "@/assets/icons/plus.svg"; // import PlusSvg from "@/assets/icons/plus.svg";
const queue = useQStore(); const queue = useQStore();
const settings = useSettingsStore();
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@ -16,7 +16,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import useQStore from "../../../stores/queue"; import useQStore from "@/stores/queue";
const q = useQStore(); const q = useQStore();

View File

@ -13,10 +13,12 @@
key-field="id" key-field="id"
v-slot="{ item, index }" v-slot="{ item, index }"
> >
<TrackItem <TrackItem
:index="index"
:track="item.track" :track="item.track"
:isCurrentPlaying="index === queue.currentindex && queue.playing"
:isCurrent="index === queue.currentindex" :isCurrent="index === queue.currentindex"
:isCurrentPlaying="index === queue.currentindex && queue.playing"
:isQueueTrack="true" :isQueueTrack="true"
@playThis="playFromQueue(index)" @playThis="playFromQueue(index)"
/> />

View File

@ -11,10 +11,7 @@
@contextmenu.prevent="showMenu" @contextmenu.prevent="showMenu"
> >
<div class="album-art"> <div class="album-art">
<img <img :src="paths.images.thumb.small + track.image" class="rounded-sm" />
:src="paths.images.thumb.small + track.image"
class="rounded-sm"
/>
<div <div
class="now-playing-track-indicator image" class="now-playing-track-indicator image"
v-if="isCurrent" v-if="isCurrent"
@ -39,7 +36,9 @@
@click.stop="queue.removeFromQueue(index)" @click.stop="queue.removeFromQueue(index)"
v-if="isQueueTrack" v-if="isQueueTrack"
> >
<DelSvg /> <div title="remove from queue" >
<DelSvg/>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -47,7 +46,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from "vue"; import { ref } from "vue";
import DelSvg from "@/assets/icons/delete.svg"; import DelSvg from "@/assets/icons/plus.svg";
import { showTrackContextMenu as showContext } from "@/composables/context"; import { showTrackContextMenu as showContext } from "@/composables/context";
import { paths } from "@/config"; import { paths } from "@/config";
import { Track } from "@/interfaces"; import { Track } from "@/interfaces";
@ -103,7 +102,7 @@ const playThis = (track: Track) => {
.remove-track { .remove-track {
opacity: 0; opacity: 0;
transition: all 0.25s ease; transition: all 0.25s ease;
transform: scale(0.75) translateY(1rem); transform: scale(0.75) translateY(1rem) rotate(45deg);
&:hover { &:hover {
opacity: 1 !important; opacity: 1 !important;
@ -113,7 +112,7 @@ const playThis = (track: Track) => {
&:hover { &:hover {
.remove-track { .remove-track {
opacity: 0.5; opacity: 0.5;
transform: scale(1) translateY(0); transform: scale(1) translateY(0) rotate(45deg);
} }
background-color: $gray5; background-color: $gray5;

View File

@ -1,3 +1,4 @@
import { ref } from "@vue/reactivity";
import { paths } from "@/config"; import { paths } from "@/config";
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { Ref } from "vue"; import { Ref } from "vue";
@ -11,7 +12,7 @@ import {
fromFolder, fromFolder,
fromPlaylist, fromPlaylist,
fromSearch, fromSearch,
Track Track,
} from "../interfaces"; } from "../interfaces";
function shuffle(tracks: Track[]) { function shuffle(tracks: Track[]) {
@ -26,6 +27,7 @@ function shuffle(tracks: Track[]) {
type From = fromFolder | fromAlbum | fromPlaylist | fromSearch; type From = fromFolder | fromAlbum | fromPlaylist | fromSearch;
let audio = new Audio(); let audio = new Audio();
audio.autoplay = false;
export default defineStore("Queue", { export default defineStore("Queue", {
state: () => ({ state: () => ({
@ -34,7 +36,6 @@ export default defineStore("Queue", {
full: 0, full: 0,
}, },
currentindex: 0, currentindex: 0,
currentid: <string | null>"",
playing: false, playing: false,
from: {} as From, from: {} as From,
tracklist: [] as Track[], tracklist: [] as Track[],
@ -51,13 +52,12 @@ export default defineStore("Queue", {
} }
const track = this.tracklist[index]; const track = this.tracklist[index];
this.currentid = track.trackid; const uri = `${paths.api.files}/${track.trackid}-${track.hash}`;
const uri = `${paths.api.files}/${track.hash}`;
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
audio.autoplay = true; audio.autoplay = true;
audio.src = uri; audio.src = uri;
audio.oncanplaythrough = resolve; audio.oncanplay = resolve;
audio.onerror = reject; audio.onerror = reject;
}) })
.then(() => { .then(() => {
@ -81,7 +81,6 @@ export default defineStore("Queue", {
"Can't play: " + track.title, "Can't play: " + track.title,
NotifType.Error NotifType.Error
); );
if (this.currentindex !== this.tracklist.length - 1) { if (this.currentindex !== this.tracklist.length - 1) {
setTimeout(() => { setTimeout(() => {
if (!this.playing) return; if (!this.playing) return;
@ -90,22 +89,31 @@ export default defineStore("Queue", {
} }
}); });
}, },
stop() {
this.playing = false;
audio.src = "";
// audio.pause();
},
playPause() { playPause() {
if (audio.src === "") { if (audio.src === "") {
this.play(this.currentindex); this.play(this.currentindex);
return;
} }
if (audio.paused) { if (audio.paused) {
audio.currentTime === 0 ? this.play(this.currentindex) : null;
audio.play(); audio.play();
this.playing = true;
} else { } else {
audio.pause(); audio.pause();
this.playing = false;
} }
if (this.playing) { // if (this.playing) {
this.playing = false; // this.playing = false;
} else { // } else {
this.playing = true; // this.playing = true;
} // }
}, },
playNext() { playNext() {
this.play(this.nextindex); this.play(this.nextindex);
@ -208,7 +216,6 @@ export default defineStore("Queue", {
}, },
clearQueue() { clearQueue() {
this.tracklist = [] as Track[]; this.tracklist = [] as Track[];
this.currentid = "";
this.currentindex = 0; this.currentindex = 0;
this.from = <From>{}; this.from = <From>{};
}, },
@ -220,7 +227,7 @@ export default defineStore("Queue", {
} }
const current = this.currenttrack; const current = this.currenttrack;
const current_hash = current.hash; const current_hash = current?.hash;
this.tracklist = shuffle(this.tracklist); this.tracklist = shuffle(this.tracklist);
// find current track after shuffle // find current track after shuffle
@ -233,7 +240,7 @@ export default defineStore("Queue", {
// remove current track from queue // remove current track from queue
this.tracklist.splice(newindex, 1); this.tracklist.splice(newindex, 1);
// insert current track at beginning of queue // insert current track at beginning of queue
this.tracklist.unshift(current); this.tracklist.unshift(current as Track);
this.currentindex = 0; this.currentindex = 0;
return; return;
} }
@ -242,7 +249,23 @@ export default defineStore("Queue", {
this.play(this.currentindex); this.play(this.currentindex);
}, },
removeFromQueue(index: number = 0) { removeFromQueue(index: number = 0) {
this.tracklist.splice(index, 1); if (index === this.currentindex) {
const is_last = index === this.tracklist.length - 1;
const was_playing = this.playing;
audio.src = "";
this.tracklist.splice(index, 1);
if (is_last) {
this.currentindex = 0;
}
if (was_playing) {
this.playPause();
}
} else {
this.tracklist.splice(index, 1);
}
}, },
setScrollFunction( setScrollFunction(
cb: (index: number) => void, cb: (index: number) => void,
@ -253,23 +276,26 @@ export default defineStore("Queue", {
}, },
}, },
getters: { getters: {
next(): Track { next(): Track | undefined {
if (this.currentindex == this.tracklist.length - 1) { if (this.currentindex == this.tracklist.length - 1) {
return this.tracklist[0]; return this.tracklist[0];
} else { } else {
return this.tracklist[this.currentindex + 1]; return this.tracklist[this.currentindex + 1];
} }
}, },
prev(): Track { prev(): Track | undefined {
if (this.currentindex === 0) { if (this.currentindex === 0) {
return this.tracklist[this.tracklist.length - 1]; return this.tracklist[this.tracklist.length - 1];
} else { } else {
return this.tracklist[this.currentindex - 1]; return this.tracklist[this.currentindex - 1];
} }
}, },
currenttrack(): Track { currenttrack(): Track | undefined {
return this.tracklist[this.currentindex]; return this.tracklist[this.currentindex];
}, },
currentid(): string {
return this.currenttrack?.trackid || "";
},
previndex(): number { previndex(): number {
return this.currentindex === 0 return this.currentindex === 0
? this.tracklist.length - 1 ? this.tracklist.length - 1

View File

@ -5,8 +5,8 @@ export default function createTrackProps(track: Track) {
return { return {
track, track,
index: track.index + 1, index: track.index + 1,
isCurrent: queue().currenttrack?.hash === track.hash, isCurrent: queue().currentid === track.trackid,
isCurrentPlaying: isCurrentPlaying:
queue().currenttrack?.hash === track.hash && queue().playing, queue().currentid === track.trackid && queue().playing,
}; };
} }

View File

@ -34,13 +34,13 @@ import { computed } from "@vue/reactivity";
import { onBeforeRouteLeave, onBeforeRouteUpdate } from "vue-router"; import { onBeforeRouteLeave, onBeforeRouteUpdate } from "vue-router";
import { Track } from "@/interfaces"; import { Track } from "@/interfaces";
import useQueueStore from "@/stores/queue"; import { isMedium, isSmall } from "@/stores/content-width";
import useLoaderStore from "@/stores/loader"; import useLoaderStore from "@/stores/loader";
import useFolderStore from "@/stores/pages/folder"; import useFolderStore from "@/stores/pages/folder";
import { isSmall, isMedium } from "@/stores/content-width"; import useQueueStore from "@/stores/queue";
import SongItem from "@/components/shared/SongItem.vue";
import FolderList from "@/components/FolderView/FolderList.vue"; import FolderList from "@/components/FolderView/FolderList.vue";
import SongItem from "@/components/shared/SongItem.vue";
const loader = useLoaderStore(); const loader = useLoaderStore();
const folder = useFolderStore(); const folder = useFolderStore();
@ -62,9 +62,9 @@ class songItem {
this.props = { this.props = {
track, track,
index: track.index + 1, index: track.index + 1,
isCurrent: queue.currenttrack?.hash === track.hash, isCurrent: queue.currentid === track.trackid,
isCurrentPlaying: isCurrentPlaying:
queue.currenttrack?.hash === track.hash && queue.playing, queue.currentid === track.trackid && queue.playing,
}; };
} }
} }

View File

@ -36,7 +36,7 @@ const queue = useQueueStore();
const playlist = usePlaylistStore(); const playlist = usePlaylistStore();
interface ScrollerItem { interface ScrollerItem {
id: string; id: string | number;
component: typeof Header | typeof SongItem; component: typeof Header | typeof SongItem;
props: Record<string, unknown>; props: Record<string, unknown>;
size: number; size: number;
@ -56,7 +56,7 @@ const scrollerItems = computed(() => {
header, header,
...playlist.tracks.map((track) => { ...playlist.tracks.map((track) => {
return { return {
id: track.trackid, id: Math.random(),
component: SongItem, component: SongItem,
props: { props: {
track: track, track: track,

View File

@ -16,9 +16,9 @@
<SongItem <SongItem
:track="item.track" :track="item.track"
:index="index + 1" :index="index + 1"
:isCurrent="queue.currenttrack?.hash === item.track.hash" :isCurrent="queue.currentid === item.trackid"
:isCurrentPlaying=" :isCurrentPlaying="
queue.currenttrack?.hash === item.track.hash && queue.playing queue.currentid === item.trackid && queue.playing
" "
@playThis="playFromQueue(index)" @playThis="playFromQueue(index)"
/> />