some bug fixes

- watch route params instead of route object in folderview
- move to script setup on album view
- use album as a reactive object instead of refs
- use axios instead of fetch to get album data
- improve clickable areas on songItem
- move album requests to POST
This commit is contained in:
geoffrey45 2022-03-01 19:46:37 +03:00
parent 8459310258
commit 6efbb47166
17 changed files with 229 additions and 183 deletions

View File

@ -1,9 +1,11 @@
from crypt import methods
import os import os
from pprint import pprint from pprint import pprint
import urllib import urllib
from typing import List from typing import List
from flask import Blueprint, request, send_file from flask import Blueprint, request, send_file
from app import functions, instances, helpers, cache
from app import functions, instances, helpers, cache, models
bp = Blueprint("api", __name__, url_prefix="") bp = Blueprint("api", __name__, url_prefix="")
@ -30,21 +32,21 @@ def say_hi():
return "^ _ ^" return "^ _ ^"
def get_tracks(query: str) -> List: def get_tracks(query: str) -> List[models.Track]:
""" """
Gets all songs with a given title. Gets all songs with a given title.
""" """
return [track for track in all_the_f_music if query.lower() in track.title.lower()] return [track for track in all_the_f_music if query.lower() in track.title.lower()]
def get_search_albums(query: str) -> List: def get_search_albums(query: str) -> List[models.Track]:
""" """
Gets all songs with a given album. Gets all songs with a given album.
""" """
return [track for track in all_the_f_music if query.lower() in track.album.lower()] return [track for track in all_the_f_music if query.lower() in track.album.lower()]
def get_artists(artist: str) -> List: def get_artists(artist: str) -> List[models.Track]:
""" """
Gets all songs with a given artist. Gets all songs with a given artist.
""" """
@ -151,12 +153,13 @@ def find_tracks():
return "🎸" return "🎸"
@bp.route("/album/<album>/<artist>/artists") @bp.route("/album/artists", methods=["POST"])
@cache.cached() def get_albumartists():
def get_albumartists(album, artist):
"""Returns a list of artists featured in a given album.""" """Returns a list of artists featured in a given album."""
album = album.replace("|", "/") data = request.get_json()
artist = artist.replace("|", "/")
album = data["album"]
artist = data["artist"]
tracks = [] tracks = []
@ -292,20 +295,24 @@ def get_albums():
return {"albums": albums} return {"albums": albums}
@bp.route("/album/<title>/<artist>/tracks") @bp.route("/album/tracks", methods=["POST"])
@cache.cached() def get_album_tracks():
def get_album_tracks(title: str, artist: str):
"""Returns all the tracks in the given album.""" """Returns all the tracks in the given album."""
data = request.get_json()
album = data["album"]
artist = data["artist"]
songs = [] songs = []
for track in all_the_f_music: for track in all_the_f_music:
if track.albumartist == artist and track.album == title: if track.albumartist == artist and track.album == album:
songs.append(track) songs.append(track)
songs = helpers.remove_duplicates(songs) songs = helpers.remove_duplicates(songs)
album_obj = { album_obj = {
"name": title, "name": album,
"count": len(songs), "count": len(songs),
"duration": "56 Minutes", "duration": "56 Minutes",
"image": songs[0].image, "image": songs[0].image,

View File

@ -7,6 +7,7 @@ import threading
import time import time
from typing import List from typing import List
import requests import requests
import colorgram
from io import BytesIO from io import BytesIO
@ -15,9 +16,10 @@ from PIL import Image
from app import instances from app import instances
from app import functions from app import functions
from app import watchdoge from app import watchdoge
from app import models
home_dir = os.path.expanduser('~') + '/' home_dir = os.path.expanduser("~") + "/"
app_dir = os.path.join(home_dir, '.musicx') app_dir = os.path.join(home_dir, ".musicx")
LAST_FM_API_KEY = "762db7a44a9e6fb5585661f5f2bdf23a" LAST_FM_API_KEY = "762db7a44a9e6fb5585661f5f2bdf23a"
@ -63,7 +65,7 @@ def run_fast_scandir(_dir: str, ext: list):
files = [] files = []
for f in os.scandir(_dir): for f in os.scandir(_dir):
if f.is_dir() and not f.name.startswith('.'): if f.is_dir() and not f.name.startswith("."):
subfolders.append(f.path) subfolders.append(f.path)
if f.is_file(): if f.is_file():
if os.path.splitext(f.name)[1].lower() in ext: if os.path.splitext(f.name)[1].lower() in ext:
@ -77,24 +79,26 @@ def run_fast_scandir(_dir: str, ext: list):
return subfolders, files return subfolders, files
def remove_duplicates(array: list) -> list: def remove_duplicates(tracklist: List[models.Track]) -> List[models.Track]:
""" """
Removes duplicates from a list. Returns a list without duplicates. Removes duplicates from a list. Returns a list without duplicates.
""" """
song_num = 0 song_num = 0
while song_num < len(array) - 1: while song_num < len(tracklist) - 1:
for index, song in enumerate(array): for index, song in enumerate(tracklist):
if array[song_num].title == song.title and \ if (
array[song_num].album == song.album and \ tracklist[song_num].title == song.title
array[song_num].artists == song.artists and \ and tracklist[song_num].album == song.album
index != song_num: and tracklist[song_num].artists == song.artists
array.remove(song) and index != song_num
):
tracklist.remove(song)
song_num += 1 song_num += 1
return array return tracklist
def save_image(url: str, path: str) -> None: def save_image(url: str, path: str) -> None:
@ -104,7 +108,7 @@ def save_image(url: str, path: str) -> None:
response = requests.get(url) response = requests.get(url)
img = Image.open(BytesIO(response.content)) img = Image.open(BytesIO(response.content))
img.save(path, 'JPEG') img.save(path, "JPEG")
def is_valid_file(filename: str) -> bool: def is_valid_file(filename: str) -> bool:
@ -112,7 +116,7 @@ def is_valid_file(filename: str) -> bool:
Checks if a file is valid. Returns True if it is, False if it isn't. Checks if a file is valid. Returns True if it is, False if it isn't.
""" """
if filename.endswith('.flac') or filename.endswith('.mp3'): if filename.endswith(".flac") or filename.endswith(".mp3"):
return True return True
else: else:
return False return False
@ -123,11 +127,10 @@ def create_config_dir() -> None:
Creates the config directory if it doesn't exist. Creates the config directory if it doesn't exist.
""" """
_home_dir = os.path.expanduser('~') _home_dir = os.path.expanduser("~")
config_folder = os.path.join(_home_dir, app_dir) config_folder = os.path.join(_home_dir, app_dir)
dirs = ["", "images", "images/defaults", dirs = ["", "images", "images/defaults", "images/artists", "images/thumbnails"]
"images/artists", "images/thumbnails"]
for _dir in dirs: for _dir in dirs:
path = os.path.join(config_folder, _dir) path = os.path.join(config_folder, _dir)
@ -140,19 +143,32 @@ def create_config_dir() -> None:
os.chmod(path, 0o755) os.chmod(path, 0o755)
def get_all_songs() -> List: def get_all_songs() -> List[models.Track]:
""" """
Gets all songs under the ~/ directory. Gets all songs under the ~/ directory.
""" """
print("Getting all songs...") print("Getting all songs...")
tracks = []
tracks: list[models.Track] = []
for track in instances.songs_instance.get_all_songs(): for track in instances.songs_instance.get_all_songs():
try: try:
os.chmod(os.path.join(track["filepath"]), 0o755) os.chmod(os.path.join(track["filepath"]), 0o755)
except FileNotFoundError: except FileNotFoundError:
instances.songs_instance.remove_song_by_filepath(track['filepath']) instances.songs_instance.remove_song_by_filepath(track["filepath"])
tracks.append(functions.create_track_class(track)) tracks.append(functions.create_track_class(track))
return tracks return tracks
def extract_colors(image) -> list:
colors = sorted(colorgram.extract(image, 2), key=lambda c: c.hsl.h)
formatted_colors = []
for color in colors:
color = f"rgb({color.rgb.r}, {color.rgb.g}, {color.rgb.b})"
formatted_colors.append(color)
return formatted_colors

17
server/poetry.lock generated
View File

@ -36,6 +36,17 @@ category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "colorgram.py"
version = "1.2.0"
description = "A Python module for extracting colors from images. Get a palette of any picture!"
category = "main"
optional = false
python-versions = "*"
[package.dependencies]
pillow = ">=3.3.1"
[[package]] [[package]]
name = "flask" name = "flask"
version = "2.0.2" version = "2.0.2"
@ -234,7 +245,7 @@ watchdog = ["watchdog"]
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.8" python-versions = "^3.8"
content-hash = "43a8f1b3d32df323e4836559445b061c5ef7540471f75ffb3365b683e953f760" content-hash = "c5fb66888aa3ddc0828c3c7794409039ada460ab96b3f824fd76caa85e27fbfb"
[metadata.files] [metadata.files]
certifi = [ certifi = [
@ -253,6 +264,10 @@ colorama = [
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
] ]
"colorgram.py" = [
{file = "colorgram.py-1.2.0-py2.py3-none-any.whl", hash = "sha256:e990769fa6df7261a450c7d5bef3a1a062f09ba1214bff67b4d6f02970a1a27b"},
{file = "colorgram.py-1.2.0.tar.gz", hash = "sha256:e77766a5f9de7207bdef8f1c22a702cbf09630eae3bc46a450b9d9f12a7bfdbf"},
]
flask = [ flask = [
{file = "Flask-2.0.2-py3-none-any.whl", hash = "sha256:cb90f62f1d8e4dc4621f52106613488b5ba826b2e1e10a33eac92f723093ab6a"}, {file = "Flask-2.0.2-py3-none-any.whl", hash = "sha256:cb90f62f1d8e4dc4621f52106613488b5ba826b2e1e10a33eac92f723093ab6a"},
{file = "Flask-2.0.2.tar.gz", hash = "sha256:7b2fb8e934ddd50731893bdcdb00fc8c0315916f9fcd50d22c7cc1a95ab634e2"}, {file = "Flask-2.0.2.tar.gz", hash = "sha256:7b2fb8e934ddd50731893bdcdb00fc8c0315916f9fcd50d22c7cc1a95ab634e2"},

View File

@ -16,6 +16,7 @@ progress = "^1.6"
gunicorn = "^20.1.0" gunicorn = "^20.1.0"
Pillow = "^9.0.1" Pillow = "^9.0.1"
Flask-Caching = "^1.10.1" Flask-Caching = "^1.10.1"
"colorgram.py" = "^1.2.0"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]

View File

@ -1,6 +1,6 @@
.b-bar { .b-bar {
height: 100%; height: 100%;
border-top: solid 1px $gray; background-color: $gray;
.grid { .grid {
display: grid; display: grid;
@ -36,7 +36,7 @@
.artists { .artists {
font-size: 0.8rem; font-size: 0.8rem;
color: $red; color: $white;
} }
} }
} }
@ -48,7 +48,6 @@
align-items: center; align-items: center;
margin: $small; margin: $small;
padding: $small; padding: $small;
background-color: $gray5;
.progress-bottom { .progress-bottom {
display: flex; display: flex;

View File

@ -1,18 +1,22 @@
<template> <template>
<div class="album-h"> <div class="album-h">
<div class="a-header rounded"> <div class="a-header rounded">
<div
class="image art shadow-lg"
:style="{ backgroundImage: `url(&quot;${encodeURI(props.album_info.image)}&quot;)` }"
></div>
<div class="info"> <div class="info">
<div class="top"> <div class="top">
<div class="h">Album</div> <div class="h">Album</div>
<div class="separator no-border"></div> <div class="separator no-border"></div>
<div class="title">{{ album_info.name }}</div> <div class="title">{{ props.album_info.name }}</div>
<div class="artist">{{ album_info.artist }}</div> <div class="artist">{{ props.album_info.artist }}</div>
</div> </div>
<div class="separator no-border"></div> <div class="separator no-border"></div>
<div class="bottom"> <div class="bottom">
<div class="stats shadow-sm"> <div class="stats shadow-sm">
{{ album_info.count }} Tracks {{ album_info.duration }} {{ props.album_info.count }} Tracks {{ props.album_info.duration }}
{{ album_info.date }} {{ props.album_info.date }}
</div> </div>
<div class="play rounded" @click="playAlbum"> <div class="play rounded" @click="playAlbum">
<div class="icon"></div> <div class="icon"></div>
@ -24,22 +28,20 @@
</div> </div>
</template> </template>
<script> <script setup>
import state from "@/composables/state.js"; import state from "@/composables/state.js";
import perks from "@/composables/perks.js"; import perks from "@/composables/perks.js";
export default { const props = defineProps({
props: ["album_info"], album_info: {
setup() { type: Object,
function playAlbum() { default: () => ({}),
perks.updateQueue(state.album_song_list.value[0], "album");
}
return {
playAlbum,
};
}, },
}; });
function playAlbum() {
perks.updateQueue(state.album.tracklist[0], "album");
}
</script> </script>
<style lang="scss"> <style lang="scss">
@ -59,7 +61,7 @@ export default {
overflow: hidden; overflow: hidden;
display: flex; display: flex;
align-items: center; align-items: center;
padding: $small; padding: 1rem;
height: 100%; height: 100%;
background-image: linear-gradient( background-image: linear-gradient(
56deg, 56deg,
@ -73,12 +75,20 @@ export default {
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
.art {
position: absolute;
width: 12rem;
height: 12rem;
left: 1rem;
}
.info { .info {
width: 100%; width: 100%;
height: calc(100%); height: calc(100%);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: flex-end; justify-content: flex-end;
margin-left: 13rem;
.top { .top {
.h { .h {
@ -88,6 +98,7 @@ export default {
font-size: 2rem; font-size: 2rem;
font-weight: 1000; font-weight: 1000;
color: white; color: white;
text-transform: capitalize;
} }
.artist { .artist {

View File

@ -13,6 +13,9 @@
</div> </div>
</div> </div>
<div class="search"> <div class="search">
<div class="loaderr">
<Loader />
</div>
<input <input
type="text" type="text"
class="search-input border" class="search-input border"
@ -26,11 +29,13 @@
<script> <script>
import perks from "@/composables/perks.js"; import perks from "@/composables/perks.js";
import { watch } from '@vue/runtime-core'; import { watch } from "@vue/runtime-core";
import useDebouncedRef from '@/composables/useDebouncedRef.js'; import useDebouncedRef from "@/composables/useDebouncedRef.js";
import Loader from "../shared/Loader.vue";
export default { export default {
props: ["path", "first_song"], props: ["path", "first_song"],
components: { Loader },
setup(props, { emit }) { setup(props, { emit }) {
const query = useDebouncedRef("", 400); const query = useDebouncedRef("", 400);
@ -63,8 +68,13 @@ export default {
.folder-top .search { .folder-top .search {
width: 50%; width: 50%;
display: grid; display: grid;
grid-template-columns: 1fr 1fr;
place-items: end; place-items: end;
.loaderr {
width: 2rem;
}
.search-input { .search-input {
max-width: 20rem; max-width: 20rem;
width: 100%; width: 100%;

View File

@ -69,7 +69,7 @@ import useDebouncedRef from "@/composables/useDebouncedRef";
import AlbumGrid from "@/components/Search/AlbumGrid.vue"; import AlbumGrid from "@/components/Search/AlbumGrid.vue";
import ArtistGrid from "@/components/Search/ArtistGrid.vue"; import ArtistGrid from "@/components/Search/ArtistGrid.vue";
import TracksGrid from "@/components/Search/TracksGrid.vue"; import TracksGrid from "@/components/Search/TracksGrid.vue";
import Loader from "@/components/Search/Loader.vue"; import Loader from "@/components/shared/Loader.vue";
import Options from "@/components/Search/Options.vue"; import Options from "@/components/Search/Options.vue";
import Filters from "@/components/Search/Filters.vue"; import Filters from "@/components/Search/Filters.vue";
import "@/assets/css/Search/Search.scss"; import "@/assets/css/Search/Search.scss";
@ -138,7 +138,7 @@ export default {
} }
function loadMoreTracks(start) { function loadMoreTracks(start) {
// scrollSearchThing(); scrollSearchThing();
loadMore.loadMoreTracks(start).then((response) => { loadMore.loadMoreTracks(start).then((response) => {
tracks.tracks = [...tracks.tracks, ...response.tracks]; tracks.tracks = [...tracks.tracks, ...response.tracks];
tracks.more = response.more; tracks.more = response.more;

View File

@ -4,15 +4,10 @@
</div> </div>
</template> </template>
<script> <script setup>
import state from "@/composables/state.js"; import state from "@/composables/state.js";
export default {
setup() { const loading = state.loading
return {
loading: state.loading,
};
},
};
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@ -1,10 +1,15 @@
<template> <template>
<tr class="songlist-item" :class="{ current: current.trackid === song.trackid }" @dblclick="emitUpdate(song)"> <tr
class="songlist-item"
:class="{ current: current.trackid === song.trackid }"
@dblclick="emitUpdate(song)"
>
<td class="index">{{ index }}</td> <td class="index">{{ index }}</td>
<td class="flex" @click="emitUpdate(song)"> <td class="flex">
<div <div
class="album-art image" class="album-art image"
:style="{ backgroundImage: `url(&quot;${song.image}&quot;` }" :style="{ backgroundImage: `url(&quot;${song.image}&quot;` }"
@click="emitUpdate(song)"
> >
<div <div
class="now-playing-track image" class="now-playing-track image"
@ -12,8 +17,8 @@
:class="{ active: is_playing, not_active: !is_playing }" :class="{ active: is_playing, not_active: !is_playing }"
></div> ></div>
</div> </div>
<div> <div @click="emitUpdate(song)">
<span class="ellip">{{ song.title }}</span> <span class="ellip title">{{ song.title }}</span>
<div class="artist ellip"> <div class="artist ellip">
<span v-for="artist in putCommas(song.artists)" :key="artist"> <span v-for="artist in putCommas(song.artists)" :key="artist">
{{ artist }} {{ artist }}
@ -35,7 +40,10 @@
</div> </div>
</td> </td>
<td class="song-album"> <td class="song-album">
<div class="ellip" @click="emitLoadAlbum(song.album, song.albumartist)"> <div
class="album ellip"
@click="emitLoadAlbum(song.album, song.albumartist)"
>
{{ song.album }} {{ song.album }}
</div> </div>
</td> </td>
@ -94,12 +102,10 @@ export default {
} }
.song-duration { .song-duration {
font-size: .8rem; font-size: 0.8rem;
width: 5rem !important; width: 5rem !important;
} }
cursor: pointer;
.flex { .flex {
position: relative; position: relative;
padding-left: 4rem; padding-left: 4rem;
@ -113,13 +119,19 @@ export default {
margin-right: 1rem; margin-right: 1rem;
display: grid; display: grid;
place-items: center; place-items: center;
border-radius: .5rem; border-radius: 0.5rem;
cursor: pointer;
}
.title {
cursor: pointer;
} }
.artist { .artist {
display: none; display: none;
font-size: 0.8rem; font-size: 0.8rem;
color: rgba(255, 255, 255, 0.719); color: rgba(255, 255, 255, 0.719);
cursor: pointer;
@include phone-only { @include phone-only {
display: unset; display: unset;
@ -136,7 +148,7 @@ export default {
border-radius: $small 0 0 $small; border-radius: $small 0 0 $small;
} }
td:nth-child(2){ td:nth-child(2) {
border-radius: 0 $small $small 0; border-radius: 0 $small $small 0;
@include phone-only { @include phone-only {
@ -194,12 +206,21 @@ export default {
} }
.song-album { .song-album {
.album {
cursor: pointer;
width: max-content;
}
@include tablet-portrait { @include tablet-portrait {
display: none; display: none;
} }
} }
.song-artists { .song-artists {
.artist {
cursor: pointer;
}
@include phone-only { @include phone-only {
display: none; display: none;
} }

View File

@ -1,44 +1,45 @@
let base_uri = "http://0.0.0.0:9876"; import axios from "axios";
import state from "./state";
const getAlbumTracks = async (name, artist) => { const getAlbumTracks = async (album, artist) => {
const res = await fetch( let data = {};
base_uri +
"/album/" +
encodeURIComponent(name) + "/" +
encodeURIComponent(artist) +
"/tracks"
);
if (!res.ok) { await axios
const message = `An error has occurred: ${res.status}`; .post(state.settings.uri + "/album/tracks", {
throw new Error(message); album: album,
} artist: artist,
})
.then((res) => {
data = res.data;
})
.catch((err) => {
console.error(err);
});
return await res.json(); return data;
}; };
const getAlbumArtists = async (name, artist) => { const getAlbumArtists = async (album, artist) => {
const res = await fetch( let artists = [];
base_uri +
"/album/" +
encodeURIComponent(name.replaceAll("/", "|")) +
"/" +
encodeURIComponent(artist.replaceAll("/", "|")) +
"/artists"
);
if (!res.ok) { await axios
const message = `An error has occurred: ${res.status}`; .post(state.settings.uri + "/album/artists", {
throw new Error(message); album: album,
} artist: artist,
})
.then((res) => {
artists = res.data.artists;
})
.catch((err) => {
console.error(err);
});
const data = await res.json(); return artists;
return data.artists;
}; };
const getAlbumBio = async (name, artist) => { const getAlbumBio = async (name, artist) => {
const res = await fetch( const res = await fetch(
base_uri + state.settings.uri +
"/album/" + "/album/" +
encodeURIComponent(name.replaceAll("/", "|")) + encodeURIComponent(name.replaceAll("/", "|")) +
"/" + "/" +

View File

@ -89,7 +89,7 @@ const updateQueue = async (song, type) => {
list = state.folder_song_list.value; list = state.folder_song_list.value;
break; break;
case "album": case "album":
list = state.album_song_list.value; list = state.album.tracklist;
break; break;
} }

View File

@ -5,24 +5,25 @@ import state from "./state.js";
async function toAlbum(title, artist) { async function toAlbum(title, artist) {
console.log("routing to album"); console.log("routing to album");
state.loading.value = true; state.loading.value = true;
await album await album
.getAlbumTracks(title, artist) .getAlbumTracks(title, artist)
.then((data) => { .then((data) => {
state.album_song_list.value = data.songs; state.album.tracklist = data.songs;
state.album_info.value = data.info; state.album.info = data.info;
}) })
.then( .then(
await album.getAlbumArtists(title, artist).then((data) => { await album.getAlbumArtists(title, artist).then((data) => {
state.album_artists.value = data; state.album.artists = data;
}) })
) )
.then( .then(
album.getAlbumBio(title, artist).then((data) => { album.getAlbumBio(title, artist).then((data) => {
if (data === "None") { if (data === "None") {
state.album_bio.value = null; state.album.bio = null;
} else { } else {
state.album_bio.value = data; state.album.bio = data;
} }
}) })
) )

View File

@ -1,4 +1,5 @@
import { ref } from "@vue/reactivity"; import { ref } from "@vue/reactivity";
import { reactive } from "vue";
const search_query = ref(""); const search_query = ref("");
@ -33,10 +34,12 @@ const prev = ref({
}, },
}); });
const album_song_list = ref([]); const album = reactive({
const album_info = ref([]); tracklist: [],
const album_artists = ref([]); info: {},
const album_bio = ref(""); artists: [],
bio: "",
});
const filters = ref([]); const filters = ref([]);
@ -45,9 +48,9 @@ const loading = ref(false);
const is_playing = ref(false); const is_playing = ref(false);
const search_tracks = ref([]); const settings = reactive({
const search_albums = ref([]); uri: "http://0.0.0.0:9876",
const search_artists = ref([]); })
export default { export default {
search_query, search_query,
@ -60,11 +63,6 @@ export default {
magic_flag, magic_flag,
loading, loading,
is_playing, is_playing,
search_tracks, album,
search_albums, settings,
search_artists,
album_song_list,
album_info,
album_artists,
album_bio,
}; };

View File

@ -5,11 +5,6 @@ import router from "./router";
import "../src/assets/css/global.scss"; import "../src/assets/css/global.scss";
import mitt from "mitt";
const emitter = mitt();
const app = createApp(App); const app = createApp(App);
app.use(router); app.use(router);
app.provide('emitter', emitter);
app.mount('#app'); app.mount('#app');

View File

@ -1,26 +1,24 @@
<template> <template>
<div class="al-view rounded"> <div class="al-view rounded">
<div> <div>
<Header :album_info="album_info" /> <Header :album_info="state.album.info" />
</div> </div>
<div class="separator" id="av-sep"></div> <div class="separator" id="av-sep"></div>
<div class="songs rounded"> <div class="songs rounded">
<SongList :songs="album_songs" /> <SongList :songs="state.album.tracklist" />
</div> </div>
<div class="separator" id="av-sep"></div> <div class="separator" id="av-sep"></div>
<FeaturedArtists :artists="artists" /> <FeaturedArtists :artists="state.album.artists" />
<div v-if="bio"> <div v-if="state.album.bio">
<div class="separator" id="av-sep"></div> <div class="separator" id="av-sep"></div>
<AlbumBio :bio="bio" v-if="bio" /> <AlbumBio :bio="state.album.bio" v-if="state.album.bio" />
</div> </div>
<!-- <div class="separator" id="av-sep"></div> -->
</div> </div>
</template> </template>
<script> <script setup>
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { onMounted } from "@vue/runtime-core"; import { onMounted } from "@vue/runtime-core";
import { onUnmounted } from "@vue/runtime-core";
import { watch } from "vue"; import { watch } from "vue";
import Header from "../components/AlbumView/Header.vue"; import Header from "../components/AlbumView/Header.vue";
import AlbumBio from "../components/AlbumView/AlbumBio.vue"; import AlbumBio from "../components/AlbumView/AlbumBio.vue";
@ -31,15 +29,10 @@ import FeaturedArtists from "../components/PlaylistView/FeaturedArtists.vue";
import state from "@/composables/state.js"; import state from "@/composables/state.js";
import routeLoader from "@/composables/routeLoader.js"; import routeLoader from "@/composables/routeLoader.js";
export default { const route = useRoute();
components: {
Header, onMounted(() => {
AlbumBio, routeLoader.toAlbum(route.params.album, route.params.artist);
SongList,
FeaturedArtists,
},
setup() {
const route = useRoute();
watch( watch(
() => route.params, () => route.params,
@ -49,27 +42,7 @@ export default {
} }
} }
); );
});
onMounted(() => {
console.log("mounted");
routeLoader.toAlbum(route.params.album, route.params.artist);
});
onUnmounted(() => {
state.album_song_list.value = [];
state.album_info.value = {};
state.album_artists.value = [];
state.album_bio.value = "";
});
return {
album_songs: state.album_song_list,
album_info: state.album_info,
artists: state.album_artists,
bio: state.album_bio,
};
},
};
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@ -101,13 +101,16 @@ export default {
getDirData(path.value); getDirData(path.value);
watch(route, (new_route) => { watch(
path.value = new_route.params.path; () => route.params,
() => {
path.value = route.params.path;
if (!path.value) return; if (!path.value) return;
getDirData(path.value); getDirData(path.value);
}); }
);
}); });
function updateQueryString(value) { function updateQueryString(value) {