From 006eece417c60718b12a89ab65330d26c7ae5c25 Mon Sep 17 00:00:00 2001 From: david kifer Date: Mon, 29 Jun 2026 09:50:54 -0400 Subject: [PATCH] Add persistent default temp directory setting with web UI - Add settings.json persistence (load/save) in backend - Add GET/POST /api/settings endpoints for default_temp_dir - Add Default Temp Directory config UI in Temporary Storage section - Auto-fallback: jobs use saved default if no per-job temp_dir set - Per-job Advanced Options placeholder syncs with saved default - Add settings.json to .gitignore for per-machine config --- .gitignore | 1 + app/main.py | 53 +++++++++++++++++++++++++++++++++++-- static/app.js | 67 +++++++++++++++++++++++++++++++++++++++++++++++ static/index.html | 22 +++++++++++++++- 4 files changed, 140 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 71b1539..c53801d 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ temp server.log .uvicorn.pid jobs.json +settings.json # OS .DS_Store diff --git a/app/main.py b/app/main.py index 40e0eb5..ad1b855 100644 --- a/app/main.py +++ b/app/main.py @@ -86,6 +86,29 @@ main_loop = None JOBS_FILE = os.path.join(upscaler.BASE_DIR, "jobs.json") +SETTINGS_FILE = os.path.join(upscaler.BASE_DIR, "settings.json") + +def load_settings() -> dict: + """Load persistent app settings from settings.json""" + defaults = {"default_temp_dir": ""} + if os.path.exists(SETTINGS_FILE): + try: + with open(SETTINGS_FILE, "r") as f: + saved = json.load(f) + defaults.update(saved) + except Exception as e: + print(f"Error loading settings: {e}") + return defaults + +def save_settings(settings: dict): + """Save persistent app settings to settings.json""" + try: + with open(SETTINGS_FILE, "w") as f: + json.dump(settings, f, indent=4) + except Exception as e: + print(f"Error saving settings: {e}") + + def load_jobs_db(): global jobs_db if os.path.exists(JOBS_FILE): @@ -452,7 +475,7 @@ def start_upscale(req: StartUpscaleRequest): ai_face_restoration=req.ai_face_restoration, ai_rife_interpolation=req.ai_rife_interpolation, ai_audio_denoise=req.ai_audio_denoise, - temp_dir=req.temp_dir + temp_dir=req.temp_dir or load_settings().get("default_temp_dir") or None ) jobs_db[job_id] = job @@ -527,7 +550,7 @@ def start_upscale_batch(req: StartBatchUpscaleRequest): ai_face_restoration=req.ai_face_restoration, ai_rife_interpolation=req.ai_rife_interpolation, ai_audio_denoise=req.ai_audio_denoise, - temp_dir=req.temp_dir + temp_dir=req.temp_dir or load_settings().get("default_temp_dir") or None ) jobs_db[job_id] = job job_queue.put(job_id) @@ -1064,6 +1087,32 @@ def setup_webhook(req: WebhookSetupRequest): global_webhook_url = req.url return {"status": "success", "webhook_url": global_webhook_url} +# ─── Settings Endpoints ───────────────────────────────────────────── +class UpdateSettingsRequest(BaseModel): + default_temp_dir: str = "" + +@app.get("/api/settings") +def get_settings(): + """Get persistent app settings""" + settings = load_settings() + return settings + +@app.post("/api/settings") +def update_settings(req: UpdateSettingsRequest): + """Update persistent app settings""" + settings = load_settings() + # Validate the directory path if provided + new_dir = req.default_temp_dir.strip() + if new_dir: + # Ensure the parent directory exists or can be created + try: + os.makedirs(new_dir, exist_ok=True) + except OSError as e: + raise HTTPException(status_code=400, detail=f"Invalid directory path: {e}") + settings["default_temp_dir"] = new_dir + save_settings(settings) + return {"status": "saved", "settings": settings} + @app.get("/api/uploads/{filename}") def get_upload_file(filename: str): file_path = os.path.join(upscaler.UPLOAD_DIR, filename) diff --git a/static/app.js b/static/app.js index 28a2ea3..93058c8 100644 --- a/static/app.js +++ b/static/app.js @@ -2122,6 +2122,55 @@ async function initializeApp() { // Load initial temp info loadTempInfo(); + + // Default temp directory setting + const saveTempDirBtn = document.getElementById("save-temp-dir-btn"); + const defaultTempDirInput = document.getElementById("default-temp-dir-input"); + const tempDirStatus = document.getElementById("temp-dir-status"); + + // Load saved default temp dir on init + loadDefaultTempDir(); + + if (saveTempDirBtn) { + saveTempDirBtn.addEventListener("click", async () => { + const newDir = defaultTempDirInput ? defaultTempDirInput.value.trim() : ""; + tempDirStatus.textContent = ""; + tempDirStatus.style.color = ""; + saveTempDirBtn.disabled = true; + saveTempDirBtn.innerHTML = ' Saving...'; + try { + const res = await fetch("/api/settings", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ default_temp_dir: newDir }) + }); + if (res.ok) { + tempDirStatus.style.color = "var(--success, #4caf50)"; + tempDirStatus.textContent = newDir + ? `\u2713 Default temp directory saved: ${newDir}` + : "\u2713 Reset to project default temp/ directory."; + // Also update the per-job input placeholder/value + const perJobInput = document.getElementById("temp-dir-input"); + if (perJobInput && !perJobInput.value.trim()) { + perJobInput.placeholder = newDir + ? `Default: ${newDir} (override here)` + : "e.g. /mnt/fast_ssd/temp (Leave empty for default temp/)"; + } + } else { + const errData = await res.json().catch(() => ({})); + tempDirStatus.style.color = "var(--danger, #f44336)"; + tempDirStatus.textContent = `\u2717 ${errData.detail || "Failed to save setting."}`; + } + } catch (err) { + tempDirStatus.style.color = "var(--danger, #f44336)"; + tempDirStatus.textContent = "\u2717 Network error saving setting."; + console.error(err); + } finally { + saveTempDirBtn.disabled = false; + saveTempDirBtn.innerHTML = ' Save'; + } + }); + } } async function loadTempInfo() { @@ -2220,4 +2269,22 @@ async function loadTempInfo() { } } +async function loadDefaultTempDir() { + try { + const res = await fetch("/api/settings"); + if (!res.ok) return; + const settings = await res.json(); + const savedDir = settings.default_temp_dir || ""; + const defaultInput = document.getElementById("default-temp-dir-input"); + if (defaultInput) defaultInput.value = savedDir; + // Update per-job input placeholder + const perJobInput = document.getElementById("temp-dir-input"); + if (perJobInput && savedDir && !perJobInput.value.trim()) { + perJobInput.placeholder = `Default: ${savedDir} (override here)`; + } + } catch (err) { + console.error("Failed to load settings:", err); + } +} + initializeApp(); diff --git a/static/index.html b/static/index.html index 8021abb..1d39721 100644 --- a/static/index.html +++ b/static/index.html @@ -580,7 +580,27 @@

Monitor temporary image frames created during upscaling. Running jobs cannot be cleared.

- + + +
+
+ + Default Temp Directory +
+

+ Set a persistent default directory for all upscale job temp files. This is applied automatically unless overridden per-job in Advanced Options. Use a fast SSD or a drive with plenty of space. +

+
+ + +
+
+
+
Total Temp Size