feat: native folder picker button via tkinter
This commit is contained in:
21
index.html
21
index.html
@@ -11,8 +11,12 @@
|
|||||||
.subtitle { color: #888; margin-bottom: 2rem; font-size: 0.95rem; }
|
.subtitle { color: #888; margin-bottom: 2rem; font-size: 0.95rem; }
|
||||||
.card { background: #16213e; border-radius: 12px; padding: 1.5rem; width: 100%; max-width: 640px; margin-bottom: 1.5rem; }
|
.card { background: #16213e; border-radius: 12px; padding: 1.5rem; width: 100%; max-width: 640px; margin-bottom: 1.5rem; }
|
||||||
label { display: block; font-size: 0.85rem; color: #aaa; margin-bottom: 0.4rem; }
|
label { display: block; font-size: 0.85rem; color: #aaa; margin-bottom: 0.4rem; }
|
||||||
|
.folder-row { display: flex; gap: 0.5rem; align-items: stretch; }
|
||||||
|
.folder-row input[type="text"] { flex: 1; }
|
||||||
input[type="text"] { width: 100%; padding: 0.6rem 0.8rem; border-radius: 8px; border: 1px solid #333; background: #0f3460; color: #fff; font-size: 1rem; }
|
input[type="text"] { width: 100%; padding: 0.6rem 0.8rem; border-radius: 8px; border: 1px solid #333; background: #0f3460; color: #fff; font-size: 1rem; }
|
||||||
input[type="text"]:focus { outline: 2px solid #e94560; }
|
input[type="text"]:focus { outline: 2px solid #e94560; }
|
||||||
|
.pick-btn { padding: 0 1rem; border-radius: 8px; border: 1px solid #555; background: #0f3460; color: #aaa; cursor: pointer; font-size: 1.1rem; white-space: nowrap; transition: border-color 0.15s, color 0.15s; }
|
||||||
|
.pick-btn:hover { border-color: #e94560; color: #fff; }
|
||||||
button.primary { margin-top: 1rem; width: 100%; padding: 0.75rem; border-radius: 8px; border: none; background: #e94560; color: #fff; font-size: 1rem; font-weight: 600; cursor: pointer; }
|
button.primary { margin-top: 1rem; width: 100%; padding: 0.75rem; border-radius: 8px; border: none; background: #e94560; color: #fff; font-size: 1rem; font-weight: 600; cursor: pointer; }
|
||||||
button.primary:hover { background: #c73652; }
|
button.primary:hover { background: #c73652; }
|
||||||
button.primary:disabled { background: #555; cursor: not-allowed; }
|
button.primary:disabled { background: #555; cursor: not-allowed; }
|
||||||
@@ -55,7 +59,10 @@
|
|||||||
<!-- Start -->
|
<!-- Start -->
|
||||||
<div id="view-start" class="view active card">
|
<div id="view-start" class="view active card">
|
||||||
<label for="folder-input">Ordnerpfad</label>
|
<label for="folder-input">Ordnerpfad</label>
|
||||||
<input type="text" id="folder-input" placeholder="/Users/name/Fotos/Shooting-2026" />
|
<div class="folder-row">
|
||||||
|
<input type="text" id="folder-input" placeholder="/Users/name/Fotos/Shooting-2026" />
|
||||||
|
<button class="pick-btn" id="pick-btn" title="Ordner auswählen">📁</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div style="margin-top: 1.5rem;">
|
<div style="margin-top: 1.5rem;">
|
||||||
<div class="toggle-row">
|
<div class="toggle-row">
|
||||||
@@ -148,6 +155,18 @@
|
|||||||
input.addEventListener("input", () => { label.textContent = input.value; });
|
input.addEventListener("input", () => { label.textContent = input.value; });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --- Folder picker ---
|
||||||
|
el("pick-btn").addEventListener("click", async () => {
|
||||||
|
try {
|
||||||
|
const res = await fetch("/pick-folder");
|
||||||
|
if (res.status === 204) return;
|
||||||
|
const data = await res.json();
|
||||||
|
el("folder-input").value = data.folder;
|
||||||
|
} catch (e) {
|
||||||
|
alert("Ordner konnte nicht geöffnet werden: " + e.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// --- Cancel ---
|
// --- Cancel ---
|
||||||
el("cancel-btn").addEventListener("click", () => location.reload());
|
el("cancel-btn").addEventListener("click", () => location.reload());
|
||||||
el("restart-btn").addEventListener("click", () => location.reload());
|
el("restart-btn").addEventListener("click", () => location.reload());
|
||||||
|
|||||||
14
server.py
14
server.py
@@ -44,6 +44,20 @@ def serve_frontend():
|
|||||||
return FileResponse("index.html")
|
return FileResponse("index.html")
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/pick-folder")
|
||||||
|
def pick_folder():
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import filedialog
|
||||||
|
root = tk.Tk()
|
||||||
|
root.withdraw()
|
||||||
|
root.attributes("-topmost", True)
|
||||||
|
folder = filedialog.askdirectory(title="Ordner auswählen")
|
||||||
|
root.destroy()
|
||||||
|
if not folder:
|
||||||
|
raise HTTPException(status_code=204, detail="Kein Ordner ausgewählt")
|
||||||
|
return {"folder": folder}
|
||||||
|
|
||||||
|
|
||||||
PREVIEW_ALLOWED_EXTENSIONS = {".jpg", ".jpeg", ".png"}
|
PREVIEW_ALLOWED_EXTENSIONS = {".jpg", ".jpeg", ".png"}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user