feat: add overlay time format toggle and robust icon selection

This commit is contained in:
2026-03-06 16:54:34 +01:00
parent 52a41b9564
commit cf3c069edb
6 changed files with 94 additions and 39 deletions

View File

@@ -35,6 +35,7 @@ pub struct OverlayConfig {
pub icon: String,
pub text_color: String,
pub bg_color: String,
pub show_hh_mm: bool,
}
impl Default for OverlayConfig {
@@ -43,6 +44,7 @@ impl Default for OverlayConfig {
icon: String::new(),
text_color: "white".to_string(),
bg_color: "transparent".to_string(),
show_hh_mm: false,
}
}
}

View File

@@ -176,6 +176,7 @@ pub async fn set_overlay_config(
icon: String,
text_color: String,
bg_color: String,
show_hh_mm: bool,
) -> Result<(), String> {
state
.overlay_configs
@@ -187,6 +188,7 @@ pub async fn set_overlay_config(
icon,
text_color,
bg_color,
show_hh_mm,
},
);
let _ = state.event_bus.send(AppEvent::ConfigChanged(id));

View File

@@ -22,12 +22,6 @@ pub async fn overlay_countdown(
State(state): State<Arc<AppState>>,
Query(q): Query<OverlayQuery>,
) -> Html<String> {
let remaining = build_snapshot_dtos(&state)
.await
.ok()
.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()
@@ -35,6 +29,12 @@ pub async fn overlay_countdown(
.get(&q.id)
.cloned()
.unwrap_or_default();
let remaining = build_snapshot_dtos(&state)
.await
.ok()
.and_then(|snaps| snaps.into_iter().find(|s| s.id == q.id))
.map(|s| format_remaining(s.duration as u64, config.show_hh_mm))
.unwrap_or_else(|| format_unknown(config.show_hh_mm));
let mut env = minijinja::Environment::new();
env.add_template(
@@ -60,15 +60,22 @@ pub async fn sse_countdown(
State(state): State<Arc<AppState>>,
Path(id): Path<u64>,
) -> Sse<impl futures_core::Stream<Item = Result<Event, axum::Error>>> {
let show_hh_mm = state
.overlay_configs
.lock()
.await
.get(&id)
.map(|cfg| cfg.show_hh_mm)
.unwrap_or(false);
let rx = state.event_bus.subscribe();
let stream = BroadcastStream::new(rx).filter_map(move |event| match event {
Ok(AppEvent::Tick(p)) if p.id == id => Some(Ok(Event::default()
.event("tick")
.data(format_remaining(p.remaining_ms)))),
.data(format_remaining(p.remaining_ms, show_hh_mm)))),
Ok(AppEvent::Changed(snaps)) => snaps.iter().find(|s| s.id == id).map(|s| {
Ok(Event::default()
.event("tick")
.data(format_remaining(s.duration as u64)))
.data(format_remaining(s.duration as u64, show_hh_mm)))
}),
Ok(AppEvent::ConfigChanged(cid)) if cid == id => {
Some(Ok(Event::default().event("reload").data("")))
@@ -82,12 +89,23 @@ pub async fn sse_countdown(
)
}
fn format_remaining(ms: u64) -> String {
fn format_remaining(ms: u64, show_hh_mm: bool) -> String {
let total_seconds = ms / 1_000;
if !show_hh_mm {
return total_seconds.to_string();
}
let h = ms / 3_600_000;
let m = (ms % 3_600_000) / 60_000;
let s = (ms % 60_000) / 1_000;
let millis = ms % 1_000;
format!("{:02}:{:02}:{:02}.{:03}", h, m, s, millis)
format!("{:02}:{:02}:{:02}", h, m, s)
}
fn format_unknown(show_hh_mm: bool) -> String {
if show_hh_mm {
"??:??:??".to_string()
} else {
"??".to_string()
}
}
pub async fn list_icons() -> Json<Vec<String>> {