"""Render the review page. The HTML/CSS/JS lives in review.html (loaded once at import). This module fills in the %%TOKENS%%: the folder-tree sidebar, the image cards, totals. The server contract is preserved: each .nsfw checkbox's value is the image's absolute path, thumbnails load via GET /img?path=, actions POST to /apply /untag /tagged. """ import html import os from pathlib import Path from urllib.parse import quote # Inline Lucide-style SVG icons (no emoji, theme-able via currentColor). _SVG_EXPAND = '' _SVG_CHECK = '' _PAGE = (Path(__file__).parent / "review.html").read_text(encoding="utf-8") def folder_tree_html(cands): """Indented folder list for the sidebar file browser, built from the candidate paths. Each row filters the grid to that folder + its subfolders (prefix match); 'All folders' resets. Counts are images directly in that folder.""" folders = {} for p, _ in cands: folders[str(p.parent)] = folders.get(str(p.parent), 0) + 1 if not folders: return "" paths = sorted(folders) root = os.path.commonpath(paths) if len(paths) > 1 else paths[0] rows = [ f'' ] for folder in paths: rel = os.path.relpath(folder, root) depth = 0 if rel == "." else rel.count(os.sep) + 1 name = os.path.basename(folder) or folder rows.append( f'' ) return "".join(rows) def render_page(cands, threshold): """Build the review page. cands: list of (Path, score) sorted desc.""" cards, seen = [], set() for p, score in cands: sp = str(p) if sp in seen: # never list the same path twice continue seen.add(sp) # No pre-selection at render. The per-folder scan decides state so persisted # marks win: nsfw -> pink, sfw -> green, undecided high-score -> red. # (A dismissed/sfw image must never come back pre-selected red on reload.) checked = "" src = f"/img?path={quote(sp)}" esc = html.escape(sp, quote=True) name = html.escape(p.name) folder = html.escape(str(p.parent)) folder_attr = html.escape(str(p.parent), quote=True) name_low = html.escape(p.name.lower(), quote=True) folder_low = html.escape(str(p.parent).lower(), quote=True) cards.append( f'