🔷 refactor context menu to accept context src

🔷 add a getCurrentDate function to get formatted date
This commit is contained in:
geoffrey45
2022-04-08 21:07:24 +03:00
parent 24db32ae09
commit 83330a7fad
13 changed files with 107 additions and 44 deletions
+1 -28
View File
@@ -1,63 +1,36 @@
# Fixes ! # Fixes !
- [ ] Use click event to play song instead of url ⚠
- [ ] Show play/pause button correctly according to state ⚠
- [ ] Click on artist image to go to artist page ⚠ - [ ] Click on artist image to go to artist page ⚠
- [ ] Play next song if current song can't be loaded ⚠ - [ ] Play next song if current song can't be loaded ⚠
- [ ] List item song icon for long song titles ⚠
<!-- --> <!-- -->
- [ ] Broken CSS
- [ ] Prevent scanning unchanged folders
- [ ] Handle '/' and '&' characters in song artists
- [ ] Nginx not serving all files in a folder
- [ ] Removing song duplicates from queries - [ ] Removing song duplicates from queries
- [ ] Different songs having same link
- [ ] ConnectionError
- [ ] Move thumbnails to .config
- [ ] Write a multithreaded file server
- [ ] Add support for WAV files - [ ] Add support for WAV files
- [ ] Support multiple folders
- [ ] Compress thumbnails - [ ] Compress thumbnails
# Features + # Features +
## Needed features ## Needed features
- [ ] Seeking current song
- [ ] Adding songs to queue - [ ] Adding songs to queue
- [ ] Implement search on frontend
<!-- --> <!-- -->
- [ ] Watching for changes in folders and updating them instantly ⚠
- [ ] Display folders and files in a tree view. ⚠ 🔵
<!-- -->
- [ ] Add favicon
- [ ] Add keyboard shortcuts - [ ] Add keyboard shortcuts
- [ ] Right click on song to do stuff
- [ ] Adjust volume - [ ] Adjust volume
- [ ] Add listening statistics for all songs - [ ] Add listening statistics for all songs
- [ ] Extract color from artist image [for use with artist card gradient] - [ ] Extract color from artist image [for use with artist card gradient]
- [ ] Adding songs to favorites - [ ] Adding songs to favorites
- [ ] Adding songs to playlist
- [ ] Playing song radio - [ ] Playing song radio
## Future features ## Future features
- [ ] Toggle shuffle - [ ] Toggle shuffle
- [ ] Toggle repeat - [ ] Toggle repeat
- [ ] Display artist albums
- [ ] Suggest similar artists - [ ] Suggest similar artists
- [ ] Getting artist info - [ ] Getting artist info
- [ ] Getting album info
- [ ] Create a Python script to build, bundle and serve the app - [ ] Create a Python script to build, bundle and serve the app
- [ ] Getting extra song info (probably from genius) - [ ] Getting extra song info (probably from genius)
- [ ] Getting lyrics - [ ] Getting lyrics
- [ ] Notifications
- [ ] Sorting songs - [ ] Sorting songs
- [ ] Suggest undiscorvered artists, albums and songs - [ ] Suggest undiscorvered artists, albums and songs
- [ ] Remember last played song - [ ] Remember last played song
- [ ] Add next and previous song transition and progress bar reset animations - [ ] Add next and previous song transition and progress bar reset animations
- [ ] Hover animations for list items - [ ] Add playlist to folder
- [ ] Highlight currently playing song in playlist
- [ ] Add functionality to 'Listen now' button - [ ] Add functionality to 'Listen now' button
- [ ] Add a 'Scan' button to the sidebar
- [ ] Paginated requests for songs - [ ] Paginated requests for songs
- [ ] Package app as installable PWA - [ ] Package app as installable PWA
## Finished ✅
-1
View File
@@ -25,7 +25,6 @@
<div class="text">Nothing down here 😑</div> <div class="text">Nothing down here 😑</div>
</div> </div>
</div> </div>
<div v-else ref="songtitle"></div>
</div> </div>
</template> </template>
+13 -1
View File
@@ -12,6 +12,7 @@
<div class="info"> <div class="info">
<div class="btns"> <div class="btns">
<PlayBtnRect :source="playSources.playlist" /> <PlayBtnRect :source="playSources.playlist" />
<Option @showDropdown="showDropdown" :src="context.src" />
</div> </div>
<div class="duration"> <div class="duration">
<span v-if="props.info.count == 0">No Tracks</span> <span v-if="props.info.count == 0">No Tracks</span>
@@ -37,11 +38,15 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { playSources } from "../../composables/enums"; import { playSources, ContextSrc } from "../../composables/enums";
import { Playlist } from "../../interfaces"; import { Playlist } from "../../interfaces";
import PlayBtnRect from "../shared/PlayBtnRect.vue"; import PlayBtnRect from "../shared/PlayBtnRect.vue";
import useModalStore from "../../stores/modal"; import useModalStore from "../../stores/modal";
import Option from "../shared/Option.vue";
import pContext from "../../contexts/playlist";
import useContextStore from "../../stores/context";
const context = useContextStore();
const modal = useModalStore(); const modal = useModalStore();
const props = defineProps<{ const props = defineProps<{
@@ -51,6 +56,10 @@ const props = defineProps<{
function editPlaylist() { function editPlaylist() {
modal.showEditPlaylistModal(props.info); modal.showEditPlaylistModal(props.info);
} }
function showDropdown(e: any) {
context.showContextMenu(e, pContext(), ContextSrc.PHeader);
}
</script> </script>
<style lang="scss"> <style lang="scss">
@@ -63,6 +72,7 @@ function editPlaylist() {
border-radius: 0.75rem; border-radius: 0.75rem;
color: $white; color: $white;
background-color: transparent; background-color: transparent;
z-index: 0;
.gradient { .gradient {
position: absolute; position: absolute;
@@ -160,6 +170,8 @@ function editPlaylist() {
.btns { .btns {
margin-top: $small; margin-top: $small;
display: flex;
gap: $small;
} }
} }
} }
+1 -1
View File
@@ -12,6 +12,7 @@
'context-many-kids': context.hasManyChildren(), 'context-many-kids': context.hasManyChildren(),
}, },
]" ]"
id="context-menu"
:style="{ :style="{
left: context.x + 'px', left: context.x + 'px',
top: context.y + 'px', top: context.y + 'px',
@@ -56,7 +57,6 @@ const context = useContextStore();
top: 0; top: 0;
left: 0; left: 0;
width: 12rem; width: 12rem;
height: min-content;
z-index: 10; z-index: 10;
transform: scale(0); transform: scale(0);
+4 -1
View File
@@ -67,6 +67,7 @@
import perks from "../../composables/perks.js"; import perks from "../../composables/perks.js";
import useContextStore from "../../stores/context"; import useContextStore from "../../stores/context";
import useModalStore from "../../stores/modal"; import useModalStore from "../../stores/modal";
import { ContextSrc } from "../../composables/enums";
import { ref } from "vue"; import { ref } from "vue";
import trackContext from "../../contexts/track_context"; import trackContext from "../../contexts/track_context";
@@ -80,7 +81,9 @@ const showContextMenu = (e: Event) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
contextStore.showContextMenu(e, trackContext(props.song, modalStore)); const menus = trackContext(props.song, modalStore);
contextStore.showContextMenu(e, menus, ContextSrc.Track);
context_on.value = true; context_on.value = true;
contextStore.$subscribe((mutation, state) => { contextStore.$subscribe((mutation, state) => {
+4 -1
View File
@@ -39,6 +39,7 @@ import { ref } from "vue";
import perks from "../../composables/perks"; import perks from "../../composables/perks";
import trackContext from "../../contexts/track_context"; import trackContext from "../../contexts/track_context";
import { Track } from "../../interfaces"; import { Track } from "../../interfaces";
import { ContextSrc } from "../../composables/enums";
import useContextStore from "../../stores/context"; import useContextStore from "../../stores/context";
import useModalStore from "../../stores/modal"; import useModalStore from "../../stores/modal";
@@ -58,7 +59,9 @@ const showContextMenu = (e: Event) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
contextStore.showContextMenu(e, trackContext(props.track, modalStore)); const menus = trackContext(props.track, modalStore);
contextStore.showContextMenu(e, menus, ContextSrc.Track);
context_on.value = true; context_on.value = true;
contextStore.$subscribe((mutation, state) => { contextStore.$subscribe((mutation, state) => {
+6
View File
@@ -17,3 +17,9 @@ export enum FromOptions {
album = "album", album = "album",
search = "search", search = "search",
} }
export enum ContextSrc {
PHeader = "PHeader",
Track = "Track",
AHeader = "AHeader",
}
+15
View File
@@ -150,9 +150,24 @@ function formatSeconds(seconds) {
} }
} }
export function getCurrentDate(){
const date = new Date();
const yyyy = date.getFullYear();
const mm = date.getMonth() + 1;
const dd = date.getDate();
const hh = date.getHours();
const min = date.getMinutes();
const sec = date.getSeconds();
return `${yyyy}-${mm}-${dd} ${hh}:${min}:${sec}`;
}
export default { export default {
putCommas, putCommas,
focusCurrent, focusCurrent,
formatSeconds, formatSeconds,
getElem, getElem,
getCurrentDate
}; };
+2 -1
View File
@@ -2,7 +2,7 @@ import axios from "axios";
import { Playlist, Track } from "../interfaces"; import { Playlist, Track } from "../interfaces";
import { Notification, NotifType } from "../stores/notification"; import { Notification, NotifType } from "../stores/notification";
import state from "./state"; import state from "./state";
import { getCurrentDate } from "../composables/perks";
/** /**
* Creates a new playlist on the server. * Creates a new playlist on the server.
* @param playlist_name The name of the playlist to create. * @param playlist_name The name of the playlist to create.
@@ -13,6 +13,7 @@ async function createNewPlaylist(playlist_name: string, track?: Track) {
await axios await axios
.post(state.settings.uri + "/playlist/new", { .post(state.settings.uri + "/playlist/new", {
name: playlist_name, name: playlist_name,
lastUpdated: getCurrentDate(),
}) })
.then((res) => { .then((res) => {
new Notification("✅ Playlist created successfullly!"); new Notification("✅ Playlist created successfullly!");
+28
View File
@@ -0,0 +1,28 @@
import { Option } from "../interfaces";
export default async () => {
const deletePlaylist: Option = {
label: "Delete playlist",
critical: true,
action: () => {
console.log("delete playlist");
},
};
const playNext: Option = {
label: "Play next",
action: () => {
console.log("play next");
},
};
const addToQueue: Option = {
label: "Add to queue",
action: () => {
console.log("add to queue");
},
};
return [playNext, addToQueue, deletePlaylist];
};
+11 -4
View File
@@ -1,23 +1,30 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import normalize from "../composables/normalizeContextMenu"; import normalize from "../composables/normalizeContextMenu";
import { Option } from "../interfaces"; import { Option } from "../interfaces";
import { ContextSrc } from "../composables/enums";
export default defineStore("context-menu", { export default defineStore("context-menu", {
state: () => ({ state: () => ({
visible: false, visible: false,
options: Array<Option>(), options: <Option[]>[],
x: 500, x: 500,
y: 500, y: 500,
normalizedX: false, normalizedX: false,
normalizedY: false, normalizedY: false,
src: "",
}), }),
actions: { actions: {
showContextMenu(e: any, context_options: Promise<Option[]>) { showContextMenu(
e: any,
context_options: Promise<Option[]>,
src: ContextSrc
) {
if (this.visible) { if (this.visible) {
this.visible = false; this.visible = false;
return; return;
} }
this.visible = true;
context_options.then((options) => { context_options.then((options) => {
this.options = options; this.options = options;
}); });
@@ -29,11 +36,11 @@ export default defineStore("context-menu", {
this.normalizedX = yo.normalizedX; this.normalizedX = yo.normalizedX;
this.normalizedY = yo.normalizedY; this.normalizedY = yo.normalizedY;
this.src = src;
this.visible = true;
}, },
hideContextMenu() { hideContextMenu() {
this.visible = false; this.visible = false;
this.src = null;
}, },
hasManyChildren() { hasManyChildren() {
let result = false; let result = false;
+17 -5
View File
@@ -4,11 +4,23 @@
<div class="separator no-border"></div> <div class="separator no-border"></div>
<div class="songlist rounded"> <div class="songlist rounded">
<SongList <div v-if="playlist.tracks.length">
:tracks="playlist.tracks" <SongList
:pname="playlist.info.name" :tracks="playlist.tracks"
:playlistid="playlist.info.playlistid" :pname="playlist.info.name"
/> :playlistid="playlist.info.playlistid"
/>
</div>
<div v-else-if="playlist.tracks.length === 0 && playlist.info.count > 0">
<div class="no-results">
<div class="text">We can't find your music 🦋</div>
</div>
</div>
<div v-else-if="playlist.tracks.length === 0 && playlist.info.count == 0">
<div class="no-results">
<div class="text">Nothing here</div>
</div>
</div>
</div> </div>
<div class="separator no-border"></div> <div class="separator no-border"></div>
<FeaturedArtists /> <FeaturedArtists />
+5 -1
View File
@@ -1,6 +1,7 @@
<template> <template>
<div id="p-view"> <div id="p-view">
<div class="grid"> <div class="grid">
<NewPlaylistCard />
<PlaylistCard <PlaylistCard
v-for="p in pStore.playlists" v-for="p in pStore.playlists"
:key="p.playlistid" :key="p.playlistid"
@@ -14,6 +15,7 @@
import PlaylistCard from "../components/playlists/PlaylistCard.vue"; import PlaylistCard from "../components/playlists/PlaylistCard.vue";
import usePStore from "../stores/playlists"; import usePStore from "../stores/playlists";
import NewPlaylistCard from "../components/playlists/NewPlaylistCard.vue";
const pStore = usePStore(); const pStore = usePStore();
</script> </script>
@@ -22,10 +24,12 @@ const pStore = usePStore();
margin: $small; margin: $small;
padding: $small; padding: $small;
overflow: auto; overflow: auto;
scrollbar-color: $gray2 transparent;
border-top: 1px solid $gray3;
.grid { .grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
gap: $small; gap: $small;
} }
} }