feat: add accordion overlay controls and icon API

This commit is contained in:
2026-03-06 16:28:03 +01:00
parent 027027b203
commit 35358c2d4e
16 changed files with 359 additions and 46 deletions

View File

@@ -1,6 +1,7 @@
use crate::app_state::AppState;
use crate::countdown::commands::build_snapshot_dtos;
use crate::countdown::events::AppEvent;
use axum::Json;
use axum::extract::{Path, Query, State};
use axum::response::sse::KeepAlive;
use axum::response::{
@@ -27,6 +28,13 @@ pub async fn overlay_countdown(
.and_then(|snaps| snaps.into_iter().find(|s| s.id == q.id))
.map(|s| format_remaining(s.duration as u64))
.unwrap_or_else(|| "??:??:??.???".to_string());
let config = state
.overlay_configs
.lock()
.await
.get(&q.id)
.cloned()
.unwrap_or_default();
let mut env = minijinja::Environment::new();
env.add_template(
@@ -37,7 +45,13 @@ pub async fn overlay_countdown(
let html = env
.get_template("page")
.unwrap()
.render(minijinja::context! { id => q.id, remaining => remaining })
.render(minijinja::context! {
id => q.id,
remaining => remaining,
icon => config.icon,
text_color => config.text_color,
bg_color => config.bg_color,
})
.unwrap();
Html(html)
}
@@ -56,6 +70,9 @@ pub async fn sse_countdown(
.event("tick")
.data(format_remaining(s.duration as u64)))
}),
Ok(AppEvent::ConfigChanged(cid)) if cid == id => {
Some(Ok(Event::default().event("reload").data("")))
}
_ => None,
});
Sse::new(stream).keep_alive(
@@ -72,3 +89,19 @@ fn format_remaining(ms: u64) -> String {
let millis = ms % 1_000;
format!("{:02}:{:02}:{:02}.{:03}", h, m, s, millis)
}
pub async fn list_icons() -> Json<Vec<String>> {
let mut names = Vec::new();
if let Ok(mut entries) = tokio::fs::read_dir("public/icons").await {
while let Ok(Some(entry)) = entries.next_entry().await {
let path = entry.path();
if matches!(path.extension().and_then(|e| e.to_str()), Some("svg" | "png")) {
if let Some(filename) = path.file_name().and_then(|s| s.to_str()) {
names.push(filename.to_string());
}
}
}
}
names.sort();
Json(names)
}