feat: implement folder and folder track sorting

This commit is contained in:
cwilvx
2024-08-04 11:34:33 +03:00
parent c77d0927c7
commit cc2d017816
5 changed files with 118 additions and 25 deletions
+46 -5
View File
@@ -23,11 +23,46 @@ api = APIBlueprint("folder", __name__, url_prefix="/folder", abp_tags=[tag])
class FolderTree(BaseModel):
folder: str = Field(
"$home", example="$home", description="The folder to things from"
folder: str = Field("$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")
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")
@@ -69,9 +104,15 @@ def get_folder_tree(body: FolderTree):
req_dir = "/" + req_dir if not req_dir.startswith("/") else req_dir
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
+24 -8
View File
@@ -1,6 +1,7 @@
import os
from pathlib import Path
from app.lib.sortlib import sort_folders, sort_tracks
from app.logger import log
from app.models import Folder
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
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.
"""
@@ -22,7 +23,6 @@ def create_folder(path: str, trackcount=0, foldercount=0) -> Folder:
path=win_replace_slash(str(folder)) + "/",
is_sym=folder.is_symlink(),
trackcount=trackcount,
foldercount=foldercount,
)
@@ -46,14 +46,22 @@ def get_folders(paths: list[str]):
"""
folders = FolderStore.count_tracks_containing_paths(paths)
return [
create_folder(f["path"], f["trackcount"], foldercount=0)
create_folder(f["path"], f["trackcount"])
for f in folders
if f["trackcount"] > 0
]
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.
@@ -102,14 +110,17 @@ def get_files_and_dirs(
tracks = []
if files:
if end == -1:
end = len(files)
if limit == -1:
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 = []
if not tracks_only:
folders = get_folders(dirs)
folders = sort_folders(folders, foldersortby, foldersort_reverse)
if skip_empty_folders and len(folders) == 1 and len(tracks) == 0:
# INFO: When we only have one folder and no tracks,
@@ -118,7 +129,11 @@ def get_files_and_dirs(
return get_files_and_dirs(
folders[0].path,
start=start,
end=end,
limit=limit,
tracksortby=tracksortby,
foldersortby=foldersortby,
tracksort_reverse=tracksort_reverse,
foldersort_reverse=foldersort_reverse,
tracks_only=tracks_only,
skip_empty_folders=True,
)
@@ -127,4 +142,5 @@ def get_files_and_dirs(
"path": path,
"tracks": serialize_tracks(tracks),
"folders": folders,
"total": len(files),
}
+4 -11
View File
@@ -14,17 +14,6 @@ from app.store.folder import FolderStore
from app.store.tracks import TrackStore
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:
def __init__(self) -> None:
@@ -36,6 +25,10 @@ class IndexEverything:
ArtistStore.load_artists(key)
FolderStore.load_filepaths()
# map colors
map_album_colors()
map_artist_colors()
map_scrobble_data()
map_favorites()
+44
View File
@@ -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)
-1
View File
@@ -7,4 +7,3 @@ class Folder:
path: str
is_sym: bool = False
trackcount: int = 0
foldercount: int = 0