diff --git a/.vscode/launch.json b/.vscode/launch.json index 14415dad..9748712e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -27,6 +27,7 @@ "program": "app/main.py", "console": "integratedTerminal", "justMyCode": true, + "subProcess": true, "env": { "YTP_CONFIG_PATH": "${workspaceFolder}/var/config", "YTP_DOWNLOAD_PATH": "${workspaceFolder}/var/downloads", @@ -34,8 +35,6 @@ "PYDEVD_DISABLE_FILE_VALIDATION": "1", "YTP_IGNORE_UI": "true" }, - "subProcess": true, - "postDebugTask": "kill-debugpy" }, { "name": "Node: Generate UI", diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index ee6cc98f..00000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "kill-debugpy", - "type": "shell", - "command": "pkill -f debugpy || true", - "problemMatcher": [], - "presentation": { - "echo": false, - "reveal": "never", - "focus": false, - "panel": "dedicated", - "showReuseMessage": false, - "clear": false - }, - "runOptions": { - "runOn": "folderOpen" - } - } - ] -} diff --git a/README.md b/README.md index efd913d8..695bf527 100644 --- a/README.md +++ b/README.md @@ -317,4 +317,5 @@ Certain configuration values can be set via environment variables, using the `-e | YTP_TASKS_HANDLER_TIMER | The cron expression for the tasks handler timer | `15 */1 * * *` | | YTP_PLAYLIST_ITEMS_CONCURRENCY | The number of playlist items be to processed at same time | `1` | | YTP_TEMP_DISABLED | Disable temp files handling. | `false` | +| YTP_DOWNLOAD_PATH_DEPTH | How many subdirectories to show in auto complete. | `1` | diff --git a/app/library/Utils.py b/app/library/Utils.py index 3ec83650..9cf1c146 100644 --- a/app/library/Utils.py +++ b/app/library/Utils.py @@ -1405,6 +1405,32 @@ def find_unpickleable(obj, name="root", seen=None): find_unpickleable(value, f"{name}.{attr}", seen) except Exception as ie: LOG.error(f"[ERROR] Accessing {name}.{attr}: {ie}") - elif isinstance(obj, (list, tuple, set)): + elif isinstance(obj, list | tuple | set): for idx, item in enumerate(obj): find_unpickleable(item, f"{name}[{idx}]", seen) + + +def list_folders(path: Path, base: Path, depth_limit: int) -> list[str]: + """ + List all folders relative to a base path, up to a specified depth limit. + + Args: + path (Path): The path to start listing folders from. + base (Path): The base path to which the folders should be relative. + depth_limit (int): The maximum depth to traverse from the base path. + + Returns: + list[str]: A list of folder paths relative to the base path, up to the specified + + """ + rel_depth: int = len(path.relative_to(base).parts) + if rel_depth > depth_limit: + return [] + + folders: list[str] = [] + for entry in path.iterdir(): + if entry.is_dir(): + folders.append(str(entry.relative_to(base))) + folders.extend(list_folders(entry, base, depth_limit)) + + return folders diff --git a/app/library/config.py b/app/library/config.py index 57407530..1d40a753 100644 --- a/app/library/config.py +++ b/app/library/config.py @@ -25,6 +25,9 @@ class Config: download_path: str = "." """The path to the download directory.""" + download_path_depth: int = 2 + """How many subdirectories to show in auto complete.""" + temp_path: str = "/tmp" """The path to the temporary directory.""" @@ -219,6 +222,7 @@ class Config: "extract_info_timeout", "debugpy_port", "playlist_items_concurrency", + "download_path_depth", ) "The variables that are integers." diff --git a/app/routes/socket/connection.py b/app/routes/socket/connection.py index 28407a4d..bce02997 100644 --- a/app/routes/socket/connection.py +++ b/app/routes/socket/connection.py @@ -10,7 +10,7 @@ from app.library.DownloadQueue import DownloadQueue from app.library.Events import EventBus, Events from app.library.Presets import Presets from app.library.router import RouteType, route -from app.library.Utils import tail_log +from app.library.Utils import list_folders, tail_log LOG: logging.Logger = logging.getLogger(__name__) @@ -29,7 +29,11 @@ async def connect(config: Config, queue: DownloadQueue, notify: EventBus, sid: s "paused": queue.is_paused(), } - data["folders"] = [folder.name for folder in Path(config.download_path).iterdir() if folder.is_dir()] + data["folders"] = list_folders( + path=Path(config.download_path), + base=Path(config.download_path), + depth_limit=config.download_path_depth-1, + ) await notify.emit( Events.CONNECTED, diff --git a/ui/app/components/NewDownload.vue b/ui/app/components/NewDownload.vue index ea846717..55cd9f34 100644 --- a/ui/app/components/NewDownload.vue +++ b/ui/app/components/NewDownload.vue @@ -88,21 +88,31 @@