use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CapturedFrame {
pub id: Uuid,
pub timestamp: DateTime<Utc>,
pub source: CaptureSource,
pub content: FrameContent,
pub metadata: FrameMetadata,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum CaptureSource {
Screen {
monitor: u32,
app: String,
window: String,
},
Audio {
device: String,
speaker: Option<String>,
},
Ui {
event_type: String,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum FrameContent {
OcrText(String),
Transcription(String),
UiEvent(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FrameMetadata {
pub app_name: Option<String>,
pub window_title: Option<String>,
pub monitor_id: Option<u32>,
pub confidence: f32,
pub language: Option<String>,
}
impl CapturedFrame {
pub fn new_screen(app: &str, window: &str, ocr_text: &str, monitor: u32) -> Self {
Self {
id: Uuid::new_v4(),
timestamp: Utc::now(),
source: CaptureSource::Screen {
monitor,
app: app.to_string(),
window: window.to_string(),
},
content: FrameContent::OcrText(ocr_text.to_string()),
metadata: FrameMetadata {
app_name: Some(app.to_string()),
window_title: Some(window.to_string()),
monitor_id: Some(monitor),
confidence: 0.9,
language: None,
},
}
}
pub fn new_audio(device: &str, transcription: &str, speaker: Option<&str>) -> Self {
Self {
id: Uuid::new_v4(),
timestamp: Utc::now(),
source: CaptureSource::Audio {
device: device.to_string(),
speaker: speaker.map(|s| s.to_string()),
},
content: FrameContent::Transcription(transcription.to_string()),
metadata: FrameMetadata {
app_name: None,
window_title: None,
monitor_id: None,
confidence: 0.85,
language: None,
},
}
}
pub fn new_ui_event(event_type: &str, description: &str) -> Self {
Self {
id: Uuid::new_v4(),
timestamp: Utc::now(),
source: CaptureSource::Ui {
event_type: event_type.to_string(),
},
content: FrameContent::UiEvent(description.to_string()),
metadata: FrameMetadata {
app_name: None,
window_title: None,
monitor_id: None,
confidence: 1.0,
language: None,
},
}
}
pub fn text_content(&self) -> &str {
match &self.content {
FrameContent::OcrText(text) => text,
FrameContent::Transcription(text) => text,
FrameContent::UiEvent(text) => text,
}
}
pub fn content_type(&self) -> &str {
match &self.content {
FrameContent::OcrText(_) => "ocr",
FrameContent::Transcription(_) => "transcription",
FrameContent::UiEvent(_) => "ui_event",
}
}
}
impl Default for FrameMetadata {
fn default() -> Self {
Self {
app_name: None,
window_title: None,
monitor_id: None,
confidence: 0.0,
language: None,
}
}
}