From a374c19978d0fd4f6b4232bfbee9795ae584c06b Mon Sep 17 00:00:00 2001 From: arabcoders Date: Wed, 15 Oct 2025 01:09:20 +0300 Subject: [PATCH] feat: make it possible to load different UI --- FAQ.md | 13 +++++++------ app/library/config.py | 5 ++++- app/routes/api/_static.py | 23 +++++++++++++++++------ 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/FAQ.md b/FAQ.md index 987747fc..8db37eaa 100644 --- a/FAQ.md +++ b/FAQ.md @@ -8,13 +8,13 @@ or the `environment:` section in `compose.yaml` file. | TZ | The timezone to use for the application | `(not_set)` | | YTP_OUTPUT_TEMPLATE | The template for the filenames of the downloaded videos | `%(title)s.%(ext)s` | | YTP_DEFAULT_PRESET | The default preset to use for the download | `default` | -| YTP_INSTANCE_TITLE | The title of the instance | `empty string` | +| YTP_INSTANCE_TITLE | The title of the instance | `(not_set)` | | YTP_FILE_LOGGING | Whether to log to file | `false` | | YTP_DOWNLOAD_PATH | Path to where the downloads will be saved | `/downloads` | | YTP_MAX_WORKERS | The maximum number of workers to use for downloading | `20` | | YTP_MAX_WORKERS_PER_EXTRACTOR | The maximum number of concurrent downloads per extractor | `2` | -| YTP_AUTH_USERNAME | Username for basic authentication | `empty string` | -| YTP_AUTH_PASSWORD | Password for basic authentication | `empty string` | +| YTP_AUTH_USERNAME | Username for basic authentication | `(not_set)` | +| YTP_AUTH_PASSWORD | Password for basic authentication | `(not_set)` | | YTP_CONSOLE_ENABLED | Whether to enable the console | `false` | | YTP_REMOVE_FILES | Remove the actual file when clicking the remove button | `false` | | YTP_CONFIG_PATH | Path to where the config files will be stored. | `/config` | @@ -31,13 +31,13 @@ or the `environment:` section in `compose.yaml` file. | YTP_DEBUGPY_PORT | The port to use for the debugpy debugger | `5678` | | YTP_EXTRACT_INFO_TIMEOUT | The timeout for extracting video information | `70` | | YTP_UI_UPDATE_TITLE | Whether to update the title of the page with the current stats | `true` | -| YTP_PIP_PACKAGES | A space separated list of pip packages to install | `empty string` | +| YTP_PIP_PACKAGES | A space separated list of pip packages to install | `(not_set)` | | YTP_PIP_IGNORE_UPDATES | Do not update the custom pip packages | `false` | -| YTP_PICTURES_BACKENDS | A comma separated list of pictures urls to use | `empty string` | +| YTP_PICTURES_BACKENDS | A comma separated list of pictures urls to use | `(not_set)` | | YTP_BROWSER_CONTROL_ENABLED | Whether to enable the file browser actions | `false` | | YTP_YTDLP_AUTO_UPDATE | Whether to enable the auto update for yt-dlp | `true` | | YTP_YTDLP_DEBUG | Whether to turn debug logging for the internal `yt-dlp` package | `false` | -| YTP_YTDLP_VERSION | The version of yt-dlp to use. Defaults to latest version | `empty string` | +| YTP_YTDLP_VERSION | The version of yt-dlp to use. Defaults to latest version | `(not_set)` | | YTP_BASE_PATH | Set this if you are serving YTPTube from sub-folder | `/` | | YTP_PREVENT_LIVE_PREMIERE | Prevents the initial youtube premiere stream from being downloaded | `false` | | YTP_TASKS_HANDLER_TIMER | The cron expression for the tasks handler timer | `15 */1 * * *` | @@ -46,6 +46,7 @@ or the `environment:` section in `compose.yaml` file. | YTP_DOWNLOAD_PATH_DEPTH | How many subdirectories to show in auto complete. | `1` | | YTP_ALLOW_INTERNAL_URLS | Allow requests to internal URLs | `false` | | YTP_SIMPLE_MODE | Switch default interface to Simple mode. | `false` | +| YTP_STATIC_UI_PATH | Path to custom static UI files. | `(not_set)` | > [!NOTE] > To raise the maximum workers for specific extractor, you need to add a ENV variable that follows the pattern `YTP_MAX_WORKERS_FOR_`. diff --git a/app/library/config.py b/app/library/config.py index 9c3ef4fb..8825ecaf 100644 --- a/app/library/config.py +++ b/app/library/config.py @@ -199,6 +199,9 @@ class Config(metaclass=Singleton): ] "The list of picture backends to use for the background." + static_ui_path: str = "" + "The path to the static UI files." + _manual_vars: tuple = ( "temp_path", "config_path", @@ -333,7 +336,7 @@ class Config(metaclass=Singleton): logging.error(f"Config variable '{k}' had non-existing config reference '{key}'.") sys.exit(1) - v = v.replace(key, getattr(self, localKey)) + v: str = v.replace(key, str(getattr(self, localKey))) setattr(self, k, v) diff --git a/app/routes/api/_static.py b/app/routes/api/_static.py index 2f976420..e2eba5ef 100644 --- a/app/routes/api/_static.py +++ b/app/routes/api/_static.py @@ -82,13 +82,24 @@ def preload_static(root_path: Path, config: Config) -> None: """ global STATIC_FILES # noqa: PLW0602 + static_dir: Path | None = None + webui_files: list[Path] = [ + (root_path / "ui" / "exported").absolute(), + (root_path.parent / "ui" / "exported").absolute(), + ] - static_dir: Path = (root_path / "ui" / "exported").absolute() - if not static_dir.exists(): - static_dir = (root_path.parent / "ui" / "exported").absolute() - if not static_dir.exists(): - msg: str = f"Could not find the frontend UI static assets. '{static_dir}'." - raise ValueError(msg) + if config.static_ui_path: + webui_files = [Path(config.static_ui_path).absolute()] + + for p in webui_files: + if p.exists(): + static_dir = p + break + + if static_dir is None: + webui_files = [str(p) for p in webui_files] + msg: str = f"Could not find the frontend UI static assets in '{webui_files=}'." + raise ValueError(msg) preloaded = 0