use apace_traits::navigation::NavigationOptions;
use apace_traits::net::NetWaker;
use futures_util::task::ArcWake;
use std::sync::mpsc::{Receiver, Sender, channel};
use std::{any::Any, sync::Arc};
use wingy::{event_loop::EventLoopProxy, window::WindowId};
#[cfg(feature = "accessibility")]
use apace_accesskit::WindowEvent as AccessKitEvent;
#[derive(Debug, Clone)]
pub enum ApaceShellEvent {
Poll {
window_id: WindowId,
},
ResumeReady {
window_id: WindowId,
},
RequestRedraw {
doc_id: usize,
},
CloseWindow {
window_id: WindowId,
},
#[cfg(feature = "accessibility")]
Accessibility {
window_id: WindowId,
data: Arc<AccessKitEvent>,
},
Embedder(Arc<dyn Any + Send + Sync>),
Navigate(Box<NavigationOptions>),
NavigationLoad {
url: String,
contents: String,
retain_scroll_position: bool,
is_md: bool,
},
#[cfg(target_arch = "wasm32")]
ResizeSettleCheck {
window_id: WindowId,
},
}
impl ApaceShellEvent {
pub fn embedder_event<T: Any + Send + Sync>(value: T) -> Self {
let boxed = Arc::new(value) as Arc<dyn Any + Send + Sync>;
Self::Embedder(boxed)
}
}
#[derive(Clone)]
pub struct ApaceShellProxy(Arc<ApaceShellProxyInner>);
pub struct ApaceShellProxyInner {
wingy_proxy: EventLoopProxy,
sender: Sender<ApaceShellEvent>,
}
impl ApaceShellProxy {
pub fn new(wingy_proxy: EventLoopProxy) -> (Self, Receiver<ApaceShellEvent>) {
let (sender, receiver) = channel();
let proxy = Self(Arc::new(ApaceShellProxyInner {
wingy_proxy,
sender,
}));
(proxy, receiver)
}
pub fn wake_up(&self) {
self.0.wingy_proxy.wake_up();
}
pub fn send_event(&self, event: impl Into<ApaceShellEvent>) {
self.send_event_impl(event.into());
}
fn send_event_impl(&self, event: ApaceShellEvent) {
let _ = self.0.sender.send(event);
self.wake_up();
}
}
impl NetWaker for ApaceShellProxy {
fn wake(&self, client_id: usize) {
self.send_event_impl(ApaceShellEvent::RequestRedraw { doc_id: client_id })
}
}
pub fn create_waker(proxy: &ApaceShellProxy, id: WindowId) -> std::task::Waker {
struct DomHandle {
proxy: ApaceShellProxy,
id: WindowId,
}
impl ArcWake for DomHandle {
fn wake_by_ref(arc_self: &Arc<Self>) {
let event = ApaceShellEvent::Poll {
window_id: arc_self.id,
};
arc_self.proxy.send_event(event)
}
}
let proxy = proxy.clone();
futures_util::task::waker(Arc::new(DomHandle { id, proxy }))
}