Merge branch 'master' into jk/global-window-fun
This commit is contained in:
200 files changed
+6082
-2375
No files matched your search
@@ -1,21 +1,27 @@
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::rc::Weak;
|
||||
|
||||
use crate::create_new_window;
|
||||
use crate::events::IpcMessage;
|
||||
use crate::protocol::AssetFuture;
|
||||
use crate::protocol::AssetHandlerRegistry;
|
||||
use crate::query::QueryEngine;
|
||||
use crate::shortcut::ShortcutId;
|
||||
use crate::shortcut::ShortcutRegistry;
|
||||
use crate::shortcut::ShortcutRegistryError;
|
||||
use crate::shortcut::{HotKey, ShortcutId, ShortcutRegistry, ShortcutRegistryError};
|
||||
use crate::AssetHandler;
|
||||
use crate::Config;
|
||||
use crate::WebviewHandler;
|
||||
use dioxus_core::ScopeState;
|
||||
use dioxus_core::VirtualDom;
|
||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
||||
use dioxus_hot_reload::HotReloadMsg;
|
||||
use dioxus_interpreter_js::binary_protocol::Channel;
|
||||
use rustc_hash::FxHashMap;
|
||||
use slab::Slab;
|
||||
use wry::application::accelerator::Accelerator;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::Debug;
|
||||
use std::fmt::Formatter;
|
||||
use std::rc::Rc;
|
||||
use std::rc::Weak;
|
||||
use std::sync::atomic::AtomicU16;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use wry::application::event::Event;
|
||||
use wry::application::event_loop::EventLoopProxy;
|
||||
use wry::application::event_loop::EventLoopWindowTarget;
|
||||
@@ -45,6 +51,45 @@ pub fn use_window(cx: &ScopeState) -> &DesktopContext {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// This handles communication between the requests that the webview makes and the interpreter. The interpreter constantly makes long running requests to the webview to get any edits that should be made to the DOM almost like server side events.
|
||||
/// It will hold onto the requests until the interpreter is ready to handle them and hold onto any pending edits until a new request is made.
|
||||
#[derive(Default, Clone)]
|
||||
pub(crate) struct EditQueue {
|
||||
queue: Arc<Mutex<Vec<Vec<u8>>>>,
|
||||
responder: Arc<Mutex<Option<wry::webview::RequestAsyncResponder>>>,
|
||||
}
|
||||
|
||||
impl Debug for EditQueue {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("EditQueue")
|
||||
.field("queue", &self.queue)
|
||||
.field("responder", {
|
||||
&self.responder.lock().unwrap().as_ref().map(|_| ())
|
||||
})
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl EditQueue {
|
||||
pub fn handle_request(&self, responder: wry::webview::RequestAsyncResponder) {
|
||||
let mut queue = self.queue.lock().unwrap();
|
||||
if let Some(bytes) = queue.pop() {
|
||||
responder.respond(wry::http::Response::new(bytes));
|
||||
} else {
|
||||
*self.responder.lock().unwrap() = Some(responder);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_edits(&self, edits: Vec<u8>) {
|
||||
let mut responder = self.responder.lock().unwrap();
|
||||
if let Some(responder) = responder.take() {
|
||||
responder.respond(wry::http::Response::new(edits));
|
||||
} else {
|
||||
self.queue.lock().unwrap().push(edits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type WebviewQueue = Rc<RefCell<Vec<WebviewHandler>>>;
|
||||
|
||||
/// An imperative interface to the current window.
|
||||
@@ -77,6 +122,13 @@ pub struct DesktopService {
|
||||
|
||||
pub(crate) shortcut_manager: ShortcutRegistry,
|
||||
|
||||
pub(crate) edit_queue: EditQueue,
|
||||
pub(crate) templates: RefCell<FxHashMap<String, u16>>,
|
||||
pub(crate) max_template_count: AtomicU16,
|
||||
|
||||
pub(crate) channel: RefCell<Channel>,
|
||||
pub(crate) asset_handlers: AssetHandlerRegistry,
|
||||
|
||||
#[cfg(target_os = "ios")]
|
||||
pub(crate) views: Rc<RefCell<Vec<*mut objc::runtime::Object>>>,
|
||||
}
|
||||
@@ -101,6 +153,8 @@ impl DesktopService {
|
||||
webviews: WebviewQueue,
|
||||
event_handlers: WindowEventHandlers,
|
||||
shortcut_manager: ShortcutRegistry,
|
||||
edit_queue: EditQueue,
|
||||
asset_handlers: AssetHandlerRegistry,
|
||||
) -> Self {
|
||||
Self {
|
||||
webview: Rc::new(webview),
|
||||
@@ -110,6 +164,11 @@ impl DesktopService {
|
||||
pending_windows: webviews,
|
||||
event_handlers,
|
||||
shortcut_manager,
|
||||
edit_queue,
|
||||
templates: Default::default(),
|
||||
max_template_count: Default::default(),
|
||||
channel: Default::default(),
|
||||
asset_handlers,
|
||||
#[cfg(target_os = "ios")]
|
||||
views: Default::default(),
|
||||
}
|
||||
@@ -243,11 +302,11 @@ impl DesktopService {
|
||||
/// Linux: Only works on x11. See [this issue](https://github.com/tauri-apps/tao/issues/331) for more information.
|
||||
pub fn create_shortcut(
|
||||
&self,
|
||||
accelerator: Accelerator,
|
||||
hotkey: HotKey,
|
||||
callback: impl FnMut() + 'static,
|
||||
) -> Result<ShortcutId, ShortcutRegistryError> {
|
||||
self.shortcut_manager
|
||||
.add_shortcut(accelerator, Box::new(callback))
|
||||
.add_shortcut(hotkey, Box::new(callback))
|
||||
}
|
||||
|
||||
/// Remove a global shortcut
|
||||
@@ -260,6 +319,20 @@ impl DesktopService {
|
||||
self.shortcut_manager.remove_all()
|
||||
}
|
||||
|
||||
/// Provide a callback to handle asset loading yourself.
|
||||
///
|
||||
/// See [`use_asset_handle`](crate::use_asset_handle) for a convenient hook.
|
||||
pub async fn register_asset_handler<F: AssetFuture>(&self, f: impl AssetHandler<F>) -> usize {
|
||||
self.asset_handlers.register_handler(f).await
|
||||
}
|
||||
|
||||
/// Removes an asset handler by its identifier.
|
||||
///
|
||||
/// Returns `None` if the handler did not exist.
|
||||
pub async fn remove_asset_handler(&self, id: usize) -> Option<()> {
|
||||
self.asset_handlers.remove_handler(id).await
|
||||
}
|
||||
|
||||
/// Push an objc view to the window
|
||||
#[cfg(target_os = "ios")]
|
||||
pub fn push_view(&self, view: objc_id::ShareId<objc::runtime::Object>) {
|
||||
@@ -379,17 +452,10 @@ impl WryWindowEventHandlerInner {
|
||||
target: &EventLoopWindowTarget<UserWindowEvent>,
|
||||
) {
|
||||
// if this event does not apply to the window this listener cares about, return
|
||||
match event {
|
||||
Event::WindowEvent { window_id, .. }
|
||||
| Event::MenuEvent {
|
||||
window_id: Some(window_id),
|
||||
..
|
||||
} => {
|
||||
if *window_id != self.window_id {
|
||||
return;
|
||||
}
|
||||
if let Event::WindowEvent { window_id, .. } = event {
|
||||
if *window_id != self.window_id {
|
||||
return;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
(self.handler)(event, target)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user