mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-03 20:13:02 +00:00
feat: implement folder and folder track sorting
This commit is contained in:
+46
-5
@@ -23,11 +23,46 @@ api = APIBlueprint("folder", __name__, url_prefix="/folder", abp_tags=[tag])
|
|||||||
|
|
||||||
|
|
||||||
class FolderTree(BaseModel):
|
class FolderTree(BaseModel):
|
||||||
folder: str = Field(
|
folder: str = Field("$home", description="The folder to things from")
|
||||||
"$home", example="$home", description="The folder to things from"
|
tracksortby: str = Field(
|
||||||
|
"default",
|
||||||
|
description="""The field to sort tracks by. Options: [
|
||||||
|
"default",
|
||||||
|
"album",
|
||||||
|
"albumartists",
|
||||||
|
"artists",
|
||||||
|
"bitrate",
|
||||||
|
"date",
|
||||||
|
"disc",
|
||||||
|
"duration",
|
||||||
|
"lastmod",
|
||||||
|
"lastplayed",
|
||||||
|
"playduration",
|
||||||
|
"playcount",
|
||||||
|
"title",
|
||||||
|
]""",
|
||||||
|
)
|
||||||
|
tracksort_reverse: bool = Field(
|
||||||
|
False,
|
||||||
|
description="Whether to reverse the sort order of the tracks",
|
||||||
|
)
|
||||||
|
foldersortby: str = Field(
|
||||||
|
"lastmod",
|
||||||
|
description="""The field to sort folders by.
|
||||||
|
Options: [
|
||||||
|
"default",
|
||||||
|
"name",
|
||||||
|
"lastmod",
|
||||||
|
"trackcount",
|
||||||
|
]
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
foldersort_reverse: bool = Field(
|
||||||
|
True,
|
||||||
|
description="Whether to reverse the sort order of the folders",
|
||||||
)
|
)
|
||||||
start: int = Field(0, description="The start index")
|
start: int = Field(0, description="The start index")
|
||||||
end: int = Field(50, description="The end index")
|
limit: int = Field(50, description="The max number of items to return")
|
||||||
tracks_only: bool = Field(False, description="Whether to only get tracks")
|
tracks_only: bool = Field(False, description="Whether to only get tracks")
|
||||||
|
|
||||||
|
|
||||||
@@ -69,9 +104,15 @@ def get_folder_tree(body: FolderTree):
|
|||||||
req_dir = "/" + req_dir if not req_dir.startswith("/") else req_dir
|
req_dir = "/" + req_dir if not req_dir.startswith("/") else req_dir
|
||||||
|
|
||||||
res = get_files_and_dirs(
|
res = get_files_and_dirs(
|
||||||
req_dir, start=body.start, end=body.end, tracks_only=tracks_only
|
req_dir,
|
||||||
|
start=body.start,
|
||||||
|
limit=body.limit,
|
||||||
|
tracks_only=tracks_only,
|
||||||
|
tracksortby=body.tracksortby,
|
||||||
|
foldersortby=body.foldersortby,
|
||||||
|
tracksort_reverse=body.tracksort_reverse,
|
||||||
|
foldersort_reverse=body.foldersort_reverse,
|
||||||
)
|
)
|
||||||
res["folders"] = sorted(res["folders"], key=lambda i: i.name)
|
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|||||||
+24
-8
@@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from app.lib.sortlib import sort_folders, sort_tracks
|
||||||
from app.logger import log
|
from app.logger import log
|
||||||
from app.models import Folder
|
from app.models import Folder
|
||||||
from app.serializers.track import serialize_tracks
|
from app.serializers.track import serialize_tracks
|
||||||
@@ -11,7 +12,7 @@ from app.utils.wintools import win_replace_slash
|
|||||||
# from app.db.libdata import TrackTable as TrackDB
|
# from app.db.libdata import TrackTable as TrackDB
|
||||||
|
|
||||||
|
|
||||||
def create_folder(path: str, trackcount=0, foldercount=0) -> Folder:
|
def create_folder(path: str, trackcount=0) -> Folder:
|
||||||
"""
|
"""
|
||||||
Creates a folder object from a path.
|
Creates a folder object from a path.
|
||||||
"""
|
"""
|
||||||
@@ -22,7 +23,6 @@ def create_folder(path: str, trackcount=0, foldercount=0) -> Folder:
|
|||||||
path=win_replace_slash(str(folder)) + "/",
|
path=win_replace_slash(str(folder)) + "/",
|
||||||
is_sym=folder.is_symlink(),
|
is_sym=folder.is_symlink(),
|
||||||
trackcount=trackcount,
|
trackcount=trackcount,
|
||||||
foldercount=foldercount,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -46,14 +46,22 @@ def get_folders(paths: list[str]):
|
|||||||
"""
|
"""
|
||||||
folders = FolderStore.count_tracks_containing_paths(paths)
|
folders = FolderStore.count_tracks_containing_paths(paths)
|
||||||
return [
|
return [
|
||||||
create_folder(f["path"], f["trackcount"], foldercount=0)
|
create_folder(f["path"], f["trackcount"])
|
||||||
for f in folders
|
for f in folders
|
||||||
if f["trackcount"] > 0
|
if f["trackcount"] > 0
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def get_files_and_dirs(
|
def get_files_and_dirs(
|
||||||
path: str, start: int, end: int, tracks_only: bool = False, skip_empty_folders=True
|
path: str,
|
||||||
|
start: int,
|
||||||
|
limit: int,
|
||||||
|
tracksortby: str,
|
||||||
|
foldersortby: str,
|
||||||
|
tracksort_reverse: bool,
|
||||||
|
foldersort_reverse: bool,
|
||||||
|
tracks_only: bool = False,
|
||||||
|
skip_empty_folders=True,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Given a path, returns a list of tracks and folders in that immediate path.
|
Given a path, returns a list of tracks and folders in that immediate path.
|
||||||
@@ -102,14 +110,17 @@ def get_files_and_dirs(
|
|||||||
|
|
||||||
tracks = []
|
tracks = []
|
||||||
if files:
|
if files:
|
||||||
if end == -1:
|
if limit == -1:
|
||||||
end = len(files)
|
limit = len(files)
|
||||||
|
|
||||||
tracks = list(FolderStore.get_tracks_by_filepaths(files[start:end]))
|
tracks = list(FolderStore.get_tracks_by_filepaths(files))
|
||||||
|
tracks = sort_tracks(tracks, tracksortby, tracksort_reverse)
|
||||||
|
tracks = tracks[start : start + limit]
|
||||||
|
|
||||||
folders = []
|
folders = []
|
||||||
if not tracks_only:
|
if not tracks_only:
|
||||||
folders = get_folders(dirs)
|
folders = get_folders(dirs)
|
||||||
|
folders = sort_folders(folders, foldersortby, foldersort_reverse)
|
||||||
|
|
||||||
if skip_empty_folders and len(folders) == 1 and len(tracks) == 0:
|
if skip_empty_folders and len(folders) == 1 and len(tracks) == 0:
|
||||||
# INFO: When we only have one folder and no tracks,
|
# INFO: When we only have one folder and no tracks,
|
||||||
@@ -118,7 +129,11 @@ def get_files_and_dirs(
|
|||||||
return get_files_and_dirs(
|
return get_files_and_dirs(
|
||||||
folders[0].path,
|
folders[0].path,
|
||||||
start=start,
|
start=start,
|
||||||
end=end,
|
limit=limit,
|
||||||
|
tracksortby=tracksortby,
|
||||||
|
foldersortby=foldersortby,
|
||||||
|
tracksort_reverse=tracksort_reverse,
|
||||||
|
foldersort_reverse=foldersort_reverse,
|
||||||
tracks_only=tracks_only,
|
tracks_only=tracks_only,
|
||||||
skip_empty_folders=True,
|
skip_empty_folders=True,
|
||||||
)
|
)
|
||||||
@@ -127,4 +142,5 @@ def get_files_and_dirs(
|
|||||||
"path": path,
|
"path": path,
|
||||||
"tracks": serialize_tracks(tracks),
|
"tracks": serialize_tracks(tracks),
|
||||||
"folders": folders,
|
"folders": folders,
|
||||||
|
"total": len(files),
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-11
@@ -14,17 +14,6 @@ from app.store.folder import FolderStore
|
|||||||
from app.store.tracks import TrackStore
|
from app.store.tracks import TrackStore
|
||||||
from app.utils.threading import background
|
from app.utils.threading import background
|
||||||
|
|
||||||
def load_and_map():
|
|
||||||
key = str(time())
|
|
||||||
FolderStore.load_filepaths()
|
|
||||||
AlbumStore.load_albums(key)
|
|
||||||
ArtistStore.load_artists(key)
|
|
||||||
|
|
||||||
map_scrobble_data()
|
|
||||||
map_favorites()
|
|
||||||
map_artist_colors()
|
|
||||||
map_album_colors()
|
|
||||||
|
|
||||||
|
|
||||||
class IndexEverything:
|
class IndexEverything:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
@@ -36,6 +25,10 @@ class IndexEverything:
|
|||||||
ArtistStore.load_artists(key)
|
ArtistStore.load_artists(key)
|
||||||
FolderStore.load_filepaths()
|
FolderStore.load_filepaths()
|
||||||
|
|
||||||
|
# map colors
|
||||||
|
map_album_colors()
|
||||||
|
map_artist_colors()
|
||||||
|
|
||||||
map_scrobble_data()
|
map_scrobble_data()
|
||||||
map_favorites()
|
map_favorites()
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
from itertools import groupby
|
||||||
|
import os
|
||||||
|
from pprint import pprint
|
||||||
|
from app.lib.albumslib import sort_by_track_no
|
||||||
|
from app.models.folder import Folder
|
||||||
|
from app.models.track import Track
|
||||||
|
from app.utils import flatten
|
||||||
|
|
||||||
|
|
||||||
|
def sort_tracks(tracks: list[Track], key: str, reverse: bool = False):
|
||||||
|
"""
|
||||||
|
Sorts a list of tracks by a key.
|
||||||
|
"""
|
||||||
|
if key == "default":
|
||||||
|
return tracks
|
||||||
|
|
||||||
|
sortfunc = lambda x: getattr(x, key)
|
||||||
|
|
||||||
|
if key == "artists" or key == "albumartists":
|
||||||
|
sortfunc = lambda x: getattr(x, key)[0]["name"]
|
||||||
|
|
||||||
|
if key == "disc":
|
||||||
|
# INFO: Group tracks into albums, then sort them by disc number.
|
||||||
|
tracks = sorted(tracks, key=lambda x: x.album)
|
||||||
|
groups = groupby(tracks, lambda x: x.albumhash)
|
||||||
|
|
||||||
|
return flatten([sort_by_track_no(list(g)) for k, g in groups])
|
||||||
|
|
||||||
|
return sorted(tracks, key=sortfunc, reverse=reverse)
|
||||||
|
|
||||||
|
|
||||||
|
def sort_folders(folders: list[Folder], key: str, reverse: bool = False):
|
||||||
|
"""
|
||||||
|
Sorts a list of folders by a key.
|
||||||
|
"""
|
||||||
|
if key == "default":
|
||||||
|
return folders
|
||||||
|
|
||||||
|
sortfunc = lambda x: getattr(x, key)
|
||||||
|
|
||||||
|
if key == "lastmod":
|
||||||
|
sortfunc = lambda x: os.path.getmtime(x.path)
|
||||||
|
|
||||||
|
return sorted(folders, key=sortfunc, reverse=reverse)
|
||||||
@@ -7,4 +7,3 @@ class Folder:
|
|||||||
path: str
|
path: str
|
||||||
is_sym: bool = False
|
is_sym: bool = False
|
||||||
trackcount: int = 0
|
trackcount: int = 0
|
||||||
foldercount: int = 0
|
|
||||||
|
|||||||
Reference in New Issue
Block a user