From 7670a52350c013ae4a2d107297f111d7af292ae1 Mon Sep 17 00:00:00 2001 From: hbrain Date: Mon, 25 May 2026 17:26:28 +0200 Subject: [PATCH] Initial movmaker web UI --- .gitignore | 5 +++ config.php | 10 +++++ index.php | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++ style.css | 1 + 4 files changed, 127 insertions(+) create mode 100644 .gitignore create mode 100644 config.php create mode 100644 index.php create mode 100644 style.css diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2635ab6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +AGENTS.md +uploads/ +videos/ +thumbs/ +*.log diff --git a/config.php b/config.php new file mode 100644 index 0000000..799dce4 --- /dev/null +++ b/config.php @@ -0,0 +1,10 @@ + "Movmaker WebUI", + "videos_dir" => __DIR__ . "/videos", + "thumbs_dir" => __DIR__ . "/thumbs", + "uploads_dir" => __DIR__ . "/uploads", + "public_videos" => "videos", + "public_thumbs" => "thumbs", + "items_per_page" => 12, +]; diff --git a/index.php b/index.php new file mode 100644 index 0000000..7e4d8ce --- /dev/null +++ b/index.php @@ -0,0 +1,111 @@ +Title,date=>Date,place=>Place,description=>Description] as $k=>$label) { + $v = trim($_POST[$k] ?? ); if ($v !== ) $lines[] = "$label: $v"; + } + file_put_contents($dir . /data.txt, implode("\n", $lines) . "\n"); + $msg = "Created movmaker input directory: uploads/$slug"; + } catch (Throwable $e) { $err = $e->getMessage(); } +} +$videos = glob($config[videos_dir]./*.mp4, GLOB_BRACE) ?: []; +usort($videos, fn($a,$b)=>filemtime($b)<=>filemtime($a)); +$page=max(1,(int)($_GET[page]??1)); $per=$config[items_per_page]; $total=count($videos); $pages=max(1,(int)ceil($total/$per)); $page=min($page,$pages); $slice=array_slice($videos,($page-1)*$per,$per); +?> +<?=h($config[site_name])?> +

+
+

Videos

No videos yet. Put generated movies in videos/.

+ +

Title,date=>Date,place=>Place,description=>Description] as $k=>$label) { + $v = trim($_POST[$k] ?? ); if ($v !== ) $lines[] = "$label: $v"; + } + file_put_contents($dir . /data.txt, implode("\n", $lines) . "\n"); + $msg = "Created movmaker input directory: uploads/$slug"; + } catch (Throwable $e) { $err = $e->getMessage(); } +} +$videos = glob($config[videos_dir]./*.webm, GLOB_BRACE) ?: []; +usort($videos, fn($a,$b)=>filemtime($b)<=>filemtime($a)); +$page=max(1,(int)($_GET[page]??1)); $per=$config[items_per_page]; $total=count($videos); $pages=max(1,(int)ceil($total/$per)); $page=min($page,$pages); $slice=array_slice($videos,($page-1)*$per,$per); +?> +<?=h($config[site_name])?> +

+
+

Videos

No videos yet. Put generated movies in videos/.

+ +

Title,date=>Date,place=>Place,description=>Description] as $k=>$label) { + $v = trim($_POST[$k] ?? ); if ($v !== ) $lines[] = "$label: $v"; + } + file_put_contents($dir . /data.txt, implode("\n", $lines) . "\n"); + $msg = "Created movmaker input directory: uploads/$slug"; + } catch (Throwable $e) { $err = $e->getMessage(); } +} +$videos = glob($config[videos_dir]./*.mov, GLOB_BRACE) ?: []; +usort($videos, fn($a,$b)=>filemtime($b)<=>filemtime($a)); +$page=max(1,(int)($_GET[page]??1)); $per=$config[items_per_page]; $total=count($videos); $pages=max(1,(int)ceil($total/$per)); $page=min($page,$pages); $slice=array_slice($videos,($page-1)*$per,$per); +?> +<?=h($config[site_name])?> +

+
+

Videos

No videos yet. Put generated movies in videos/.

+ +

Title,date=>Date,place=>Place,description=>Description] as $k=>$label) { + $v = trim($_POST[$k] ?? ); if ($v !== ) $lines[] = "$label: $v"; + } + file_put_contents($dir . /data.txt, implode("\n", $lines) . "\n"); + $msg = "Created movmaker input directory: uploads/$slug"; + } catch (Throwable $e) { $err = $e->getMessage(); } +} +$videos = glob($config[videos_dir]./*.m4v, GLOB_BRACE) ?: []; +usort($videos, fn($a,$b)=>filemtime($b)<=>filemtime($a)); +$page=max(1,(int)($_GET[page]??1)); $per=$config[items_per_page]; $total=count($videos); $pages=max(1,(int)ceil($total/$per)); $page=min($page,$pages); $slice=array_slice($videos,($page-1)*$per,$per); +?> +<?=h($config[site_name])?> +

+
+

Videos

No videos yet. Put generated movies in videos/.

+ + +
+

Add new movie input

+
diff --git a/style.css b/style.css new file mode 100644 index 0000000..6e7317b --- /dev/null +++ b/style.css @@ -0,0 +1 @@ +:root{font-family:system-ui,sans-serif;color:#17202a;background:#f6f7fb}body{margin:0}header{background:#101827;color:white;padding:1.2rem 2rem;display:flex;justify-content:space-between;align-items:center}a{color:#2563eb}.button,button{background:#2563eb;color:white;border:0;border-radius:.5rem;padding:.7rem 1rem;text-decoration:none;cursor:pointer}nav a{margin-left:1rem;color:white}main{max-width:1100px;margin:2rem auto;padding:0 1rem}.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:1rem}.card,form{background:white;border-radius:.8rem;padding:1rem;box-shadow:0 2px 10px #0001}.card video{width:100%;aspect-ratio:16/9;background:#111;border-radius:.5rem}label{display:block;margin:.8rem 0;font-weight:600}input,textarea{display:block;width:100%;box-sizing:border-box;margin-top:.3rem;padding:.65rem;border:1px solid #cbd5e1;border-radius:.45rem}textarea{min-height:6rem}.ok,.err{padding:1rem;border-radius:.5rem;margin-bottom:1rem}.ok{background:#dcfce7}.err{background:#fee2e2}.pages a{display:inline-block;margin:.2rem;padding:.45rem .7rem;background:white;border-radius:.4rem;text-decoration:none}.pages .active{background:#2563eb;color:white}footer{text-align:center;color:#667085;padding:2rem}