add featured artists in albumview

This commit is contained in:
geoffrey45 2022-01-15 18:18:55 +03:00
parent 1b9e6821d6
commit a720891c20
13 changed files with 166 additions and 148 deletions

View File

@ -13,7 +13,7 @@ all_the_f_music = helpers.getAllSongs()
def initialize() -> None: def initialize() -> None:
helpers.create_config_dir() helpers.create_config_dir()
# helpers.check_for_new_songs() helpers.check_for_new_songs()
initialize() initialize()
@ -54,9 +54,8 @@ def search_by_title():
album['image'] = "image" album['image'] = "image"
for song in ar: for song in ar:
a = song["artists"].split(', ')
for artist in a: for artist in song["artists"]:
if query.lower() in artist.lower(): if query.lower() in artist.lower():
artist_obj = { artist_obj = {
@ -75,30 +74,34 @@ def x():
return "🎸" return "🎸"
@bp.route("/folder/artists") @bp.route("/album/<album>/<artist>/artists")
def get_folder_artists(): @cache.cached()
dir = request.args.get('dir') def get_album_artists(album, artist):
album = album.replace('|', '/')
artist = artist.replace('|', '/')
tracks = []
songs = instances.songs_instance.find_songs_by_folder(dir) for track in all_the_f_music:
without_duplicates = helpers.remove_duplicates(songs) if track["album"] == album and track["album_artist"] == artist:
tracks.append(track)
artists = [] artists = []
for song in without_duplicates: for track in tracks:
this_artists = song['artists'].split(', ') print(track['artists'])
for artist in this_artists:
for artist in track['artists']:
if artist not in artists: if artist not in artists:
artists.append(artist) artists.append(artist)
final_artists = [] final_artists = []
for artist in artists:
for artist in artists[:15]: artist_obj = {
artist_obj = instances.artist_instance.find_artists_by_name(artist) "name": artist,
"image": "http://127.0.0.1:8900/images/artists/" + artist.replace('/', '::') + ".jpg"
if artist_obj != []: }
final_artists.append(artist_obj) final_artists.append(artist_obj)
return {'artists': final_artists} return {'artists': final_artists}
@ -106,6 +109,7 @@ def get_folder_artists():
@bp.route("/populate/images") @bp.route("/populate/images")
def populate_images(): def populate_images():
functions.populate_images() functions.populate_images()
return "Done"
@bp.route("/artist/<artist>") @bp.route("/artist/<artist>")
@ -129,9 +133,6 @@ def getArtistData(artist: str):
albums = instances.songs_instance.find_songs_by_album_artist(artist) albums = instances.songs_instance.find_songs_by_album_artist(artist)
for song in songs:
song['artists'] = song['artists'].split(', ')
for song in albums: for song in albums:
if song['album'] not in artist_albums: if song['album'] not in artist_albums:
artist_albums.append(song['album']) artist_albums.append(song['album'])
@ -200,12 +201,6 @@ def getFolderTree(folder: str = None):
if x['folder'] == req_dir: if x['folder'] == req_dir:
songs.append(x) songs.append(x)
for song in songs:
try:
song['artists'] = song['artists'].split(', ')
except:
pass
return {"files": helpers.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')
@ -215,9 +210,7 @@ def populateArtists():
artists = [] artists = []
for song in all_songs: for song in all_songs:
artist = song['artists'].split(', ') for a in song['artists']:
for a in artist:
a_obj = { a_obj = {
"name": a, "name": a,
} }
@ -252,11 +245,11 @@ 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 = instances.songs_instance.find_songs_by_album(album, artist) songs = []
for song in songs: for track in all_the_f_music:
song['artists'] = song['artists'].split(', ') if track['album'] == album and track['album_artist'] == artist:
song['image'] = "http://127.0.0.1:8900/images/thumbnails/" + song['image'] songs.append(track)
album_obj = { album_obj = {
"name": album, "name": album,

View File

@ -2,13 +2,14 @@
This module contains larger functions for the server This module contains larger functions for the server
""" """
import time
from progress.bar import Bar from progress.bar import Bar
import requests import requests
import os import os
from mutagen.flac import MutagenError from mutagen.flac import MutagenError
from app import helpers from app import helpers
from app import instances from app import instances
from app import api
def populate(): def populate():
''' '''
@ -18,6 +19,7 @@ def populate():
also checks if the album art exists in the image path, if not tries to also checks if the album art exists in the image path, if not tries to
extract it. extract it.
''' '''
print('\nchecking for new tracks')
files = helpers.run_fast_scandir(helpers.home_dir, [".flac", ".mp3"])[1] files = helpers.run_fast_scandir(helpers.home_dir, [".flac", ".mp3"])[1]
for file in files: for file in files:
@ -36,8 +38,8 @@ def populate():
helpers.getTags(file) helpers.getTags(file)
except MutagenError: except MutagenError:
pass pass
api.all_the_f_music = helpers.getAllSongs()
return {'msg': 'updated everything'} print('\ncheck done')
def populate_images(): def populate_images():
@ -54,35 +56,29 @@ def populate_images():
bar = Bar('Processing images', max=len(artists)) bar = Bar('Processing images', max=len(artists))
for artist in artists: for artist in artists:
file_path = helpers.app_dir + '/images/artists/' + artist + '.jpg' file_path = helpers.app_dir + '/images/artists/' + \
artist.replace('/', '::') + '.jpg'
if not os.path.exists(file_path): if not os.path.exists(file_path):
url = 'https://api.deezer.com/search/artist?q={}'.format(artist) url = 'https://api.deezer.com/search/artist?q={}'.format(artist)
response = requests.get(url)
try:
response = requests.get(url)
except:
print('\n sleeping for 5 seconds')
time.sleep(5)
response = requests.get(url)
data = response.json() data = response.json()
try: try:
image_path = data['data'][0]['picture_xl'] img_data = data['data'][0]['picture_xl']
except: except:
image_path = None img_data = None
if image_path is not None: if img_data is not None:
try: helpers.save_image(img_data, file_path)
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.next()
bar.finish() bar.finish()
artists_in_db = instances.artist_instance.get_all_artists()
return {'sample': artists_in_db[:25]}

View File

@ -268,8 +268,11 @@ def getAllSongs() -> None:
except FileNotFoundError: except FileNotFoundError:
instances.songs_instance.remove_song_by_filepath( instances.songs_instance.remove_song_by_filepath(
os.path.join(home_dir, track['filepath'])) os.path.join(home_dir, track['filepath']))
if track['image'] is not None: if track['image'] is not None:
track['image'] = "http://127.0.0.1:8900/images/thumbnails/" + \ track['image'] = "http://127.0.0.1:8900/images/thumbnails/" + \
track['image'] track['image']
if track['artists'] is not None:
track['artists'] = track['artists'].split(', ')
return tracks return tracks

View File

@ -52,6 +52,7 @@ a {
button { button {
border: none; border: none;
outline: none;
color: inherit; color: inherit;
font-size: 1rem; font-size: 1rem;
cursor: pointer; cursor: pointer;

View File

@ -5,9 +5,11 @@
<div class="icon"></div> <div class="icon"></div>
Play Play
</button> </button>
<div class="ellip text"> <div class="text">
<div class="icon image"></div> <div class="icon image"></div>
{{ path.split("/").splice(-1) + "" }} <div class="ellip">
{{ path.split("/").splice(-1) + "" }}
</div>
</div> </div>
</div> </div>
<div class="search"> <div class="search">
@ -25,17 +27,17 @@
<script> <script>
import perks from "@/composables/perks.js"; import perks from "@/composables/perks.js";
import state from "@/composables/state.js" import state from "@/composables/state.js";
export default { export default {
props: ["path", "first_song"], props: ["path", "first_song"],
setup() { setup() {
function playFolder(song) { function playFolder(song) {
perks.updateQueue(song, "folder") perks.updateQueue(song, "folder");
} }
return { return {
playFolder, playFolder,
search_query: state.search_query search_query: state.search_query,
}; };
}, },
}; };
@ -60,7 +62,7 @@ export default {
max-width: 20rem; max-width: 20rem;
width: 100%; width: 100%;
border: 1px solid $separator; border: 1px solid $separator;
border-radius: .5rem; border-radius: 0.5rem;
padding-left: 1rem; padding-left: 1rem;
background-color: #46454500; background-color: #46454500;
color: #fff; color: #fff;
@ -96,14 +98,18 @@ export default {
} }
.text { .text {
position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
border-radius: $small; border-radius: $small;
background-color: rgb(24, 22, 22); background-color: rgb(24, 22, 22);
padding: $small; padding: $small;
padding-left: 2.25rem;
.icon { .icon {
position: absolute;
left: $small;
height: 1.5rem; height: 1.5rem;
width: 1.5rem; width: 1.5rem;
background-image: url(../../assets/icons/folder.svg); background-image: url(../../assets/icons/folder.svg);

View File

@ -39,7 +39,7 @@ 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";
import getAlbum from "@/composables/getAlbum.js"; import album from "@/composables/album.js";
import perks from "@/composables/perks.js"; import perks from "@/composables/perks.js";
import state from "@/composables/state.js"; import state from "@/composables/state.js";
import { useRouter, useRoute } from "vue-router"; import { useRouter, useRoute } from "vue-router";
@ -104,7 +104,7 @@ export default {
function loadAlbum(title, album_artist) { function loadAlbum(title, album_artist) {
state.loading.value = true; state.loading.value = true;
getAlbum(title, album_artist).then((data) => { album.getAlbumTracks(title, album_artist).then((data) => {
state.album_song_list.value = data.songs; state.album_song_list.value = data.songs;
state.album_info.value = data.info; state.album_info.value = data.info;
@ -189,7 +189,7 @@ th {
th { th {
text-transform: uppercase; text-transform: uppercase;
font-weight: normal; font-weight: normal;
display: none; // display: none;
} }
td .artist { td .artist {

View File

@ -4,7 +4,7 @@
<div class="nav-button" id="home-button"> <div class="nav-button" id="home-button">
<div class="in"> <div class="in">
<div class="nav-icon image" id="home-icon"></div> <div class="nav-icon image" id="home-icon"></div>
<span id="text">Home</span> <span>Home</span>
</div> </div>
</div> </div>
</router-link> </router-link>
@ -13,7 +13,7 @@
<div class="nav-button" id="album-button"> <div class="nav-button" id="album-button">
<div class="in"> <div class="in">
<div class="nav-icon image" id="album-icon"></div> <div class="nav-icon image" id="album-icon"></div>
<span id="text">Albums</span> <span>Albums</span>
</div> </div>
</div> </div>
</router-link> </router-link>
@ -22,7 +22,7 @@
<div class="nav-button" id="artists-button"> <div class="nav-button" id="artists-button">
<div class="in"> <div class="in">
<div class="nav-icon image" id="artists-icon"></div> <div class="nav-icon image" id="artists-icon"></div>
<span id="text">Artists</span> <span>Artists</span>
</div> </div>
</div> </div>
</router-link> </router-link>
@ -31,7 +31,7 @@
<div class="nav-button" id="playlists-button"> <div class="nav-button" id="playlists-button">
<div class="in"> <div class="in">
<div class="nav-icon image" id="playlists-icon"></div> <div class="nav-icon image" id="playlists-icon"></div>
<span id="text">Playlist</span> <span>Playlist</span>
</div> </div>
</div> </div>
</router-link> </router-link>
@ -40,7 +40,7 @@
<div class="nav-button" id="mixes-button"> <div class="nav-button" id="mixes-button">
<div class="in"> <div class="in">
<div class="nav-icon image" id="mixes-icon"></div> <div class="nav-icon image" id="mixes-icon"></div>
<span id="text">Mixes</span> <span>Mixes</span>
</div> </div>
</div> </div>
</router-link> </router-link>
@ -49,7 +49,7 @@
<div class="nav-button" id="folders-button"> <div class="nav-button" id="folders-button">
<div class="in"> <div class="in">
<div class="nav-icon image" id="folders-icon"></div> <div class="nav-icon image" id="folders-icon"></div>
<span id="text">Folders</span> <span>Folders</span>
</div> </div>
</div> </div>
</router-link> </router-link>
@ -58,7 +58,7 @@
<div class="nav-button" id="folders-button"> <div class="nav-button" id="folders-button">
<div class="in"> <div class="in">
<div class="nav-icon image" id="settings-icon"></div> <div class="nav-icon image" id="settings-icon"></div>
<span id="text">Settings</span> <span>Settings</span>
</div> </div>
</div> </div>
</router-link> </router-link>
@ -97,7 +97,6 @@ export default {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
justify-content: flex-start; justify-content: flex-start;
background-color: transparent;
height: 100%; height: 100%;
padding: 0.6rem 0 0.6rem 0; padding: 0.6rem 0 0.6rem 0;
@ -106,10 +105,12 @@ export default {
} }
.nav-icon { .nav-icon {
height: 1.5rem; height: 2rem;
width: 1.5rem; width: 2rem;
margin-right: 0.5rem; margin-right: 0.5rem;
margin-left: 10px; margin-left: 0.6rem;
border-radius: $small;
background-color: rgb(26, 24, 24);
} }
.in { .in {
@ -117,6 +118,16 @@ export default {
align-items: center; align-items: center;
} }
#home-icon,
#album-icon,
#artists-icon,
#playlists-icon,
#mixes-icon,
#folders-icon,
#settings-icon {
background-size: 1.5rem;
}
#home-icon { #home-icon {
background-image: url(../../assets/icons/home.svg); background-image: url(../../assets/icons/home.svg);
} }
@ -125,10 +136,6 @@ export default {
background-image: url(../../assets/icons/album.svg); background-image: url(../../assets/icons/album.svg);
} }
#text {
margin-top: 5px;
}
#artists-icon { #artists-icon {
background-image: url(../../assets/icons/artist.svg); background-image: url(../../assets/icons/artist.svg);
} }

View File

@ -1,10 +1,10 @@
<template> <template>
<div class="f-artists"> <div class="f-artists">
<div class="xcontrols"> <div class="xcontrols">
<div class="prev" @click="scrollLeftX"></div> <div class="prev" @click="scrollLeft"></div>
<div class="next" @click="scrollRightX"></div> <div class="next" @click="scrollRight"></div>
</div> </div>
<div class="artists" ref="artists_dom" v-on:mouseover="say"> <div class="artists" ref="artists_dom" v-on:mouseover="scrollArtists">
<div class="artist c1"> <div class="artist c1">
<div class="blur"></div> <div class="blur"></div>
<div class="s2"></div> <div class="s2"></div>
@ -12,8 +12,11 @@
</div> </div>
<div class="artist" v-for="artist in artists" :key="artist"> <div class="artist" v-for="artist in artists" :key="artist">
<div> <div>
<div class="artist-image image"></div> <div
<p class="artist-name ellipsis">{{ artist }}</p> class="artist-image image"
:style="{ backgroundImage: `url('${artist.image}')` }"
></div>
<p class="artist-name ellipsis">{{ artist.name }}</p>
<div class="a-circle"></div> <div class="a-circle"></div>
</div> </div>
</div> </div>
@ -24,24 +27,11 @@
import { ref } from "@vue/reactivity"; import { ref } from "@vue/reactivity";
export default { export default {
props: ["artists"],
setup() { setup() {
const artists = [
"Michael John Montgomery",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
];
const artists_dom = ref(null); const artists_dom = ref(null);
const scrollLeftX = () => { const scrollLeft = () => {
const dom = artists_dom.value; const dom = artists_dom.value;
dom.scrollBy({ dom.scrollBy({
left: -700, left: -700,
@ -49,7 +39,7 @@ export default {
}); });
}; };
const scrollRightX = () => { const scrollRight = () => {
const dom = artists_dom.value; const dom = artists_dom.value;
dom.scrollBy({ dom.scrollBy({
left: 700, left: 700,
@ -64,7 +54,7 @@ export default {
}); });
}; };
const say = () => { const scrollArtists = () => {
artists_dom.value.addEventListener("wheel", (e) => { artists_dom.value.addEventListener("wheel", (e) => {
e.preventDefault(); e.preventDefault();
scroll(e); scroll(e);
@ -72,11 +62,10 @@ export default {
}; };
return { return {
artists,
artists_dom, artists_dom,
say, scrollArtists,
scrollLeftX, scrollLeft,
scrollRightX, scrollRight,
}; };
}, },
}; };
@ -87,7 +76,7 @@ export default {
position: relative; position: relative;
height: 13em; height: 13em;
width: calc(100%); width: calc(100%);
background-color: #1f1e1d; background-color: $card-dark;
padding: $small; padding: $small;
border-radius: $small; border-radius: $small;
user-select: none; user-select: none;
@ -127,7 +116,7 @@ export default {
.next:hover, .next:hover,
.prev:hover { .prev:hover {
background-color: rgb(3, 1, 1); background-color: $blue;
transition: all 0.5s ease; transition: all 0.5s ease;
} }
} }
@ -156,7 +145,7 @@ export default {
width: 9em; width: 9em;
height: 9em; height: 9em;
border-radius: $small; border-radius: $small;
background-color: #fd5c63; background-color: #0f0e0e;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@ -189,11 +178,8 @@ export default {
.f-artists .c1 { .f-artists .c1 {
position: relative; position: relative;
background: rgb(145, 42, 56); background: rgb(16, 25, 51);
width: 15em; width: 15em;
background-image: url(../../assets/images/gradient1.gif);
overflow: hidden;
margin-left: -0.1rem;
&:hover > .s2 { &:hover > .s2 {
background: rgba(53, 53, 146, 0.8); background: rgba(53, 53, 146, 0.8);
@ -206,23 +192,11 @@ export default {
position: absolute; position: absolute;
bottom: -2rem; bottom: -2rem;
margin-left: 0.5rem; margin-left: 0.5rem;
z-index: 1;
font-size: 2rem; font-size: 2rem;
font-weight: 700; font-weight: 700;
color: #ffffff; color: #ffffff;
} }
.blur {
position: absolute;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0);
backdrop-filter: blur(40px);
-webkit-backdrop-filter: blur(40px);
-moz-backdrop-filter: blur(40px);
border-radius: $small;
}
.s2 { .s2 {
position: absolute; position: absolute;
left: -2em; left: -2em;

View File

@ -62,7 +62,6 @@ export default {
} }
function emitLoadAlbum(title, artist){ function emitLoadAlbum(title, artist){
console.log(title, artist)
emit("loadAlbum", title, artist) emit("loadAlbum", title, artist)
} }

44
src/composables/album.js Normal file
View File

@ -0,0 +1,44 @@
let base_uri = "http://127.0.0.1:9876";
const getAlbumTracks = async (name, artist) => {
const res = await fetch(
base_uri +
"/albums/" +
encodeURIComponent(name.replaceAll("/", "|")) +
"::" +
encodeURIComponent(artist.replaceAll("/", "|"))
);
if (!res.ok) {
const message = `An error has occured: ${res.status}`;
throw new Error(message);
}
const data = await res.json();
return data;
};
const getAlbumArtists = async (name, artist) => {
const res = await fetch(
base_uri +
"/album/" +
encodeURIComponent(name.replaceAll("/", "|")) +
"/" +
encodeURIComponent(artist.replaceAll("/", "|")) +
"/artists"
);
if (!res.ok) {
const message = `An error has occured: ${res.status}`;
throw new Error(message);
}
const data = await res.json();
return data.artists;
};
export default {
getAlbumTracks,
getAlbumArtists,
};

View File

@ -1,16 +0,0 @@
let base_uri = "http://127.0.0.1:9876";
const getAlbum = async (name, artist) => {
const res = await fetch(base_uri + "/albums/" + encodeURIComponent(name.replaceAll("/", "|")) + "::" + encodeURIComponent(artist.replaceAll("/", "|")));
if (!res.ok) {
const message = `An error has occured: ${res.status}`;
throw new Error(message);
}
const data = await res.json();
return data;
};
export default getAlbum;

View File

@ -33,8 +33,9 @@ const prev = ref({
const album_song_list = ref([]) const album_song_list = ref([])
const album_info = ref([]) const album_info = ref([])
const album_artists = ref([])
const filters = ref([]); const filters = ref([]);
const magic_flag = ref(false); const magic_flag = ref(false);
const loading = ref(false); const loading = ref(false);
@ -59,5 +60,6 @@ export default {
search_albums, search_albums,
search_artists, search_artists,
album_song_list, album_song_list,
album_info album_info,
album_artists
}; };

View File

@ -8,7 +8,7 @@
<SongList :songs="album_songs" /> <SongList :songs="album_songs" />
</div> </div>
<div class="separator" id="av-sep"></div> <div class="separator" id="av-sep"></div>
<FeaturedArtists /> <FeaturedArtists :artists="artists" />
<div class="separator" id="av-sep"></div> <div class="separator" id="av-sep"></div>
<AlbumBio /> <AlbumBio />
<div class="separator" id="av-sep"></div> <div class="separator" id="av-sep"></div>
@ -27,7 +27,7 @@ import FromTheSameArtist from "../components/AlbumView/FromTheSameArtist.vue";
import SongList from "../components/FolderView/SongList.vue"; import SongList from "../components/FolderView/SongList.vue";
import FeaturedArtists from "../components/PlaylistView/FeaturedArtists.vue"; import FeaturedArtists from "../components/PlaylistView/FeaturedArtists.vue";
import getAlbum from "../composables/getAlbum.js"; import album from "@/composables/album.js";
import state from "@/composables/state.js"; import state from "@/composables/state.js";
import { onUnmounted } from "@vue/runtime-core"; import { onUnmounted } from "@vue/runtime-core";
@ -46,23 +46,32 @@ export default {
onMounted(() => { onMounted(() => {
if (!state.album_song_list.value.length) { if (!state.album_song_list.value.length) {
getAlbum(title, album_artists).then((data) => { album.getAlbumTracks(title, album_artists).then((data) => {
state.album_song_list.value = data.songs; state.album_song_list.value = data.songs;
state.album_info.value = data.info; state.album_info.value = data.info;
state.loading.value = false; state.loading.value = false;
}); });
} }
if (state.album_artists.value.length == 0) {
album.getAlbumArtists(title, album_artists).then((data) => {
state.album_artists.value = data;
console.log(state.album_artists.value)
});
}
}); });
onUnmounted(() => { onUnmounted(() => {
state.album_song_list.value = []; state.album_song_list.value = [];
state.album_info.value = {}; state.album_info.value = {};
state.album_artists.value = [];
}); });
return { return {
album_songs: state.album_song_list, album_songs: state.album_song_list,
album_info: state.album_info, album_info: state.album_info,
artists: state.album_artists,
}; };
}, },
}; };