use std::time::Instant;
use anyhow::anyhow;
use gio::Cancellable;
use gtk::prelude::*;
use log::{debug, warn};
use webkit2gtk::traits::WebViewExt;
use webkit2gtk::{WebContext, WebView};
use crate::assets::PageState;
use crate::input::Config;
#[derive(Clone)]
pub struct Browser {
webview: WebView,
config: Config,
}
impl Browser {
pub fn new(config: Config) -> anyhow::Result<Self> {
let web_context = WebContext::default().
ok_or_else(|| anyhow!("Couldn't initialize GTK WebContext"))?;
let webview = WebView::with_context(&web_context);
webview.set_zoom_level(config.zoom);
Ok(Browser { webview, config })
}
pub fn attach_to(&self, window: >k::Window) {
window.add(&self.webview);
}
pub fn load_uri(&self, uri: &str) {
self.webview.load_uri(uri);
}
pub fn reload(&self) {
self.webview.reload();
}
pub fn zoom_in(&self) {
let zoom_level = self.webview.zoom_level();
self.webview.set_zoom_level(zoom_level + 0.1);
debug!("Zoom level set to: {}", zoom_level);
}
pub fn zoom_out(&self) {
let zoom_level = self.webview.zoom_level();
if zoom_level > 0.2 {
self.webview.set_zoom_level(zoom_level - 0.1);
debug!("Zoom level set to: {}", zoom_level);
}
}
pub fn zoom_reset(&self) {
self.webview.set_zoom_level(self.config.zoom);
debug!("Zoom level set to: {}", self.config.zoom);
}
pub fn get_page_state(&self) -> PageState {
match self.webview.title() {
Some(t) => {
serde_json::from_str(t.as_str()).unwrap_or_else(|e| {
warn!("Failed to get page state from {}: {:?}", t, e);
PageState::default()
})
},
None => PageState::default(),
}
}
pub fn execute_js(&self, js_code: &'static str) {
let now = Instant::now();
self.webview.run_javascript(js_code, None::<&Cancellable>, move |result| {
if let Err(e) = result {
warn!("Javascript execution error: {}", e);
} else {
debug!("Javascript executed in {}ms:\n> {}", now.elapsed().as_millis(), js_code);
}
});
}
}