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

Fix: always-on-top setting #3347

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 packages/cli/src/cli/autoformat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl Autoformat {
..Default::default()
};
let dx_crate =
DioxusCrate::new(&target_args).context("failed to parse crate graph")?;
DioxusCrate::new(&target_args, None).context("failed to parse crate graph")?;

Cow::Owned(dx_crate.crate_dir())
} else {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/cli/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl BuildArgs {
tracing::info!("Building project...");

let krate =
DioxusCrate::new(&self.target_args).context("Failed to load Dioxus workspace")?;
DioxusCrate::new(&self.target_args, None).context("Failed to load Dioxus workspace")?;

self.resolve(&krate).await?;

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/cli/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl Bundle {
pub(crate) async fn bundle(mut self) -> Result<StructuredOutput> {
tracing::info!("Bundling project...");

let krate = DioxusCrate::new(&self.build_arguments.target_args)
let krate = DioxusCrate::new(&self.build_arguments.target_args, None)
.context("Failed to load Dioxus workspace")?;

// We always use `release` mode for bundling
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/cli/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl Check {
match self.file {
// Default to checking the project
None => {
let dioxus_crate = DioxusCrate::new(&self.target_args)?;
let dioxus_crate = DioxusCrate::new(&self.target_args, None)?;
check_project_and_report(dioxus_crate)
.await
.context("error checking project")?;
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/cli/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl Config {
Config::FormatPrint {} => {
tracing::info!(
"{:#?}",
crate::dioxus_crate::DioxusCrate::new(&TargetArgs::default())?.config
crate::dioxus_crate::DioxusCrate::new(&TargetArgs::default(), None)?.config
);
}
Config::CustomHtml {} => {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/cli/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub(crate) struct RunArgs {

impl RunArgs {
pub(crate) async fn run(mut self) -> Result<StructuredOutput> {
let krate = DioxusCrate::new(&self.build_args.target_args)
let krate = DioxusCrate::new(&self.build_args.target_args, None)
.context("Failed to load Dioxus workspace")?;

self.build_args.resolve(&krate).await?;
Expand Down
51 changes: 16 additions & 35 deletions packages/cli/src/cli/serve.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::*;
use crate::{AddressArguments, BuildArgs, DioxusCrate, Platform};
use crate::{AddressArguments, BuildArgs, CliSettings, DioxusCrate, Platform};

/// Serve the project
#[derive(Clone, Debug, Default, Parser)]
Expand All @@ -10,16 +10,16 @@ pub(crate) struct ServeArgs {
pub(crate) address: AddressArguments,

/// 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(crate) open: Option<bool>,
#[arg(long, num_args=0..=1)]
open: Option<bool>,

/// Enable full hot reloading for the app [default: true - unless cli settings are set]
#[clap(long, group = "release-incompatible")]
pub(crate) hot_reload: Option<bool>,
hot_reload: Option<bool>,

/// Configure always-on-top for desktop apps [default: true - unless cli settings are set]
#[clap(long, default_missing_value = "true")]
pub(crate) always_on_top: Option<bool>,
#[clap(long)]
always_on_top: Option<bool>,

/// Set cross-origin-policy to same-origin [default: false]
#[clap(name = "cross-origin-policy")]
Expand All @@ -31,8 +31,8 @@ pub(crate) struct ServeArgs {
pub(crate) args: Vec<String>,

/// Sets the interval in seconds that the CLI will poll for file changes on WSL.
#[clap(long, default_missing_value = "2")]
pub(crate) wsl_file_poll_interval: Option<u16>,
#[clap(long)]
wsl_file_poll_interval: Option<u16>,

/// Run the server in interactive mode
#[arg(long, default_missing_value="true", num_args=0..=1, short = 'i')]
Expand All @@ -55,42 +55,23 @@ impl ServeArgs {
}

pub(crate) async fn load_krate(&mut self) -> Result<DioxusCrate> {
let krate = DioxusCrate::new(&self.build_arguments.target_args)?;
let override_settings = CliSettings {
always_hot_reload: self.hot_reload,
always_open_browser: self.open,
always_on_top: self.always_on_top,
wsl_file_poll_interval: self.wsl_file_poll_interval,
};

let krate = DioxusCrate::new(&self.build_arguments.target_args, Some(override_settings))?;
self.resolve(&krate).await?;
Ok(krate)
}

pub(crate) async fn resolve(&mut self, krate: &DioxusCrate) -> Result<()> {
// Enable hot reload.
if self.hot_reload.is_none() {
self.hot_reload = Some(krate.settings.always_hot_reload.unwrap_or(true));
}

// Open browser.
if self.open.is_none() {
self.open = Some(krate.settings.always_open_browser.unwrap_or_default());
}

// Set WSL file poll interval.
if self.wsl_file_poll_interval.is_none() {
self.wsl_file_poll_interval = Some(krate.settings.wsl_file_poll_interval.unwrap_or(2));
}

// Set always-on-top for desktop.
if self.always_on_top.is_none() {
self.always_on_top = Some(krate.settings.always_on_top.unwrap_or(true))
}

// Resolve the build arguments
self.build_arguments.resolve(krate).await?;

Ok(())
}

pub(crate) fn should_hotreload(&self) -> bool {
self.hot_reload.unwrap_or(true)
}

pub(crate) fn build_args(&self) -> BuildArgs {
self.build_arguments.clone()
}
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/dioxus_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub(crate) static PROFILE_ANDROID: &str = "android-dev";
pub(crate) static PROFILE_SERVER: &str = "server-dev";

impl DioxusCrate {
pub(crate) fn new(target: &TargetArgs) -> Result<Self> {
pub(crate) fn new(target: &TargetArgs, settings_override: Option<CliSettings>) -> Result<Self> {
tracing::debug!("Loading crate");
let cmd = Cmd::new();
let builder = krates::Builder::new();
Expand Down Expand Up @@ -61,7 +61,7 @@ impl DioxusCrate {
.with_context(|| format!("Failed to find target {target_name}"))?
.clone();

let settings = CliSettings::load();
let settings = CliSettings::load(settings_override);

Ok(Self {
krates: Arc::new(krates),
Expand Down
10 changes: 8 additions & 2 deletions packages/cli/src/serve/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,19 @@ impl AppHandle {
tracing::debug!("Proxying fullstack server from port {:?}", addr);
}

let krate = &self.app.build.krate;

// Set the env vars that the clients will expect
// These need to be stable within a release version (ie 0.6.0)
let mut envs = vec![
(dioxus_cli_config::CLI_ENABLED_ENV, "true".to_string()),
(
dioxus_cli_config::ALWAYS_ON_TOP_ENV,
krate.settings.get_always_on_top().to_string(),
),
(
dioxus_cli_config::APP_TITLE_ENV,
self.app.build.krate.config.web.app.title.clone(),
krate.config.web.app.title.clone(),
),
("RUST_BACKTRACE", "1".to_string()),
(
Expand All @@ -85,7 +91,7 @@ impl AppHandle {
("CARGO_MANIFEST_DIR", "".to_string()),
];

if let Some(base_path) = &self.app.build.krate.config.web.app.base_path {
if let Some(base_path) = &krate.config.web.app.base_path {
envs.push((dioxus_cli_config::ASSET_ROOT_ENV, base_path.clone()));
}

Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/serve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub(crate) async fn serve_all(mut args: ServeArgs) -> Result<()> {
// Note that starting the builder will queue up a build immediately
let mut builder = Builder::start(&krate, args.build_args())?;
let mut devserver = WebServer::start(&krate, &args)?;
let mut watcher = Watcher::start(&krate, &args);
let mut watcher = Watcher::start(&krate);
let mut runner = AppRunner::start(&krate);
let mut screen = Output::start(&args)?;

Expand Down Expand Up @@ -82,7 +82,7 @@ pub(crate) async fn serve_all(mut args: ServeArgs) -> Result<()> {

match msg {
ServeUpdate::FilesChanged { files } => {
if files.is_empty() || !args.should_hotreload() {
if files.is_empty() || !krate.settings.should_hot_reload() {
continue;
}

Expand Down Expand Up @@ -171,7 +171,7 @@ pub(crate) async fn serve_all(mut args: ServeArgs) -> Result<()> {
bundle,
devserver.devserver_address(),
devserver.proxied_server_address(),
args.open.unwrap_or(false),
krate.settings.should_open_browser(),
)
.await;

Expand Down
10 changes: 5 additions & 5 deletions packages/cli/src/serve/watcher.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::detect::is_wsl;
use super::update::ServeUpdate;
use crate::{cli::serve::ServeArgs, dioxus_crate::DioxusCrate};
use crate::dioxus_crate::DioxusCrate;
use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
use futures_util::StreamExt;
use ignore::gitignore::Gitignore;
Expand All @@ -23,11 +23,11 @@ pub(crate) struct Watcher {
}

impl Watcher {
pub(crate) fn start(krate: &DioxusCrate, serve: &ServeArgs) -> Self {
pub(crate) fn start(krate: &DioxusCrate) -> Self {
let (tx, rx) = futures_channel::mpsc::unbounded();

let mut watcher = Self {
watcher: create_notify_watcher(serve, tx.clone()),
watcher: create_notify_watcher(krate, tx.clone()),
_tx: tx,
krate: krate.clone(),
rx,
Expand Down Expand Up @@ -140,7 +140,7 @@ fn handle_notify_error(err: notify::Error) {
}

fn create_notify_watcher(
serve: &ServeArgs,
krate: &DioxusCrate,
tx: UnboundedSender<notify::Event>,
) -> Box<dyn NotifyWatcher> {
// Build the event handler for notify.
Expand Down Expand Up @@ -174,7 +174,7 @@ fn create_notify_watcher(
return Box::new(notify::recommended_watcher(handler).expect(NOTIFY_ERROR_MSG));
}

let poll_interval = Duration::from_secs(serve.wsl_file_poll_interval.unwrap_or(2) as u64);
let poll_interval = Duration::from_secs(krate.settings.get_wsl_file_poll_interval() as u64);

Box::new(
notify::PollWatcher::new(handler, Config::default().with_poll_interval(poll_interval))
Expand Down
68 changes: 50 additions & 18 deletions packages/cli/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,50 @@ pub(crate) struct CliSettings {
/// Describes whether desktop apps in development will be pinned always-on-top.
pub(crate) always_on_top: Option<bool>,
/// Describes the interval in seconds that the CLI should poll for file changes on WSL.
#[serde(default = "default_wsl_file_poll_interval")]
pub(crate) wsl_file_poll_interval: Option<u16>,
}

impl CliSettings {
pub(crate) fn should_hot_reload(&self) -> bool {
self.always_hot_reload.unwrap_or(true)
}

pub(crate) fn should_open_browser(&self) -> bool {
self.always_open_browser.unwrap_or(true)
}

pub(crate) fn get_always_on_top(&self) -> bool {
self.always_on_top.unwrap_or(true)
}

pub(crate) fn get_wsl_file_poll_interval(&self) -> u16 {
self.wsl_file_poll_interval.unwrap_or(2)
}

/// Load the settings from the local, global, or default config in that order
pub(crate) fn load() -> Self {
Self::from_global().unwrap_or_default()
pub(crate) fn load(settings_override: Option<Self>) -> Self {
let mut settings = Self::from_global().unwrap_or_default();

// Handle overriding settings from command args.
if let Some(settings_override) = settings_override {
if settings_override.always_hot_reload.is_some() {
settings.always_hot_reload = settings_override.always_hot_reload
}

if settings_override.always_open_browser.is_some() {
settings.always_open_browser = settings_override.always_open_browser;
}

if settings_override.always_on_top.is_some() {
settings.always_on_top = settings_override.always_on_top;
}

if settings_override.wsl_file_poll_interval.is_some() {
settings.wsl_file_poll_interval = settings_override.wsl_file_poll_interval;
}
}

settings
}

/// Get the current settings structure from global.
Expand Down Expand Up @@ -56,9 +92,18 @@ impl CliSettings {
data
}

/// Modify the settings toml file
pub(crate) fn modify_settings(with: impl FnOnce(&mut CliSettings)) -> Result<()> {
let mut settings = Self::load(None);
with(&mut settings);
settings.save()?;

Ok(())
}

/// Save the current structure to the global settings toml.
/// This does not save to project-level settings.
pub(crate) fn save(self) -> Result<Self> {
fn save(self) -> Result<Self> {
let path = Self::get_settings_path().ok_or_else(|| {
error!(dx_src = ?TraceSrc::Dev, "failed to get settings path");
anyhow::anyhow!("failed to get settings path")
Expand Down Expand Up @@ -94,25 +139,12 @@ impl CliSettings {
}

/// Get the path to the settings toml file.
pub(crate) fn get_settings_path() -> Option<PathBuf> {
fn get_settings_path() -> Option<PathBuf> {
let Some(path) = dirs::data_local_dir() else {
warn!("failed to get local data directory, some config keys may be missing");
return None;
};

Some(path.join(GLOBAL_SETTINGS_FILE_NAME))
}

/// Modify the settings toml file
pub(crate) fn modify_settings(with: impl FnOnce(&mut CliSettings)) -> Result<()> {
let mut settings = Self::load();
with(&mut settings);
settings.save()?;

Ok(())
}
}

fn default_wsl_file_poll_interval() -> Option<u16> {
Some(2)
}
Loading