Update app.py

This commit is contained in:
2026-01-16 15:09:15 +01:00
parent 5b35e4e695
commit 378683df83

76
app.py
View File

@@ -1,59 +1,61 @@
import streamlit as st import streamlit as st
import os import os
from PIL import Image
import shutil import shutil
from PIL import Image
from io import BytesIO from io import BytesIO
st.set_page_config(layout="wide", page_title="Unraid Image Sorter") st.set_page_config(layout="wide", page_title="Universal Image Sorter")
# --- UI Sidebar --- # --- UI Sidebar ---
st.sidebar.header("📁 Folder Configuration") st.sidebar.header("📁 Select Folders")
# These paths should match your Unraid Container Path mappings st.sidebar.info("Base path is set to /storage (your Unraid mount)")
path_a = st.sidebar.text_input("Folder A (Internal Path)", value="/media/folder1")
path_b = st.sidebar.text_input("Folder B (Internal Path)", value="/media/folder2")
quality = st.sidebar.slider("Bandwidth Compression (Quality)", 5, 100, 40)
def get_valid_files(path): # User types the subpath relative to the mount, or the full container path
if not os.path.exists(path): return [] path_a = st.sidebar.text_input("Path to Folder 1", value="/storage/Photos/FolderA")
return [f for f in os.listdir(path) if f.lower().endswith(('.jpg', '.jpeg', '.png', '.webp'))] path_b = st.sidebar.text_input("Path to Folder 2", value="/storage/Photos/FolderB")
files_a = get_valid_files(path_a) comp_level = st.sidebar.slider("Bandwidth Compression", 5, 100, 40)
files_b = get_valid_files(path_b)
# --- Logic to find matching files ---
def get_files(p):
if os.path.exists(p):
return [f for f in os.listdir(p) if f.lower().endswith(('.jpg', '.jpeg', '.png'))]
return []
files_a = get_files(path_a)
files_b = get_files(path_b)
common = sorted(list(set(files_a) & set(files_b))) common = sorted(list(set(files_a) & set(files_b)))
if 'idx' not in st.session_state: if 'idx' not in st.session_state:
st.session_state.idx = 0 st.session_state.idx = 0
# --- Action Logic --- # --- File Operations ---
def process_files(action, filename): def handle_click(action):
current_file = common[st.session_state.idx]
if action == "move": if action == "move":
for base_path in [path_a, path_b]: for p in [path_a, path_b]:
target_dir = os.path.join(base_path, "unused") target = os.path.join(p, "unused")
os.makedirs(target_dir, exist_ok=True) os.makedirs(target, exist_ok=True)
shutil.move(os.path.join(base_path, filename), os.path.join(target_dir, filename)) shutil.move(os.path.join(p, current_file), os.path.join(target, current_file))
st.toast(f"Moved {filename} to unused")
else:
st.toast(f"Kept {filename}")
st.session_state.idx += 1 st.session_state.idx += 1
# --- Display Logic --- # --- Layout ---
if st.session_state.idx < len(common): if not common:
st.warning("No matching files found. Check your paths.")
elif st.session_state.idx >= len(common):
st.success("Finished all images!")
if st.button("Reset"): st.session_state.idx = 0
else:
fname = common[st.session_state.idx] fname = common[st.session_state.idx]
st.subheader(f"Comparing: {fname} ({st.session_state.idx + 1} of {len(common)})") st.write(f"**Current Image:** {fname} ({st.session_state.idx+1}/{len(common)})")
col1, col2 = st.columns(2) col1, col2 = st.columns(2)
for i, base in enumerate([path_a, path_b]): for i, p in enumerate([path_a, path_b]):
img_path = os.path.join(base, fname) with Image.open(os.path.join(p, fname)) as img:
with Image.open(img_path) as img:
# Compression for Web UI
buf = BytesIO() buf = BytesIO()
img.convert("RGB").save(buf, format="JPEG", quality=quality) img.convert("RGB").save(buf, format="JPEG", quality=comp_level)
(col1 if i==0 else col2).image(buf, use_container_width=True) (col1 if i==0 else col2).image(buf, use_container_width=True)
st.divider() c1, c2 = st.columns(2)
btn1, btn2 = st.columns(2) c1.button("❌ Move to Unused", on_click=handle_click, args=("move",), use_container_width=True)
btn1.button("🗑️ Move to Unused", on_click=process_files, args=("move", fname), use_container_width=True) c2.button("✅ Keep Both", on_click=handle_click, args=("keep",), use_container_width=True)
btn2.button("⭐ Keep Both", on_click=process_files, args=("keep", fname), use_container_width=True)
else:
st.success("Comparison complete! No more matching files found.")