mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 14:44:12 +00:00
Merge branch 'master' into feat/window_close_behaviour
This commit is contained in:
commit
d56fabfe9a
17 changed files with 285 additions and 28 deletions
1
.github/workflows/main.yml
vendored
1
.github/workflows/main.yml
vendored
|
@ -13,6 +13,7 @@ on:
|
|||
- lib.rs
|
||||
- Cargo.toml
|
||||
- Makefile.toml
|
||||
- playwrite-tests/**
|
||||
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
|
|
@ -39,6 +39,7 @@ members = [
|
|||
"playwrite-tests/web",
|
||||
"playwrite-tests/fullstack",
|
||||
]
|
||||
exclude = ["examples/mobile_demo"]
|
||||
|
||||
# dependencies that are shared across packages
|
||||
[workspace.dependencies]
|
||||
|
|
|
@ -4,15 +4,15 @@ There are many packages in the Dioxus organization. This document will help you
|
|||
|
||||
## Renderers
|
||||
|
||||
- [Desktop](https://github.com/DioxusLabs/dioxus/tree/master/packages/desktop): A Render that Runs Dioxus applications natively, but renders them with the system webview
|
||||
- [Mobile](https://github.com/DioxusLabs/dioxus/tree/master/packages/mobile): A Render that Runs Dioxus applications natively, but renders them with the system webview. This is currently a copy of the desktop render
|
||||
- [Web](https://github.com/DioxusLabs/dioxus/tree/master/packages/Web): Renders Dioxus applications in the browser by compiling to WASM and manipulating the DOM
|
||||
- [Liveview](https://github.com/DioxusLabs/dioxus/tree/master/packages/liveview): A Render that Runs on the server, and renders using a websocket proxy in the browser
|
||||
- [Rink](https://github.com/DioxusLabs/dioxus/tree/master/packages/rink): A Renderer that renders a HTML-like tree into a terminal
|
||||
- [TUI](https://github.com/DioxusLabs/dioxus/tree/master/packages/dioxus-tui): A Renderer that uses Rink to render a Dioxus application in a terminal
|
||||
- [Desktop](https://github.com/DioxusLabs/dioxus/tree/master/packages/desktop): A renderer that runs Dioxus applications natively, but renders them with the system webview.
|
||||
- [Mobile](https://github.com/DioxusLabs/dioxus/tree/master/packages/mobile): A renderer that runs Dioxus applications natively, but renders them with the system webview. This is currently a copy of the desktop renderer.
|
||||
- [Web](https://github.com/DioxusLabs/dioxus/tree/master/packages/Web): Renders Dioxus applications in the browser by compiling to WASM and manipulating the DOM.
|
||||
- [Liveview](https://github.com/DioxusLabs/dioxus/tree/master/packages/liveview): A renderer that runs on the server, and renders using a websocket proxy in the browser.
|
||||
- [Rink](https://github.com/DioxusLabs/dioxus/tree/master/packages/rink): A renderer that renders a HTML-like tree into a terminal.
|
||||
- [TUI](https://github.com/DioxusLabs/dioxus/tree/master/packages/dioxus-tui): A renderer that uses Rink to render a Dioxus application in a terminal.
|
||||
- [Blitz-Core](https://github.com/DioxusLabs/blitz/tree/master/blitz-core): An experimental native renderer that renders a HTML-like tree using WGPU.
|
||||
- [Blitz](https://github.com/DioxusLabs/blitz): An experimental native renderer that uses Blitz-Core to render a Dioxus application using WGPU.
|
||||
- [SSR](https://github.com/DioxusLabs/dioxus/tree/master/packages/ssr): A Render that Runs Dioxus applications on the server, and renders them to HTML
|
||||
- [SSR](https://github.com/DioxusLabs/dioxus/tree/master/packages/ssr): A renderer that runs Dioxus applications on the server, and renders them to HTML.
|
||||
|
||||
## State Management/Hooks
|
||||
|
||||
|
|
10
examples/mobile_demo/.gitignore
vendored
Normal file
10
examples/mobile_demo/.gitignore
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Rust
|
||||
target/
|
||||
**/*.rs.bk
|
||||
|
||||
# tauri-mobile
|
||||
.cargo/
|
||||
/gen
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
54
examples/mobile_demo/Cargo.toml
Normal file
54
examples/mobile_demo/Cargo.toml
Normal file
|
@ -0,0 +1,54 @@
|
|||
[package]
|
||||
name = "mobile-demo"
|
||||
version = "0.1.0"
|
||||
authors = ["Jonathan Kelley <jkelleyrtp@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[[bin]]
|
||||
name = "mobile-demo-desktop"
|
||||
path = "gen/bin/desktop.rs"
|
||||
|
||||
[package.metadata.cargo-android]
|
||||
app-activity-name = "com.example.mobile_demo.MainActivity"
|
||||
app-dependencies = [
|
||||
"androidx.webkit:webkit:1.6.1",
|
||||
"androidx.appcompat:appcompat:1.6.1",
|
||||
"com.google.android.material:material:1.8.0",
|
||||
]
|
||||
project-dependencies = ["org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21"]
|
||||
app-plugins = ["org.jetbrains.kotlin.android"]
|
||||
app-permissions = ["android.permission.INTERNET"]
|
||||
app-theme-parent = "Theme.MaterialComponents.DayNight.DarkActionBar"
|
||||
vulkan-validation = false
|
||||
|
||||
[package.metadata.cargo-android.env-vars]
|
||||
WRY_ANDROID_PACKAGE = "com.example.mobile_demo"
|
||||
WRY_ANDROID_LIBRARY = "mobile_demo"
|
||||
WRY_ANDROID_KOTLIN_FILES_OUT_DIR = "<android-project-dir>/app/src/main/kotlin/com/example/mobile_demo"
|
||||
|
||||
[package.metadata.cargo-apple.ios]
|
||||
frameworks = ["WebKit"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.56"
|
||||
log = "0.4.11"
|
||||
wry = "0.28.0"
|
||||
dioxus = { path = "../../packages/dioxus" }
|
||||
dioxus-desktop = { path = "../../packages/desktop", features = [
|
||||
"tokio_runtime",
|
||||
], default-features = false }
|
||||
|
||||
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
android_logger = "0.9.0"
|
||||
jni = "0.19.0"
|
||||
paste = "1.0"
|
||||
|
||||
[target.'cfg(not(target_os = "android"))'.dependencies]
|
||||
env_logger = "0.9.0"
|
||||
|
||||
[target.'cfg(target_os = "ios")'.dependencies]
|
||||
core-foundation = "0.9.3"
|
46
examples/mobile_demo/README.md
Normal file
46
examples/mobile_demo/README.md
Normal file
|
@ -0,0 +1,46 @@
|
|||
# Dioxus Mobile demo
|
||||
|
||||
## How this project was generated
|
||||
|
||||
Right now, Dioxus supports mobile targets including iOS and Android. However, our tooling is not mature enough to include the build commands directly.
|
||||
|
||||
This project was generated using [tauri-mobile](https://github.com/tauri-apps/tauri-mobile). We have yet to integrate this generation into the Dioxus-CLI. The open issue for this is [#1157](https://github.com/DioxusLabs/dioxus/issues/1157).
|
||||
|
||||
## Running on iOS
|
||||
|
||||
First, you'll want to make sure you have the appropriate iOS targets installed.
|
||||
|
||||
The two targets you'll use the most are:
|
||||
|
||||
- `aarch64-apple-ios-sim`
|
||||
- `aarch64-apple-ios`
|
||||
|
||||
These can be added using
|
||||
- `rustup target add aarch64-apple-ios-sim`
|
||||
- `rustup target add aarch64-apple-ios`
|
||||
|
||||
From there, you'll want to get a build of the crate using whichever platform you're targeting (simulator or actual hardware). For now, we'll just stick with the simulator:
|
||||
- `cargo build --target aarch64-apple-ios-sim`
|
||||
|
||||
Then, you'll want to open XCode. This might take awhile if you've never opened XCode before. The command you want to use is:
|
||||
- `cargo apple open`
|
||||
|
||||
This will open XCode with this particular project.
|
||||
|
||||
From there, just click the "play" button with the right target and the app should be running!
|
||||
|
||||
![ios_demo](ios_demo.png)
|
||||
|
||||
Note that clicking play doesn't cause a new build, so you'll need to keep rebuilding the app between changes. The tooling here is very young, so please be patient. If you want to contribute to make things easier, please do! We'll be happy to help.
|
||||
|
||||
|
||||
## Running on Android
|
||||
|
||||
Again, we want to make sure we have the right targets installed.
|
||||
|
||||
The common targets here are
|
||||
- aarch64-linux-android
|
||||
- armv7-linux-androideabi
|
||||
- i686-linux-android
|
||||
- x86_64-linux-android
|
||||
|
8
examples/mobile_demo/mobile.toml
Normal file
8
examples/mobile_demo/mobile.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[app]
|
||||
name = "mobile-demo"
|
||||
stylized-name = "Mobile Demo"
|
||||
domain = "example.com"
|
||||
template-pack = "wry"
|
||||
|
||||
[apple]
|
||||
development-team = "34U4FG9TJ8"
|
12
examples/mobile_demo/src/index.html
Normal file
12
examples/mobile_demo/src/index.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Dioxus app</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<!-- CUSTOM HEAD -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="main"></div>
|
||||
<!-- MODULE LOADER -->
|
||||
</body>
|
||||
</html>
|
86
examples/mobile_demo/src/lib.rs
Normal file
86
examples/mobile_demo/src/lib.rs
Normal file
|
@ -0,0 +1,86 @@
|
|||
use anyhow::Result;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_desktop::Config;
|
||||
#[cfg(target_os = "android")]
|
||||
use wry::android_binding;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
fn init_logging() {
|
||||
android_logger::init_once(
|
||||
android_logger::Config::default()
|
||||
.with_min_level(log::Level::Trace)
|
||||
.with_tag("mobile-demo"),
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn init_logging() {
|
||||
env_logger::init();
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
fn stop_unwind<F: FnOnce() -> T, T>(f: F) -> T {
|
||||
match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) {
|
||||
Ok(t) => t,
|
||||
Err(err) => {
|
||||
eprintln!("attempt to unwind out of `rust` with err: {:?}", err);
|
||||
std::process::abort()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
fn _start_app() {
|
||||
stop_unwind(|| main().unwrap());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[inline(never)]
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
pub extern "C" fn start_app() {
|
||||
#[cfg(target_os = "android")]
|
||||
android_binding!(com_example, mobile_demo, _start_app);
|
||||
#[cfg(target_os = "ios")]
|
||||
_start_app()
|
||||
}
|
||||
|
||||
pub fn main() -> Result<()> {
|
||||
init_logging();
|
||||
|
||||
// Right now we're going through dioxus-desktop but we'd like to go through dioxus-mobile
|
||||
// That will seed the index.html with some fixes that prevent the page from scrolling/zooming etc
|
||||
dioxus_desktop::launch_cfg(
|
||||
app,
|
||||
// Note that we have to disable the viewport goofiness of the browser.
|
||||
// Dioxus_mobile should do this for us
|
||||
Config::default().with_custom_index(include_str!("index.html").to_string()),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn app(cx: Scope) -> Element {
|
||||
let items = cx.use_hook(|| vec![1, 2, 3]);
|
||||
|
||||
log::debug!("Hello from the app");
|
||||
|
||||
render! {
|
||||
div {
|
||||
h1 { "Hello, Mobile"}
|
||||
div { margin_left: "auto", margin_right: "auto", width: "200px", padding: "10px", border: "1px solid black",
|
||||
button {
|
||||
onclick: move|_| {
|
||||
println!("Clicked!");
|
||||
items.push(items.len());
|
||||
cx.needs_update_any(ScopeId(0));
|
||||
println!("Requested update");
|
||||
},
|
||||
"Add item"
|
||||
}
|
||||
for item in items.iter() {
|
||||
div { "- {item}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@ pub(crate) struct ElementRef {
|
|||
pub template: Option<NonNull<VNode<'static>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum ElementPath {
|
||||
Deep(&'static [u8]),
|
||||
Root(usize),
|
||||
|
|
|
@ -21,7 +21,7 @@ serde = "1.0.136"
|
|||
serde_json = "1.0.79"
|
||||
thiserror = "1.0.30"
|
||||
log = { workspace = true }
|
||||
wry = { version = "0.27.2" }
|
||||
wry = { version = "0.28.0" }
|
||||
futures-channel = { workspace = true }
|
||||
tokio = { workspace = true, features = [
|
||||
"sync",
|
||||
|
@ -39,7 +39,8 @@ slab = { workspace = true }
|
|||
futures-util = { workspace = true }
|
||||
urlencoding = "2.1.2"
|
||||
|
||||
[target.'cfg(not(target_os = "ios"))'.dependencies]
|
||||
|
||||
[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]
|
||||
rfd = "0.11.3"
|
||||
|
||||
[target.'cfg(target_os = "ios")'.dependencies]
|
||||
|
|
|
@ -20,6 +20,7 @@ pub(crate) fn check_app_exits(app: Component) {
|
|||
Config::new().with_window(WindowBuilder::new().with_visible(false)),
|
||||
);
|
||||
|
||||
// Stop deadman's switch
|
||||
should_panic.store(false, std::sync::atomic::Ordering::SeqCst);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,12 +13,28 @@ pub(crate) struct FileDialogRequest {
|
|||
pub bubbles: bool,
|
||||
}
|
||||
|
||||
#[cfg(target_os = "ios")]
|
||||
#[cfg(not(any(
|
||||
target_os = "windows",
|
||||
target_os = "macos",
|
||||
target_os = "linux",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
)))]
|
||||
pub(crate) fn get_file_event(_request: &FileDialogRequest) -> Vec<PathBuf> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
#[cfg(any(
|
||||
target_os = "windows",
|
||||
target_os = "macos",
|
||||
target_os = "linux",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
pub(crate) fn get_file_event(request: &FileDialogRequest) -> Vec<PathBuf> {
|
||||
let mut dialog = rfd::FileDialog::new();
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ pub use eval::{use_eval, EvalResult};
|
|||
use futures_util::{pin_mut, FutureExt};
|
||||
use shortcut::ShortcutRegistry;
|
||||
pub use shortcut::{use_global_shortcut, ShortcutHandle, ShortcutId, ShortcutRegistryError};
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use std::task::Waker;
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
@ -156,18 +157,10 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
|
|||
|
||||
let shortcut_manager = ShortcutRegistry::new(&event_loop);
|
||||
|
||||
let web_view = create_new_window(
|
||||
cfg,
|
||||
&event_loop,
|
||||
&proxy,
|
||||
VirtualDom::new_with_props(root, props),
|
||||
&queue,
|
||||
&event_handlers,
|
||||
shortcut_manager.clone(),
|
||||
);
|
||||
|
||||
// By default, we'll create a new window when the app starts
|
||||
queue.borrow_mut().push(web_view);
|
||||
// move the props into a cell so we can pop it out later to create the first window
|
||||
// iOS panics if we create a window before the event loop is started
|
||||
let props = Rc::new(Cell::new(Some(props)));
|
||||
let cfg = Rc::new(Cell::new(Some(cfg)));
|
||||
|
||||
event_loop.run(move |window_event, event_loop, control_flow| {
|
||||
*control_flow = ControlFlow::Wait;
|
||||
|
@ -210,8 +203,27 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
|
|||
_ => {}
|
||||
},
|
||||
|
||||
Event::NewEvents(StartCause::Init)
|
||||
| Event::UserEvent(UserWindowEvent(EventData::NewWindow, _)) => {
|
||||
Event::NewEvents(StartCause::Init) => {
|
||||
//
|
||||
let props = props.take().unwrap();
|
||||
let cfg = cfg.take().unwrap();
|
||||
|
||||
let handler = create_new_window(
|
||||
cfg,
|
||||
event_loop,
|
||||
&proxy,
|
||||
VirtualDom::new_with_props(root, props),
|
||||
&queue,
|
||||
&event_handlers,
|
||||
shortcut_manager.clone(),
|
||||
);
|
||||
|
||||
let id = handler.desktop_context.webview.window().id();
|
||||
webviews.insert(id, handler);
|
||||
_ = proxy.send_event(UserWindowEvent(EventData::Poll, id));
|
||||
}
|
||||
|
||||
Event::UserEvent(UserWindowEvent(EventData::NewWindow, _)) => {
|
||||
for handler in queue.borrow_mut().drain(..) {
|
||||
let id = handler.desktop_context.webview.window().id();
|
||||
webviews.insert(id, handler);
|
||||
|
|
|
@ -113,7 +113,15 @@ impl ShortcutRegistry {
|
|||
callbacks.remove(id.number);
|
||||
if callbacks.is_empty() {
|
||||
if let Some(_shortcut) = shortcuts.remove(&id.id) {
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
#[cfg(any(
|
||||
target_os = "windows",
|
||||
target_os = "macos",
|
||||
target_os = "linux",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
let _ = self.manager.borrow_mut().unregister(_shortcut.shortcut);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ dioxus-rsx = { workspace = true }
|
|||
dioxus-core = { workspace = true, features = ["serialize"] }
|
||||
dioxus-html = { workspace = true, features = ["hot-reload-context"] }
|
||||
|
||||
interprocess-docfix = { version = "1.2.1" }
|
||||
interprocess-docfix = { version = "1.2.2" }
|
||||
notify = "5.0.0"
|
||||
chrono = { version = "0.4.24", default-features = false, features = ["clock"] }
|
||||
serde_json = "1.0.91"
|
||||
|
|
|
@ -53,6 +53,7 @@ struct AppProps {
|
|||
count: i32,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn app(cx: Scope<AppProps>) -> Element {
|
||||
let mut count = use_state(cx, || cx.props.count);
|
||||
let text = use_state(cx, || "...".to_string());
|
||||
|
|
Loading…
Reference in a new issue