use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::time::Duration;
use crate::{CommandPoint, FileType};
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct BrowserScreenshot {
pub filename: String,
pub data: String,
pub format: String,
pub size: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct ElementBox {
pub x: f64,
pub y: f64,
pub width: f64,
pub height: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct BoundingBoxElement {
pub selector: String,
pub index: usize,
pub tag: String,
pub text: Option<String>,
pub attributes: serde_json::Value,
pub bounding_box: ElementBox,
pub center: CommandPoint,
pub visibility: bool,
pub clickable: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub html: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct WaitForElementCheck {
pub found: bool,
pub visible: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct ClickTarget {
pub target_id: String,
pub tag: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub text: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub attributes: Option<serde_json::Map<String, Value>>,
pub bounding_box: ElementBox,
pub center: CommandPoint,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct DomElementDescriptor {
pub index: usize,
pub tag: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub selector: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub role: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub text: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub attributes: Option<serde_json::Map<String, Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bounding_box: Option<ElementBox>,
pub in_viewport: bool,
pub clickable: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct DomSnapshot {
pub url: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
pub viewport: (u32, u32),
pub captured_at: i64,
pub interactive: Vec<DomElementDescriptor>,
#[serde(skip_serializing_if = "Option::is_none")]
pub interactive_text: Option<String>,
}
#[derive(Debug, Clone)]
pub struct ObservationOptions {
pub full_page: Option<bool>,
pub with_overlay: bool,
pub use_image: bool,
pub include_content: bool,
pub max_elements: usize,
pub wait_for_load: bool,
pub wait_timeout: Duration,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct ObserveResponse {
#[serde(flatten)]
pub dom_snapshot: DomSnapshot,
pub state_text: String,
pub screenshot: Option<FileType>,
pub click_targets: Vec<ClickTarget>,
}
impl ObservationOptions {
pub fn for_command(full_page: Option<bool>, with_overlay: bool) -> Self {
Self {
full_page,
with_overlay,
use_image: true,
include_content: false,
max_elements: 140,
wait_for_load: true,
wait_timeout: Duration::from_millis(1500),
}
}
pub fn lightweight(full_page: Option<bool>, with_overlay: bool, use_image: bool) -> Self {
Self {
use_image,
include_content: false,
..Self::for_command(full_page, with_overlay)
}
}
}