diff --git a/packages/cli-config/src/config.rs b/packages/cli-config/src/config.rs index d3722b973..c67ff4473 100644 --- a/packages/cli-config/src/config.rs +++ b/packages/cli-config/src/config.rs @@ -89,6 +89,9 @@ pub struct DioxusConfig { #[serde(default)] pub web: WebConfig, + #[serde(default)] + pub desktop: DesktopConfig, + #[serde(default)] pub bundle: BundleConfig, } @@ -129,6 +132,7 @@ impl Default for DioxusConfig { pre_compress: true, wasm_opt: Default::default(), }, + desktop: DesktopConfig::default(), bundle: BundleConfig { identifier: Some(format!("io.github.{name}")), publisher: Some(name), @@ -206,6 +210,22 @@ impl Default for WebConfig { } } +/// Represents configuration items for the desktop platform. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DesktopConfig { + /// Describes whether a debug-mode desktop app should be always-on-top. + #[serde(default)] + pub always_on_top: bool, +} + +impl Default for DesktopConfig { + fn default() -> Self { + Self { + always_on_top: true, + } + } +} + /// The wasm-opt configuration #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct WasmOptConfig { diff --git a/packages/cli/src/cli/config.rs b/packages/cli/src/cli/config.rs index 87a0d8a4b..2b62714a5 100644 --- a/packages/cli/src/cli/config.rs +++ b/packages/cli/src/cli/config.rs @@ -30,21 +30,42 @@ pub enum Config { SetGlobal { setting: Setting, value: Value }, } -#[derive(Debug, Clone, Deserialize, clap::ValueEnum)] +#[derive(Debug, Clone, Copy, Deserialize, clap::ValueEnum)] pub enum Setting { /// Set the value of the always-hot-reload setting. AlwaysHotReload, /// Set the value of the always-open-browser setting. AlwaysOpenBrowser, + /// Set the value of the always-on-top desktop setting. + AlwaysOnTop, +} + +impl Display for Setting { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::AlwaysHotReload => write!(f, "always_hot_reload"), + Self::AlwaysOpenBrowser => write!(f, "always_open_browser"), + Self::AlwaysOnTop => write!(f, "always_on_top"), + } + } } // NOTE: Unsure of an alternative to get the desired behavior with clap, if it exists. -#[derive(Debug, Clone, Deserialize, clap::ValueEnum)] +#[derive(Debug, Clone, Copy, Deserialize, clap::ValueEnum)] pub enum Value { True, False, } +impl Display for Value { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::True => write!(f, "true"), + Self::False => write!(f, "false"), + } + } +} + impl From for bool { fn from(value: Value) -> Self { match value { @@ -90,11 +111,14 @@ impl Config { file.write_all(content.as_bytes())?; tracing::info!("🚩 Create custom html file done."); } + // Handle configuration of global CLI settings. Config::SetGlobal { setting, value } => { CliSettings::modify_settings(|settings| match setting { Setting::AlwaysHotReload => settings.always_hot_reload = Some(value.into()), Setting::AlwaysOpenBrowser => settings.always_open_browser = Some(value.into()), + Setting::AlwaysOnTop => settings.always_on_top = Some(value.into()), })?; + tracing::info!("🚩 CLI setting `{setting}` has been set to `{value}`") } } Ok(()) diff --git a/packages/cli/src/cli/serve.rs b/packages/cli/src/cli/serve.rs index 212292c38..5be509d1d 100644 --- a/packages/cli/src/cli/serve.rs +++ b/packages/cli/src/cli/serve.rs @@ -16,14 +16,18 @@ pub struct ServeArguments { #[clap(flatten)] pub address: AddressArguments, - /// Open the app in the default browser [default: false - unless project or global settings are set] + /// Open the app in the default browser [default: true - unless cli settings are set] #[arg(long, default_missing_value="true", num_args=0..=1)] pub open: Option, - /// Enable full hot reloading for the app [default: true - unless project or global settings are set] + /// Enable full hot reloading for the app [default: true - unless cli settings are set] #[clap(long, group = "release-incompatible")] pub hot_reload: Option, + /// Configure always-on-top for desktop apps [default: true - unless cli settings are set] + #[clap(long, default_missing_value = "true")] + pub always_on_top: Option, + /// Set cross-origin-policy to same-origin [default: false] #[clap(name = "cross-origin-policy")] #[clap(long)] @@ -64,6 +68,11 @@ impl Serve { if self.server_arguments.open.is_none() { self.server_arguments.open = Some(settings.always_open_browser.unwrap_or_default()); } + if self.server_arguments.always_on_top.is_none() { + self.server_arguments.always_on_top = Some(settings.always_on_top.unwrap_or(true)) + } + crate_config.dioxus_config.desktop.always_on_top = + self.server_arguments.always_on_top.unwrap_or(true); // Resolve the build arguments self.build_arguments.resolve(crate_config)?; diff --git a/packages/cli/src/settings.rs b/packages/cli/src/settings.rs index fb0310273..af4f19027 100644 --- a/packages/cli/src/settings.rs +++ b/packages/cli/src/settings.rs @@ -23,6 +23,8 @@ pub struct CliSettings { pub always_hot_reload: Option, /// Describes whether the CLI should always open the browser for Web targets. pub always_open_browser: Option, + /// Describes whether desktop apps in development will be pinned always-on-top. + pub always_on_top: Option, } impl CliSettings { diff --git a/packages/desktop/src/config.rs b/packages/desktop/src/config.rs index b80e7cdb4..19f955110 100644 --- a/packages/desktop/src/config.rs +++ b/packages/desktop/src/config.rs @@ -49,15 +49,21 @@ impl Config { /// Initializes a new `WindowBuilder` with default values. #[inline] pub fn new() -> Self { - let window: WindowBuilder = WindowBuilder::new() - .with_title( - dioxus_cli_config::CURRENT_CONFIG - .as_ref() - .map(|c| c.application.name.clone()) - .unwrap_or("Dioxus App".to_string()), - ) - // During development we want the window to be on top so we can see it while we work - .with_always_on_top(cfg!(debug_assertions)); + let dioxus_config = dioxus_cli_config::CURRENT_CONFIG.as_ref(); + + let mut window: WindowBuilder = WindowBuilder::new().with_title( + dioxus_config + .map(|c| c.application.name.clone()) + .unwrap_or("Dioxus App".to_string()), + ); + + // During development we want the window to be on top so we can see it while we work + let always_on_top = dioxus_config + .map(|c| c.desktop.always_on_top) + .unwrap_or(true); + if cfg!(debug_assertions) { + window = window.with_always_on_top(always_on_top); + } Self { window,