Version 3.6 mit URL Zoom Funktion

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
Erik Thiele
2026-04-27 13:03:45 +02:00
parent 4cd170c9df
commit 0fa3c00319
5 changed files with 162 additions and 69 deletions

161
app.py
View File

@@ -23,7 +23,7 @@ BASE_DIR = os.path.dirname(os.path.abspath(__file__))
MEDIA_DIR = os.path.join(BASE_DIR, "media")
CONFIG_FILE = os.path.join(BASE_DIR, "config.json")
APP_VERSION = "3.5.0"
APP_VERSION = "3.6.0"
UPLOAD_EXTENSIONS = {".jpg", ".jpeg", ".png", ".mp4"}
app = Flask(__name__)
@@ -50,10 +50,21 @@ def save_config(cfg):
def is_url(value):
return (
isinstance(value, str)
and value.lower().startswith(("http://", "https://"))
)
"""Check if value is a URL (string or dict with 'url' key)"""
if isinstance(value, str):
return value.lower().startswith(("http://", "https://"))
if isinstance(value, dict) and "url" in value:
url = value.get("url", "")
return isinstance(url, str) and url.lower().startswith(("http://", "https://"))
return False
def normalize_url(value):
"""Convert URL string to dict with zoom factor, or return existing dict"""
if isinstance(value, dict) and "url" in value:
return value
if isinstance(value, str) and value.lower().startswith(("http://", "https://")):
return {"url": value, "zoom": 1.0}
return None
# -------------------------------------------------
@@ -133,13 +144,15 @@ def player(screen):
normal_files = []
# 1. Playlist-Reihenfolge
for name in playlist:
if is_url(name):
normal_files.append({"kind": "url", "url": name})
for item in playlist:
if is_url(item):
url_data = normalize_url(item)
if url_data:
normal_files.append({"kind": "url", "url": url_data["url"], "zoom": url_data.get("zoom", 1.0)})
continue
if os.path.exists(os.path.join(folder, name)) and allowed_file(name):
normal_files.append({"kind": "file", "name": name})
if os.path.exists(os.path.join(folder, item)) and allowed_file(item):
normal_files.append({"kind": "file", "name": item})
existing_file_names = {
item["name"] for item in normal_files if item["kind"] == "file"
@@ -160,14 +173,16 @@ def player(screen):
if priority_cfg.get("enabled", False):
prio_files = []
for name in priority_cfg.get("playlist", []):
if is_url(name):
prio_files.append({"kind": "url", "url": name})
for item in priority_cfg.get("playlist", []):
if is_url(item):
url_data = normalize_url(item)
if url_data:
prio_files.append({"kind": "url", "url": url_data["url"], "zoom": url_data.get("zoom", 1.0)})
continue
file_path = os.path.join(MEDIA_DIR, "priority", name)
file_path = os.path.join(MEDIA_DIR, "priority", item)
if os.path.exists(file_path):
prio_files.append({"kind": "file", "name": name})
prio_files.append({"kind": "file", "name": item})
else:
prio_files = []
@@ -234,25 +249,28 @@ def admin():
screen_cfg["newsticker_enabled"] = screen_cfg.get("newsticker_enabled", False)
# 1⃣ Playlist-Reihenfolge
for name in playlist:
if is_url(name):
files.append({
"name": name,
"type": "url",
"size": "URL"
})
for item in playlist:
if is_url(item):
url_data = normalize_url(item)
if url_data:
files.append({
"name": url_data["url"],
"type": "url",
"size": "URL",
"zoom": url_data.get("zoom", 1.0)
})
continue
file_path = os.path.join(path, name)
file_path = os.path.join(path, item)
if not os.path.exists(file_path):
continue
ext = os.path.splitext(name)[1].lower()
ext = os.path.splitext(item)[1].lower()
ftype = "video" if ext == ".mp4" else "image"
size = os.path.getsize(file_path) // 1024
files.append({
"name": name,
"name": item,
"type": ftype,
"size": size
})
@@ -286,25 +304,28 @@ def admin():
prio_playlist = cfg["priority"].get("playlist", [])
# 1⃣ Playlist-Reihenfolge
for name in prio_playlist:
if is_url(name):
priority_files.append({
"name": name,
"type": "url",
"size": "URL"
})
for item in prio_playlist:
if is_url(item):
url_data = normalize_url(item)
if url_data:
priority_files.append({
"name": url_data["url"],
"type": "url",
"size": "URL",
"zoom": url_data.get("zoom", 1.0)
})
continue
file_path = os.path.join(prio_dir, name)
file_path = os.path.join(prio_dir, item)
if not os.path.exists(file_path):
continue
ext = os.path.splitext(name)[1].lower()
ext = os.path.splitext(item)[1].lower()
ftype = "video" if ext == ".mp4" else "image"
size = os.path.getsize(file_path) // 1024
priority_files.append({
"name": name,
"name": item,
"type": ftype,
"size": size
})
@@ -388,12 +409,24 @@ def upload(screen):
@login_required
def add_url(screen):
url = request.form.get("url", "").strip()
zoom = request.form.get("zoom", "1.0").strip()
if not is_url(url):
return redirect("/admin")
try:
zoom_factor = float(zoom)
if zoom_factor <= 0:
zoom_factor = 1.0
except (ValueError, TypeError):
zoom_factor = 1.0
# Store as object with zoom factor
url_data = {"url": url, "zoom": zoom_factor}
config = load_config()
if screen == "priority":
config.setdefault("priority", {}).setdefault("playlist", []).append(url)
config.setdefault("priority", {}).setdefault("playlist", []).append(url_data)
else:
screen_cfg = config.setdefault("screens", {}).setdefault(screen, {
"interval": 10,
@@ -401,7 +434,7 @@ def add_url(screen):
"show_videos": True,
"playlist": []
})
screen_cfg.setdefault("playlist", []).append(url)
screen_cfg.setdefault("playlist", []).append(url_data)
save_config(config)
return redirect("/admin")
@@ -424,12 +457,18 @@ def delete_file(screen, filename):
# --- Playlist bereinigen ---
if screen == "priority":
playlist = cfg.get("priority", {}).get("playlist", [])
if filename in playlist:
playlist.remove(filename)
# Remove both string URLs and dict-based URLs
playlist[:] = [item for item in playlist if not (
(isinstance(item, str) and item == filename) or
(isinstance(item, dict) and item.get("url") == filename)
)]
else:
playlist = cfg["screens"].get(screen, {}).get("playlist", [])
if filename in playlist:
playlist.remove(filename)
# Remove both string URLs and dict-based URLs
playlist[:] = [item for item in playlist if not (
(isinstance(item, str) and item == filename) or
(isinstance(item, dict) and item.get("url") == filename)
)]
save_config(cfg)
return redirect("/admin")
@@ -444,20 +483,36 @@ def delete_file(screen, filename):
def save_playlist(screen):
cfg = load_config()
data = request.get_json()
new_order = data["playlist"] # List of filenames/URLs as strings
# Get the current playlist with all data (including zoom factors)
if screen == "priority":
cfg.setdefault("priority", {}).setdefault("playlist", [])
cfg["priority"]["playlist"] = data["playlist"]
old_playlist = cfg.get("priority", {}).get("playlist", [])
else:
screen_cfg = cfg.setdefault("screens", {}).setdefault(screen, {
"interval": 10,
"show_images": True,
"show_videos": True,
"playlist": [],
"newsticker_text": "",
"newsticker_enabled": False
})
screen_cfg["playlist"] = data["playlist"]
old_playlist = cfg.get("screens", {}).get(screen, {}).get("playlist", [])
# Create a mapping: filename/url -> full item (preserves zoom factor)
item_map = {}
for item in old_playlist:
if isinstance(item, dict) and "url" in item:
key = item["url"] # URL as key
else:
key = item # Filename as key
item_map[key] = item
# Build new playlist: use the mapping to preserve zoom factors
new_playlist = []
for key in new_order:
if key in item_map:
new_playlist.append(item_map[key])
else:
# Item not found in mapping - add as is
new_playlist.append(key)
if screen == "priority":
cfg.setdefault("priority", {})["playlist"] = new_playlist
else:
cfg.setdefault("screens", {}).setdefault(screen, {})["playlist"] = new_playlist
save_config(cfg)
return "", 204