Skip to content

Commit

Permalink
pass configs through to android mobile launch
Browse files Browse the repository at this point in the history
  • Loading branch information
jkelleyrtp committed Jan 18, 2025
1 parent 7718f0a commit d6d2a27
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 36 deletions.
19 changes: 5 additions & 14 deletions packages/cli/src/config/serve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,18 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4};
pub(crate) struct AddressArguments {
/// The port the server will run on
#[clap(long)]
#[clap(default_value_t = default_port())]
pub(crate) port: u16,
pub(crate) port: Option<u16>,

/// The address the server will run on
#[clap(long, default_value_t = default_address())]
pub(crate) addr: std::net::IpAddr,
#[clap(long)]
pub(crate) addr: Option<std::net::IpAddr>,
}

impl Default for AddressArguments {
fn default() -> Self {
Self {
port: default_port(),
addr: default_address(),
port: None,
addr: None,
}
}
}

fn default_port() -> u16 {
8080
}

fn default_address() -> IpAddr {
IpAddr::V4(std::net::Ipv4Addr::new(0, 0, 0, 0))
}
6 changes: 2 additions & 4 deletions packages/cli/src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::{serve::ServeUpdate, Cli, Commands, Platform as TargetPlatform, Verbo
use cargo_metadata::{diagnostic::DiagnosticLevel, CompilerMessage};
use clap::Parser;
use futures_channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender};
use once_cell::sync::{Lazy, OnceCell};
use once_cell::sync::OnceCell;
use std::{
collections::HashMap,
env,
Expand All @@ -27,7 +27,7 @@ use std::{
path::PathBuf,
sync::{
atomic::{AtomicBool, Ordering},
Arc, Mutex,
Mutex,
},
time::Instant,
};
Expand All @@ -46,8 +46,6 @@ const LOG_ENV: &str = "DIOXUS_LOG";
const LOG_FILE_NAME: &str = "dx.log";
const DX_SRC_FLAG: &str = "dx_src";

pub static TUI_INTERACTIVE_DISABLED: Lazy<Arc<AtomicBool>> =
Lazy::new(|| Arc::new(AtomicBool::new(false)));
static TUI_ACTIVE: AtomicBool = AtomicBool::new(false);
static TUI_TX: OnceCell<UnboundedSender<TraceMsg>> = OnceCell::new();
pub static VERBOSITY: OnceCell<Verbosity> = OnceCell::new();
Expand Down
29 changes: 23 additions & 6 deletions packages/cli/src/serve/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,19 +71,28 @@ impl WebServer {
let (hot_reload_sockets_tx, hot_reload_sockets_rx) = futures_channel::mpsc::unbounded();
let (build_status_sockets_tx, build_status_sockets_rx) = futures_channel::mpsc::unbounded();

let devserver_bind_ip = args.address.addr;
let devserver_port = args.address.port;
let devserver_bind_address = SocketAddr::new(devserver_bind_ip, devserver_port);
const SELF_IP: IpAddr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));

// Use 0.0.0.0 as the default address if none is specified - this will let us expose the
// devserver to the network (for other devices like phones/embedded)
let devserver_bind_ip = args.address.addr.unwrap_or_else(|| SELF_IP);

// If the user specified a port, use that, otherwise use any available port, preferring 8080
let devserver_port = args
.address
.port
.unwrap_or_else(|| get_available_port(devserver_bind_ip, Some(8080)).unwrap_or(8080));

// All servers will end up behind us (the devserver) but on a different port
// This is so we can serve a loading screen as well as devtools without anything particularly fancy
let proxied_port = args
.should_proxy_build()
.then(|| get_available_port(devserver_bind_ip))
.then(|| get_available_port(devserver_bind_ip, None))
.flatten();

// Create the listener that we'll pass into the devserver, but save its IP here so
// we can display it to the user in the tui
let devserver_bind_address = SocketAddr::new(devserver_bind_ip, devserver_port);
let listener = std::net::TcpListener::bind(devserver_bind_address).with_context(|| {
anyhow::anyhow!(
"Failed to bind server to: {devserver_bind_address}, is there another devserver running?\nTo run multiple devservers, use the --port flag to specify a different port"
Expand All @@ -92,7 +101,7 @@ impl WebServer {

// If the IP is 0.0.0.0, we need to get the actual IP of the machine
// This will let ios/android/network clients connect to the devserver
let devserver_exposed_ip = if devserver_bind_ip == IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)) {
let devserver_exposed_ip = if devserver_bind_ip == SELF_IP {
local_ip_address::local_ip().unwrap_or(devserver_bind_ip)
} else {
devserver_bind_ip
Expand Down Expand Up @@ -626,7 +635,15 @@ async fn get_rustls(web_config: &WebHttpsConfig) -> Result<(String, String)> {
///
/// Todo: we might want to do this on every new build in case the OS tries to bind things to this port
/// and we don't already have something bound to it. There's no great way of "reserving" a port.
fn get_available_port(address: IpAddr) -> Option<u16> {
fn get_available_port(address: IpAddr, prefer: Option<u16>) -> Option<u16> {
// First, try to bind to the preferred port
if let Some(port) = prefer {
if let Ok(_listener) = TcpListener::bind((address, port)) {
return Some(port);
}
}

// Otherwise, try to bind to any port and return the first one we can
TcpListener::bind((address, 0))
.map(|listener| listener.local_addr().unwrap().port())
.ok()
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ pub(crate) fn to_java_load_asset(filepath: &str) -> Option<Vec<u8>> {
}
}

use std::{io::Read, ptr::NonNull};
use std::ptr::NonNull;

let ctx = ndk_context::android_context();
let vm = unsafe { jni::JavaVM::from_raw(ctx.vm().cast()) }.unwrap();
Expand Down
2 changes: 1 addition & 1 deletion packages/dioxus/src/launch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl LaunchBuilder {
#[cfg_attr(docsrs, doc(cfg(feature = "mobile")))]
pub fn mobile() -> LaunchBuilder {
LaunchBuilder {
launch_fn: |root, contexts, cfg| dioxus_mobile::launch::launch(root, contexts, cfg),
launch_fn: |root, contexts, cfg| dioxus_mobile::launch_cfg(root, contexts, cfg),
contexts: Vec::new(),
configs: Vec::new(),
}
Expand Down
49 changes: 39 additions & 10 deletions packages/mobile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@

pub use dioxus_desktop::*;
use dioxus_lib::prelude::*;
use std::any::Any;
use std::sync::Mutex;

pub mod launch_bindings {
use std::any::Any;

use super::*;
pub fn launch(
root: fn() -> Element,
_contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
_platform_config: Vec<Box<dyn Any>>,
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
platform_config: Vec<Box<dyn Any>>,
) {
super::launch(root);
super::launch_cfg(root, contexts, platform_config);
}

pub fn launch_virtual_dom(_virtual_dom: VirtualDom, _desktop_config: Config) -> ! {
Expand All @@ -24,27 +24,56 @@ pub mod launch_bindings {
}

/// Launch via the binding API
pub fn launch(incoming: fn() -> Element) {
pub fn launch(root: fn() -> Element) {
launch_cfg(root, vec![], vec![]);
}

pub fn launch_cfg(
root: fn() -> Element,
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
platform_config: Vec<Box<dyn Any>>,
) {
#[cfg(target_os = "android")]
{
*APP_FN_PTR.lock().unwrap() = Some(incoming);
*APP_OBJECTS.lock().unwrap() = Some(BoundLaunchObjects {
root,
contexts,
platform_config,
});
}

#[cfg(not(target_os = "android"))]
{
dioxus_desktop::launch::launch(incoming, vec![], Default::default());
dioxus_desktop::launch::launch(root, contexts, platform_config);
}
}

static APP_FN_PTR: Mutex<Option<fn() -> Element>> = Mutex::new(None);
static APP_OBJECTS: Mutex<Option<BoundLaunchObjects>> = Mutex::new(None);

struct BoundLaunchObjects {
root: fn() -> Element,
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
platform_config: Vec<Box<dyn Any>>,
}

unsafe impl Send for BoundLaunchObjects {}
unsafe impl Sync for BoundLaunchObjects {}

#[doc(hidden)]
pub fn root() {
let app = APP_FN_PTR
let app = APP_OBJECTS
.lock()
.expect("APP_FN_PTR lock failed")
.take()
.expect("Android to have set the app trampoline");

dioxus_desktop::launch::launch(app, vec![], Default::default());
let BoundLaunchObjects {
root,
contexts,
platform_config,
} = app;

dioxus_desktop::launch::launch(root, contexts, platform_config);
}

/// Expose the `Java_dev_dioxus_main_WryActivity_create` function to the JNI layer.
Expand Down

0 comments on commit d6d2a27

Please sign in to comment.