use tokio::sync::broadcast::Sender;
#[derive(Debug, Clone)]
pub enum CaptureEvent {
Start,
#[cfg(feature = "cli")]
Screenshot {
timecode_ms: u128,
},
Stop,
}
#[cfg(feature = "cli")]
#[derive(Debug, Clone)]
pub enum FlashEvent {
ScreenshotTaken,
RecordingStarted,
}
#[cfg(feature = "cli")]
#[derive(Debug, Clone)]
pub enum LifecycleEvent {
Shutdown,
}
#[derive(Debug, Clone)]
pub enum Event {
Capture(CaptureEvent),
#[cfg(feature = "cli")]
Flash(FlashEvent),
#[cfg(feature = "cli")]
Lifecycle(LifecycleEvent),
}
#[derive(Clone)]
pub struct EventRouter {
tx: Sender<Event>,
}
impl Default for EventRouter {
fn default() -> Self {
Self::new()
}
}
impl EventRouter {
pub fn new() -> Self {
let (tx, _rx) = tokio::sync::broadcast::channel::<Event>(100);
Self { tx }
}
pub fn send(&self, event: Event) {
let _ = self.tx.send(event);
}
#[cfg(feature = "cli")]
pub fn try_send(
&self,
event: Event,
) -> Result<usize, tokio::sync::broadcast::error::SendError<Event>> {
self.tx.send(event)
}
#[cfg(feature = "cli")]
pub fn shutdown(&self) {
let _ = self.tx.send(Event::Lifecycle(LifecycleEvent::Shutdown));
}
pub fn subscribe(&self) -> tokio::sync::broadcast::Receiver<Event> {
self.tx.subscribe()
}
}
#[cfg(all(test, feature = "cli"))]
mod tests {
use super::*;
#[test]
fn test_event_router() {
let router = EventRouter::new();
let mut receiver = router.subscribe();
router.send(Event::Capture(CaptureEvent::Start));
router.send(Event::Flash(FlashEvent::ScreenshotTaken));
assert!(matches!(
receiver.blocking_recv(),
Ok(Event::Capture(CaptureEvent::Start))
));
assert!(matches!(
receiver.blocking_recv(),
Ok(Event::Flash(FlashEvent::ScreenshotTaken))
));
}
#[test]
fn test_event_broadcast() {
let router = EventRouter::new();
let mut receiver1 = router.subscribe();
let mut receiver2 = router.subscribe();
router.send(Event::Capture(CaptureEvent::Start));
assert!(matches!(
receiver1.blocking_recv(),
Ok(Event::Capture(CaptureEvent::Start))
));
assert!(matches!(
receiver2.blocking_recv(),
Ok(Event::Capture(CaptureEvent::Start))
));
}
#[test]
fn test_event_router_shutdown() {
let router = EventRouter::new();
let mut receiver = router.subscribe();
router.shutdown();
assert!(matches!(
receiver.blocking_recv(),
Ok(Event::Lifecycle(LifecycleEvent::Shutdown))
));
}
}