use std::io;
use rich_embed::{PageState, ScreencastFrame};
use serde_json::Value;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct TabId(pub u32);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum HistoryStep {
Back,
Forward,
Reload,
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Rect {
pub x: f64,
pub y: f64,
pub width: f64,
pub height: f64,
}
impl Rect {
pub fn new(x: f64, y: f64, width: f64, height: f64) -> Rect {
Rect {
x,
y,
width,
height,
}
}
pub fn right(&self) -> f64 {
self.x + self.width
}
pub fn bottom(&self) -> f64 {
self.y + self.height
}
pub fn is_empty(&self) -> bool {
self.width <= 0.0 || self.height <= 0.0
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Format {
Png,
Jpeg,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Frame {
pub format: Format,
pub bytes: Vec<u8>,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct PageSnapshot {
pub dom: Value,
pub ax: Value,
}
pub type NodeId = i64;
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Playback {
pub paused: bool,
pub muted: bool,
pub volume: f64,
pub time: f64,
pub duration: Option<f64>,
pub ended: bool,
pub ready: u8,
pub failed: bool,
}
impl Playback {
pub fn label(&self) -> &'static str {
if self.failed {
"ERROR"
} else if self.ended {
"ENDED"
} else if self.paused {
"PAUSED"
} else if self.ready < 3 {
"BUFFERING"
} else {
"PLAYING"
}
}
pub fn playing(&self) -> bool {
!self.paused && !self.ended && !self.failed
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum MediaOp {
Play,
Pause,
Mute(bool),
Volume(f64),
Seek(f64),
}
#[derive(Clone, Debug, PartialEq)]
pub enum PageAction {
Click(NodeId),
ClickAt { node: NodeId, x: f64, y: f64 },
ClickPoint { x: f64, y: f64 },
Key(rich_intuituive::interact::Key),
Focus(NodeId),
InsertText(String),
SetValue { node: NodeId, value: String },
SelectOption { select: NodeId, option: NodeId },
SetRange { node: NodeId, value: f64 },
ScrollTo(f64),
Wheel(f64),
Media { node: NodeId, op: MediaOp },
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Metrics {
pub scroll_y: f64,
pub content_height: f64,
pub viewport_height: f64,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct LiveRead {
pub order: Vec<u64>,
pub fresh: Vec<(u64, Value)>,
pub first_shown: Option<u64>,
pub interactive: bool,
}
#[derive(Clone, Debug, PartialEq)]
pub enum EngineEvent {
Changed,
Live,
Navigated(String),
Loaded,
DownloadBegan {
guid: String,
name: String,
url: String,
},
DownloadDone { guid: String, path: String },
}
pub trait Engine: Send {
fn resize(&mut self, columns: u16, rows: u16) -> io::Result<()>;
fn open(&mut self, tab: TabId, url: &str) -> io::Result<()>;
fn new_tab(&mut self, _url: &str) -> io::Result<TabId> {
Err(io::Error::new(
io::ErrorKind::Unsupported,
"this engine has one tab",
))
}
fn close_tab(&mut self, _tab: TabId) -> io::Result<()> {
Err(io::Error::new(
io::ErrorKind::Unsupported,
"this engine has one tab",
))
}
fn history(&mut self, tab: TabId, step: HistoryStep) -> io::Result<()>;
fn state(&self, tab: TabId) -> PageState;
fn snapshot(&mut self, tab: TabId) -> io::Result<PageSnapshot>;
fn capture(&mut self, tab: TabId, region: Rect, format: Format) -> io::Result<Frame>;
fn act(&mut self, tab: TabId, action: &PageAction) -> io::Result<()>;
fn playback(&mut self, _tab: TabId, _node: NodeId) -> io::Result<Playback> {
Err(io::Error::new(io::ErrorKind::Unsupported, "no media here"))
}
fn resource(&mut self, _tab: TabId, _url: &str) -> io::Result<Vec<u8>> {
Err(io::Error::new(
io::ErrorKind::Unsupported,
"no resources here",
))
}
fn image_ready(&mut self, _tab: TabId, _node: NodeId) -> io::Result<bool> {
Ok(true)
}
fn metrics(&mut self, _tab: TabId) -> io::Result<Metrics> {
Err(io::Error::new(
io::ErrorKind::Unsupported,
"no metrics here",
))
}
fn set_screencast(&mut self, _tab: TabId, _on: bool) -> io::Result<()> {
Err(io::Error::new(
io::ErrorKind::Unsupported,
"no screencast here",
))
}
fn set_screencast_scale(&mut self, _tab: TabId, _scale: f64) -> io::Result<()> {
Ok(())
}
fn screencast_frame(&mut self, _tab: TabId) -> Option<ScreencastFrame> {
None
}
fn can_play(&mut self, _tab: TabId, types: &[&str]) -> io::Result<Vec<String>> {
Ok(vec![String::new(); types.len()])
}
fn product(&mut self, _tab: TabId) -> String {
"unknown".into()
}
fn read_live(&mut self, _tab: TabId, _node: NodeId, _full: bool) -> io::Result<LiveRead> {
Err(io::Error::new(
io::ErrorKind::Unsupported,
"no live reads here",
))
}
fn appended(&mut self, _tab: TabId) -> io::Result<Vec<NodeId>> {
Ok(Vec::new())
}
fn events(&mut self) -> Vec<EngineEvent>;
}