|
@@ -1,13 +1,11 @@
|
|
|
-use std::{cell::RefCell, rc::Rc};
|
|
|
+use std::rc::Rc;
|
|
|
|
|
|
use dioxus_core::ElementId;
|
|
|
-use dioxus_html::{
|
|
|
- MountedResult, MountedReturn, MountedReturnData, NodeUpdate, NodeUpdateData,
|
|
|
- RenderedElementBacking,
|
|
|
-};
|
|
|
-use slab::Slab;
|
|
|
+use dioxus_html::{geometry::euclid::Rect, MountedResult, RenderedElementBacking};
|
|
|
use wry::webview::WebView;
|
|
|
|
|
|
+use crate::query::QueryEngine;
|
|
|
+
|
|
|
/// A mounted element passed to onmounted events
|
|
|
pub struct DesktopElement {
|
|
|
id: ElementId,
|
|
@@ -19,16 +17,6 @@ impl DesktopElement {
|
|
|
pub(crate) fn new(id: ElementId, webview: Rc<WebView>, query: QueryEngine) -> Self {
|
|
|
Self { id, webview, query }
|
|
|
}
|
|
|
-
|
|
|
- /// Get the id of the element
|
|
|
- pub fn id(&self) -> ElementId {
|
|
|
- self.id
|
|
|
- }
|
|
|
-
|
|
|
- /// Get the webview the element is mounted in
|
|
|
- pub fn webview(&self) -> &Rc<WebView> {
|
|
|
- &self.webview
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
impl RenderedElementBacking for DesktopElement {
|
|
@@ -45,19 +33,21 @@ impl RenderedElementBacking for DesktopElement {
|
|
|
>,
|
|
|
>,
|
|
|
> {
|
|
|
+ let script = format!("return window.interpreter.GetClientRect({});", self.id.0);
|
|
|
+
|
|
|
let fut = self
|
|
|
.query
|
|
|
- .new_query(self.id, NodeUpdateData::GetClientRect {}, &self.webview)
|
|
|
+ .new_query::<Option<Rect<f64, f64>>>(&script, &self.webview)
|
|
|
.resolve();
|
|
|
Box::pin(async move {
|
|
|
match fut.await {
|
|
|
- Some(MountedReturnData::GetClientRect(rect)) => Ok(rect),
|
|
|
- Some(_) => MountedResult::Err(dioxus_html::MountedError::OperationFailed(
|
|
|
- Box::new(DesktopQueryError::MismatchedReturn),
|
|
|
+ Ok(Some(rect)) => Ok(rect),
|
|
|
+ Ok(None) => MountedResult::Err(dioxus_html::MountedError::OperationFailed(
|
|
|
+ Box::new(DesktopQueryError::FailedToQuery),
|
|
|
)),
|
|
|
- None => MountedResult::Err(dioxus_html::MountedError::OperationFailed(Box::new(
|
|
|
- DesktopQueryError::FailedToQuery,
|
|
|
- ))),
|
|
|
+ Err(err) => {
|
|
|
+ MountedResult::Err(dioxus_html::MountedError::OperationFailed(Box::new(err)))
|
|
|
+ }
|
|
|
}
|
|
|
})
|
|
|
}
|
|
@@ -66,23 +56,25 @@ impl RenderedElementBacking for DesktopElement {
|
|
|
&self,
|
|
|
behavior: dioxus_html::ScrollBehavior,
|
|
|
) -> std::pin::Pin<Box<dyn futures_util::Future<Output = dioxus_html::MountedResult<()>>>> {
|
|
|
+ let script = format!(
|
|
|
+ "return window.interpreter.ScrollTo({}, {});",
|
|
|
+ self.id.0,
|
|
|
+ serde_json::to_string(&behavior).expect("Failed to serialize ScrollBehavior")
|
|
|
+ );
|
|
|
+
|
|
|
let fut = self
|
|
|
.query
|
|
|
- .new_query(
|
|
|
- self.id,
|
|
|
- NodeUpdateData::ScrollTo { behavior },
|
|
|
- &self.webview,
|
|
|
- )
|
|
|
+ .new_query::<bool>(&script, &self.webview)
|
|
|
.resolve();
|
|
|
Box::pin(async move {
|
|
|
match fut.await {
|
|
|
- Some(MountedReturnData::ScrollTo(())) => Ok(()),
|
|
|
- Some(_) => MountedResult::Err(dioxus_html::MountedError::OperationFailed(
|
|
|
- Box::new(DesktopQueryError::MismatchedReturn),
|
|
|
+ Ok(true) => Ok(()),
|
|
|
+ Ok(false) => MountedResult::Err(dioxus_html::MountedError::OperationFailed(
|
|
|
+ Box::new(DesktopQueryError::FailedToQuery),
|
|
|
)),
|
|
|
- None => MountedResult::Err(dioxus_html::MountedError::OperationFailed(Box::new(
|
|
|
- DesktopQueryError::FailedToQuery,
|
|
|
- ))),
|
|
|
+ Err(err) => {
|
|
|
+ MountedResult::Err(dioxus_html::MountedError::OperationFailed(Box::new(err)))
|
|
|
+ }
|
|
|
}
|
|
|
})
|
|
|
}
|
|
@@ -91,116 +83,41 @@ impl RenderedElementBacking for DesktopElement {
|
|
|
&self,
|
|
|
focus: bool,
|
|
|
) -> std::pin::Pin<Box<dyn futures_util::Future<Output = dioxus_html::MountedResult<()>>>> {
|
|
|
+ let script = format!(
|
|
|
+ "return window.interpreter.SetFocus({}, {});",
|
|
|
+ self.id.0, focus
|
|
|
+ );
|
|
|
+
|
|
|
+ println!("script: {}", script);
|
|
|
let fut = self
|
|
|
.query
|
|
|
- .new_query(self.id, NodeUpdateData::SetFocus { focus }, &self.webview)
|
|
|
+ .new_query::<bool>(&script, &self.webview)
|
|
|
.resolve();
|
|
|
+ println!("fut");
|
|
|
+
|
|
|
Box::pin(async move {
|
|
|
match fut.await {
|
|
|
- Some(MountedReturnData::SetFocus(())) => Ok(()),
|
|
|
- Some(_) => MountedResult::Err(dioxus_html::MountedError::OperationFailed(
|
|
|
- Box::new(DesktopQueryError::MismatchedReturn),
|
|
|
+ Ok(true) => Ok(()),
|
|
|
+ Ok(false) => MountedResult::Err(dioxus_html::MountedError::OperationFailed(
|
|
|
+ Box::new(DesktopQueryError::FailedToQuery),
|
|
|
)),
|
|
|
- None => MountedResult::Err(dioxus_html::MountedError::OperationFailed(Box::new(
|
|
|
- DesktopQueryError::FailedToQuery,
|
|
|
- ))),
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#[derive(Default, Clone)]
|
|
|
-struct SharedSlab {
|
|
|
- slab: Rc<RefCell<Slab<()>>>,
|
|
|
-}
|
|
|
-
|
|
|
-#[derive(Clone)]
|
|
|
-pub(crate) struct QueryEngine {
|
|
|
- sender: Rc<tokio::sync::broadcast::Sender<MountedReturn>>,
|
|
|
- active_requests: SharedSlab,
|
|
|
-}
|
|
|
-
|
|
|
-impl Default for QueryEngine {
|
|
|
- fn default() -> Self {
|
|
|
- let (sender, _) = tokio::sync::broadcast::channel(8);
|
|
|
- Self {
|
|
|
- sender: Rc::new(sender),
|
|
|
- active_requests: SharedSlab::default(),
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl QueryEngine {
|
|
|
- fn new_query(&self, id: ElementId, update: NodeUpdateData, webview: &WebView) -> Query {
|
|
|
- let request_id = self.active_requests.slab.borrow_mut().insert(());
|
|
|
-
|
|
|
- let update = NodeUpdate {
|
|
|
- id: id.0 as u32,
|
|
|
- request_id,
|
|
|
- data: update,
|
|
|
- };
|
|
|
-
|
|
|
- // start the query
|
|
|
- webview
|
|
|
- .evaluate_script(&format!(
|
|
|
- "window.interpreter.handleNodeUpdate({})",
|
|
|
- serde_json::to_string(&update).unwrap()
|
|
|
- ))
|
|
|
- .unwrap();
|
|
|
-
|
|
|
- Query {
|
|
|
- slab: self.active_requests.clone(),
|
|
|
- id: request_id,
|
|
|
- reciever: self.sender.subscribe(),
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- pub fn send(&self, data: MountedReturn) {
|
|
|
- self.sender.send(data).unwrap();
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-struct Query {
|
|
|
- slab: SharedSlab,
|
|
|
- id: usize,
|
|
|
- reciever: tokio::sync::broadcast::Receiver<MountedReturn>,
|
|
|
-}
|
|
|
-
|
|
|
-impl Query {
|
|
|
- async fn resolve(mut self) -> Option<MountedReturnData> {
|
|
|
- let result = loop {
|
|
|
- match self.reciever.recv().await {
|
|
|
- Ok(result) => {
|
|
|
- if result.id == self.id {
|
|
|
- break result.data;
|
|
|
- }
|
|
|
- }
|
|
|
- Err(_) => {
|
|
|
- break None;
|
|
|
+ Err(err) => {
|
|
|
+ MountedResult::Err(dioxus_html::MountedError::OperationFailed(Box::new(err)))
|
|
|
}
|
|
|
}
|
|
|
- };
|
|
|
-
|
|
|
- // Remove the query from the slab
|
|
|
- self.slab.slab.borrow_mut().remove(self.id);
|
|
|
-
|
|
|
- result
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
enum DesktopQueryError {
|
|
|
FailedToQuery,
|
|
|
- MismatchedReturn,
|
|
|
}
|
|
|
|
|
|
impl std::fmt::Display for DesktopQueryError {
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
match self {
|
|
|
DesktopQueryError::FailedToQuery => write!(f, "Failed to query the element"),
|
|
|
- DesktopQueryError::MismatchedReturn => {
|
|
|
- write!(f, "The return type did not match the query")
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
}
|