feat: add accordion overlay controls and icon API
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user