Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor desktop crate, update to wry 0.35, use muda for Menu #1787

Merged
merged 44 commits into from
Jan 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
9a6d745
Refactor desktop into App type
jkelleyrtp Jan 4, 2024
4366353
Get compiling
jkelleyrtp Jan 5, 2024
d38ce34
Tiny bit of cleanups
jkelleyrtp Jan 5, 2024
c91071a
Merge branch 'master' into jk/rework-desktop-crate
jkelleyrtp Jan 5, 2024
1518c22
Don't drop tokio runtime immediately
jkelleyrtp Jan 5, 2024
62a9583
Fix merge conflict
jkelleyrtp Jan 5, 2024
ec3eaa6
Add ID to filedrop handler
jkelleyrtp Jan 5, 2024
2171263
More cleanup work
jkelleyrtp Jan 5, 2024
6e08703
Fix compile issue
jkelleyrtp Jan 5, 2024
d47e494
More cleaning up of the desktop crate
jkelleyrtp Jan 5, 2024
fef7b83
Rename editqueue type
jkelleyrtp Jan 5, 2024
7444796
Simplify asset code a bit
jkelleyrtp Jan 5, 2024
0604908
Clean up desktop even more
jkelleyrtp Jan 5, 2024
73d5069
Move launch functions into their own file
jkelleyrtp Jan 5, 2024
38216fa
Make the tokio runtime optional
jkelleyrtp Jan 5, 2024
2e9737e
Clean up and document the protocol handler
jkelleyrtp Jan 5, 2024
4adc912
Collapse objects into single shared object
jkelleyrtp Jan 5, 2024
b5a125b
Refactor IPC a bit
jkelleyrtp Jan 5, 2024
4d95bc1
Document ipc a bit
jkelleyrtp Jan 5, 2024
42e25c4
A few more stylistic changes
jkelleyrtp Jan 5, 2024
fa425dc
Merge branch 'master' into jk/rework-desktop-crate
jkelleyrtp Jan 5, 2024
47306bf
Merge branch 'master' into jk/rework-desktop-crate
jkelleyrtp Jan 5, 2024
8e9984b
Fix merge conflicts with new event system
jkelleyrtp Jan 5, 2024
cbed09b
Clean up shared context in desktop
jkelleyrtp Jan 5, 2024
bc857bf
Make clippy happy
jkelleyrtp Jan 5, 2024
8323e45
Call handlers from context of a runtime and scope
jkelleyrtp Jan 6, 2024
347351d
Finish asset handler
jkelleyrtp Jan 6, 2024
2013536
Put asset collection behind a feature flag
jkelleyrtp Jan 6, 2024
a95f4df
fmt
jkelleyrtp Jan 6, 2024
2e0cded
Make clippy happy
jkelleyrtp Jan 6, 2024
e9e7219
Add os-webview feature to wry to fix builds
jkelleyrtp Jan 6, 2024
0ac8955
Fix android/ios muda cfg
jkelleyrtp Jan 6, 2024
ce088ac
use proper extension traits
jkelleyrtp Jan 6, 2024
7a439ed
disable muda entirely on mobile
jkelleyrtp Jan 6, 2024
9494993
Tweak menubar export
jkelleyrtp Jan 6, 2024
8679656
fix ios build of desktop
jkelleyrtp Jan 6, 2024
d078086
disable linux menubar
jkelleyrtp Jan 6, 2024
d7c6aa4
fix builds for windows
jkelleyrtp Jan 6, 2024
9efeb51
Fix windows build, again
jkelleyrtp Jan 6, 2024
a8eaf3d
Exclude mobile from ci
jkelleyrtp Jan 6, 2024
f01a684
fix windows
jkelleyrtp Jan 6, 2024
4d8592e
add xdo to dev
jkelleyrtp Jan 6, 2024
9d4a8e1
add window ext trait
jkelleyrtp Jan 6, 2024
729bfa3
Fix eval provider
jkelleyrtp Jan 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
- uses: Swatinem/rust-cache@v2
- uses: ilammy/setup-nasm@v1
- run: sudo apt-get update
- run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev
- run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev
- uses: davidB/rust-cargo-make@v1
- uses: browser-actions/setup-firefox@latest
- uses: jetli/wasm-pack-action@v0.4.0
Expand Down
2 changes: 2 additions & 0 deletions Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ args = [
"dioxus-router",
"--exclude",
"dioxus-desktop",
"--exclude",
"dioxus-mobile",
]
private = true

Expand Down
4 changes: 2 additions & 2 deletions examples/calculator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ This calculator version uses React-style state management. All state is held as
use dioxus::events::*;
use dioxus::html::input_data::keyboard_types::Key;
use dioxus::prelude::*;
use dioxus_desktop::{Config, WindowBuilder};
use dioxus_desktop::{Config, LogicalSize, WindowBuilder};

fn main() {
let config = Config::new().with_window(
WindowBuilder::default()
.with_title("Calculator")
.with_inner_size(dioxus_desktop::LogicalSize::new(300.0, 500.0)),
.with_inner_size(LogicalSize::new(300.0, 500.0)),
);

dioxus_desktop::launch_cfg(app, config);
Expand Down
2 changes: 1 addition & 1 deletion examples/clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fn app(cx: Scope) -> Element {

use_future!(cx, || async move {
loop {
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
count += 1;
println!("current: {count}");
}
Expand Down
2 changes: 1 addition & 1 deletion examples/compose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ fn compose(cx: Scope<ComposeProps>) -> Element {
},
"Click to send"
}

input { oninput: move |e| user_input.set(e.value()), value: "{user_input}" }
}
})
Expand Down
22 changes: 10 additions & 12 deletions examples/dynamic_asset.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
use dioxus::prelude::*;
use dioxus_desktop::wry::http::Response;
use dioxus_desktop::{use_asset_handler, AssetRequest};
use std::path::Path;
use dioxus_desktop::{use_asset_handler, wry::http::Response};

fn main() {
dioxus_desktop::launch(app);
}

fn app(cx: Scope) -> Element {
use_asset_handler(cx, |request: &AssetRequest| {
let path = request.path().to_path_buf();
async move {
if path != Path::new("logo.png") {
return None;
}
let image_data: &[u8] = include_bytes!("./assets/logo.png");
Some(Response::new(image_data.into()))
use_asset_handler(cx, "logos", |request, response| {
// Note that the "logos" prefix is stripped from the URI
//
// However, the asset is absolute to its "virtual folder" - meaning it starts with a leading slash
if request.uri().path() != "/logo.png" {
return;
}

response.respond(Response::new(include_bytes!("./assets/logo.png").to_vec()));
});

cx.render(rsx! {
div {
img {
src: "logo.png"
src: "/logos/logo.png"
}
}
})
Expand Down
2 changes: 1 addition & 1 deletion examples/mobile_demo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ frameworks = ["WebKit"]
[dependencies]
anyhow = "1.0.56"
log = "0.4.11"
wry = "0.34.0"
wry = "0.35.0"
dioxus = { path = "../../packages/dioxus" }
dioxus-desktop = { path = "../../packages/desktop", features = [
"tokio_runtime",
Expand Down
2 changes: 1 addition & 1 deletion examples/pattern_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use dioxus::events::*;
use dioxus::html::input_data::keyboard_types::Key;
use dioxus::html::MouseEvent;
use dioxus::prelude::*;
use dioxus_desktop::wry::application::dpi::LogicalSize;
use dioxus_desktop::tao::dpi::LogicalSize;
use dioxus_desktop::{Config, WindowBuilder};

fn main() {
Expand Down
34 changes: 19 additions & 15 deletions examples/video_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use dioxus_desktop::wry::http;
use dioxus_desktop::wry::http::Response;
use dioxus_desktop::{use_asset_handler, AssetRequest};
use http::{header::*, response::Builder as ResponseBuilder, status::StatusCode};
use std::borrow::Cow;
use std::{io::SeekFrom, path::PathBuf};
use tokio::io::AsyncReadExt;
use tokio::io::AsyncSeekExt;
Expand Down Expand Up @@ -31,28 +30,33 @@ fn main() {
}

fn app(cx: Scope) -> Element {
use_asset_handler(cx, move |request: &AssetRequest| {
let request = request.clone();
async move {
use_asset_handler(cx, "videos", move |request, responder| {
// Using dioxus::spawn works, but is slower than a dedicated thread
tokio::task::spawn(async move {
let video_file = PathBuf::from(VIDEO_PATH);
let mut file = tokio::fs::File::open(&video_file).await.unwrap();
let response: Option<Response<Cow<'static, [u8]>>> =
match get_stream_response(&mut file, &request).await {
Ok(response) => Some(response.map(Cow::Owned)),
Err(err) => {
eprintln!("Error: {}", err);
None
}
};
response
}

match get_stream_response(&mut file, &request).await {
Ok(response) => responder.respond(response),
Err(err) => eprintln!("Error: {}", err),
}
});
});

render! {
div { video { src: "test_video.mp4", autoplay: true, controls: true, width: 640, height: 480 } }
div {
video {
src: "/videos/test_video.mp4",
autoplay: true,
controls: true,
width: 640,
height: 480
}
}
}
}

/// This was taken from wry's example
async fn get_stream_response(
asset: &mut (impl tokio::io::AsyncSeek + tokio::io::AsyncRead + Unpin + Send + Sync),
request: &AssetRequest,
Expand Down
2 changes: 1 addition & 1 deletion examples/window_focus.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use dioxus::prelude::*;
use dioxus_desktop::tao::event::Event as WryEvent;
use dioxus_desktop::tao::event::WindowEvent;
use dioxus_desktop::use_wry_event_handler;
use dioxus_desktop::wry::application::event::Event as WryEvent;
use dioxus_desktop::{Config, WindowCloseBehaviour};

fn main() {
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/error_boundary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
use std::{
any::{Any, TypeId},
backtrace::Backtrace,
cell::RefCell,
cell::{Cell, RefCell},
error::Error,
fmt::{Debug, Display},
rc::Rc,
Expand Down Expand Up @@ -472,8 +472,8 @@ pub fn ErrorBoundary<'a>(cx: Scope<'a, ErrorBoundaryProps<'a>>) -> Element {
attr_paths: &[],
};
VNode {
parent: Default::default(),
stable_id: Default::default(),
parent: Cell::new(None),
stable_id: Cell::new(None),
key: None,
template: std::cell::Cell::new(TEMPLATE),
root_ids: bumpalo::collections::Vec::with_capacity_in(1usize, __cx.bump()).into(),
Expand Down
21 changes: 21 additions & 0 deletions packages/core/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ impl Runtime {
self.scope_stack.borrow().last().copied()
}

/// Call this function with the current scope set to the given scope
///
/// Useful in a limited number of scenarios, not public.
pub(crate) fn with_scope<O>(&self, id: ScopeId, f: impl FnOnce() -> O) -> O {
self.scope_stack.borrow_mut().push(id);
let o = f();
self.scope_stack.borrow_mut().pop();
o
}

/// Get the context for any scope given its ID
///
/// This is useful for inserting or removing contexts from a scope, or rendering out its root node
Expand Down Expand Up @@ -137,6 +147,17 @@ impl RuntimeGuard {
push_runtime(runtime.clone());
Self(runtime)
}

/// Run a function with a given runtime and scope in context
pub fn with<O>(runtime: Rc<Runtime>, scope: Option<ScopeId>, f: impl FnOnce() -> O) -> O {
let guard = Self::new(runtime.clone());
let o = match scope {
Some(scope) => Runtime::with_scope(&runtime, scope, f),
None => f(),
};
drop(guard);
o
}
}

impl Drop for RuntimeGuard {
Expand Down
7 changes: 6 additions & 1 deletion packages/core/src/scope_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,11 +318,16 @@ pub fn spawn(fut: impl Future<Output = ()> + 'static) {
with_current_scope(|cx| cx.spawn(fut));
}

/// Spawn a future on a component given its [`ScopeId`].
pub fn spawn_at(fut: impl Future<Output = ()> + 'static, scope_id: ScopeId) -> Option<TaskId> {
with_runtime(|rt| rt.get_context(scope_id).unwrap().push_future(fut))
}

/// Spawn a future that Dioxus won't clean up when this component is unmounted
///
/// This is good for tasks that need to be run after the component has been dropped.
pub fn spawn_forever(fut: impl Future<Output = ()> + 'static) -> Option<TaskId> {
with_current_scope(|cx| cx.spawn_forever(fut))
spawn_at(fut, ScopeId(0))
}

/// Informs the scheduler that this task is no longer needed and should be removed.
Expand Down
21 changes: 18 additions & 3 deletions packages/core/tests/event_propagation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ fn events_propagate() {
_ = dom.rebuild();

// Top-level click is registered
dom.handle_event("click", Rc::new(PlatformEventData::new(Box::<SerializedMouseData>::default())), ElementId(1), true);
dom.handle_event(
"click",
Rc::new(PlatformEventData::new(Box::<SerializedMouseData>::default())),
ElementId(1),
true,
);
assert_eq!(*CLICKS.lock().unwrap(), 1);

// break reference....
Expand All @@ -22,7 +27,12 @@ fn events_propagate() {
}

// Lower click is registered
dom.handle_event("click", Rc::new(PlatformEventData::new(Box::<SerializedMouseData>::default())), ElementId(2), true);
dom.handle_event(
"click",
Rc::new(PlatformEventData::new(Box::<SerializedMouseData>::default())),
ElementId(2),
true,
);
assert_eq!(*CLICKS.lock().unwrap(), 3);

// break reference....
Expand All @@ -32,7 +42,12 @@ fn events_propagate() {
}

// Stop propagation occurs
dom.handle_event("click", Rc::new(PlatformEventData::new(Box::<SerializedMouseData>::default())), ElementId(2), true);
dom.handle_event(
"click",
Rc::new(PlatformEventData::new(Box::<SerializedMouseData>::default())),
ElementId(2),
true,
);
assert_eq!(*CLICKS.lock().unwrap(), 3);
}

Expand Down
25 changes: 20 additions & 5 deletions packages/desktop/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,24 @@ keywords = ["dom", "ui", "gui", "react"]

[dependencies]
dioxus-core = { workspace = true, features = ["serialize"] }
dioxus-html = { workspace = true, features = ["serialize", "native-bind", "mounted", "eval"] }
dioxus-html = { workspace = true, features = [
"serialize",
"native-bind",
"mounted",
"eval",
] }
dioxus-interpreter-js = { workspace = true, features = ["binary-protocol"] }
dioxus-hot-reload = { workspace = true, optional = true }

serde = "1.0.136"
serde_json = "1.0.79"
thiserror = { workspace = true }
tracing.workspace = true
wry = { version = "0.34.0", default-features = false, features = ["tao", "protocol", "file-drop"] }
tracing = { workspace = true }
wry = { version = "0.35.0", default-features = false, features = [
"os-webview",
"protocol",
"file-drop",
] }
futures-channel = { workspace = true }
tokio = { workspace = true, features = [
"sync",
Expand All @@ -39,12 +48,17 @@ futures-util = { workspace = true }
urlencoding = "2.1.2"
async-trait = "0.1.68"
crossbeam-channel = "0.5.8"
tao = { version = "0.24.0", features = ["rwh_05"] }

[target.'cfg(any(target_os = "windows",target_os = "macos",target_os = "linux",target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))'.dependencies]
# This is only for debug mode, and it appears mobile does not support some packages this uses
manganis-cli-support = { git = "https://github.com/DioxusLabs/collect-assets", features = ["webp", "html"] }
manganis-cli-support = { git = "https://github.com/DioxusLabs/collect-assets", optional = true, features = [
"webp",
"html",
] }
rfd = "0.12"
global-hotkey = { git = "https://github.com/tauri-apps/global-hotkey" }
global-hotkey = "0.4.1"
muda = "0.11.3"

[target.'cfg(target_os = "ios")'.dependencies]
objc = "0.2.7"
Expand All @@ -61,6 +75,7 @@ fullscreen = ["wry/fullscreen"]
transparent = ["wry/transparent"]
devtools = ["wry/devtools"]
hot-reload = ["dioxus-hot-reload"]
asset-collect = ["manganis-cli-support"]
gnu = []

[package.metadata.docs.rs]
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop/headless_tests/rendering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use dioxus::prelude::*;
use dioxus_desktop::DesktopContext;

pub(crate) fn check_app_exits(app: Component) {
use dioxus_desktop::tao::window::WindowBuilder;
use dioxus_desktop::Config;
use tao::window::WindowBuilder;
// This is a deadman's switch to ensure that the app exits
let should_panic = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(true));
let should_panic_clone = should_panic.clone();
Expand Down
Loading
Loading