Prevent desktop reloads at the wry level (#4422)
* Prevent desktop reloads at the wry level * add a test * only allow one navigation
This commit is contained in:
1 parent
393246b923
commit
0d2e1f4051
7 files changed
+124
-20
No files matched your search
@@ -138,6 +138,11 @@ name = "check_rendering"
|
||||
path = "headless_tests/rendering.rs"
|
||||
harness = false
|
||||
|
||||
[[test]]
|
||||
name = "check_forms"
|
||||
path = "headless_tests/forms.rs"
|
||||
harness = false
|
||||
|
||||
[[test]]
|
||||
name = "check_eval"
|
||||
path = "headless_tests/eval.rs"
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_desktop::DesktopContext;
|
||||
use dioxus_document::eval;
|
||||
|
||||
#[path = "./utils.rs"]
|
||||
mod utils;
|
||||
|
||||
fn main() {
|
||||
#[cfg(not(windows))]
|
||||
utils::check_app_exits(check_html_renders);
|
||||
}
|
||||
|
||||
async fn inner_html(count: usize) -> String {
|
||||
let html = document::eval(&format!(
|
||||
r#"// Wait until the element is available
|
||||
const interval = setInterval(() => {{
|
||||
const element = document.getElementById('div-{count}');
|
||||
if (element) {{
|
||||
dioxus.send(element.innerHTML);
|
||||
clearInterval(interval);
|
||||
}}
|
||||
}}, 100);"#
|
||||
))
|
||||
.recv::<String>()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
println!("html: {html}");
|
||||
html
|
||||
}
|
||||
|
||||
fn check_html_renders() -> Element {
|
||||
let mut signal = use_signal(|| 0);
|
||||
|
||||
use_effect(move || {
|
||||
let signal = signal();
|
||||
// Pass the test once the count is greater than 10
|
||||
if signal > 10 {
|
||||
let desktop_context: DesktopContext = consume_context();
|
||||
desktop_context.close();
|
||||
}
|
||||
|
||||
spawn(async move {
|
||||
let raw_html = inner_html(signal).await;
|
||||
println!("{raw_html}");
|
||||
// Make sure the html contains count is {signal}
|
||||
assert!(raw_html.contains(&format!("count is {}", signal)));
|
||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
||||
eval(
|
||||
r#"let button = document.querySelector('#increment');
|
||||
button.dispatchEvent(new MouseEvent('click', {
|
||||
view: window,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
buttons: 2,
|
||||
button: 2,
|
||||
}));"#,
|
||||
);
|
||||
|
||||
// If the signal is even, also submit the form. This should not effect the count because the navigation is blocked
|
||||
if signal % 2 == 0 {
|
||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
||||
eval(
|
||||
r#"let form = document.getElementById('form-submit');
|
||||
form.dispatchEvent(new Event('click', {
|
||||
view: window,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
buttons: 2,
|
||||
button: 2,
|
||||
}));"#,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
rsx! {
|
||||
div {
|
||||
id: "div-{signal}",
|
||||
h1 { "Form" }
|
||||
form {
|
||||
input {
|
||||
r#type: "text",
|
||||
name: "username",
|
||||
id: "username",
|
||||
value: "goodbye"
|
||||
}
|
||||
input { r#type: "text", name: "full-name", value: "lorem" }
|
||||
input { r#type: "password", name: "password", value: "ipsum" }
|
||||
input {
|
||||
r#type: "radio",
|
||||
name: "color",
|
||||
value: "red",
|
||||
checked: true
|
||||
}
|
||||
input { r#type: "radio", name: "color", value: "blue" }
|
||||
button { id: "form-submit", r#type: "submit", value: "Submit", "Submit the form" }
|
||||
}
|
||||
|
||||
button {
|
||||
id: "increment",
|
||||
onclick: move |_| {
|
||||
signal += 1;
|
||||
},
|
||||
"count is {signal}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ use dioxus_history::{History, MemoryHistory};
|
||||
use dioxus_hooks::to_owned;
|
||||
use dioxus_html::{HasFileData, HtmlEvent, PlatformEventData};
|
||||
use futures_util::{pin_mut, FutureExt};
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
use std::{cell::OnceCell, time::Duration};
|
||||
use std::{rc::Rc, task::Waker};
|
||||
@@ -300,6 +301,8 @@ impl WebviewInstance {
|
||||
}
|
||||
};
|
||||
|
||||
let page_loaded = AtomicBool::new(false);
|
||||
|
||||
let mut webview = WebViewBuilder::new_with_web_context(&mut web_context)
|
||||
.with_bounds(wry::Rect {
|
||||
position: wry::dpi::Position::Logical(wry::dpi::LogicalPosition::new(0.0, 0.0)),
|
||||
@@ -311,11 +314,13 @@ impl WebviewInstance {
|
||||
.with_transparent(cfg.window.window.transparent)
|
||||
.with_url("dioxus://index.html/")
|
||||
.with_ipc_handler(ipc_handler)
|
||||
.with_navigation_handler(|var| {
|
||||
.with_navigation_handler(move |var| {
|
||||
// We don't want to allow any navigation
|
||||
// We only want to serve the index file and assets
|
||||
if var.starts_with("dioxus://") || var.starts_with("http://dioxus.") {
|
||||
true
|
||||
// After the page has loaded once, don't allow any more navigation
|
||||
let page_loaded = page_loaded.swap(true, std::sync::atomic::Ordering::SeqCst);
|
||||
!page_loaded
|
||||
} else {
|
||||
if var.starts_with("http://")
|
||||
|| var.starts_with("https://")
|
||||
|
||||
Reference in new issue
Block a user