mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-05 04:53:01 +00:00
major refactors
This commit is contained in:
@@ -30,7 +30,14 @@ def get_all_playlists():
|
|||||||
@playlist_bp.route("/playlist/new", methods=["POST"])
|
@playlist_bp.route("/playlist/new", methods=["POST"])
|
||||||
def create_playlist():
|
def create_playlist():
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
playlist = {"name": data["name"], "description": [], "tracks": []}
|
|
||||||
|
playlist = {
|
||||||
|
"name": data["name"],
|
||||||
|
"description": [],
|
||||||
|
"tracks": [],
|
||||||
|
"count": 0,
|
||||||
|
"lastUpdated": 0,
|
||||||
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
p_in_db = instances.playlist_instance.get_playlist_by_name(playlist["name"])
|
p_in_db = instances.playlist_instance.get_playlist_by_name(playlist["name"])
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class AllSongs(db.Mongo):
|
|||||||
# def drop_db(self):
|
# def drop_db(self):
|
||||||
# self.collection.drop()
|
# self.collection.drop()
|
||||||
|
|
||||||
def insert_song(self, song_obj: dict) -> None:
|
def insert_song(self, song_obj: dict) -> str:
|
||||||
"""
|
"""
|
||||||
Inserts a new track object into the database.
|
Inserts a new track object into the database.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -69,11 +69,12 @@ def populate():
|
|||||||
for file in files:
|
for file in files:
|
||||||
tags = get_tags(file)
|
tags = get_tags(file)
|
||||||
|
|
||||||
if tags not in api.PRE_TRACKS:
|
|
||||||
api.PRE_TRACKS.append(tags)
|
|
||||||
|
|
||||||
if tags is not None:
|
if tags is not None:
|
||||||
instances.songs_instance.insert_song(tags)
|
upsert_id = instances.songs_instance.insert_song(tags)
|
||||||
|
|
||||||
|
if upsert_id is not None:
|
||||||
|
tags["_id"] = {"$oid": upsert_id}
|
||||||
|
api.PRE_TRACKS.append(tags)
|
||||||
|
|
||||||
_bar.next()
|
_bar.next()
|
||||||
_bar.finish()
|
_bar.finish()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
This library contains all the functions related to albums.
|
This library contains all the functions related to albums.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from pprint import pprint
|
||||||
import urllib
|
import urllib
|
||||||
from typing import List
|
from typing import List
|
||||||
from app import models, functions, helpers
|
from app import models, functions, helpers
|
||||||
@@ -52,9 +53,12 @@ def get_album_tracks(album: str, artist: str) -> List:
|
|||||||
tracks = []
|
tracks = []
|
||||||
|
|
||||||
for track in api.PRE_TRACKS:
|
for track in api.PRE_TRACKS:
|
||||||
|
try:
|
||||||
if track["album"] == album and track["albumartist"] == artist:
|
if track["album"] == album and track["albumartist"] == artist:
|
||||||
tracks.append(track)
|
tracks.append(track)
|
||||||
|
except TypeError:
|
||||||
|
pprint(track, indent=4)
|
||||||
|
print(album, artist)
|
||||||
return tracks
|
return tracks
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ Contains all the models for objects generation and typing.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from datetime import date
|
||||||
from typing import List
|
from typing import List
|
||||||
from app import api
|
from app import api
|
||||||
from app import settings
|
from app import settings
|
||||||
@@ -95,6 +96,8 @@ class Playlist:
|
|||||||
description: str
|
description: str
|
||||||
image: str
|
image: str
|
||||||
tracks: List[Track]
|
tracks: List[Track]
|
||||||
|
count: int
|
||||||
|
lastUpdated: int
|
||||||
"""A list of track objects in the playlist"""
|
"""A list of track objects in the playlist"""
|
||||||
|
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
@@ -103,6 +106,9 @@ class Playlist:
|
|||||||
self.description = data["description"]
|
self.description = data["description"]
|
||||||
self.image = ""
|
self.image = ""
|
||||||
self.tracks = create_playlist_tracks(data["tracks"])
|
self.tracks = create_playlist_tracks(data["tracks"])
|
||||||
|
self.count = len(data["tracks"])
|
||||||
|
self.lastUpdated = data["lastUpdated"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
+5
-1
@@ -39,11 +39,15 @@ import useContextStore from "./stores/context";
|
|||||||
import ContextMenu from "./components/contextMenu.vue";
|
import ContextMenu from "./components/contextMenu.vue";
|
||||||
import Modal from "./components/modal.vue";
|
import Modal from "./components/modal.vue";
|
||||||
import Notification from "./components/Notification.vue";
|
import Notification from "./components/Notification.vue";
|
||||||
|
import useQStore from "./stores/queue";
|
||||||
|
|
||||||
const context_store = useContextStore();
|
const context_store = useContextStore();
|
||||||
|
const queue = useQStore();
|
||||||
|
|
||||||
|
queue.readQueueFromLocalStorage();
|
||||||
|
|
||||||
const RightSideBar = Main;
|
const RightSideBar = Main;
|
||||||
perks.readQueue();
|
|
||||||
const collapsed = ref(false);
|
const collapsed = ref(false);
|
||||||
|
|
||||||
const app_dom = document.getElementById("app");
|
const app_dom = document.getElementById("app");
|
||||||
|
|||||||
@@ -1,23 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="hotkeys">
|
<div class="hotkeys">
|
||||||
<div class="image ctrl-btn" id="previous" @click="playPrev"></div>
|
<div class="image ctrl-btn" id="previous" @click="props.prev"></div>
|
||||||
<div
|
<div
|
||||||
class="image ctrl-btn play-pause"
|
class="image ctrl-btn play-pause"
|
||||||
@click="playPause"
|
@click="playPause"
|
||||||
:class="{ isPlaying: isPlaying }"
|
:class="{ isPlaying: props.playing }"
|
||||||
></div>
|
></div>
|
||||||
<div class="image ctrl-btn" id="next" @click="playNext"></div>
|
<div class="image ctrl-btn" id="next" @click="props.next"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import playAudio from '../../../composables/playAudio';
|
const props = defineProps<{
|
||||||
|
playing: boolean;
|
||||||
const playPause = playAudio.playPause;
|
playPause: () => void;
|
||||||
const playNext = playAudio.playNext;
|
next: () => void;
|
||||||
const playPrev = playAudio.playPrev;
|
prev: () => void;
|
||||||
|
}>();
|
||||||
const isPlaying = playAudio.playing;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<input
|
<input
|
||||||
id="progress"
|
id="progress"
|
||||||
type="range"
|
type="range"
|
||||||
:value="pos"
|
:value="props.pos"
|
||||||
min="0"
|
min="0"
|
||||||
max="100"
|
max="100"
|
||||||
step="0.1"
|
step="0.1"
|
||||||
@@ -10,12 +10,14 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { ref } from "vue";
|
|
||||||
import playAudio from "../../../composables/playAudio";
|
|
||||||
const pos = ref(playAudio.pos);
|
|
||||||
|
|
||||||
const seek = () => {
|
const seek = () => {
|
||||||
playAudio.seek(document.getElementById("progress").value);
|
const value = Number(document.getElementById("progress").value);
|
||||||
|
props.seek(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
pos: number;
|
||||||
|
seek: (time: number) => void;
|
||||||
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,39 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<div
|
|
||||||
v-if="props.collapsed"
|
|
||||||
class="image art"
|
|
||||||
:style="{
|
|
||||||
backgroundImage: `url("${track.image}")`,
|
|
||||||
}"
|
|
||||||
></div>
|
|
||||||
<div class="desc">
|
<div class="desc">
|
||||||
<div>
|
<div>
|
||||||
<div class="title ellip">{{ track.title }}</div>
|
<div class="title ellip">{{ props.track.title }}</div>
|
||||||
<div class="separator no-border"></div>
|
<div class="separator no-border"></div>
|
||||||
<div class="artists ellip" v-if="track.artists[0] !== ''">
|
<div class="artists ellip" v-if="props.track.artists[0] !== ''">
|
||||||
<span v-for="artist in putCommas(track.artists)" :key="artist">{{
|
<span
|
||||||
artist
|
v-for="artist in putCommas(props.track.artists)"
|
||||||
}}</span>
|
:key="artist"
|
||||||
|
>{{ artist }}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="artists" v-else>
|
<div class="artists" v-else>
|
||||||
<span>{{ track.albumartist }}</span>
|
<span>{{ props.track.albumartist }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import perks from "../../composables/perks";
|
import perks from "../../composables/perks";
|
||||||
import state from "../../composables/state";
|
import { Track } from "../../interfaces";
|
||||||
|
|
||||||
const track = state.current;
|
|
||||||
const props = defineProps({
|
|
||||||
collapsed: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const putCommas = perks.putCommas;
|
const putCommas = perks.putCommas;
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
track: Track;
|
||||||
|
}>();
|
||||||
</script>
|
</script>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="l_ rounded" v-if="!props.collapsed">
|
<div class="l_ rounded">
|
||||||
<div class="headin">Now Playing</div>
|
<div class="headin">Now Playing</div>
|
||||||
<div class="button menu image rounded"></div>
|
<div class="button menu image rounded"></div>
|
||||||
<div class="separator no-border"></div>
|
<div class="separator no-border"></div>
|
||||||
@@ -8,32 +8,30 @@
|
|||||||
<div
|
<div
|
||||||
class="l-image image rounded"
|
class="l-image image rounded"
|
||||||
:style="{
|
:style="{
|
||||||
backgroundImage: `url("${current.image}")`,
|
backgroundImage: `url("${queue.current.image}")`,
|
||||||
}"
|
}"
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="separator no-border"></div>
|
<div class="separator no-border"></div>
|
||||||
<SongCard />
|
<SongCard :track="queue.current" />
|
||||||
<Progress />
|
<Progress :seek="queue.seek" :pos="queue.current_time" />
|
||||||
<HotKeys />
|
<HotKeys
|
||||||
|
:playing="queue.playing"
|
||||||
|
:playPause="queue.playPause"
|
||||||
|
:next="queue.playNext"
|
||||||
|
:prev="queue.playPrev"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
|
||||||
import state from "../../composables/state";
|
|
||||||
import SongCard from "./SongCard.vue";
|
import SongCard from "./SongCard.vue";
|
||||||
import HotKeys from "./NP/HotKeys.vue";
|
import HotKeys from "./NP/HotKeys.vue";
|
||||||
import Progress from "./NP/Progress.vue";
|
import Progress from "./NP/Progress.vue";
|
||||||
|
import useQStore from "../../stores/queue";
|
||||||
|
|
||||||
const current = ref(state.current);
|
const queue = useQStore();
|
||||||
const props = defineProps({
|
|
||||||
collapsed: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.l_ {
|
.l_ {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const props = defineProps<{
|
|||||||
|
|
||||||
.image {
|
.image {
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
height: 8.5rem;
|
height: 10rem;
|
||||||
background-image: url("../../assets/images/eggs.jpg");
|
background-image: url("../../assets/images/eggs.jpg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,8 @@ const loading = state.loading
|
|||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.loaderx {
|
.loaderx {
|
||||||
position: absolute;
|
|
||||||
top: 0.65rem;
|
|
||||||
width: 1.5rem;
|
width: 1.5rem;
|
||||||
height: 1.5rem;
|
height:1.5rem;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,10 +79,7 @@ const showContextMenu = (e: Event) => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
contextStore.showContextMenu(
|
contextStore.showContextMenu(e, trackContext(props.song, modalStore));
|
||||||
e,
|
|
||||||
trackContext(props.song, modalStore)
|
|
||||||
);
|
|
||||||
context_on.value = true;
|
context_on.value = true;
|
||||||
|
|
||||||
contextStore.$subscribe((mutation, state) => {
|
contextStore.$subscribe((mutation, state) => {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
@click="playThis(props.track)"
|
@click="playThis(props.track)"
|
||||||
:class="[
|
:class="[
|
||||||
{
|
{
|
||||||
currentInQueue: current.trackid === props.track.trackid,
|
currentInQueue: props.isCurrent,
|
||||||
},
|
},
|
||||||
{ 'context-on': context_on },
|
{ 'context-on': context_on },
|
||||||
]"
|
]"
|
||||||
@@ -18,8 +18,8 @@
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="now-playing-track image"
|
class="now-playing-track image"
|
||||||
v-if="current.trackid === props.track.trackid"
|
v-if="props.isCurrent"
|
||||||
:class="{ active: is_playing, not_active: !is_playing }"
|
:class="{ active: props.isPlaying, not_active: !props.isPlaying }"
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tags">
|
<div class="tags">
|
||||||
@@ -34,21 +34,31 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import perks from "../../composables/perks";
|
import perks from "../../composables/perks";
|
||||||
import playAudio from "../../composables/playAudio";
|
|
||||||
import useContextStore from "@/stores/context";
|
|
||||||
import trackContext from "../../contexts/track_context";
|
import trackContext from "../../contexts/track_context";
|
||||||
|
import { Track } from "../../interfaces";
|
||||||
|
|
||||||
|
import useContextStore from "../../stores/context";
|
||||||
|
import useModalStore from "../../stores/modal";
|
||||||
|
|
||||||
const contextStore = useContextStore();
|
const contextStore = useContextStore();
|
||||||
|
const modalStore = useModalStore();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
track: Track;
|
||||||
|
isCurrent: boolean;
|
||||||
|
isPlaying: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
const context_on = ref(false);
|
const context_on = ref(false);
|
||||||
|
|
||||||
const showContextMenu = (e) => {
|
const showContextMenu = (e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
contextStore.showContextMenu(e, trackContext(props.track));
|
contextStore.showContextMenu(e, trackContext(props.track, modalStore));
|
||||||
context_on.value = true;
|
context_on.value = true;
|
||||||
|
|
||||||
contextStore.$subscribe((mutation, state) => {
|
contextStore.$subscribe((mutation, state) => {
|
||||||
@@ -57,18 +67,16 @@ const showContextMenu = (e) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const props = defineProps({
|
|
||||||
track: Object,
|
const emit = defineEmits<{
|
||||||
default: () => ({}),
|
(e: "PlayThis", track: Track): void;
|
||||||
});
|
}>();
|
||||||
|
|
||||||
const current = ref(perks.current);
|
const current = ref(perks.current);
|
||||||
const putCommas = perks.putCommas;
|
const putCommas = perks.putCommas;
|
||||||
const is_playing = ref(playAudio.playing);
|
|
||||||
|
|
||||||
const playThis = (song) => {
|
const playThis = (track: Track) => {
|
||||||
playAudio.playAudio(song.trackid);
|
emit("PlayThis", track);
|
||||||
perks.current.value = song;
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,41 +1,44 @@
|
|||||||
|
import { Track } from "../interfaces.js";
|
||||||
import perks from "./perks.js";
|
import perks from "./perks.js";
|
||||||
import playAudio from "./playAudio.js";
|
|
||||||
|
|
||||||
let showMediaNotif = () => {
|
|
||||||
let current = perks.current.value;
|
|
||||||
|
|
||||||
|
export default (
|
||||||
|
track: Track,
|
||||||
|
playPause: () => void,
|
||||||
|
playNext: () => void,
|
||||||
|
playPrev: () => void
|
||||||
|
) => {
|
||||||
if ("mediaSession" in navigator) {
|
if ("mediaSession" in navigator) {
|
||||||
navigator.mediaSession.metadata = new window.MediaMetadata({
|
navigator.mediaSession.metadata = new window.MediaMetadata({
|
||||||
title: current.title,
|
title: track.title,
|
||||||
artist: current.artists,
|
artist: track.artists.join(", "),
|
||||||
artwork: [
|
artwork: [
|
||||||
{
|
{
|
||||||
src: current.image,
|
src: track.image,
|
||||||
sizes: "96x96",
|
sizes: "96x96",
|
||||||
type: "image/jpeg",
|
type: "image/jpeg",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: current.image,
|
src: track.image,
|
||||||
sizes: "128x128",
|
sizes: "128x128",
|
||||||
type: "image/webp",
|
type: "image/webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: current.image,
|
src: track.image,
|
||||||
sizes: "192x192",
|
sizes: "192x192",
|
||||||
type: "image/webp",
|
type: "image/webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: current.image,
|
src: track.image,
|
||||||
sizes: "256x256",
|
sizes: "256x256",
|
||||||
type: "image/webp",
|
type: "image/webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: current.image,
|
src: track.image,
|
||||||
sizes: "384x384",
|
sizes: "384x384",
|
||||||
type: "image/webp",
|
type: "image/webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: current.image,
|
src: track.image,
|
||||||
sizes: "512x512",
|
sizes: "512x512",
|
||||||
type: "image/webp",
|
type: "image/webp",
|
||||||
},
|
},
|
||||||
@@ -43,22 +46,16 @@ let showMediaNotif = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
navigator.mediaSession.setActionHandler("play", function () {
|
navigator.mediaSession.setActionHandler("play", function () {
|
||||||
playAudio.playPause();
|
playPause();
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler("pause", function () {
|
navigator.mediaSession.setActionHandler("pause", function () {
|
||||||
playAudio.playPause();
|
playPause();
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler("seekbackward", function () {});
|
|
||||||
navigator.mediaSession.setActionHandler("seekforward", function () {});
|
|
||||||
navigator.mediaSession.setActionHandler("previoustrack", function () {
|
navigator.mediaSession.setActionHandler("previoustrack", function () {
|
||||||
playAudio.playPrev();
|
playPrev();
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler("nexttrack", function () {
|
navigator.mediaSession.setActionHandler("nexttrack", function () {
|
||||||
playAudio.playNext();
|
playNext();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
|
||||||
showMediaNotif,
|
|
||||||
};
|
|
||||||
+3
-114
@@ -1,26 +1,3 @@
|
|||||||
import { ref } from "@vue/reactivity";
|
|
||||||
import { watch } from "@vue/runtime-core";
|
|
||||||
import media from "./mediaNotification.js";
|
|
||||||
import playAudio from "./playAudio.js";
|
|
||||||
import state from "./state";
|
|
||||||
|
|
||||||
const current = ref(state.current);
|
|
||||||
|
|
||||||
const next = ref({
|
|
||||||
title: "The next song",
|
|
||||||
artists: ["... blah blah blah"],
|
|
||||||
image: "http://127.0.0.1:8900/images/defaults/4.webp",
|
|
||||||
_id: {
|
|
||||||
$oid: "",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const prev = ref(state.prev);
|
|
||||||
|
|
||||||
const queue = ref(state.queue);
|
|
||||||
|
|
||||||
const search = ref("");
|
|
||||||
|
|
||||||
const putCommas = (artists) => {
|
const putCommas = (artists) => {
|
||||||
let result = [];
|
let result = [];
|
||||||
|
|
||||||
@@ -35,74 +12,6 @@ const putCommas = (artists) => {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
function updateNext(song_) {
|
|
||||||
const index = state.queue.value.findIndex(
|
|
||||||
(item) => item.trackid === song_.trackid
|
|
||||||
);
|
|
||||||
|
|
||||||
if (index === queue.value.length - 1) {
|
|
||||||
next.value = queue.value[0];
|
|
||||||
state.prev.value = queue.value[queue.value.length - 2];
|
|
||||||
} else if (index === 0) {
|
|
||||||
next.value = queue.value[1];
|
|
||||||
} else {
|
|
||||||
next.value = queue.value[index + 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updatePrev(song) {
|
|
||||||
const index = state.queue.value.findIndex(
|
|
||||||
(item) => item.trackid === song.trackid
|
|
||||||
);
|
|
||||||
|
|
||||||
if (index === 0) {
|
|
||||||
prev.value = queue.value[queue.value.length - 1];
|
|
||||||
} else if (index === queue.value.length - 1) {
|
|
||||||
prev.value = queue.value[index - 1];
|
|
||||||
} else {
|
|
||||||
prev.value = queue.value[index - 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const readQueue = () => {
|
|
||||||
const prev_queue = JSON.parse(localStorage.getItem("queue"));
|
|
||||||
const last_played = JSON.parse(localStorage.getItem("current"));
|
|
||||||
|
|
||||||
if (last_played) {
|
|
||||||
state.current.value = last_played;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prev_queue) {
|
|
||||||
state.queue.value = prev_queue;
|
|
||||||
|
|
||||||
updateNext(state.current.value);
|
|
||||||
updatePrev(state.current.value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateQueue = async (song, type) => {
|
|
||||||
playAudio.playAudio(song.trackid);
|
|
||||||
let list;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case "folder":
|
|
||||||
list = state.folder_song_list.value;
|
|
||||||
break;
|
|
||||||
case "album":
|
|
||||||
list = state.album.tracklist;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.queue.value[0].trackid !== list[0].trackid) {
|
|
||||||
const new_queue = list;
|
|
||||||
localStorage.setItem("queue", JSON.stringify(new_queue));
|
|
||||||
state.queue.value = new_queue;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.current.value = song;
|
|
||||||
localStorage.setItem("current", JSON.stringify(song));
|
|
||||||
};
|
|
||||||
|
|
||||||
function focusCurrent() {
|
function focusCurrent() {
|
||||||
const elem = document.getElementsByClassName("currentInQueue")[0];
|
const elem = document.getElementsByClassName("currentInQueue")[0];
|
||||||
|
|
||||||
@@ -132,17 +41,6 @@ function focusSearchBox() {
|
|||||||
elem.focus();
|
elem.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
watch(current, (new_current) => {
|
|
||||||
media.showMediaNotif();
|
|
||||||
|
|
||||||
updateNext(new_current);
|
|
||||||
updatePrev(new_current);
|
|
||||||
|
|
||||||
localStorage.setItem("current", JSON.stringify(new_current));
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
let key_down_fired = false;
|
let key_down_fired = false;
|
||||||
|
|
||||||
window.addEventListener("keydown", (e) => {
|
window.addEventListener("keydown", (e) => {
|
||||||
@@ -161,7 +59,7 @@ window.addEventListener("keydown", (e) => {
|
|||||||
key_down_fired = false;
|
key_down_fired = false;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
playAudio.playNext();
|
// playAudio.playNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -173,7 +71,7 @@ window.addEventListener("keydown", (e) => {
|
|||||||
|
|
||||||
key_down_fired = true;
|
key_down_fired = true;
|
||||||
|
|
||||||
playAudio.playPrev();
|
// playAudio.playPrev();
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
key_down_fired = false;
|
key_down_fired = false;
|
||||||
@@ -190,7 +88,7 @@ window.addEventListener("keydown", (e) => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
key_down_fired = true;
|
key_down_fired = true;
|
||||||
|
|
||||||
playAudio.playPause();
|
// playAudio.playPause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,8 +110,6 @@ window.addEventListener("keyup", () => {
|
|||||||
key_down_fired = false;
|
key_down_fired = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function formatSeconds(seconds) {
|
function formatSeconds(seconds) {
|
||||||
// check if there are arguments
|
// check if there are arguments
|
||||||
|
|
||||||
@@ -256,14 +152,7 @@ function formatSeconds(seconds) {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
putCommas,
|
putCommas,
|
||||||
readQueue,
|
|
||||||
focusCurrent,
|
focusCurrent,
|
||||||
updateQueue,
|
|
||||||
formatSeconds,
|
formatSeconds,
|
||||||
getElem,
|
getElem,
|
||||||
current,
|
|
||||||
queue,
|
|
||||||
next,
|
|
||||||
prev,
|
|
||||||
search,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
import {ref} from "@vue/reactivity";
|
|
||||||
|
|
||||||
import perks from "./perks";
|
|
||||||
import media from "./mediaNotification.js";
|
|
||||||
import state from "./state";
|
|
||||||
|
|
||||||
const audio = ref(new Audio()).value;
|
|
||||||
|
|
||||||
const pos = ref(0);
|
|
||||||
const current_time = ref(0);
|
|
||||||
|
|
||||||
const playing = ref(state.is_playing);
|
|
||||||
|
|
||||||
const url = "http://127.0.0.1:9876//file/";
|
|
||||||
|
|
||||||
const playAudio = (trackid) => {
|
|
||||||
const elem = document.getElementById('progress');
|
|
||||||
|
|
||||||
const full_path = url + encodeURIComponent(trackid);
|
|
||||||
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
audio.src = full_path;
|
|
||||||
audio.oncanplaythrough = resolve;
|
|
||||||
audio.onerror = reject;
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
audio.play().then(() => {
|
|
||||||
perks.focusCurrent()
|
|
||||||
state.is_playing.value = true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
audio.ontimeupdate = () => {
|
|
||||||
current_time.value = audio.currentTime;
|
|
||||||
pos.value = (audio.currentTime / audio.duration) * 100;
|
|
||||||
let bg_size = ((audio.currentTime / audio.duration) * 100)
|
|
||||||
|
|
||||||
elem.style.backgroundSize = `${bg_size}% 100%`;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.catch((err) => console.log(err));
|
|
||||||
};
|
|
||||||
|
|
||||||
function playNext() {
|
|
||||||
playAudio(perks.next.value.trackid);
|
|
||||||
perks.current.value = perks.next.value;
|
|
||||||
media.showMediaNotif();
|
|
||||||
}
|
|
||||||
|
|
||||||
function playPrev() {
|
|
||||||
playAudio(state.prev.value.trackid);
|
|
||||||
perks.current.value = perks.prev.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function seek(position) {
|
|
||||||
audio.currentTime = (position / 100) * audio.duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
function playPause() {
|
|
||||||
if (audio.src === "") {
|
|
||||||
playAudio(perks.current.value.trackid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (audio.paused) {
|
|
||||||
audio.play();
|
|
||||||
} else {
|
|
||||||
audio.pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
audio.addEventListener("play", () => {
|
|
||||||
state.is_playing.value = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
audio.addEventListener("pause", () => {
|
|
||||||
state.is_playing.value = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
audio.addEventListener("ended", () => {
|
|
||||||
playNext();
|
|
||||||
});
|
|
||||||
|
|
||||||
export default {playAudio, playNext, playPrev, playPause, seek, pos, playing, current_time};
|
|
||||||
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
// Try implementing classes to play audio .ie. Make the seek, playNext, playPrev, etc the methods of a class. etc
|
|
||||||
@@ -12,6 +12,7 @@ import SettingsView from "../views/SettingsView.vue";
|
|||||||
|
|
||||||
import usePStore from "../stores/playlists";
|
import usePStore from "../stores/playlists";
|
||||||
import usePTrackStore from "../stores/p.ptracks";
|
import usePTrackStore from "../stores/p.ptracks";
|
||||||
|
import useFStore from "../stores/folder";
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
@@ -23,6 +24,10 @@ const routes = [
|
|||||||
path: "/folder/:path",
|
path: "/folder/:path",
|
||||||
name: "FolderView",
|
name: "FolderView",
|
||||||
component: FolderView,
|
component: FolderView,
|
||||||
|
beforeEnter: async (to) => {
|
||||||
|
console.log("beforeEnter")
|
||||||
|
await useFStore().fetchAll(to.params.path);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/folder/",
|
path: "/folder/",
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { defineStore } from "pinia";
|
||||||
|
import { Folder, Track } from "../interfaces";
|
||||||
|
|
||||||
|
import fetchThem from "../composables/getFilesAndFolders";
|
||||||
|
|
||||||
|
export default defineStore("FolderDirs&Tracks", {
|
||||||
|
state: () => ({
|
||||||
|
path: <string>{},
|
||||||
|
dirs: <Folder[]>[],
|
||||||
|
tracks: <Track[]>[],
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
async fetchAll(path: string) {
|
||||||
|
const { tracks, folders } = await fetchThem(path);
|
||||||
|
|
||||||
|
this.path = path;
|
||||||
|
this.dirs = folders;
|
||||||
|
this.tracks = tracks;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { Track } from "../interfaces";
|
import { Track } from "../interfaces";
|
||||||
enum ModalOptions {
|
enum ModalOptions {
|
||||||
newPlaylist = "newPlaylist",
|
newPlaylist,
|
||||||
editPlaylist = "editPlaylist",
|
editPlaylist,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineStore("newModal", {
|
export default defineStore("newModal", {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ const playlist = usePTrackStore().playlist;
|
|||||||
const info = {
|
const info = {
|
||||||
name: playlist.name,
|
name: playlist.name,
|
||||||
count: playlist.tracks.length,
|
count: playlist.tracks.length,
|
||||||
|
desc: playlist.description,
|
||||||
duration: "3 hours, 4 minutes",
|
duration: "3 hours, 4 minutes",
|
||||||
lastUpdated: "yesterday",
|
lastUpdated: "yesterday",
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user