implement pinning playlists

+ update migrations to add pinned attr to plalist
+ misc
This commit is contained in:
mungai-njoroge 2023-08-22 15:36:43 +03:00
parent c3c9cb059f
commit e3a61c109b
5 changed files with 68 additions and 71 deletions

View File

@ -97,7 +97,12 @@ def insert_playlist(name: str, image: str = None):
"name": name,
"trackhashes": json.dumps([]),
"settings": json.dumps(
{"has_gif": False, "banner_pos": 50, "square_img": True if image else False}
{
"has_gif": False,
"banner_pos": 50,
"square_img": True if image else False,
"pinned": False,
}
),
}
@ -170,12 +175,12 @@ def add_item_to_playlist(playlist_id: str):
itemtype = None
try:
itemhash = data["itemhash"]
itemhash: str = data["itemhash"]
except KeyError:
itemhash = None
if itemtype == "track":
trackhashes = [itemhash]
if itemtype == "tracks":
trackhashes = itemhash.split(",")
elif itemtype == "folder":
trackhashes = get_path_trackhashes(itemhash)
elif itemtype == "album":
@ -190,8 +195,6 @@ def add_item_to_playlist(playlist_id: str):
if insert_count == 0:
return {"error": "Item already exists in playlist"}, 409
PL.update_last_updated(int(playlist_id))
return {"msg": "Done"}, 200
@ -220,13 +223,6 @@ def get_playlist(playlistid: str):
if not playlist.has_image:
playlist.images = get_first_4_images(tracks)
if len(playlist.images) > 2:
# swap 3rd image with first (3rd image is the visible image in UI)
playlist.images[2], playlist.images[0] = (
playlist.images[0],
playlist.images[2],
)
playlist.clear_lists()
return {"info": playlist, "tracks": tracks if not no_tracks else []}
@ -288,6 +284,28 @@ def update_playlist_info(playlistid: str):
}
@api.route("/playlist/<playlistid>/pin_unpin", methods=["GET"])
def pin_unpin_playlist(playlistid: str):
"""
Pins or unpins a playlist.
"""
playlist = PL.get_playlist_by_id(int(playlistid))
if playlist is None:
return {"error": "Playlist not found"}, 404
settings = playlist.settings
try:
settings["pinned"] = not settings["pinned"]
except KeyError:
settings["pinned"] = True
PL.update_settings(int(playlistid), settings)
return {"msg": "Done"}, 200
@api.route("/playlist/<playlistid>/remove-img", methods=["GET"])
def remove_playlist_image(playlistid: str):
"""
@ -308,7 +326,6 @@ def remove_playlist_image(playlistid: str):
playlist.images = get_first_4_images(trackhashes=playlist.trackhashes)
playlist.last_updated = date_string_to_time_passed(playlist.last_updated)
PL.update_last_updated(pid)
return {"playlist": playlist}, 200
@ -334,24 +351,6 @@ def remove_playlist():
return {"msg": "Done"}, 200
@api.route("/playlist/<pid>/set-image-pos", methods=["POST"])
def update_image_position(pid: int):
data = request.get_json()
message = {"msg": "No data provided"}
if data is None:
return message, 400
try:
pos = data["pos"]
except KeyError:
return message, 400
PL.update_banner_pos(pid, pos)
return {"msg": "Image position saved"}, 200
@api.route("/playlist/<pid>/remove-tracks", methods=["POST"])
def remove_tracks_from_playlist(pid: int):
data = request.get_json()
@ -366,7 +365,6 @@ def remove_tracks_from_playlist(pid: int):
tracks = data["tracks"]
PL.remove_tracks_from_playlist(pid, tracks)
PL.update_last_updated(pid)
return {"msg": "Done"}, 200
@ -404,30 +402,29 @@ def save_item_as_playlist():
if itemtype is None or playlist_name is None or itemhash is None:
return msg
if itemtype == "track":
trackhashes = [itemhash]
if itemtype == "tracks":
trackhashes = itemhash.split(",")
elif itemtype == "folder":
trackhashes = get_path_trackhashes(itemhash)
elif itemtype == "album":
trackhashes = get_album_trackhashes(itemhash)
elif itemtype == "artist":
trackhashes = get_artist_trackhashes(itemhash)
elif itemtype == "queue":
trackhashes = itemhash.split(",")
else:
trackhashes = []
if len(trackhashes) == 0:
return {"error": "No tracks founds"}, 404
image = itemhash + ".webp" if itemtype != "folder" and itemtype != "queue" else None
image = itemhash + ".webp" if itemtype != "folder" and itemtype != "tracks" else None
playlist = insert_playlist(playlist_name, image)
if playlist is None:
return {"error": "Playlist could not be created"}, 500
if itemtype != "folder" and itemtype != "queue":
# save image
if itemtype != "folder" and itemtype != "tracks":
filename = itemhash + ".webp"
base_path = (
@ -444,6 +441,5 @@ def save_item_as_playlist():
)
PL.add_tracks_to_playlist(playlist.id, trackhashes)
PL.update_last_updated(playlist.id)
return {"playlist": playlist}, 201

View File

@ -13,6 +13,14 @@ class SQLitePlaylistMethods:
This class contains methods for interacting with the playlists table.
"""
@staticmethod
def update_last_updated(playlist_id: int):
"""Updates the last updated date of a playlist."""
sql = """UPDATE playlists SET last_updated = ? WHERE id = ?"""
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (create_new_date(), playlist_id))
@staticmethod
def insert_one_playlist(playlist: dict):
# banner_pos,
@ -92,8 +100,8 @@ class SQLitePlaylistMethods:
# FIXME: Extract the "add_track_to_playlist" method to use it for both the artisthash and trackhash lists.
@staticmethod
def add_item_to_json_list(playlist_id: int, field: str, items: set[str]):
@classmethod
def add_item_to_json_list(cls, playlist_id: int, field: str, items: set[str]):
"""
Adds a string item to a json dumped list using a playlist id and field name.
Takes the playlist ID, a field name, an item to add to the field.
@ -118,6 +126,8 @@ class SQLitePlaylistMethods:
cur.execute(sql, (json.dumps(db_items), playlist_id))
return len(items)
cls.update_last_updated(playlist_id)
@classmethod
def add_tracks_to_playlist(cls, playlist_id: int, trackhashes: list[str]):
"""
@ -125,8 +135,8 @@ class SQLitePlaylistMethods:
"""
return cls.add_item_to_json_list(playlist_id, "trackhashes", trackhashes)
@staticmethod
def update_playlist(playlist_id: int, playlist: dict):
@classmethod
def update_playlist(cls, playlist_id: int, playlist: dict):
sql = """UPDATE playlists SET
image = ?,
last_updated = ?,
@ -145,13 +155,16 @@ class SQLitePlaylistMethods:
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, params)
@staticmethod
def update_last_updated(playlist_id: int):
"""Updates the last updated date of a playlist."""
sql = """UPDATE playlists SET last_updated = ? WHERE id = ?"""
cls.update_last_updated(playlist_id)
@classmethod
def update_settings(cls, playlist_id: int, settings: dict):
sql = """UPDATE playlists SET settings = ? WHERE id = ?"""
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (create_new_date(), playlist_id))
cur.execute(sql, (json.dumps(settings), playlist_id))
cls.update_last_updated(playlist_id)
@staticmethod
def delete_playlist(pid: str):
@ -160,21 +173,6 @@ class SQLitePlaylistMethods:
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (pid,))
@staticmethod
def update_banner_pos(playlistid: int, pos: int):
playlist = SQLitePlaylistMethods.get_playlist_by_id(playlistid)
if playlist is None:
return
playlist.settings["banner_pos"] = pos
settings_str = json.dumps(playlist.settings)
sql = """UPDATE playlists SET settings = ? WHERE id = ?"""
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (settings_str, playlistid))
@staticmethod
def remove_banner(playlistid: int):
sql = """UPDATE playlists SET image = NULL WHERE id = ?"""
@ -182,8 +180,8 @@ class SQLitePlaylistMethods:
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (playlistid,))
@staticmethod
def remove_tracks_from_playlist(playlistid: int, tracks: list[dict[str, int]]):
@classmethod
def remove_tracks_from_playlist(cls, playlistid: int, tracks: list[dict[str, int]]):
"""
Removes tracks from a playlist by trackhash and position.
"""
@ -211,3 +209,5 @@ class SQLitePlaylistMethods:
trackhashes.remove(track["trackhash"])
cur.execute(sql, (json.dumps(trackhashes), playlistid))
cls.update_last_updated(playlistid)

View File

@ -40,8 +40,8 @@ def extract_thumb(filepath: str, webp_path: str, overwrite=False) -> bool:
img.resize((tsize, tsize), Image.ANTIALIAS).save(lg_img_path, "webp")
img.resize((sm_tsize, sm_tsize), Image.ANTIALIAS).save(sm_img_path, "webp")
if not overwrite and os.path.exists(lg_img_path):
img_size = os.path.getsize(lg_img_path)
if not overwrite and os.path.exists(sm_img_path):
img_size = os.path.getsize(sm_img_path)
if img_size > 0:
return True

View File

@ -69,8 +69,6 @@ class AddSettingsToPlaylistTable(Migration):
@staticmethod
def migrate():
# existing_playlists = []
select_playlists_sql = "SELECT * FROM playlists"
with SQLiteManager(userdata_db=True) as cur:
@ -117,6 +115,7 @@ class AddSettingsToPlaylistTable(Migration):
"has_gif": False,
"banner_pos": playlist[1],
"square_img": False,
"pinned": False,
}
),
}

View File

@ -22,13 +22,15 @@ class Playlist:
duration: int = 0
has_image: bool = False
images: list[str] = dataclasses.field(default_factory=list)
pinned: bool = False
def __post_init__(self):
self.trackhashes = json.loads(str(self.trackhashes))
self.count = len(self.trackhashes)
if isinstance(self.settings, str):
self.settings = json.loads(self.settings)
self.settings = dict(json.loads(self.settings))
self.pinned = self.settings.get("pinned", False)
self.has_image = (
Path(settings.Paths.get_playlist_img_path()) / str(self.image)