diff --git a/app.py b/app.py index 7bf64c1..2f967a9 100644 --- a/app.py +++ b/app.py @@ -2032,6 +2032,21 @@ def api_clear_history(): return {"ok": True, "cleared": count} +@app.post("/api/open-storage") +def api_open_storage(): + root = resolve_storage(load_global()["storage_dir"]) + if not root.exists(): + return JSONResponse({"detail": f"{root} does not exist yet. It is created when the first job runs"}, status_code=400) + opener = "open" if sys.platform == "darwin" else shutil.which("xdg-open") + if not opener: + return JSONResponse({"detail": "No file browser is available on this machine"}, status_code=400) + try: + subprocess.Popen([opener, str(root)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except OSError as e: + return JSONResponse({"detail": f"Could not open the folder: {e}"}, status_code=400) + return {"ok": True} + + @app.get("/api/trending") def api_trending(): try: diff --git a/static/index.html b/static/index.html index a1ba49e..ee481a4 100644 --- a/static/index.html +++ b/static/index.html @@ -175,6 +175,9 @@ input:disabled,select:disabled{opacity:.55} #log .ERROR,#log .CRITICAL{color:var(--coral)} #log .WARNING{color:var(--amber)} #log .DEBUG{color:var(--faint)} +.storage-line{display:flex;align-items:center;gap:8px;margin-top:18px;flex-wrap:wrap} +.icon-btn.folder{width:30px;height:30px} +.icon-btn.folder:hover{color:var(--gold-text)} .tools{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:0 0 22px} .tools .status{font-size:14px;color:var(--muted)} #trending-panel{margin:0 0 24px} @@ -235,7 +238,7 @@ main{padding:20px 16px 120px}
-

+

@@ -498,6 +501,7 @@ if(!confirm("Unlink the YouTube channel from this profile?"))return; await api("/auth/unlink",{method:"POST"});lastChannel="";await loadSettings();refresh()} else{window.location.href="/auth/start"}} $("#save").onclick=saveSettings; +$("#open-folder").onclick=async()=>{const m=$("#folder-msg");try{await api("/api/open-storage",{method:"POST"});m.textContent=""}catch(e){m.textContent=e.message}}; $("#clear").onclick=()=>{$("#log").innerHTML=""}; $("#copy-log").onclick=async()=>{ const text=$("#log").innerText.trim();const m=$("#copy-msg");