major refactoring

- move instances to new file
- import functions as modules
- add docstrings to helper functions
- add threaded populate() function
- remove unused functions and files
- add typing info to helper functions
- other unremembered changes to the client
This commit is contained in:
geoffrey45 2022-01-14 20:46:55 +03:00
parent e473b5db92
commit 00e2b06e9d
12 changed files with 304 additions and 312 deletions

View File

@ -1,60 +1,25 @@
from app.models import Artists
from app.helpers import (
all_songs_instance,
getTags,
remove_duplicates,
save_image,
create_config_dir,
extract_thumb,
run_fast_scandir,
convert_one_to_json,
convert_to_json,
home_dir, app_dir,
)
from app import cache
import os import os
import requests
import urllib import urllib
from flask import Blueprint, request
from progress.bar import Bar from app import functions, instances, helpers, cache
from mutagen.flac import MutagenError
from flask import Blueprint, request, send_from_directory
bp = Blueprint('api', __name__, url_prefix='') bp = Blueprint('api', __name__, url_prefix='')
artist_instance = Artists()
img_path = "http://127.0.0.1:8900/images/thumbnails/"
all_the_f_music = [] all_the_f_music = []
home_dir = helpers.home_dir
def getAllSongs(): all_the_f_music = helpers.getAllSongs()
all_the_f_music.clear()
all_the_f_music.extend(all_songs_instance.get_all_songs())
def initialize() -> None:
helpers.create_config_dir()
helpers.check_for_new_songs()
def main_whatever(): initialize()
create_config_dir()
# populate()
getAllSongs()
@bp.route('/') @bp.route('/')
def adutsfsd(): def adutsfsd():
for song in all_the_f_music: return "^ _ ^"
print(os.path.join(home_dir, song['filepath']))
os.chmod(os.path.join(home_dir, song['filepath']), 0o755)
return "Done"
main_whatever()
@bp.route('/search') @bp.route('/search')
@ -67,9 +32,9 @@ def search_by_title():
albums = [] albums = []
artists = [] artists = []
s = all_songs_instance.find_song_by_title(query) s = instances.songs_instance.find_song_by_title(query)
al = all_songs_instance.search_songs_by_album(query) al = instances.songs_instance.search_songs_by_album(query)
ar = all_songs_instance.search_songs_by_artist(query) ar = instances.songs_instance.search_songs_by_artist(query)
for song in al: for song in al:
album_obj = { album_obj = {
@ -82,7 +47,7 @@ def search_by_title():
for album in albums: for album in albums:
# try: # try:
# image = convert_one_to_json(all_songs_instance.get_song_by_album(album['name'], album['artists']))['image'] # image = convert_one_to_json(instances.songs_instance.get_song_by_album(album['name'], album['artists']))['image']
# except: # except:
# image: None # image: None
@ -101,52 +66,21 @@ def search_by_title():
if artist_obj not in artists: if artist_obj not in artists:
artists.append(artist_obj) artists.append(artist_obj)
return {'songs': remove_duplicates(s), 'albums': albums, 'artists': artists} return {'songs': helpers.remove_duplicates(s), 'albums': albums, 'artists': artists}
@bp.route('/populate') @bp.route('/populate')
def populate(): def x():
''' functions.populate()
Populate the database with all songs in the music directory return "🎸"
checks if the song is in the database, if not, it adds it
also checks if the album art exists in the image path, if not tries to
extract it.
'''
files = run_fast_scandir(home_dir, [".flac", ".mp3"])[1]
bar = Bar('Processing', max=len(files))
for file in files:
file_in_db_obj = all_songs_instance.find_song_by_path(file)
try:
image = file_in_db_obj['image']
if not os.path.exists(os.path.join(app_dir, 'images', 'thumbnails', image)):
extract_thumb(file)
except:
image = None
if image is None:
try:
getTags(file)
except MutagenError:
pass
bar.next()
bar.finish()
return {'msg': 'updated everything'}
@bp.route("/folder/artists") @bp.route("/folder/artists")
def get_folder_artists(): def get_folder_artists():
dir = request.args.get('dir') dir = request.args.get('dir')
songs = all_songs_instance.find_songs_by_folder(dir) songs = instances.songs_instance.find_songs_by_folder(dir)
without_duplicates = remove_duplicates(songs) without_duplicates = helpers.remove_duplicates(songs)
artists = [] artists = []
@ -161,7 +95,7 @@ def get_folder_artists():
final_artists = [] final_artists = []
for artist in artists[:15]: for artist in artists[:15]:
artist_obj = artist_instance.find_artists_by_name(artist) artist_obj = instances.artist_instance.find_artists_by_name(artist)
if artist_obj != []: if artist_obj != []:
final_artists.append(artist_obj) final_artists.append(artist_obj)
@ -171,51 +105,7 @@ def get_folder_artists():
@bp.route("/populate/images") @bp.route("/populate/images")
def populate_images(): def populate_images():
all_songs = all_songs_instance.get_all_songs() functions.populate_images()
artists = []
for song in all_songs:
this_artists = song['artists'].split(', ')
for artist in this_artists:
if artist not in artists:
artists.append(artist)
bar = Bar('Processing images', max=len(artists))
for artist in artists:
file_path = app_dir + '/images/artists/' + artist + '.jpg'
if not os.path.exists(file_path):
url = 'https://api.deezer.com/search/artist?q={}'.format(artist)
response = requests.get(url)
data = response.json()
try:
image_path = data['data'][0]['picture_xl']
except:
image_path = None
if image_path is not None:
try:
save_image(image_path, file_path)
artist_obj = {
'name': artist
}
artist_instance.insert_artist(artist_obj)
except:
pass
else:
pass
bar.next()
bar.finish()
artists_in_db = artist_instance.get_all_artists()
return {'sample': artists_in_db[:25]}
@bp.route("/artist/<artist>") @bp.route("/artist/<artist>")
@ -223,21 +113,21 @@ def populate_images():
def getArtistData(artist: str): def getArtistData(artist: str):
print(artist) print(artist)
artist = urllib.parse.unquote(artist) artist = urllib.parse.unquote(artist)
artist_obj = artist_instance.get_artists_by_name(artist) artist_obj = instances.artist_instance.get_artists_by_name(artist)
def getArtistSongs(): def getArtistSongs():
songs = all_songs_instance.find_songs_by_artist(artist) songs = instances.songs_instance.find_songs_by_artist(artist)
return songs return songs
artist_songs = getArtistSongs() artist_songs = getArtistSongs()
songs = remove_duplicates(artist_songs) songs = helpers.remove_duplicates(artist_songs)
def getArtistAlbums(): def getArtistAlbums():
artist_albums = [] artist_albums = []
albums_with_count = [] albums_with_count = []
albums = all_songs_instance.find_songs_by_album_artist(artist) albums = instances.songs_instance.find_songs_by_album_artist(artist)
for song in songs: for song in songs:
song['artists'] = song['artists'].split(', ') song['artists'] = song['artists'].split(', ')
@ -282,7 +172,8 @@ def getFolderTree(folder: str = None):
for entry in dir_content: for entry in dir_content:
if entry.is_dir() and not entry.name.startswith('.'): if entry.is_dir() and not entry.name.startswith('.'):
files_in_dir = run_fast_scandir(entry.path, [".flac", ".mp3"])[1] files_in_dir = helpers.run_fast_scandir(
entry.path, [".flac", ".mp3"])[1]
if len(files_in_dir) != 0: if len(files_in_dir) != 0:
dir = { dir = {
@ -295,12 +186,12 @@ def getFolderTree(folder: str = None):
# if entry.is_file(): # if entry.is_file():
# if isValidFile(entry.name) == True: # if isValidFile(entry.name) == True:
# file = all_songs_instance.find_song_by_path(entry.path) # file = instances.songs_instance.find_song_by_path(entry.path)
# if not file: # if not file:
# getTags(entry.path) # getTags(entry.path)
# songs_array = all_songs_instance.find_songs_by_folder( # songs_array = instances.songs_instance.find_songs_by_folder(
# req_dir) # req_dir)
songs = [] songs = []
@ -311,19 +202,16 @@ def getFolderTree(folder: str = None):
for song in songs: for song in songs:
try: try:
song['artists'] = song['artists'].split(', ') or None song['artists'] = song['artists'].split(', ')
except: except:
pass pass
if song['image'] is not None:
print(song['image'])
song['image'] = img_path + song['image']
return {"files": remove_duplicates(songs), "folders": sorted(folders, key=lambda i: i['name'])} return {"files": helpers.remove_duplicates(songs), "folders": sorted(folders, key=lambda i: i['name'])}
@bp.route('/qwerty') @bp.route('/qwerty')
def populateArtists(): def populateArtists():
all_songs = all_songs_instance.get_all_songs() all_songs = instances.songs_instance.get_all_songs()
artists = [] artists = []
@ -338,14 +226,14 @@ def populateArtists():
if a_obj not in artists: if a_obj not in artists:
artists.append(a_obj) artists.append(a_obj)
artist_instance.insert_artist(a_obj) instances.artist_instance.insert_artist(a_obj)
return {'songs': artists} return {'songs': artists}
@bp.route('/albums') @bp.route('/albums')
def getAlbums(): def getAlbums():
s = all_songs_instance.get_all_songs() s = instances.songs_instance.get_all_songs()
albums = [] albums = []
@ -366,13 +254,13 @@ def getAlbumSongs(query: str):
album = query.split('::')[0].replace('|', '/') album = query.split('::')[0].replace('|', '/')
artist = query.split('::')[1].replace('|', '/') artist = query.split('::')[1].replace('|', '/')
songs = all_songs_instance.find_songs_by_album(album, artist) songs = instances.songs_instance.find_songs_by_album(album, artist)
print(artist) print(artist)
for song in songs: for song in songs:
song['artists'] = song['artists'].split(', ') song['artists'] = song['artists'].split(', ')
song['image'] = img_path + song['image'] song['image'] = "http://127.0.0.1:8900/images/thumbnails/" + song['image']
album_obj = { album_obj = {
"name": album, "name": album,

View File

@ -1,6 +0,0 @@
default_configs = {
"dirs": [
"/home/cwilvx/Music/",
"/home/cwilvx/FreezerMusic"
]
}

94
server/app/functions.py Normal file
View File

@ -0,0 +1,94 @@
"""
This module contains larger functions for the server
"""
from progress.bar import Bar
import requests
import os
from mutagen.flac import MutagenError
from app import helpers
from app import instances
def populate():
'''
Populate the database with all songs in the music directory
checks if the song is in the database, if not, it adds it
also checks if the album art exists in the image path, if not tries to
extract it.
'''
files = helpers.run_fast_scandir(helpers.home_dir, [".flac", ".mp3"])[1]
bar = Bar('Indexing files', max=len(files))
for file in files:
file_in_db_obj = instances.songs_instance.find_song_by_path(file)
try:
image = file_in_db_obj['image']
if not os.path.exists(os.path.join(helpers.app_dir, 'images', 'thumbnails', image)):
helpers.extract_thumb(file)
except:
image = None
if image is None:
try:
helpers.getTags(file)
except MutagenError:
pass
bar.next()
bar.finish()
return {'msg': 'updated everything'}
def populate_images():
all_songs = instances.songs_instance.get_all_songs()
artists = []
for song in all_songs:
this_artists = song['artists'].split(', ')
for artist in this_artists:
if artist not in artists:
artists.append(artist)
bar = Bar('Processing images', max=len(artists))
for artist in artists:
file_path = helpers.app_dir + '/images/artists/' + artist + '.jpg'
if not os.path.exists(file_path):
url = 'https://api.deezer.com/search/artist?q={}'.format(artist)
response = requests.get(url)
data = response.json()
try:
image_path = data['data'][0]['picture_xl']
except:
image_path = None
if image_path is not None:
try:
helpers.save_image(image_path, file_path)
artist_obj = {
'name': artist
}
instances.artist_instance.insert_artist(artist_obj)
except:
pass
else:
pass
bar.next()
bar.finish()
artists_in_db = instances.artist_instance.get_all_artists()
return {'sample': artists_in_db[:25]}

View File

@ -1,32 +1,49 @@
from genericpath import exists """
This module contains mimi functions for the server.
"""
import os import os
import json import threading
import time
import requests import requests
import urllib
from mutagen.mp3 import MP3 from mutagen.mp3 import MP3
from mutagen.id3 import ID3 from mutagen.id3 import ID3
from mutagen.flac import FLAC from mutagen.flac import FLAC
from bson import json_util
from io import BytesIO from io import BytesIO
from PIL import Image from PIL import Image
from app.models import AllSongs from app import instances
from app.configs import default_configs from app import functions
all_songs_instance = AllSongs()
music_dir = os.environ.get("music_dir")
music_dirs = os.environ.get("music_dirs")
home_dir = os.path.expanduser('~') + "/" home_dir = os.path.expanduser('~') + "/"
app_dir = home_dir + '/.musicx' app_dir = home_dir + '/.musicx'
PORT = os.environ.get("PORT")
def background(f):
'''
a threading decorator
use @background above the function you want to run in the background
'''
def backgrnd_func(*a, **kw):
threading.Thread(target=f, args=a, kwargs=kw).start()
return backgrnd_func
@background
def check_for_new_songs():
flag = False
while flag is False:
functions.populate()
time.sleep(300)
def run_fast_scandir(dir, ext): def run_fast_scandir(dir: str, ext: str) -> list:
"""
Scans a directory for files with a specific extension. Returns a list of files and folders in the directory.
"""
subfolders = [] subfolders = []
files = [] files = []
@ -45,7 +62,11 @@ def run_fast_scandir(dir, ext):
return subfolders, files return subfolders, files
def extract_thumb(path): def extract_thumb(path: str) -> str:
"""
Extracts the thumbnail from an audio file. Returns the path to the thumbnail.
"""
webp_path = path.split('/')[-1] + '.webp' webp_path = path.split('/')[-1] + '.webp'
img_path = app_dir + "/images/thumbnails/" + webp_path img_path = app_dir + "/images/thumbnails/" + webp_path
@ -88,7 +109,11 @@ def extract_thumb(path):
return webp_path return webp_path
def getTags(full_path): def getTags(full_path: str) -> dict:
"""
Returns a dictionary of tags for a given file.
"""
if full_path.endswith('.flac'): if full_path.endswith('.flac'):
try: try:
audio = FLAC(full_path) audio = FLAC(full_path)
@ -169,120 +194,56 @@ def getTags(full_path):
} }
} }
all_songs_instance.insert_song(tags) instances.songs_instance.insert_song(tags)
return tags return tags
def convert_one_to_json(song): def remove_duplicates(array: list) -> list:
json_song = json.dumps(song, default=json_util.default) """
loaded_song = json.loads(json_song) Removes duplicates from a list. Returns a list without duplicates.
"""
return loaded_song
def convert_to_json(array):
songs = []
for song in array:
json_song = json.dumps(song, default=json_util.default)
loaded_song = json.loads(json_song)
songs.append(loaded_song)
return songs
def get_folders():
folders = []
for dir in default_configs['dirs']:
entry = os.scandir(dir)
folders.append(entry)
def remove_duplicates(array):
song_num = 0 song_num = 0
while song_num < len(array) -1: while song_num < len(array) - 1:
for index, song in enumerate(array): for index, song in enumerate(array):
try: try:
if array[song_num]["title"] == song["title"] and array[song_num]["album"] == song["album"] and array[song_num]["artists"] == song["artists"] and index != song_num: if array[song_num]["title"] == song["title"] and array[song_num]["album"] == song["album"] and array[song_num]["artists"] == song["artists"] and index != song_num:
array.remove(song) array.remove(song)
except: except:
print('whe') print('whe')
song_num += 1 song_num += 1
return array return array
def save_image(url, path): def save_image(url: str, path: str) -> None:
"""
Saves an image from a url to a path.
"""
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 isValidFile(filename): def isValidFile(filename: str) -> bool:
"""
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
def isValidAudioFrom(folder): def create_config_dir() -> None:
folder_content = os.scandir(folder) """
files = [] Creates the config directory if it doesn't exist.
"""
for entry in folder_content:
if isValidFile(entry.name) == True:
file = {
"path": entry.path,
"name": entry.name
}
files.append(file)
return files
def getFolderContents(filepath, folder):
folder_name = urllib.parse.unquote(folder)
path = filepath
name = filepath.split('/')[-1]
tags = {}
if name.endswith('.flac'):
image_path = folder_name + '/.thumbnails/' + \
name.replace('.flac', '.jpg')
audio = FLAC(path)
if name.endswith('.mp3'):
image_path = folder_name + '/.thumbnails/' + \
name.replace('.mp3', '.jpg')
audio = MP3(path)
abslt_path = urllib.parse.quote(path.replace(music_dir, ''))
if os.path.exists(image_path):
img_url = 'http://localhost:{}/{}'.format(
PORT,
urllib.parse.quote(image_path.replace(music_dir, ''))
)
try:
audio_url = 'http://localhost:{}/{}'.format(
PORT, abslt_path
)
tags = getTags(audio_url, audio, img_url, folder_name)
except:
pass
return tags
def create_config_dir():
home_dir = os.path.expanduser('~') home_dir = os.path.expanduser('~')
config_folder = home_dir + app_dir config_folder = home_dir + app_dir
@ -291,3 +252,24 @@ def create_config_dir():
for dir in dirs: for dir in dirs:
if not os.path.exists(config_folder + dir): if not os.path.exists(config_folder + dir):
os.makedirs(config_folder + dir) os.makedirs(config_folder + dir)
def getAllSongs() -> None:
"""
Gets all songs under the ~/ directory.
"""
tracks = []
tracks.extend(instances.songs_instance.get_all_songs())
for track in tracks:
try:
os.chmod(os.path.join(home_dir, track['filepath']), 0o755)
except FileNotFoundError:
instances.songs_instance.remove_song_by_filepath(
os.path.join(home_dir, track['filepath']))
if track['image'] is not None:
track['image'] = "http://127.0.0.1:8900/images/thumbnails/" + \
track['image']
return tracks

5
server/app/instances.py Normal file
View File

@ -0,0 +1,5 @@
from app.models import AllSongs
from app.models import Artists
songs_instance = AllSongs()
artist_instance = Artists()

View File

@ -1,14 +1,3 @@
export PORT=8000
export music_dir="/home/cwilvx/Music/"
# export FLASK_APP=app
# export FLASK_DEBUG=1
# export FLASK_RUN_PORT=8008
# export music_dirs="['/home/cwilvx/Music/', '/home/cwilvx/FreezerMusic']"
# flask run
python manage.py python manage.py
# gunicorn -b 0.0.0.0:9876 --workers=4 "wsgi:create_app()" --log-level=debug # gunicorn -b 0.0.0.0:9876 --workers=4 "wsgi:create_app()" --log-level=debug

View File

@ -19,8 +19,6 @@
@collapseSearch="collapseSearch" @collapseSearch="collapseSearch"
/> />
</div> </div>
<!-- <div class="separator no-border"></div> -->
<router-view /> <router-view />
</div> </div>
<div class="r-sidebar"> <div class="r-sidebar">

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="folder-top flex"> <div class="folder-top flex">
<div class="fname"> <div class="fname">
<button class="play image"> <button class="play image" @click="playThis(first_song)">
<div class="icon"></div> <div class="icon"></div>
Play Play
</button> </button>
@ -10,25 +10,63 @@
{{ path.split("/").splice(-1) + "" }} {{ path.split("/").splice(-1) + "" }}
</div> </div>
</div> </div>
<div class="search">
<input
type="text"
class="search-input"
placeholder="Ctrl + F"
v-model="search_query"
@keyup.enter="search()"
/>
<div class="search-icon image"></div>
</div>
</div> </div>
</template> </template>
<script> <script>
import perks from "@/composables/perks.js";
export default { export default {
props: ["path"], props: ["path", "first_song"],
setup() {
return {
playThis: perks.updateQueue,
};
},
}; };
</script> </script>
<style lang="scss"> <style lang="scss">
.folder-top { .folder-top {
display: grid;
grid-template-columns: 1fr 1fr;
border-bottom: 1px solid $separator; border-bottom: 1px solid $separator;
width: calc(100% - 0.5rem); width: calc(100% - 0.5rem);
padding-bottom: $small; padding-bottom: $small;
height: 3rem; height: 3rem;
} }
.folder-top .search {
width: 50%;
display: grid;
place-items: end;
.search-input {
max-width: 20rem;
width: 100%;
border: 1px solid $separator;
border-radius: .5rem;
padding-left: 1rem;
background-color: #46454500;
color: #fff;
font-size: 1rem;
line-height: 2.2rem;
outline: none;
}
}
.folder-top .fname { .folder-top .fname {
// width: 50%; width: 50%;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="folder"> <div class="folder">
<div class="table rounded" ref="songtitle" v-if="searchSongs.length"> <div class="table rounded" ref="songtitle" v-if="songs.length">
<table> <table>
<thead> <thead>
<tr> <tr>
@ -12,20 +12,18 @@
</thead> </thead>
<tbody> <tbody>
<SongItem <SongItem
:searchSongs="searchSongs"
:songTitleWidth="songTitleWidth" :songTitleWidth="songTitleWidth"
:minWidth="minWidth" :minWidth="minWidth"
v-for="song in searchSongs" v-for="song in songs"
:key="song" :key="song"
:song="song" :song="song"
:current="current" :current="current"
:class="{ current: current._id == song._id }"
@updateQueue="updateQueue" @updateQueue="updateQueue"
/> />
</tbody> </tbody>
</table> </table>
</div> </div>
<div ref="songtitle" v-else-if="searchSongs.length === 0 && search_query"> <div ref="songtitle" v-else-if="songs.length === 0 && search_query">
<div class="no-results"> <div class="no-results">
<div class="icon"></div> <div class="icon"></div>
<div class="text"> Track not found!</div> <div class="text"> Track not found!</div>
@ -36,7 +34,7 @@
</template> </template>
<script> <script>
import { computed, ref, toRefs } from "@vue/reactivity"; import { ref } from "@vue/reactivity";
import { onMounted, onUnmounted } from "@vue/runtime-core"; import { onMounted, onUnmounted } from "@vue/runtime-core";
import SongItem from "../SongItem.vue"; import SongItem from "../SongItem.vue";
@ -48,8 +46,7 @@ export default {
components: { components: {
SongItem, SongItem,
}, },
setup(props) { setup() {
const song_list = toRefs(props).songs;
const songtitle = ref(null); const songtitle = ref(null);
const songTitleWidth = ref(null); const songTitleWidth = ref(null);
@ -86,32 +83,7 @@ export default {
perks.updateQueue(song) perks.updateQueue(song)
} }
const searchSongs = computed(() => {
const songs = [];
if (search_query.value.length > 2) {
state.loading.value = true;
for (let i = 0; i < song_list.value.length; i++) {
if (
song_list.value[i].title
.toLowerCase()
.includes(search_query.value.toLowerCase())
) {
songs.push(song_list.value[i]);
}
}
state.loading.value = false;
return songs;
} else {
return song_list.value;
}
});
return { return {
searchSongs,
updateQueue, updateQueue,
songtitle, songtitle,
songTitleWidth, songTitleWidth,

View File

@ -176,7 +176,8 @@ export default {
} }
watch(query, (new_query) => { watch(query, (new_query) => {
searchMusic(new_query); // search music
// searchMusic(new_query);
state.search_query.value = new_query; state.search_query.value = new_query;
if (new_query !== "") { if (new_query !== "") {

View File

@ -1,5 +1,5 @@
<template> <template>
<tr> <tr :class="{ current: current._id == song._id }">
<td <td
:style="{ width: songTitleWidth + 'px' }" :style="{ width: songTitleWidth + 'px' }"
class="flex" class="flex"
@ -61,7 +61,7 @@ export default {
props: ["song", "current", "songTitleWidth", "minWidth"], props: ["song", "current", "songTitleWidth", "minWidth"],
setup(props, { emit }) { setup(props, { emit }) {
function emitUpdate(song) { function emitUpdate(song) {
emit('updateQueue', song); emit("updateQueue", song);
} }
return { return {

View File

@ -1,18 +1,18 @@
<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" /> <Header :path="path" :first_song="songs[0]" />
</div> </div>
<div id="scrollable" ref="scrollable"> <div id="scrollable" ref="scrollable">
<FolderList :folders="folders" />
<div class="separator" v-if="folders.length && songs.length"></div>
<SongList :songs="songs" /> <SongList :songs="songs" />
<div class="separator" v-if="folders.length && songs.length"></div>
<FolderList :folders="folders" />
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { ref } from "@vue/reactivity"; import { computed, ref } from "@vue/reactivity";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import SongList from "@/components/FolderView/SongList.vue"; import SongList from "@/components/FolderView/SongList.vue";
@ -33,7 +33,7 @@ export default {
const route = useRoute(); const route = useRoute();
const path = ref(route.params.path); const path = ref(route.params.path);
const songs = ref(state.song_list); const song_list = ref(state.song_list);
const folders = ref(state.folder_list); const folders = ref(state.folder_list);
const scrollable = ref(null); const scrollable = ref(null);
@ -42,6 +42,38 @@ export default {
console.log("focusSearch"); console.log("focusSearch");
} }
const search_query = ref(state.search_query);
const filters = ref(state.filters);
const songs = computed(() => {
const songs = [];
if (!filters.value.includes("🈁")) {
return song_list.value;
}
if (search_query.value.length > 2) {
state.loading.value = true;
for (let i = 0; i < song_list.value.length; i++) {
if (
song_list.value[i].title
.toLowerCase()
.includes(search_query.value.toLowerCase())
) {
songs.push(song_list.value[i]);
}
}
state.song_list.value = songs;
state.loading.value = false;
return songs;
} else {
return song_list.value;
}
});
onMounted(() => { onMounted(() => {
const getPathFolders = (path, last_id) => { const getPathFolders = (path, last_id) => {
state.loading.value = true; state.loading.value = true;
@ -89,7 +121,6 @@ export default {
height: min-content; height: min-content;
width: calc(100% - 1rem); width: calc(100% - 1rem);
top: 0.5rem; top: 0.5rem;
} }
#scrollable { #scrollable {