use std::{
ffi::{CStr, c_char, c_void},
fmt,
};
use serde::Serialize;
use crate::ffi::*;
pub struct Frame(pub(crate) *mut wef_frame_t);
unsafe impl Send for Frame {}
unsafe impl Sync for Frame {}
impl fmt::Debug for Frame {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Frame")
.field("name", &self.name())
.field("identifier", &self.identifier())
.field("url", &self.url())
.finish()
}
}
impl Drop for Frame {
fn drop(&mut self) {
unsafe { wef_frame_destroy(self.0) };
}
}
impl Frame {
pub fn is_valid(&self) -> bool {
unsafe { wef_frame_is_valid(self.0) }
}
pub fn is_main(&self) -> bool {
unsafe { wef_frame_is_main(self.0) }
}
pub fn name(&self) -> Option<String> {
let mut name = String::new();
unsafe { wef_frame_name(self.0, &mut name as *mut _ as _, get_string_callback) };
(!name.is_empty()).then_some(name)
}
pub fn identifier(&self) -> Option<String> {
let mut id = String::new();
unsafe { wef_frame_identifier(self.0, &mut id as *mut _ as _, get_string_callback) };
(!id.is_empty()).then_some(id)
}
pub fn url(&self) -> String {
let mut url = String::new();
unsafe { wef_frame_get_url(self.0, &mut url as *mut _ as _, get_string_callback) };
url
}
pub fn load_url(&self, url: &str) {
let c_url = std::ffi::CString::new(url).unwrap();
unsafe { wef_frame_load_url(self.0, c_url.as_ptr()) };
}
pub fn parent(&self) -> Option<Frame> {
let frame = unsafe { wef_frame_parent(self.0) };
if !frame.is_null() {
Some(Frame(frame))
} else {
None
}
}
pub fn undo(&self) {
unsafe { wef_frame_undo(self.0) };
}
pub fn redo(&self) {
unsafe { wef_frame_redo(self.0) };
}
pub fn cut(&self) {
unsafe { wef_frame_cut(self.0) };
}
pub fn copy(&self) {
unsafe { wef_frame_copy(self.0) };
}
pub fn paste(&self) {
unsafe { wef_frame_paste(self.0) };
}
pub fn paste_and_match_style(&self) {
unsafe { wef_frame_paste_and_match_style(self.0) };
}
pub fn delete(&self) {
unsafe { wef_frame_delete(self.0) };
}
pub fn select_all(&self) {
unsafe { wef_frame_select_all(self.0) };
}
pub fn execute_javascript(&self, script: &str) {
if script.is_empty() {
return;
}
let c_script = std::ffi::CString::new(script).unwrap();
unsafe { wef_frame_execute_javascript(self.0, c_script.as_ptr()) };
}
pub fn emit(&self, message: impl Serialize) {
let Ok(message) = serde_json::to_string(&message) else {
return;
};
self.execute_javascript(&format!("window.jsBridge.__internal.emit({})", message));
}
}
extern "C" fn get_string_callback(output: *mut c_void, value: *const c_char) {
unsafe {
*(output as *mut String) = CStr::from_ptr(value)
.to_str()
.unwrap_or_default()
.to_string();
}
}