From 22da349948904b58f82bd3e62d5f67a17b53108c Mon Sep 17 00:00:00 2001 From: geoffrey45 Date: Thu, 12 Jan 2023 16:43:04 +0300 Subject: [PATCH] add repeat functionality + add "play next" context menu svg icon + handle focusing current track in sidebar queue on component mounted --- src/assets/icons/add-to-queue.svg | 4 ++ src/assets/icons/play-next.svg | 4 ++ src/assets/icons/repeat-one.svg | 4 ++ src/assets/icons/repeat.svg | 2 +- src/components/BottomBar.vue | 38 ++++++++++++++-- src/components/Contextmenu/ContextItem.vue | 7 ++- src/components/RightSideBar/Queue.vue | 1 + src/contexts/track_context.ts | 2 +- src/stores/queue.ts | 53 ++++++++++++++++------ src/stores/settings/index.ts | 22 +++++++++ 10 files changed, 117 insertions(+), 20 deletions(-) create mode 100644 src/assets/icons/add-to-queue.svg create mode 100644 src/assets/icons/play-next.svg create mode 100644 src/assets/icons/repeat-one.svg diff --git a/src/assets/icons/add-to-queue.svg b/src/assets/icons/add-to-queue.svg new file mode 100644 index 0000000..20ca7dd --- /dev/null +++ b/src/assets/icons/add-to-queue.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icons/play-next.svg b/src/assets/icons/play-next.svg new file mode 100644 index 0000000..99c1387 --- /dev/null +++ b/src/assets/icons/play-next.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icons/repeat-one.svg b/src/assets/icons/repeat-one.svg new file mode 100644 index 0000000..23708f1 --- /dev/null +++ b/src/assets/icons/repeat-one.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icons/repeat.svg b/src/assets/icons/repeat.svg index 94a6be7..6f08054 100644 --- a/src/assets/icons/repeat.svg +++ b/src/assets/icons/repeat.svg @@ -1,3 +1,3 @@ - + diff --git a/src/components/BottomBar.vue b/src/components/BottomBar.vue index c694c5f..0654130 100644 --- a/src/components/BottomBar.vue +++ b/src/components/BottomBar.vue @@ -25,6 +25,21 @@ @handleFav="handleFav" /> +
@@ -72,17 +87,22 @@ import { Routes } from "@/router/routes"; import { paths } from "@/config"; import { formatSeconds } from "@/utils"; +import { favType } from "@/composables/enums"; +import favoriteHandler from "@/composables/favoriteHandler"; + +import useQStore from "@/stores/queue"; +import useSettingsStore from "@/stores/settings"; import HotKeys from "@/components/LeftSidebar/NP/HotKeys.vue"; import Progress from "@/components/LeftSidebar/NP/Progress.vue"; import ArtistName from "@/components/shared/ArtistName.vue"; -import useQStore from "@/stores/queue"; -import HeartSvg from "./shared/HeartSvg.vue"; // import PlusSvg from "@/assets/icons/plus.svg"; -import favoriteHandler from "@/composables/favoriteHandler"; -import { favType } from "@/composables/enums"; +import HeartSvg from "./shared/HeartSvg.vue"; +import RepeatAllSvg from "@/assets/icons/repeat.svg"; +import RepeatOneSvg from "@/assets/icons/repeat-one.svg"; const queue = useQStore(); +const settings = useSettingsStore(); function handleFav() { favoriteHandler( @@ -147,6 +167,16 @@ function handleFav() { padding: 0; border: none; } + + button.repeat { + svg { + transform: scale(0.75); + } + } + + button.repeat.repeat-disabled { + opacity: 0.25; + } } img { diff --git a/src/components/Contextmenu/ContextItem.vue b/src/components/Contextmenu/ContextItem.vue index c213777..b356d20 100644 --- a/src/components/Contextmenu/ContextItem.vue +++ b/src/components/Contextmenu/ContextItem.vue @@ -189,10 +189,15 @@ function runChildAction(action: () => void) { background-image: url("../../assets/icons/plus.svg"); } - .add_to_queue { + .play_next { background-image: url("../../assets/icons/add_to_queue.svg"); } + .add_to_queue { + background-image: url("../../assets/icons/add-to-queue.svg"); + transform: scale(0.8); // reason: icon is not from same source as other + } + .heart { background-image: url("../../assets/icons/heart.svg"); } diff --git a/src/components/RightSideBar/Queue.vue b/src/components/RightSideBar/Queue.vue index 9a20056..d00df8c 100644 --- a/src/components/RightSideBar/Queue.vue +++ b/src/components/RightSideBar/Queue.vue @@ -61,6 +61,7 @@ function scrollToCurrent() { onMounted(() => { queue.setScrollFunction(scrollToCurrent, mouseover); + queue.focusCurrentInSidebar(); }); onBeforeUnmount(() => { diff --git a/src/contexts/track_context.ts b/src/contexts/track_context.ts index 9dea41c..a2287da 100644 --- a/src/contexts/track_context.ts +++ b/src/contexts/track_context.ts @@ -92,7 +92,7 @@ export default async ( action: () => { QueueStore().playTrackNext(track); }, - icon: "add_to_queue", + icon: "play_next", }; const go_to_folder: Option = { diff --git a/src/stores/queue.ts b/src/stores/queue.ts index 3743dd5..645f82c 100644 --- a/src/stores/queue.ts +++ b/src/stores/queue.ts @@ -6,6 +6,7 @@ import { NotifType, useNotifStore } from "./notification"; import { favType, FromOptions } from "../composables/enums"; import updateMediaNotif from "../composables/mediaNotification"; import { isFavorite } from "@/composables/fetch/favorite"; +import useSettingsStore from "./settings"; import { fromAlbum, @@ -51,13 +52,17 @@ export default defineStore("Queue", { mousover: null, }), actions: { + focusCurrentInSidebar(timeout = 500) { + if (!this.mousover) { + setTimeout(() => { + this.queueScrollFunction(this.currentindex - 1); + }, timeout); + } + }, play(index: number = 0) { if (this.tracklist.length === 0) return; this.currentindex = index; - - if (!this.mousover) { - this.queueScrollFunction(this.currentindex - 1); - } + this.focusCurrentInSidebar(); const track = this.tracklist[index]; const uri = `${paths.api.files}/${track.trackhash}`; @@ -79,7 +84,7 @@ export default defineStore("Queue", { }; audio.onended = () => { - this.playNext(); + this.autoPlayNext(); }; }); }) @@ -92,15 +97,14 @@ export default defineStore("Queue", { if (this.currentindex !== this.tracklist.length - 1) { setTimeout(() => { if (!this.playing) return; - this.playNext(); + this.autoPlayNext(); }, 5000); } }); }, stop() { - this.playing = false; audio.src = ""; - // audio.pause(); + this.playing = false; }, playPause() { if (audio.src === "") { @@ -116,12 +120,28 @@ export default defineStore("Queue", { audio.pause(); this.playing = false; } + }, + autoPlayNext() { + const settings = useSettingsStore(); + const is_last = this.currentindex === this.tracklist.length - 1; - // if (this.playing) { - // this.playing = false; - // } else { - // this.playing = true; - // } + if (settings.repeat_one) { + this.play(this.currentindex); + return; + } + + if (settings.repeat_all) { + this.play(is_last ? 0 : this.currentindex + 1); + return; + } + + const resetQueue = () => { + this.currentindex = 0; + this.playing = false; + this.focusCurrentInSidebar(); + }; + + !is_last ? this.play(this.currentindex + 1) : resetQueue(); }, playNext() { this.play(this.nextindex); @@ -152,6 +172,13 @@ export default defineStore("Queue", { this.tracklist = []; this.tracklist.push(...tracklist); } + + const settings = useSettingsStore(); + + if (settings.repeat_one) { + settings.toggleRepeatMode(); + } + this.focusCurrentInSidebar(1000); }, playFromFolder(fpath: string, tracks: Track[]) { console.log("play from folder"); diff --git a/src/stores/settings/index.ts b/src/stores/settings/index.ts index e93f5ee..8df791d 100644 --- a/src/stores/settings/index.ts +++ b/src/stores/settings/index.ts @@ -9,6 +9,8 @@ export default defineStore("settings", { extend_width: false, contextChildrenShowMode: contextChildrenShowMode.click, artist_top_tracks_count: 5, + repeat_all: true, + repeat_one: false, }), actions: { toggleUseNPImg() { @@ -29,11 +31,31 @@ export default defineStore("settings", { ? contextChildrenShowMode.hover : contextChildrenShowMode.click; }, + toggleRepeatMode() { + if (this.repeat_all) { + this.repeat_all = false; + this.repeat_one = true; + return; + } + + if (this.repeat_one) { + this.repeat_one = false; + this.repeat_all = false; + return; + } + + if (!this.repeat_all && !this.repeat_one) { + this.repeat_all = true; + } + }, }, getters: { can_extend_width(): boolean { return xxl.value; }, + no_repeat(): boolean { + return !this.repeat_all && !this.repeat_one; + }, }, persist: true, });