mirror of
https://github.com/tcsenpai/swingmusic.git
synced 2025-06-08 12:15:39 +00:00
server: add get album bio from last fm function
- co-written by Github Copilot
This commit is contained in:
parent
a720891c20
commit
2ee8d27bf0
11
Pipfile
Normal file
11
Pipfile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[[source]]
|
||||||
|
url = "https://pypi.python.org/simple"
|
||||||
|
verify_ssl = true
|
||||||
|
name = "pypi"
|
||||||
|
|
||||||
|
[packages]
|
||||||
|
|
||||||
|
[dev-packages]
|
||||||
|
|
||||||
|
[requires]
|
||||||
|
python_version = "3.8"
|
@ -5,18 +5,19 @@ from app import functions, instances, helpers, cache
|
|||||||
|
|
||||||
bp = Blueprint('api', __name__, url_prefix='')
|
bp = Blueprint('api', __name__, url_prefix='')
|
||||||
|
|
||||||
all_the_f_music = []
|
|
||||||
home_dir = helpers.home_dir
|
home_dir = helpers.home_dir
|
||||||
|
|
||||||
|
|
||||||
all_the_f_music = helpers.getAllSongs()
|
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()
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/')
|
@bp.route('/')
|
||||||
def adutsfsd():
|
def adutsfsd():
|
||||||
return "^ _ ^"
|
return "^ _ ^"
|
||||||
@ -161,7 +162,7 @@ def getArtistData(artist: str):
|
|||||||
|
|
||||||
@bp.route("/f/<folder>")
|
@bp.route("/f/<folder>")
|
||||||
@cache.cached()
|
@cache.cached()
|
||||||
def getFolderTree(folder: str = None):
|
def getFolderTree(folder: str):
|
||||||
req_dir = folder.replace('|', '/')
|
req_dir = folder.replace('|', '/')
|
||||||
|
|
||||||
if folder == "home":
|
if folder == "home":
|
||||||
@ -180,21 +181,11 @@ def getFolderTree(folder: str = None):
|
|||||||
dir = {
|
dir = {
|
||||||
"name": entry.name,
|
"name": entry.name,
|
||||||
"count": len(files_in_dir),
|
"count": len(files_in_dir),
|
||||||
"path": entry.path.replace(home_dir, "")
|
"path": entry.path.replace(home_dir, ""),
|
||||||
}
|
}
|
||||||
|
|
||||||
folders.append(dir)
|
folders.append(dir)
|
||||||
|
|
||||||
# if entry.is_file():
|
|
||||||
# if isValidFile(entry.name) == True:
|
|
||||||
# file = instances.songs_instance.find_song_by_path(entry.path)
|
|
||||||
|
|
||||||
# if not file:
|
|
||||||
# getTags(entry.path)
|
|
||||||
|
|
||||||
# songs_array = instances.songs_instance.find_songs_by_folder(
|
|
||||||
# req_dir)
|
|
||||||
|
|
||||||
songs = []
|
songs = []
|
||||||
|
|
||||||
for x in all_the_f_music:
|
for x in all_the_f_music:
|
||||||
@ -203,6 +194,7 @@ def getFolderTree(folder: str = None):
|
|||||||
|
|
||||||
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')
|
||||||
def populateArtists():
|
def populateArtists():
|
||||||
all_songs = instances.songs_instance.get_all_songs()
|
all_songs = instances.songs_instance.get_all_songs()
|
||||||
@ -222,6 +214,7 @@ def populateArtists():
|
|||||||
|
|
||||||
return {'songs': artists}
|
return {'songs': artists}
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/albums')
|
@bp.route('/albums')
|
||||||
def getAlbums():
|
def getAlbums():
|
||||||
s = instances.songs_instance.get_all_songs()
|
s = instances.songs_instance.get_all_songs()
|
||||||
@ -239,6 +232,7 @@ def getAlbums():
|
|||||||
|
|
||||||
return {'albums': albums}
|
return {'albums': albums}
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/albums/<query>')
|
@bp.route('/albums/<query>')
|
||||||
@cache.cached()
|
@cache.cached()
|
||||||
def getAlbumSongs(query: str):
|
def getAlbumSongs(query: str):
|
||||||
@ -260,3 +254,8 @@ def getAlbumSongs(query: str):
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {'songs': helpers.remove_duplicates(songs), 'info': album_obj}
|
return {'songs': helpers.remove_duplicates(songs), 'info': album_obj}
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/album/<title>/<artist>/bio')
|
||||||
|
def drop_db(title, artist):
|
||||||
|
return functions.getAlbumBio(title, artist)
|
||||||
|
@ -3,14 +3,23 @@ This module contains larger functions for the server
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import time
|
import time
|
||||||
from progress.bar import Bar
|
|
||||||
import requests
|
|
||||||
import os
|
import os
|
||||||
|
import requests
|
||||||
|
import random
|
||||||
|
|
||||||
from mutagen.flac import MutagenError
|
from mutagen.flac import MutagenError
|
||||||
|
from mutagen.mp3 import MP3
|
||||||
|
from mutagen.id3 import ID3
|
||||||
|
from mutagen.flac import FLAC
|
||||||
|
from progress.bar import Bar
|
||||||
|
from PIL import Image
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
from app import helpers
|
from app import helpers
|
||||||
from app import instances
|
from app import instances
|
||||||
from app import api
|
from app import api
|
||||||
|
|
||||||
|
|
||||||
def populate():
|
def populate():
|
||||||
'''
|
'''
|
||||||
Populate the database with all songs in the music directory
|
Populate the database with all songs in the music directory
|
||||||
@ -23,21 +32,8 @@ def populate():
|
|||||||
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:
|
||||||
file_in_db_obj = instances.songs_instance.find_song_by_path(file)
|
getTags(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
|
|
||||||
api.all_the_f_music = helpers.getAllSongs()
|
api.all_the_f_music = helpers.getAllSongs()
|
||||||
print('\ncheck done')
|
print('\ncheck done')
|
||||||
|
|
||||||
@ -82,3 +78,163 @@ def populate_images():
|
|||||||
bar.next()
|
bar.next()
|
||||||
|
|
||||||
bar.finish()
|
bar.finish()
|
||||||
|
|
||||||
|
|
||||||
|
def extract_thumb(path: str) -> str:
|
||||||
|
"""
|
||||||
|
Extracts the thumbnail from an audio file. Returns the path to the thumbnail.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def use_defaults() -> str:
|
||||||
|
"""
|
||||||
|
Returns a path to a random image in the defaults directory.
|
||||||
|
"""
|
||||||
|
path = "http://127.0.0.1:8900/images/defaults/" + \
|
||||||
|
str(random.randint(0, 10)) + '.webp'
|
||||||
|
return path
|
||||||
|
|
||||||
|
webp_path = path.split('/')[-1] + '.webp'
|
||||||
|
img_path = os.path.join(helpers.app_dir, "images", "thumbnails", webp_path)
|
||||||
|
|
||||||
|
if os.path.exists(img_path):
|
||||||
|
return "http://127.0.0.1:8900/images/thumbnails/" + webp_path
|
||||||
|
|
||||||
|
if path.endswith('.flac'):
|
||||||
|
try:
|
||||||
|
audio = FLAC(path)
|
||||||
|
album_art = audio.pictures[0].data
|
||||||
|
except:
|
||||||
|
album_art = None
|
||||||
|
elif path.endswith('.mp3'):
|
||||||
|
try:
|
||||||
|
audio = ID3(path)
|
||||||
|
album_art = audio.getall('APIC')[0].data
|
||||||
|
except:
|
||||||
|
album_art = None
|
||||||
|
|
||||||
|
if album_art is None:
|
||||||
|
return use_defaults()
|
||||||
|
else:
|
||||||
|
img = Image.open(BytesIO(album_art))
|
||||||
|
|
||||||
|
try:
|
||||||
|
small_img = img.resize((150, 150), Image.ANTIALIAS)
|
||||||
|
small_img.save(img_path, format="webp")
|
||||||
|
except OSError:
|
||||||
|
try:
|
||||||
|
png = img.convert('RGB')
|
||||||
|
small_img = png.resize((150, 150), Image.ANTIALIAS)
|
||||||
|
small_img.save(img_path, format="webp")
|
||||||
|
except:
|
||||||
|
return use_defaults()
|
||||||
|
|
||||||
|
final_path = "http://127.0.0.1:8900/images/thumbnails/" + webp_path
|
||||||
|
|
||||||
|
return final_path
|
||||||
|
|
||||||
|
|
||||||
|
def getTags(full_path: str) -> dict:
|
||||||
|
"""
|
||||||
|
Returns a dictionary of tags for a given file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if full_path.endswith('.flac'):
|
||||||
|
try:
|
||||||
|
audio = FLAC(full_path)
|
||||||
|
except:
|
||||||
|
return
|
||||||
|
elif full_path.endswith('.mp3'):
|
||||||
|
try:
|
||||||
|
audio = MP3(full_path)
|
||||||
|
except:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
artists = audio['artist'][0]
|
||||||
|
except KeyError:
|
||||||
|
try:
|
||||||
|
artists = audio['TPE1'][0]
|
||||||
|
except:
|
||||||
|
artists = 'Unknown'
|
||||||
|
except IndexError:
|
||||||
|
artists = 'Unknown'
|
||||||
|
|
||||||
|
try:
|
||||||
|
album_artist = audio['albumartist'][0]
|
||||||
|
except KeyError:
|
||||||
|
try:
|
||||||
|
album_artist = audio['TPE2'][0]
|
||||||
|
except:
|
||||||
|
album_artist = 'Unknown'
|
||||||
|
except IndexError:
|
||||||
|
album_artist = 'Unknown'
|
||||||
|
|
||||||
|
try:
|
||||||
|
title = audio['title'][0]
|
||||||
|
except KeyError:
|
||||||
|
try:
|
||||||
|
title = audio['TIT2'][0]
|
||||||
|
except:
|
||||||
|
title = full_path.split('/')[-1]
|
||||||
|
except:
|
||||||
|
title = full_path.split('/')[-1]
|
||||||
|
|
||||||
|
try:
|
||||||
|
album = audio['album'][0]
|
||||||
|
except KeyError:
|
||||||
|
try:
|
||||||
|
album = audio['TALB'][0]
|
||||||
|
except:
|
||||||
|
album = "Unknown"
|
||||||
|
except IndexError:
|
||||||
|
album = "Unknown"
|
||||||
|
|
||||||
|
try:
|
||||||
|
genre = audio['genre'][0]
|
||||||
|
except KeyError:
|
||||||
|
try:
|
||||||
|
genre = audio['TCON'][0]
|
||||||
|
except:
|
||||||
|
genre = "Unknown"
|
||||||
|
except IndexError:
|
||||||
|
genre = "Unknown"
|
||||||
|
|
||||||
|
img_path = extract_thumb(full_path)
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
"filepath": full_path.replace(helpers.home_dir, ''),
|
||||||
|
"folder": os.path.dirname(full_path).replace(helpers.home_dir, ""),
|
||||||
|
"title": title,
|
||||||
|
"artists": artists,
|
||||||
|
"album_artist": album_artist,
|
||||||
|
"album": album,
|
||||||
|
"genre": genre,
|
||||||
|
"length": round(audio.info.length),
|
||||||
|
"bitrate": audio.info.bitrate,
|
||||||
|
"image": img_path,
|
||||||
|
"type": {
|
||||||
|
"name": None,
|
||||||
|
"id": None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
instances.songs_instance.insert_song(tags)
|
||||||
|
return tags
|
||||||
|
|
||||||
|
|
||||||
|
def getAlbumBio(title: str, album_artist: str) -> dict:
|
||||||
|
last_fm_url = 'http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key={}&artist={}&album={}&format=json'.format(
|
||||||
|
helpers.last_fm_api_key, album_artist, title)
|
||||||
|
|
||||||
|
response = requests.get(last_fm_url)
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
try:
|
||||||
|
bio = data['album']['wiki']['content']
|
||||||
|
except KeyError:
|
||||||
|
bio = None
|
||||||
|
|
||||||
|
if bio is None:
|
||||||
|
return "None"
|
||||||
|
|
||||||
|
return {'data': data}
|
||||||
|
@ -7,28 +7,25 @@ import threading
|
|||||||
import time
|
import time
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from mutagen.mp3 import MP3
|
|
||||||
from mutagen.id3 import ID3
|
|
||||||
from mutagen.flac import FLAC
|
|
||||||
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
from app import instances
|
from app import instances
|
||||||
from app import functions
|
from app import functions
|
||||||
|
|
||||||
home_dir = os.path.expanduser('~') + "/"
|
home_dir = os.path.expanduser('~') + '/'
|
||||||
app_dir = home_dir + '/.musicx'
|
app_dir = os.path.join(home_dir, '.musicx')
|
||||||
|
last_fm_api_key = "762db7a44a9e6fb5585661f5f2bdf23a"
|
||||||
|
|
||||||
def background(f):
|
def background(f):
|
||||||
'''
|
'''
|
||||||
a threading decorator
|
a threading decorator
|
||||||
use @background above the function you want to run in the background
|
use @background above the function you want to run in the background
|
||||||
'''
|
'''
|
||||||
def backgrnd_func(*a, **kw):
|
def background_func(*a, **kw):
|
||||||
threading.Thread(target=f, args=a, kwargs=kw).start()
|
threading.Thread(target=f, args=a, kwargs=kw).start()
|
||||||
return backgrnd_func
|
return background_func
|
||||||
|
|
||||||
|
|
||||||
@background
|
@background
|
||||||
def check_for_new_songs():
|
def check_for_new_songs():
|
||||||
@ -62,142 +59,6 @@ def run_fast_scandir(dir: str, ext: str) -> list:
|
|||||||
return subfolders, files
|
return subfolders, files
|
||||||
|
|
||||||
|
|
||||||
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'
|
|
||||||
img_path = app_dir + "/images/thumbnails/" + webp_path
|
|
||||||
|
|
||||||
if os.path.exists(img_path):
|
|
||||||
return webp_path
|
|
||||||
|
|
||||||
if path.endswith('.flac'):
|
|
||||||
try:
|
|
||||||
audio = FLAC(path)
|
|
||||||
album_art = audio.pictures[0].data
|
|
||||||
except:
|
|
||||||
album_art = None
|
|
||||||
elif path.endswith('.mp3'):
|
|
||||||
try:
|
|
||||||
audio = ID3(path)
|
|
||||||
album_art = audio.getall('APIC')[0].data
|
|
||||||
except:
|
|
||||||
album_art = None
|
|
||||||
|
|
||||||
if album_art is None:
|
|
||||||
return "null.webp"
|
|
||||||
else:
|
|
||||||
img = Image.open(BytesIO(album_art))
|
|
||||||
|
|
||||||
try:
|
|
||||||
small_img = img.resize((150, 150), Image.ANTIALIAS)
|
|
||||||
small_img.save(img_path, format="webp")
|
|
||||||
except OSError:
|
|
||||||
try:
|
|
||||||
png = img.convert('RGB')
|
|
||||||
small_img = png.resize((150, 150), Image.ANTIALIAS)
|
|
||||||
small_img.save(img_path, format="webp")
|
|
||||||
print('{} :: was png'.format(
|
|
||||||
img_path
|
|
||||||
))
|
|
||||||
|
|
||||||
except:
|
|
||||||
img_path = None
|
|
||||||
|
|
||||||
return webp_path
|
|
||||||
|
|
||||||
|
|
||||||
def getTags(full_path: str) -> dict:
|
|
||||||
"""
|
|
||||||
Returns a dictionary of tags for a given file.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if full_path.endswith('.flac'):
|
|
||||||
try:
|
|
||||||
audio = FLAC(full_path)
|
|
||||||
except:
|
|
||||||
return
|
|
||||||
elif full_path.endswith('.mp3'):
|
|
||||||
try:
|
|
||||||
audio = MP3(full_path)
|
|
||||||
except:
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
artists = audio['artist'][0]
|
|
||||||
except KeyError:
|
|
||||||
try:
|
|
||||||
artists = audio['TPE1'][0]
|
|
||||||
except:
|
|
||||||
artists = 'Unknown'
|
|
||||||
except IndexError:
|
|
||||||
artists = 'Unknown'
|
|
||||||
|
|
||||||
try:
|
|
||||||
album_artist = audio['albumartist'][0]
|
|
||||||
except KeyError:
|
|
||||||
try:
|
|
||||||
album_artist = audio['TPE2'][0]
|
|
||||||
except:
|
|
||||||
album_artist = 'Unknown'
|
|
||||||
except IndexError:
|
|
||||||
album_artist = 'Unknown'
|
|
||||||
|
|
||||||
try:
|
|
||||||
title = audio['title'][0]
|
|
||||||
except KeyError:
|
|
||||||
try:
|
|
||||||
title = audio['TIT2'][0]
|
|
||||||
except:
|
|
||||||
title = full_path.split('/')[-1]
|
|
||||||
except:
|
|
||||||
title = full_path.split('/')[-1]
|
|
||||||
|
|
||||||
try:
|
|
||||||
album = audio['album'][0]
|
|
||||||
except KeyError:
|
|
||||||
try:
|
|
||||||
album = audio['TALB'][0]
|
|
||||||
except:
|
|
||||||
album = "Unknown"
|
|
||||||
except IndexError:
|
|
||||||
album = "Unknown"
|
|
||||||
|
|
||||||
try:
|
|
||||||
genre = audio['genre'][0]
|
|
||||||
except KeyError:
|
|
||||||
try:
|
|
||||||
genre = audio['TCON'][0]
|
|
||||||
except:
|
|
||||||
genre = "Unknown"
|
|
||||||
except IndexError:
|
|
||||||
genre = "Unknown"
|
|
||||||
|
|
||||||
img_path = extract_thumb(full_path)
|
|
||||||
|
|
||||||
tags = {
|
|
||||||
"filepath": full_path.replace(home_dir, ''),
|
|
||||||
"folder": os.path.dirname(full_path).replace(home_dir, ""),
|
|
||||||
"title": title,
|
|
||||||
"artists": artists,
|
|
||||||
"album_artist": album_artist,
|
|
||||||
"album": album,
|
|
||||||
"genre": genre,
|
|
||||||
"length": round(audio.info.length),
|
|
||||||
"bitrate": audio.info.bitrate,
|
|
||||||
"image": img_path,
|
|
||||||
"type": {
|
|
||||||
"name": None,
|
|
||||||
"id": None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
instances.songs_instance.insert_song(tags)
|
|
||||||
return tags
|
|
||||||
|
|
||||||
|
|
||||||
def remove_duplicates(array: list) -> list:
|
def remove_duplicates(array: list) -> list:
|
||||||
"""
|
"""
|
||||||
Removes duplicates from a list. Returns a list without duplicates.
|
Removes duplicates from a list. Returns a list without duplicates.
|
||||||
@ -245,13 +106,18 @@ def create_config_dir() -> None:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
home_dir = os.path.expanduser('~')
|
home_dir = os.path.expanduser('~')
|
||||||
config_folder = home_dir + app_dir
|
config_folder = os.path.join(home_dir, app_dir)
|
||||||
|
|
||||||
dirs = ["", "/images", "/images/artists", "/images/thumbnails"]
|
dirs = ["", "images", "images/defaults",
|
||||||
|
"images/artists", "images/thumbnails"]
|
||||||
|
|
||||||
for dir in dirs:
|
for dir in dirs:
|
||||||
if not os.path.exists(config_folder + dir):
|
path = os.path.join(config_folder, dir)
|
||||||
os.makedirs(config_folder + dir)
|
os.chmod(path, 0o755)
|
||||||
|
try:
|
||||||
|
os.makedirs(path)
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def getAllSongs() -> None:
|
def getAllSongs() -> None:
|
||||||
@ -259,19 +125,14 @@ def getAllSongs() -> None:
|
|||||||
Gets all songs under the ~/ directory.
|
Gets all songs under the ~/ directory.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
tracks = []
|
tracks = instances.songs_instance.get_all_songs()
|
||||||
tracks.extend(instances.songs_instance.get_all_songs())
|
|
||||||
|
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
try:
|
try:
|
||||||
os.chmod(os.path.join(home_dir, track['filepath']), 0o755)
|
os.chmod(os.path.join(home_dir, track['filepath']), 0o755)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
instances.songs_instance.remove_song_by_filepath(
|
instances.songs_instance.remove_song_by_filepath(track['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']
|
|
||||||
if track['artists'] is not None:
|
if track['artists'] is not None:
|
||||||
track['artists'] = track['artists'].split(', ')
|
track['artists'] = track['artists'].split(', ')
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ class AllSongs(Mongo):
|
|||||||
|
|
||||||
def remove_song_by_filepath(self, filepath):
|
def remove_song_by_filepath(self, filepath):
|
||||||
try:
|
try:
|
||||||
self.collection.remove({'filepath': filepath})
|
self.collection.delete_one({'filepath': filepath})
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
@ -8,4 +8,3 @@ $separator: #ffffff46;
|
|||||||
// sizes
|
// sizes
|
||||||
$small: .5em;
|
$small: .5em;
|
||||||
$smaller: .25em;
|
$smaller: .25em;
|
||||||
|
|
||||||
|
@ -74,18 +74,6 @@ button {
|
|||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background: rgba(0, 0, 0, 0.575);
|
background: rgba(0, 0, 0, 0.575);
|
||||||
backdrop-filter: blur(40px);
|
|
||||||
-webkit-backdrop-filter: blur(40px);
|
|
||||||
-moz-backdrop-filter: blur(40px);
|
|
||||||
}
|
|
||||||
|
|
||||||
#bg-blur {
|
|
||||||
position: absolute;
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
background-color: rgba(27, 27, 27, 0.548);
|
|
||||||
background-image: url(../images/dark-bg.jpg);
|
|
||||||
z-index: -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.l-sidebar {
|
.l-sidebar {
|
||||||
|
BIN
src/assets/images/featured-artists.webp
Normal file
BIN
src/assets/images/featured-artists.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
@ -1,10 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="al-bio rounded">
|
<div class="al-bio rounded">
|
||||||
<div class="heading">ALBUM BIOGRAPHY</div>
|
<div class="heading">
|
||||||
|
The Very Best Of UB40: ALBUM BIOGRAPHY
|
||||||
|
<div class="tags">
|
||||||
|
<div class="item" v-for="tag in tags" :key="tag">
|
||||||
|
{{ tag }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
Two years after he prematurely left us, the Juice WRLD story continues
|
Two years after he prematurely left us, the Juice WRLD story continues
|
||||||
with Fighting Demons. The rapper’s second posthumous album dropped at
|
with Fighting Demons. The rapper's second posthumous album dropped at
|
||||||
midnight, and is the followup to Legends Never Die, which arrived in July
|
midnight, and is the followup to Legends Never Die, which arrived in July
|
||||||
2020 and hit No. 1 on the Billboard 200 chart.
|
2020 and hit No. 1 on the Billboard 200 chart.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
@ -16,21 +23,28 @@
|
|||||||
and codeine. Following his death on Dec. 9, 2019, his mother, Carmela
|
and codeine. Following his death on Dec. 9, 2019, his mother, Carmela
|
||||||
Wallace, created the Live Free 999 Fund, to help youth struggling with
|
Wallace, created the Live Free 999 Fund, to help youth struggling with
|
||||||
mental health and substance use issues.
|
mental health and substance use issues.
|
||||||
<br><br>
|
<br /><br />
|
||||||
“Jarad was always searingly honest
|
“Jarad was always searingly honest about his struggles and through his
|
||||||
about his struggles and through his musical genius he articulated what was
|
musical genius he articulated what was on his heart and mind vividly
|
||||||
on his heart and mind vividly through his art. He never gave up and his
|
through his art. He never gave up and his friends and family never gave up
|
||||||
friends and family never gave up on offering their support to him,” she
|
on offering their support to him,” she continued. “We encourage all of you
|
||||||
continued. “We encourage all of you who struggle with addiction and mental
|
who struggle with addiction and mental health to never give up the fight."
|
||||||
health to never give up the fight.” Juice’s fast rise in the hip-hop space
|
Juice's fast rise in the hip-hop space and untimely passing is the focus
|
||||||
and untimely passing is the focus of Into the Abyss, a Tommy
|
of Into the Abyss, a Tommy Oliver-directed documentary set to premiere
|
||||||
Oliver-directed documentary set to premiere Dec. 16 at 8PM on HBO Max.
|
Dec. 16 at 8PM on HBO Max.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {};
|
export default {
|
||||||
|
setup() {
|
||||||
|
const tags = ["reggea", "ub40", "ali campbell", "astro"];
|
||||||
|
return {
|
||||||
|
tags,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -40,6 +54,25 @@ export default {};
|
|||||||
|
|
||||||
.heading {
|
.heading {
|
||||||
margin: 0 0 0 $small;
|
margin: 0 0 0 $small;
|
||||||
|
height: 2rem;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.tags {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
font-weight: normal;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
padding: $small;
|
||||||
|
background-color: rgb(15, 74, 114);
|
||||||
|
margin-left: $small;
|
||||||
|
border-radius: $small;
|
||||||
|
}
|
||||||
|
.item::before {
|
||||||
|
content: "#"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
@ -1,30 +1,27 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="folder">
|
<div class="folder">
|
||||||
<div class="table rounded" ref="songtitle" v-if="songs.length">
|
<div class="table rounded" v-if="songs.length">
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Track</th>
|
<th>Track</th>
|
||||||
<th>Artist</th>
|
<th>Artist</th>
|
||||||
<th>Album</th>
|
<th>Album</th>
|
||||||
<th v-if="songTitleWidth > minWidth">Duration</th>
|
<th>Duration</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<SongItem
|
<SongItem
|
||||||
:songTitleWidth="songTitleWidth"
|
|
||||||
:minWidth="minWidth"
|
|
||||||
v-for="song in songs"
|
v-for="song in songs"
|
||||||
:key="song"
|
:key="song"
|
||||||
:song="song"
|
:song="song"
|
||||||
:current="current"
|
|
||||||
@updateQueue="updateQueue"
|
@updateQueue="updateQueue"
|
||||||
@loadAlbum="loadAlbum"
|
@loadAlbum="loadAlbum"
|
||||||
/>
|
/>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div ref="songtitle" v-else-if="songs.length === 0 && search_query">
|
<div 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 +33,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ref } from "@vue/reactivity";
|
import { ref } from "@vue/reactivity";
|
||||||
import { onMounted, onUnmounted } from "@vue/runtime-core";
|
import { onMounted } from "@vue/runtime-core";
|
||||||
|
|
||||||
import SongItem from "../SongItem.vue";
|
import SongItem from "../SongItem.vue";
|
||||||
import album from "@/composables/album.js";
|
import album from "@/composables/album.js";
|
||||||
@ -50,40 +47,14 @@ export default {
|
|||||||
SongItem,
|
SongItem,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const songtitle = ref(null);
|
|
||||||
const songTitleWidth = ref(null);
|
|
||||||
|
|
||||||
const minWidth = ref(300);
|
|
||||||
let routex;
|
let routex;
|
||||||
|
|
||||||
const current = ref(perks.current);
|
const current = ref(perks.current);
|
||||||
const search_query = ref(state.search_query);
|
const search_query = ref(state.search_query);
|
||||||
const route = useRouter();
|
const route = useRouter();
|
||||||
|
|
||||||
const resizeSongTitleWidth = () => {
|
|
||||||
try {
|
|
||||||
let a = songtitle.value.clientWidth;
|
|
||||||
|
|
||||||
songTitleWidth.value = a > minWidth.value * 4 ? a / 4 : a / 3;
|
|
||||||
} catch (error) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
routex = useRoute().name;
|
routex = useRoute().name;
|
||||||
|
|
||||||
resizeSongTitleWidth();
|
|
||||||
|
|
||||||
window.addEventListener("resize", () => {
|
|
||||||
resizeSongTitleWidth();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
window.removeEventListener("resize", () => {
|
|
||||||
resizeSongTitleWidth();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function updateQueue(song) {
|
function updateQueue(song) {
|
||||||
@ -122,9 +93,6 @@ export default {
|
|||||||
return {
|
return {
|
||||||
updateQueue,
|
updateQueue,
|
||||||
loadAlbum,
|
loadAlbum,
|
||||||
songtitle,
|
|
||||||
songTitleWidth,
|
|
||||||
minWidth,
|
|
||||||
current,
|
current,
|
||||||
search_query,
|
search_query,
|
||||||
};
|
};
|
||||||
@ -161,7 +129,34 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder .table table td .album-art {
|
.folder .table table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
text-transform: capitalize;
|
||||||
|
width: 100%;
|
||||||
|
table-layout: fixed;
|
||||||
|
|
||||||
|
thead {
|
||||||
|
height: 2rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
th {
|
||||||
|
text-align: left;
|
||||||
|
padding-left: $small;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tbody tr {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.flex {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 4rem;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.album-art {
|
||||||
|
position: absolute;
|
||||||
|
left: $small;
|
||||||
width: 3rem;
|
width: 3rem;
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
@ -169,42 +164,14 @@ export default {
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder .table .flex {
|
|
||||||
position: relative;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder .table .flex > div > span {
|
td {
|
||||||
position: absolute;
|
height: 4rem;
|
||||||
bottom: 1.5rem;
|
padding: $small;
|
||||||
width: calc(100% - 6rem);
|
|
||||||
}
|
|
||||||
td,
|
|
||||||
th {
|
|
||||||
padding: $small 0 $small $small;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-weight: normal;
|
|
||||||
// display: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
td .artist {
|
|
||||||
margin-right: 0.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.folder .table table {
|
|
||||||
border-collapse: collapse;
|
|
||||||
text-transform: capitalize;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
tbody tr {
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.1s ease;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
& {
|
& {
|
||||||
& > td {
|
& > td {
|
||||||
|
@ -73,17 +73,22 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.collapsed .nav-button {
|
.collapsed {
|
||||||
|
.nav-button {
|
||||||
font-size: smaller;
|
font-size: smaller;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
.in {
|
.in {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.side-nav-container {
|
.side-nav-container {
|
||||||
padding: $small;
|
padding: $small;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<div class="next" @click="scrollRight"></div>
|
<div class="next" @click="scrollRight"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="artists" ref="artists_dom" v-on:mouseover="scrollArtists">
|
<div class="artists" ref="artists_dom" v-on:mouseover="scrollArtists">
|
||||||
<div class="artist c1">
|
<div class="artist c1 image">
|
||||||
<div class="blur"></div>
|
<div class="blur"></div>
|
||||||
<div class="s2"></div>
|
<div class="s2"></div>
|
||||||
<p>Featured Artists</p>
|
<p>Featured Artists</p>
|
||||||
@ -74,7 +74,7 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.f-artists {
|
.f-artists {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 13em;
|
height: 15em;
|
||||||
width: calc(100%);
|
width: calc(100%);
|
||||||
background-color: $card-dark;
|
background-color: $card-dark;
|
||||||
padding: $small;
|
padding: $small;
|
||||||
@ -143,69 +143,69 @@ export default {
|
|||||||
margin-left: $smaller;
|
margin-left: $smaller;
|
||||||
margin-right: $smaller;
|
margin-right: $smaller;
|
||||||
width: 9em;
|
width: 9em;
|
||||||
height: 9em;
|
height: 11em;
|
||||||
border-radius: $small;
|
border-radius: $small;
|
||||||
background-color: #0f0e0e;
|
background-color: #0f0e0e;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
transition: all 0.5s ease-in-out;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
border: solid 1px rgba(165, 151, 151, 0.055);
|
||||||
|
|
||||||
.artist-image {
|
.artist-image {
|
||||||
width: 7em;
|
width: 7em;
|
||||||
height: 7em;
|
height: 7em;
|
||||||
margin-left: 0.5em;
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin-bottom: $small;
|
margin-bottom: $small;
|
||||||
background: url(../../assets/images/girl1.jpg);
|
background: url(../../assets/images/girl1.jpg);
|
||||||
background-size: cover;
|
background-size: 7rem 7rem;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
|
transition: all 0.75s ease-in-out;
|
||||||
|
border: solid 1px rgba(165, 151, 151, 0.055);
|
||||||
|
box-shadow: 0px 0px 80px rgb(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.artist-image {
|
||||||
|
background-position: 50% 20%;
|
||||||
|
border-radius: 20%;
|
||||||
|
background-size: 10rem 10rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.artist-name {
|
.artist-name {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: small;
|
font-size: 0.9rem;
|
||||||
width: 10em;
|
font-weight: 510;
|
||||||
}
|
max-width: 7rem;
|
||||||
&:hover {
|
|
||||||
transform: translateY(-0.5em);
|
|
||||||
transition: all 0.5s ease-in-out;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.f-artists .c1 {
|
.f-artists .c1 {
|
||||||
position: relative;
|
position: relative;
|
||||||
background: rgb(16, 25, 51);
|
background-size: 400px 11rem;
|
||||||
width: 15em;
|
background-position: 100%;
|
||||||
|
|
||||||
&:hover > .s2 {
|
background-image: linear-gradient(
|
||||||
background: rgba(53, 53, 146, 0.8);
|
320deg,
|
||||||
transition: all 0.5s ease;
|
hsl(0deg 3% 6%) 13%,
|
||||||
width: 12em;
|
hsl(211deg 81% 23%) 50%,
|
||||||
height: 12em;
|
hsl(209deg 94% 30%) 87%
|
||||||
|
);
|
||||||
|
|
||||||
|
transition: all 0.75s ease-in-out;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-position: 10%;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
position: absolute;
|
margin-left: 1rem;
|
||||||
bottom: -2rem;
|
font-size: 1.5rem;
|
||||||
margin-left: 0.5rem;
|
|
||||||
font-size: 2rem;
|
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #ffffff;
|
text-shadow: 0px 0px 80px rgb(0, 0, 0);
|
||||||
}
|
|
||||||
|
|
||||||
.s2 {
|
|
||||||
position: absolute;
|
|
||||||
left: -2em;
|
|
||||||
bottom: -4em;
|
|
||||||
width: 10em;
|
|
||||||
height: 10em;
|
|
||||||
background: rgba(53, 53, 146, 0.445);
|
|
||||||
border-radius: 50%;
|
|
||||||
transition: all 0.5s ease;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -1,94 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="folder" id="p-table">
|
|
||||||
<div class="table rounded" ref="songtitle">
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Track</th>
|
|
||||||
<th>Artist</th>
|
|
||||||
<th>Album</th>
|
|
||||||
<th v-if="songTitleWidth > minWidth">Duration</th>
|
|
||||||
</tr>
|
|
||||||
<tr v-for="song in songs" :key="song">
|
|
||||||
<td :style="{ width: songTitleWidth + 'px' }" class="flex">
|
|
||||||
<div class="album-art rounded image"></div>
|
|
||||||
<div>
|
|
||||||
<span class="ellipsis">{{ song.title }}</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td :style="{ width: songTitleWidth + 'px' }">
|
|
||||||
<span class="artist" v-for="artist in song.artists" :key="artist">{{
|
|
||||||
artist
|
|
||||||
}}</span>
|
|
||||||
</td>
|
|
||||||
<td :style="{ width: songTitleWidth + 'px' }">{{ song.album }}</td>
|
|
||||||
<td
|
|
||||||
:style="{ width: songTitleWidth + 'px' }"
|
|
||||||
v-if="songTitleWidth > minWidth"
|
|
||||||
>
|
|
||||||
{{ song.duration }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { ref } from "@vue/reactivity";
|
|
||||||
import { onMounted, onUnmounted } from "@vue/runtime-core";
|
|
||||||
import Songs from "../../data/songs.js";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
setup() {
|
|
||||||
const songtitle = ref(null);
|
|
||||||
const songTitleWidth = ref(null);
|
|
||||||
|
|
||||||
const minWidth = ref(300);
|
|
||||||
|
|
||||||
const songs = Songs.songs;
|
|
||||||
|
|
||||||
const resizeSongTitleWidth = () => {
|
|
||||||
let a = songtitle.value.clientWidth;
|
|
||||||
|
|
||||||
songTitleWidth.value = a > minWidth.value * 4 ? a / 4 : a / 3;
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
resizeSongTitleWidth();
|
|
||||||
|
|
||||||
window.addEventListener("resize", () => {
|
|
||||||
resizeSongTitleWidth();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
window.removeEventListener("resize", () => {
|
|
||||||
resizeSongTitleWidth();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return { songtitle, songTitleWidth, songs, minWidth };
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
#p-table {
|
|
||||||
height: calc(100% - 0rem) !important;
|
|
||||||
overflow: hidden;
|
|
||||||
padding-bottom: 0rem;
|
|
||||||
|
|
||||||
table {
|
|
||||||
&::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
position: sticky;
|
|
||||||
background-color: rgb(58, 57, 57);
|
|
||||||
top: 0;
|
|
||||||
z-index: 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -276,8 +276,8 @@ export default {
|
|||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
margin-right: 0.5rem;
|
margin-right: 0.5rem;
|
||||||
margin-left: $small;
|
margin-left: $small;
|
||||||
background-color: #ad1717a8;
|
// background-color: #ad1717a8;
|
||||||
background-image: url(../../assets/images/null.webp);
|
background-image: url("../../assets/images/null.webp");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<tr :class="{ current: current._id.$oid == song._id.$oid }">
|
<tr :class="{ current: current._id.$oid == song._id.$oid }">
|
||||||
<td
|
<td
|
||||||
:style="{ width: songTitleWidth + 'px' }"
|
|
||||||
class="flex"
|
class="flex"
|
||||||
@click="emitUpdate(song)"
|
@click="emitUpdate(song)"
|
||||||
>
|
>
|
||||||
@ -21,7 +20,7 @@
|
|||||||
<span class="ellip">{{ song.title }}</span>
|
<span class="ellip">{{ song.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td :style="{ width: songTitleWidth + 'px' }">
|
<td>
|
||||||
<div class="ellip" v-if="song.artists[0] != ''">
|
<div class="ellip" v-if="song.artists[0] != ''">
|
||||||
<span
|
<span
|
||||||
class="artist"
|
class="artist"
|
||||||
@ -34,7 +33,7 @@
|
|||||||
<span class="artist">{{ song.album_artist }}</span>
|
<span class="artist">{{ song.album_artist }}</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td :style="{ width: songTitleWidth + 'px' }">
|
<td>
|
||||||
<div
|
<div
|
||||||
class="ellip"
|
class="ellip"
|
||||||
@click="emitLoadAlbum(song.album, song.album_artist)"
|
@click="emitLoadAlbum(song.album, song.album_artist)"
|
||||||
@ -42,8 +41,6 @@
|
|||||||
>
|
>
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
:style="{ width: songTitleWidth + 'px' }"
|
|
||||||
v-if="songTitleWidth > minWidth"
|
|
||||||
>
|
>
|
||||||
{{ `${Math.trunc(song.length / 60)} min` }}
|
{{ `${Math.trunc(song.length / 60)} min` }}
|
||||||
</td>
|
</td>
|
||||||
@ -55,7 +52,7 @@ import perks from "@/composables/perks.js";
|
|||||||
import state from "@/composables/state.js";
|
import state from "@/composables/state.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ["song", "songTitleWidth", "minWidth"],
|
props: ["song"],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
function emitUpdate(song) {
|
function emitUpdate(song) {
|
||||||
emit("updateQueue", song);
|
emit("updateQueue", song);
|
||||||
|
@ -10,6 +10,7 @@ const current = ref(state.current);
|
|||||||
const next = ref({
|
const next = ref({
|
||||||
title: "The next song",
|
title: "The next song",
|
||||||
artists: ["... blah blah blah"],
|
artists: ["... blah blah blah"],
|
||||||
|
image: "http://127.0.0.1:8900/images/defaults/4.webp",
|
||||||
_id: {
|
_id: {
|
||||||
$oid: "",
|
$oid: "",
|
||||||
},
|
},
|
||||||
|
@ -6,18 +6,20 @@ const queue = ref([
|
|||||||
{
|
{
|
||||||
title: "Nothing played yet",
|
title: "Nothing played yet",
|
||||||
artists: ["... blah blah blah"],
|
artists: ["... blah blah blah"],
|
||||||
|
image: "http://127.0.0.1:8900/images/defaults/5.webp",
|
||||||
_id: {
|
_id: {
|
||||||
$oid: "",
|
$oid: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const folder_song_list = ref([])
|
const folder_song_list = ref([]);
|
||||||
const folder_list = ref([])
|
const folder_list = ref([]);
|
||||||
|
|
||||||
const current = ref({
|
const current = ref({
|
||||||
title: "Nothing played yet",
|
title: "Nothing played yet",
|
||||||
artists: ["... blah blah blah"],
|
artists: ["... blah blah blah"],
|
||||||
|
image: "http://127.0.0.1:8900/images/defaults/1.webp",
|
||||||
_id: {
|
_id: {
|
||||||
$oid: "",
|
$oid: "",
|
||||||
},
|
},
|
||||||
@ -31,9 +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 album_artists = ref([]);
|
||||||
const filters = ref([]);
|
const filters = ref([]);
|
||||||
|
|
||||||
const magic_flag = ref(false);
|
const magic_flag = ref(false);
|
||||||
@ -61,5 +63,5 @@ export default {
|
|||||||
search_artists,
|
search_artists,
|
||||||
album_song_list,
|
album_song_list,
|
||||||
album_info,
|
album_info,
|
||||||
album_artists
|
album_artists,
|
||||||
};
|
};
|
||||||
|
@ -57,7 +57,6 @@ export default {
|
|||||||
if (state.album_artists.value.length == 0) {
|
if (state.album_artists.value.length == 0) {
|
||||||
album.getAlbumArtists(title, album_artists).then((data) => {
|
album.getAlbumArtists(title, album_artists).then((data) => {
|
||||||
state.album_artists.value = data;
|
state.album_artists.value = data;
|
||||||
console.log(state.album_artists.value)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Header from "@/components/PlaylistView/Header.vue";
|
import Header from "@/components/PlaylistView/Header.vue";
|
||||||
import SongList from "@/components/PlaylistView/SongList.vue";
|
import SongList from "@/components/FolderView/SongList.vue";
|
||||||
import FeaturedArtists from "@/components/PlaylistView/FeaturedArtists.vue";
|
import FeaturedArtists from "@/components/PlaylistView/FeaturedArtists.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user