fix albumView using watch function

- other minor changes to almost all files
This commit is contained in:
geoffrey45 2022-02-02 21:45:23 +03:00
parent bdfbb59d76
commit 73dec9189e
27 changed files with 231 additions and 231 deletions

View File

@ -28,6 +28,8 @@ def adutsfsd():
@bp.route('/search') @bp.route('/search')
def search_by_title(): def search_by_title():
query:str = ""
if not request.args.get('q'): if not request.args.get('q'):
query = "mexican girl" query = "mexican girl"
else: else:
@ -83,20 +85,20 @@ def search_by_title():
else: else:
more_tracks = False more_tracks = False
if len(artists_dicts) > 8: if len(artists_dicts) > 6:
more_artists = True more_artists = True
else: else:
more_artists = False more_artists = False
if len(albums_dicts) > 8: if len(albums_dicts) > 6:
more_albums = True more_albums = True
else: else:
more_albums = False more_albums = False
return {'data': [ return {'data': [
{'tracks': tracks[:5], 'more': more_tracks}, {'tracks': tracks[:5], 'more': more_tracks},
{'albums': albums_dicts[:8], 'more': more_albums}, {'albums': albums_dicts[:6], 'more': more_albums},
{'artists': artists_dicts[:8], 'more': more_artists} {'artists': artists_dicts[:6], 'more': more_artists}
]} ]}

View File

@ -83,7 +83,7 @@ def populate_images():
bar.finish() bar.finish()
def extract_thumb(audio_file_path: str = None) -> str: def extract_thumb(audio_file_path: str) -> str:
""" """
Extracts the thumbnail from an audio file. Returns the path to the thumbnail. Extracts the thumbnail from an audio file. Returns the path to the thumbnail.
""" """

View File

@ -5,6 +5,7 @@ This module contains mimi functions for the server.
import os import os
import threading import threading
import time import time
from typing import List
import requests import requests
from io import BytesIO from io import BytesIO
@ -37,10 +38,11 @@ def check_for_new_songs():
while flag is False: while flag is False:
functions.populate() functions.populate()
functions.populate_images()
time.sleep(300) time.sleep(300)
def run_fast_scandir(dir: str, ext: str) -> list: def run_fast_scandir(dir: str, ext: str):
""" """
Scans a directory for files with a specific extension. Returns a list of files and folders in the directory. Scans a directory for files with a specific extension. Returns a list of files and folders in the directory.
""" """
@ -125,7 +127,7 @@ def create_config_dir() -> None:
os.chmod(path, 0o755) os.chmod(path, 0o755)
def getAllSongs() -> None: def getAllSongs() -> List:
""" """
Gets all songs under the ~/ directory. Gets all songs under the ~/ directory.
""" """

View File

@ -67,7 +67,6 @@ export default {
#toggle { #toggle {
position: absolute; position: absolute;
left: 0.2rem;
width: 3rem; width: 3rem;
height: 100%; height: 100%;
background: url(./assets/icons/menu.svg); background: url(./assets/icons/menu.svg);

View File

@ -21,18 +21,20 @@ input[type="range"]::-webkit-slider-thumb {
input[type="range"]::-moz-range-thumb { input[type="range"]::-moz-range-thumb {
-webkit-appearance: none; -webkit-appearance: none;
height: 1rem; height: 0.8rem;
width: 1rem; width: 0.8rem;
border-radius: 50%; border-radius: 50%;
background: $blue; background: $blue;
border: none;
} }
input[type="range"]::-ms-thumb { input[type="range"]::-ms-thumb {
-webkit-appearance: none; -webkit-appearance: none;
height: 1rem; height: 0.8rem;
width: 1rem; width: 0.8rem;
border-radius: 50%; border-radius: 50%;
background: $blue; background: $blue;
border: none;
} }
input[type="range"]::-webkit-slider-thumb:hover { input[type="range"]::-webkit-slider-thumb:hover {

View File

@ -8,11 +8,10 @@
width: auto; width: auto;
height: 100%; height: 100%;
padding: $small $small 0 $small; padding: $small $small 0 $small;
// margin: $small 0 $small 0;
.no-res { .no-res {
text-align: center; text-align: center;
height: calc(100% - 1rem); // height: calc(100% - 1rem);
display: grid; display: grid;
.highlight { .highlight {
@ -45,30 +44,6 @@
background-image: url(../../icons/search.svg); background-image: url(../../icons/search.svg);
background-size: 70%; background-size: 70%;
} }
.v11 {
opacity: 0;
transform: translateY(-4rem);
transition: all 0.2s ease-in;
}
.v00 {
opacity: 1;
transition: all 0.2s ease-in;
}
.suggestions {
display: flex;
gap: 0.5rem;
margin-left: 1rem;
position: absolute;
right: 2.5rem;
.item::before {
content: "#";
color: grey;
}
}
} }
.right-search .scrollable { .right-search .scrollable {

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="b-bar border card-dark"> <div class="b-bar border card-dark">
<div class="grid"> <div class="grid">
<SongCard /> <SongCard/>
<div class="controlsx border rounded"> <div class="controlsx border rounded">
<div class="controls controls-bottom"> <div class="controls controls-bottom">
<HotKeys /> <HotKeys />
@ -9,7 +9,7 @@
<div class="progress progress-bottom"> <div class="progress progress-bottom">
<span class="durationx">0:45</span> <span class="durationx">0:45</span>
<Progress /> <Progress />
<span class="durationx">3:55</span> <span class="durationx">{{ state.current.value.length }}</span>
</div> </div>
<div class="r-group"> <div class="r-group">
<div class="heart image"></div> <div class="heart image"></div>
@ -18,24 +18,15 @@
</div> </div>
<div class="controls controls-bottom"></div> <div class="controls controls-bottom"></div>
</div> </div>
<div class="volume-group"> <div class="volume-group"></div>
</div>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from "vue";
import "../../assets/css/BottomBar/BottomBar.scss"; import "../../assets/css/BottomBar/BottomBar.scss";
import playAudio from "../../composables/playAudio";
import SongCard from "./SongCard.vue"; import SongCard from "./SongCard.vue";
import Progress from "../shared/Progress.vue"; import Progress from "../shared/Progress.vue";
import HotKeys from "../shared/HotKeys.vue"; import HotKeys from "../shared/HotKeys.vue";
import state from "../../composables/state";
const isPlaying = ref(playAudio.playing);
const { playNext } = playAudio;
const { playPrev } = playAudio;
const { playPause } = playAudio;
</script> </script>

View File

@ -26,8 +26,9 @@
<script setup> <script setup>
import { ref } from "vue"; import { ref } from "vue";
import perks from "../../composables/perks"; import perks from "../../composables/perks";
import state from "../../composables/state";
const track = ref(perks.current); const track = ref(state.current);
const putCommas = perks.putCommas; const putCommas = perks.putCommas;
</script> </script>

View File

@ -14,7 +14,7 @@
<tbody> <tbody>
<SongItem <SongItem
v-for="(song, index) in props.songs" v-for="(song, index) in props.songs"
:key="song" :key="song.id"
:song="song" :song="song"
:index="index + 1" :index="index + 1"
@updateQueue="updateQueue" @updateQueue="updateQueue"
@ -25,8 +25,7 @@
</div> </div>
<div v-else-if="props.songs.length === 0 && search_query"> <div v-else-if="props.songs.length === 0 && search_query">
<div class="no-results"> <div class="no-results">
<div class="icon"></div> <div class="text">Nothing down here 😑</div>
<div class="text">No tracks 🎸</div>
</div> </div>
</div> </div>
<div v-else ref="songtitle"></div> <div v-else ref="songtitle"></div>
@ -47,8 +46,8 @@ import state from "@/composables/state.js";
const props = defineProps({ const props = defineProps({
songs: { songs: {
type: Array, type: Array,
required: true required: true,
} },
}); });
let route; let route;
@ -85,7 +84,15 @@ function loadAlbum(title, album_artist) {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-direction: column;
padding: 1rem; padding: 1rem;
// .icon {
// height: 10rem;
// width: 15rem;
// border: solid;
// background-image: url("../../assets/images/sokka.webp");
// }
} }
.table { .table {
@ -138,7 +145,7 @@ table {
display: none; display: none;
} }
width: 5rem; width: 6rem;
} }
th.album-header { th.album-header {
@ -152,4 +159,4 @@ table {
} }
} }
} }
</style> </style>

View File

@ -110,6 +110,7 @@ export default {
align-items: flex-end; align-items: flex-end;
flex-wrap: nowrap; flex-wrap: nowrap;
overflow-x: scroll; overflow-x: scroll;
gap: $small;
&::-webkit-scrollbar { &::-webkit-scrollbar {
display: none; display: none;

View File

@ -1,20 +1,16 @@
<template> <template>
<div class="r-sidebar"> <div class="r-sidebar">
<div class="grid"> <div class="grid">
<div class="r-content border rounded"> <div class="r-content rounded">
<div class="r-dash" v-if="current_tab == tabs.home"> <div class="r-dash" v-show="current_tab == tabs.home">
<DashBoard/> <DashBoard />
</div> </div>
<div class="r-search" v-if="current_tab == tabs.search"> <div class="r-search" v-show="current_tab == tabs.search">
<Search <Search />
v-model:search="search"
@expandSearch="expandSearch"
@collapseSearch="collapseSearch"
/>
</div> </div>
<div class="r-queue" v-if="current_tab == tabs.queue"> <div class="r-queue" v-show="current_tab == tabs.queue">
<UpNext v-model:up_next="up_next" @expandQueue="expandQueue" /> <UpNext />
</div> </div>
</div> </div>
<div class="tab-keys card-dark border"> <div class="tab-keys card-dark border">
@ -33,28 +29,13 @@ import Main from "./Home/Main.vue";
const DashBoard = Main; const DashBoard = Main;
let up_next = ref(true);
let search = ref(false);
const expandQueue = () => {
up_next.value = !up_next.value;
};
const expandSearch = () => {
search.value = true;
};
const collapseSearch = () => {
search.value = false;
};
const tabs = { const tabs = {
home: "home", home: "home",
search: "search", search: "search",
queue: "queue", queue: "queue",
}; };
const current_tab = ref(tabs.search); const current_tab = ref(tabs.queue);
function changeTab(tab) { function changeTab(tab) {
current_tab.value = tab; current_tab.value = tab;
@ -63,18 +44,30 @@ function changeTab(tab) {
<style lang="scss"> <style lang="scss">
.r-sidebar { .r-sidebar {
width: 34em; width: 34.5em;
margin: $small 0 $small 0;
@include phone-only {
display: none;
}
// @include tablet-landscape {
// width: 3rem;
// }
.grid { .grid {
height: 100%; height: 100%;
display: grid; display: flex;
grid-template-areas: "content tabs"; position: relative;
.r-content { .r-content {
grid-area: content; grid-area: content;
width: 100%; width: 31rem;
overflow: hidden; overflow: hidden;
margin: $small $small $small 0;
// @include tablet-landscape {
// display: none;
// }
.r-search { .r-search {
height: 100%; height: 100%;
@ -90,10 +83,12 @@ function changeTab(tab) {
} }
.tab-keys { .tab-keys {
right: 0;
height: 100%;
position: absolute;
grid-area: tabs; grid-area: tabs;
width: 3rem;
padding: $small; padding: $small;
margin-left: $small; border-radius: $small 0 0 $small;
} }
} }
} }

View File

@ -19,8 +19,10 @@
</p> </p>
</div> </div>
</div> </div>
<div class="scrollable-r border"> <div class="scrl border rounded">
<TrackItem v-for="song in queue" :key="song" :track="song" /> <div class="scrollable-r">
<TrackItem v-for="song in queue" :key="song.id" :track="song" />
</div>
</div> </div>
</div> </div>
</div> </div>
@ -76,8 +78,6 @@ export default {
overflow: hidden; overflow: hidden;
height: 100%; height: 100%;
.heading { .heading {
position: relative; position: relative;
margin: 0.5rem 0 1rem 0; margin: 0.5rem 0 1rem 0;
@ -127,13 +127,19 @@ export default {
width: 100%; width: 100%;
display: grid; display: grid;
grid-template-rows: min-content 1fr; grid-template-rows: min-content 1fr;
padding-bottom: $small;
.scrl {
overflow: hidden;
height: 100%;
}
.scrollable-r { .scrollable-r {
margin-bottom: $small; height: 100%;
padding: $small; padding: $small;
overflow: auto; overflow: auto;
background-color: $card-dark; background-color: $card-dark;
border-radius: 0.5rem; scrollbar-color: grey transparent;
&::-webkit-scrollbar-track { &::-webkit-scrollbar-track {
background-color: transparent; background-color: transparent;

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="right-search" ref="searchComponent"> <div class="right-search border">
<div> <div>
<div class="input"> <div class="input">
<Loader /> <Loader />
@ -8,29 +8,17 @@
<input <input
type="text" type="text"
id="search" id="search"
@focus="activateMagicFlag"
@blur="removeMagicFlag"
@keyup.backspace="removeLastFilter" @keyup.backspace="removeLastFilter"
placeholder="find your music" placeholder="find your music"
v-model="query" v-model="query"
/> />
<div class="search-icon image"></div> <div class="search-icon image"></div>
<!-- -->
</div>
<div
class="suggestions v00"
:class="{
v00: !filters.length && !query,
v11: filters.length || query,
}"
>
<div class="item">Kenny Rogers</div>
</div> </div>
</div> </div>
<div class="separator no-border"></div> <div class="separator no-border"></div>
<Options :magic_flag="magic_flag" @addFilter="addFilter" /> <Options @addFilter="addFilter" />
</div> </div>
<div class="scrollable" :class="{ v0: !is_hidden, v1: is_hidden }"> <div class="scrollable">
<TracksGrid <TracksGrid
:tracks="tracks.tracks" :tracks="tracks.tracks"
:more="tracks.more" :more="tracks.more"
@ -52,22 +40,24 @@
v-if=" v-if="
!artists.artists.length && !artists.artists.length &&
!tracks.tracks.length && !tracks.tracks.length &&
!albums.albums.length !albums.albums.length && query.length != 0
" "
> >
<div class="no-res-icon image"></div>
<div class="no-res-text"> <div class="no-res-text">
No results for <span class="highlight rounded">{{ query }}</span> No results for <span class="highlight rounded">{{ query }}</span>
</div> </div>
</div> </div>
<div v-else-if="query.length == 0" class="no-res">
<div class="no-res-text">Find your music 🔍😀</div>
</div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { reactive, ref, toRefs } from "@vue/reactivity"; import { reactive, ref } from "@vue/reactivity";
import { onMounted, watch } from "@vue/runtime-core"; import { watch } from "@vue/runtime-core";
import state from "@/composables/state.js"; import state from "@/composables/state.js";
import searchMusic from "@/composables/searchMusic.js"; import searchMusic from "@/composables/searchMusic.js";
import useDebouncedRef from "@/composables/useDebouncedRef"; import useDebouncedRef from "@/composables/useDebouncedRef";
@ -80,8 +70,6 @@ import Filters from "@/components/Search/Filters.vue";
import "@/assets/css/Search/Search.scss"; import "@/assets/css/Search/Search.scss";
export default { export default {
emits: ["expandSearch", "collapseSearch"],
props: ["search"],
components: { components: {
AlbumGrid, AlbumGrid,
ArtistGrid, ArtistGrid,
@ -91,9 +79,8 @@ export default {
Filters, Filters,
}, },
setup(props, { emit }) { setup() {
const loading = ref(state.loading); const loading = ref(state.loading);
const searchComponent = ref(null);
const filters = ref([]); const filters = ref([]);
const tracks = reactive({ const tracks = reactive({
@ -111,9 +98,7 @@ export default {
more: false, more: false,
}); });
const query = useDebouncedRef("", 400); const query = useDebouncedRef("", 600);
const magic_flag = ref(state.magic_flag);
const is_hidden = toRefs(props).search;
function addFilter(filter) { function addFilter(filter) {
if (!filters.value.includes(filter)) { if (!filters.value.includes(filter)) {
@ -137,24 +122,15 @@ export default {
} }
} }
function activateMagicFlag() {
setTimeout(() => {
state.magic_flag.value = true;
}, 300);
}
function removeMagicFlag() {
setTimeout(() => {
if (
(!filters.value.length && query.value == null) ||
query.value == ""
) {
state.magic_flag.value = false;
}
}, 3000);
}
watch(query, (new_query) => { watch(query, (new_query) => {
if (query.value == "" || query.value == " " || query.value.length < 2) {
albums.albums = [];
artists.artists = [];
tracks.tracks = [];
return;
};
searchMusic(new_query).then((res) => { searchMusic(new_query).then((res) => {
albums.albums = res.albums.albums; albums.albums = res.albums.albums;
albums.more = res.albums.more; albums.more = res.albums.more;
@ -165,43 +141,19 @@ export default {
tracks.tracks = res.tracks.tracks; tracks.tracks = res.tracks.tracks;
tracks.more = res.tracks.more; tracks.more = res.tracks.more;
}); });
state.search_query.value = new_query;
if (new_query !== "" && new_query.length > 2) {
counter = 0;
emit("expandSearch");
} else {
emit("collapseSearch");
}
});
onMounted(() => {
const dom = document.getElementsByClassName("right-search")[0];
document.addEventListener("click", (e) => {
var isClickedInside = dom.contains(e.target);
if (!isClickedInside) {
emit("collapseSearch");
}
});
}); });
return { return {
addFilter, addFilter,
activateMagicFlag,
removeMagicFlag,
removeFilter, removeFilter,
removeLastFilter, removeLastFilter,
tracks, tracks,
albums, albums,
artists, artists,
query, query,
is_hidden,
magic_flag,
filters, filters,
searchComponent,
loading, loading,
searchMusic,
}; };
}, },
}; };

View File

@ -34,17 +34,15 @@ export default {
.right-search .albums-results { .right-search .albums-results {
border-radius: 0.5rem; border-radius: 0.5rem;
background: #0f131b44; background: #0f131b44;
margin-top: $small; margin-top: $small;
padding: $small 0; padding-bottom: $small;
padding-top: $small;
overflow-x: hidden; overflow-x: hidden;
.grid { .grid {
display: grid; display: flex;
grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
flex-wrap: wrap; flex-wrap: wrap;
padding: 0 0 0 $small; padding: $small $small 0 $small;
gap: $small; gap: $small;
} }
} }

View File

@ -42,9 +42,10 @@ export default {
margin-bottom: $small; margin-bottom: $small;
.grid { .grid {
padding: 0 0 0 $small; padding: $small $small 0 $small;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: $small;
} }
} }
</style> </style>

View File

@ -32,8 +32,8 @@ export default {
margin-left: 2rem; margin-left: 2rem;
height: 2rem; height: 2rem;
.item { .item {
transition: all 0.2s ease-in-out;
&:hover { &:hover {
width: 4rem; width: 4rem;
@ -48,4 +48,4 @@ export default {
} }
} }
} }
</style> </style>

View File

@ -1,13 +1,16 @@
<template> <template>
<div class="options border rounded"> <div class="options border rounded">
<div class="item info">Filter by:</div> <div class="item info header">Filter by:</div>
<div <div
class="item" class="item"
v-for="option in options" v-for="option in options"
:key="option" :key="option"
@click="addFilter(option.icon)" @click="addFilter(option.icon)"
> >
{{ option.title }} <div>
<span class="icon">{{ option.icon }}</span>
<span class="title">&nbsp;&nbsp;{{ option.title }}</span>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -18,23 +21,23 @@ export default {
setup(props, { emit }) { setup(props, { emit }) {
const options = [ const options = [
{ {
title: "🎵 Track", title: "Track",
icon: "🎵", icon: "🎵",
}, },
{ {
title: "💿 Album", title: "Album",
icon: "💿", icon: "💿",
}, },
{ {
title: "🙄 Artist", title: "Artist",
icon: "🙄", icon: "🙄",
}, },
{ {
title: "😍 Playlist", title: "Playlist",
icon: "😍", icon: "😍",
}, },
{ {
title: "📁 Folder", title: "Folder",
icon: "📁", icon: "📁",
}, },
]; ];
@ -58,6 +61,38 @@ export default {
.item { .item {
margin: $small; margin: $small;
width: 2.5rem;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
transition: all 0.2s ease-in-out;
position: relative;
.title {
position: absolute;
left: 1.5rem;
top: 0.5rem;
visibility: hidden;
}
.icon {
position: absolute;
top: 0.5rem;
left: .75rem;
}
&:hover {
width: 5.5rem;
.title {
visibility: visible;
}
}
}
.header {
width: 5.5rem;
} }
} }
</style> </style>

View File

@ -6,7 +6,7 @@
<tbody> <tbody>
<TrackItem <TrackItem
v-for="track in props.tracks" v-for="track in props.tracks"
:key="track" :key="track.id"
:track="track" :track="track"
/> />
</tbody> </tbody>

View File

@ -32,6 +32,7 @@ export default {
border-radius: $small; border-radius: $small;
text-align: left !important; text-align: left !important;
width: 9rem; width: 9rem;
// border: solid 1px red !important;
.album-art { .album-art {
height: 7rem; height: 7rem;

View File

@ -21,7 +21,6 @@ export default {
flex: 0 0 auto; flex: 0 0 auto;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
margin: 0 $small 0 0;
width: 9em; width: 9em;
height: 11em; height: 11em;

View File

@ -14,7 +14,6 @@
</div> </div>
<div> <div>
<span class="ellip">{{ song.title }}</span> <span class="ellip">{{ song.title }}</span>
<div class="separator no-border"></div>
<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 }}

View File

@ -60,6 +60,9 @@ const playThis = (song) => {
align-items: center; align-items: center;
padding: 0.5rem; padding: 0.5rem;
border-radius: 0.5rem; border-radius: 0.5rem;
position: relative;
height: 4rem;
padding-left: 4rem;
&:hover { &:hover {
cursor: pointer; cursor: pointer;
@ -72,6 +75,8 @@ const playThis = (song) => {
} }
.album-art { .album-art {
position: absolute;
left: $small;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@ -83,7 +88,6 @@ const playThis = (song) => {
background-image: url(../../assets/images/null.webp); background-image: url(../../assets/images/null.webp);
} }
.artist { .artist {
width: 20rem;
font-size: small; font-size: small;
color: rgba(255, 255, 255, 0.637); color: rgba(255, 255, 255, 0.637);
} }

View File

@ -1,6 +1,6 @@
let base_uri = "http://0.0.0.0:9876"; let base_uri = "http://0.0.0.0:9876";
const getData = async (path) => { const getTracksAndDirs = async (path) => {
let url; let url;
const encoded_path = encodeURIComponent(path.replaceAll("/", "|")); const encoded_path = encodeURIComponent(path.replaceAll("/", "|"));
@ -21,4 +21,4 @@ const getData = async (path) => {
return { songs, folders }; return { songs, folders };
}; };
export default getData; export default getTracksAndDirs;

View File

@ -37,9 +37,7 @@ const putCommas = (artists) => {
}; };
function updateNext(song_) { function updateNext(song_) {
const index = state.queue.value.findIndex( const index = state.queue.value.findIndex((item) => item.id === song_.id);
(item) => item.id === song_.id
);
if (index == queue.value.length - 1) { if (index == queue.value.length - 1) {
next.value = queue.value[0]; next.value = queue.value[0];
@ -52,9 +50,7 @@ function updateNext(song_) {
} }
function updatePrev(song) { function updatePrev(song) {
const index = state.queue.value.findIndex( const index = state.queue.value.findIndex((item) => item.id === song.id);
(item) => item.id === song.id
);
if (index == 0) { if (index == 0) {
prev.value = queue.value[queue.value.length - 1]; prev.value = queue.value[queue.value.length - 1];
@ -82,7 +78,7 @@ const readQueue = () => {
}; };
const updateQueue = async (song, type) => { const updateQueue = async (song, type) => {
playAudio.playAudio(song.filepath) playAudio.playAudio(song.filepath);
let list; let list;
switch (type) { switch (type) {
@ -93,9 +89,9 @@ const updateQueue = async (song, type) => {
list = state.album_song_list.value; list = state.album_song_list.value;
break; break;
} }
if (state.queue.value[0].id !==list[0].id) { if (state.queue.value[0].id !== list[0].id) {
const new_queue =list; const new_queue = list;
localStorage.setItem("queue", JSON.stringify(new_queue)); localStorage.setItem("queue", JSON.stringify(new_queue));
state.queue.value = new_queue; state.queue.value = new_queue;
} }
@ -152,6 +148,8 @@ window.addEventListener("keydown", (e) => {
switch (e.key) { switch (e.key) {
case "ArrowRight": case "ArrowRight":
if (target.tagName == "INPUT") return;
{ {
if (!key_down_fired) { if (!key_down_fired) {
key_down_fired = true; key_down_fired = true;
@ -168,6 +166,8 @@ window.addEventListener("keydown", (e) => {
case "ArrowLeft": case "ArrowLeft":
{ {
if (!key_down_fired) { if (!key_down_fired) {
if (target.tagName == "INPUT") return;
key_down_fired = true; key_down_fired = true;
playAudio.playPrev(); playAudio.playPrev();

View File

@ -4,6 +4,7 @@ import album from "./album.js";
import state from "./state.js"; import state from "./state.js";
function toAlbum(title, artist) { function toAlbum(title, artist) {
state.loading.value = true;
album album
.getAlbumTracks(title, artist) .getAlbumTracks(title, artist)
.then((data) => { .then((data) => {
@ -24,15 +25,16 @@ function toAlbum(title, artist) {
} }
}) })
) )
.then( .then(() => {
Router.push({ Router.push({
name: "AlbumView", name: "AlbumView",
params: { params: {
album: title, album: title,
artist: artist, artist: artist,
}, },
}) });
) state.loading.value = false;
})
.catch((error) => { .catch((error) => {
console.log(error); console.log(error);
}); });

View File

@ -10,7 +10,7 @@
<div class="separator" id="av-sep"></div> <div class="separator" id="av-sep"></div>
<FeaturedArtists :artists="artists" /> <FeaturedArtists :artists="artists" />
<div class="separator" id="av-sep"></div> <div class="separator" id="av-sep"></div>
<AlbumBio :bio="bio" v-if="bio"/> <AlbumBio :bio="bio" v-if="bio" />
<div class="separator" id="av-sep"></div> <div class="separator" id="av-sep"></div>
</div> </div>
</template> </template>
@ -19,7 +19,7 @@
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 { onUnmounted } from "@vue/runtime-core";
import { watch, ref } 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";
@ -27,7 +27,7 @@ import SongList from "../components/FolderView/SongList.vue";
import FeaturedArtists from "../components/PlaylistView/FeaturedArtists.vue"; 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 { export default {
components: { components: {
@ -38,13 +38,16 @@ export default {
}, },
setup() { setup() {
const route = useRoute(); const route = useRoute();
const title = route.params.album;
const album_artists = route.params.artist; watch(
() => route.params,
() => {
routeLoader.toAlbum(route.params.album, route.params.artist);
}
);
onMounted(() => { onMounted(() => {
if (!state.album_song_list.value.length) { routeLoader.toAlbum(route.params.album, route.params.artist);
routeLoader.toAlbum(title, album_artists);
}
}); });
onUnmounted(() => { onUnmounted(() => {
@ -69,7 +72,7 @@ export default {
height: calc(100% - 1rem); height: calc(100% - 1rem);
overflow: auto; overflow: auto;
margin-top: $small; margin-top: $small;
scrollbar-width: none;
.songs { .songs {
padding: $small; padding: $small;
background-color: $card-dark; background-color: $card-dark;
@ -83,4 +86,4 @@ export default {
border: none; border: none;
} }
} }
</style> </style>

View File

@ -1,7 +1,7 @@
<template> <template>
<div id="f-view-parent" class="rounded"> <div id="f-view-parent" class="rounded">
<div class="fixed"> <div class="fixed">
<Header :path="path" :first_song="songs[0]" @search="filterSongs" /> <Header :path="path" :first_song="songs[0]" @search="updateQueryString" />
</div> </div>
<div id="scrollable" ref="scrollable"> <div id="scrollable" ref="scrollable">
<FolderList :folders="folders" /> <FolderList :folders="folders" />
@ -19,7 +19,7 @@ import SongList from "@/components/FolderView/SongList.vue";
import FolderList from "@/components/FolderView/FolderList.vue"; import FolderList from "@/components/FolderView/FolderList.vue";
import Header from "@/components/FolderView/Header.vue"; import Header from "@/components/FolderView/Header.vue";
import getData from "../composables/getFiles.js"; import getTracksAndDirs from "../composables/getFiles.js";
import { onMounted, watch } from "@vue/runtime-core"; import { onMounted, watch } from "@vue/runtime-core";
import state from "@/composables/state.js"; import state from "@/composables/state.js";
@ -34,16 +34,16 @@ export default {
const path = ref(route.params.path); const path = ref(route.params.path);
const song_list = ref(state.folder_song_list); const song_list = ref(state.folder_song_list);
const folders = ref(state.folder_list); const folders_list = ref(state.folder_list);
const scrollable = ref(null); const scrollable = ref(null);
const query = ref(''); const query = ref("");
const songs = computed(() => { const songs = computed(() => {
const songs_ = []; const songs_ = [];
if (query.value.length > 2) { if (query.value.length > 1) {
for (let i = 0; i < song_list.value.length; i++) { for (let i = 0; i < song_list.value.length; i++) {
if ( if (
song_list.value[i].title song_list.value[i].title
@ -60,37 +60,62 @@ export default {
} }
}); });
const folders = computed(() => {
const folders_ = [];
if (query.value.length > 1) {
for (let i = 0; i < folders_list.value.length; i++) {
if (
folders_list.value[i].name
.toLowerCase()
.includes(query.value.toLowerCase())
) {
folders_.push(folders_list.value[i]);
}
}
return folders_;
} else {
return folders_list.value;
}
});
onMounted(() => { onMounted(() => {
const getPathFolders = (path, last_id) => { const getDirData = (path) => {
state.loading.value = true; state.loading.value = true;
getData(path, last_id).then((data) => { getTracksAndDirs(path)
scrollable.value.scrollTop = 0; .then((data) => {
scrollable.value.scrollTop = 0;
state.folder_song_list.value = data.songs; state.folder_song_list.value = data.songs;
state.folder_list.value = data.folders; state.folder_list.value = data.folders;
state.loading.value = false; state.loading.value = false;
}); })
.then(() => {
setTimeout(() => {
query.value = "";
}, 100);
});
}; };
getPathFolders(path.value); getDirData(path.value);
watch(route, (new_route) => { watch(route, (new_route) => {
state.search_query.value = "";
path.value = new_route.params.path; path.value = new_route.params.path;
if (!path.value) return; if (!path.value) return;
getPathFolders(path.value); getDirData(path.value);
}); });
}); });
function filterSongs(value) { function updateQueryString(value) {
query.value = value; query.value = value;
} }
return { return {
filterSongs, updateQueryString,
songs, songs,
folders, folders,
path, path,
@ -129,4 +154,4 @@ export default {
} }
} }
} }
</style> </style>