use super::GalleryState; use crate::MediaEvent; use crate::db; use crate::server::AppState; use crate::server::hx::Media; use askama::Template; use axum::{ Router, extract::{Query, State}, response::sse::{Event, KeepAlive, Sse}, routing::get, }; use futures_util::stream::{Stream, StreamExt as _}; use std::convert::Infallible; use tokio_stream::wrappers::BroadcastStream; #[derive(Template)] #[template(path = "web/gallery/media.html")] struct HxMedia<'a> { features: &'a crate::server::Features, media: &'a Media, oob: bool, } async fn convert_event( app_state: AppState, state: GalleryState, event: MediaEvent, ) -> Option { tracing::debug!("Got media event for SSE: {:?}", event); match event { MediaEvent::Added(uuid) => { if let Ok((_, media, after)) = db::media_get(&app_state.pool, &state, &state, &uuid).await && let Some(media) = media && let Some(after) = after { let media: Media = (media, &app_state.config.pathfinder).into(); let tmpl = HxMedia { features: &app_state.config.features, media: &media, oob: false, }; if let Ok(res) = tmpl.render() { return Some(Event::default().data(format!( r#"
{res}
"#, after.id ))); } } None } MediaEvent::Changed(uuid) => { if let Ok((_, media, _)) = db::media_get(&app_state.pool, &state, &state, &uuid).await && let Some(media) = media { let media: Media = (media, &app_state.config.pathfinder).into(); let tmpl = HxMedia { features: &app_state.config.features, media: &media, oob: true, }; if let Ok(res) = tmpl.render() { return Some(Event::default().data(res)); } } None } MediaEvent::Archived(uuid) => Some(Event::default().data(format!( r#"
  • "# ))), } } async fn handler( State(app_state): State, Query(state): Query, ) -> Sse>> { let rx = app_state.media_events.subscribe(); let stream = BroadcastStream::new(rx) .filter_map(|result| std::future::ready(result.ok())) .then(move |event| convert_event(app_state.clone(), state.clone(), event)) .filter_map(std::future::ready) .map(Ok); Sse::new(stream).keep_alive(KeepAlive::default()) } pub fn create_router() -> Router { Router::new().route("/", get(handler)) }