diff --git a/espanso/src/cli/daemon/mod.rs b/espanso/src/cli/daemon/mod.rs index 1a7793b..f770583 100644 --- a/espanso/src/cli/daemon/mod.rs +++ b/espanso/src/cli/daemon/mod.rs @@ -35,6 +35,7 @@ use crate::{VERSION, exit_code::{ use super::{CliModule, CliModuleArgs}; mod ipc; +mod ui; mod watcher; pub fn new() -> CliModule { @@ -55,6 +56,8 @@ fn daemon_main(args: CliModuleArgs) -> i32 { let config_store = args .config_store .expect("missing config store in worker main"); + let preferences = crate::preferences::get_default(&paths.runtime).expect("unable to obtain preferences"); + let cli_args = args.cli_args.expect("missing cli_args in daemon main"); // Make sure only one instance of the daemon is running let lock_file = acquire_daemon_lock(&paths.runtime); @@ -95,6 +98,10 @@ fn daemon_main(args: CliModuleArgs) -> i32 { .expect("unable to initialize config watcher thread"); } + if cli_args.is_present("show-welcome") { + ui::show_welcome_screen(&preferences); + } + loop { select! { recv(watcher_signal) -> _ => { diff --git a/espanso/src/cli/daemon/ui.rs b/espanso/src/cli/daemon/ui.rs new file mode 100644 index 0000000..9d0ff5a --- /dev/null +++ b/espanso/src/cli/daemon/ui.rs @@ -0,0 +1,36 @@ +/* + * This file is part of espanso. + * + * Copyright (C) 2019-2021 Federico Terzi + * + * espanso is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * espanso is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with espanso. If not, see . + */ + +use crate::preferences::Preferences; + +#[cfg(feature = "modulo")] +pub fn show_welcome_screen(preferences: &impl Preferences) { + if preferences.should_display_welcome() { + let espanso_exe_path = std::env::current_exe().expect("unable to determine executable path"); + let mut command = std::process::Command::new(&espanso_exe_path.to_string_lossy().to_string()); + command.args(&["modulo", "welcome"]); + + command.spawn().expect("unable to show welcome screen"); + } +} + +#[cfg(not(feature = "modulo"))] +pub fn show_welcome_screen(_: &impl Preferences) { + // NOOP +} \ No newline at end of file diff --git a/espanso/src/cli/modulo/mod.rs b/espanso/src/cli/modulo/mod.rs index 4b444c7..753b2ba 100644 --- a/espanso/src/cli/modulo/mod.rs +++ b/espanso/src/cli/modulo/mod.rs @@ -23,6 +23,8 @@ use super::{CliModule, CliModuleArgs}; mod form; #[cfg(feature = "modulo")] mod search; +#[cfg(feature = "modulo")] +mod welcome; pub fn new() -> CliModule { #[allow(clippy::needless_update)] @@ -49,6 +51,10 @@ fn modulo_main(args: CliModuleArgs) -> i32 { return search::search_main(matches, &icon_paths); } + if let Some(_) = cli_args.subcommand_matches("welcome") { + return welcome::welcome_main(&paths, &icon_paths); + } + 0 } diff --git a/espanso/src/cli/modulo/welcome.rs b/espanso/src/cli/modulo/welcome.rs new file mode 100644 index 0000000..e559ec4 --- /dev/null +++ b/espanso/src/cli/modulo/welcome.rs @@ -0,0 +1,48 @@ +/* + * This file is part of espanso. + * + * Copyright (C) 2019-2021 Federico Terzi + * + * espanso is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * espanso is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with espanso. If not, see . + */ + +use crate::icon::IconPaths; +use crate::preferences::Preferences; +use espanso_modulo::welcome::*; +use espanso_path::Paths; + +pub fn welcome_main(paths: &Paths, icon_paths: &IconPaths) -> i32 { + let preferences = + crate::preferences::get_default(&paths.runtime).expect("unable to initialize preferences"); + + let dont_show_again_handler = Box::new(move |dont_show: bool| { + preferences.set_should_display_welcome(!dont_show); + }); + + espanso_modulo::welcome::show(WelcomeOptions{ + window_icon_path: icon_paths + .wizard_icon + .as_ref() + .map(|path| path.to_string_lossy().to_string()), + tray_image_path: icon_paths + .tray_explain_image + .as_ref() + .map(|path| path.to_string_lossy().to_string()), + handlers: WelcomeHandlers { + dont_show_again_changed: Some(dont_show_again_handler), + }, + }); + + 0 +} diff --git a/espanso/src/icon.rs b/espanso/src/icon.rs index 8ae39e5..3ba5e9f 100644 --- a/espanso/src/icon.rs +++ b/espanso/src/icon.rs @@ -30,6 +30,8 @@ const WINDOWS_NORMAL_DARK_ICO_BINARY: &[u8] = include_bytes!("res/windows/normal const WINDOWS_DISABLED_DARK_ICO_BINARY: &[u8] = include_bytes!("res/windows/disabled_dark.ico"); #[cfg(target_os = "windows")] const WINDOWS_LOGO_ICO_BINARY: &[u8] = include_bytes!("res/windows/logo.ico"); +#[cfg(target_os = "windows")] +const WINDOWS_TRAY_EXPLAIN_IMAGE: &[u8] = include_bytes!("res/windows/tray_explain_image.png"); #[cfg(target_os = "macos")] @@ -55,6 +57,7 @@ pub struct IconPaths { pub accessibility_image_1: Option, pub accessibility_image_2: Option, + pub tray_explain_image: Option, pub logo: Option, pub logo_no_background: Option, @@ -70,6 +73,7 @@ pub fn load_icon_paths(runtime_dir: &Path) -> Result { tray_icon_disabled: Some(extract_icon(WINDOWS_DISABLED_DARK_ICO_BINARY, &runtime_dir.join("disabled.ico"))?), logo: Some(extract_icon(ICON_BINARY, &runtime_dir.join("icon.png"))?), logo_no_background: Some(extract_icon(LOGO_NO_BACKGROUND_BINARY, &runtime_dir.join("icon_no_background.png"))?), + tray_explain_image: Some(extract_icon(WINDOWS_TRAY_EXPLAIN_IMAGE, &runtime_dir.join("tray_explain_image.png"))?), ..Default::default() }) } diff --git a/espanso/src/main.rs b/espanso/src/main.rs index 4269b7e..7f8f1eb 100644 --- a/espanso/src/main.rs +++ b/espanso/src/main.rs @@ -163,6 +163,12 @@ fn main() { .subcommand( SubCommand::with_name("daemon") .setting(AppSettings::Hidden) + .arg( + Arg::with_name("show-welcome") + .long("show-welcome") + .required(false) + .takes_value(false) + ) .about("Start the daemon without spawning a new process."), ) // .subcommand(SubCommand::with_name("register") @@ -207,6 +213,10 @@ fn main() { .takes_value(false) .help("Interpret the input data as JSON"), ), + ) + .subcommand( + SubCommand::with_name("welcome") + .about("Display the welcome screen") ), ) // .subcommand(SubCommand::with_name("start") diff --git a/espanso/src/preferences/default.rs b/espanso/src/preferences/default.rs index f58da01..03caf6e 100644 --- a/espanso/src/preferences/default.rs +++ b/espanso/src/preferences/default.rs @@ -19,13 +19,13 @@ use espanso_kvs::KVS; use serde::{de::DeserializeOwned, Serialize}; -use std::path::Path; use anyhow::Result; use super::Preferences; const HAS_COMPLETED_WIZARD_KEY: &str = "has_completed_wizard"; +const SHOULD_DISPLAY_WELCOME_KEY: &str = "should_display_welcome"; #[derive(Clone)] pub struct DefaultPreferences { @@ -33,7 +33,7 @@ pub struct DefaultPreferences { } impl DefaultPreferences { - pub fn new(runtime_dir: &Path, kvs: KVSType) -> Result { + pub fn new(kvs: KVSType) -> Result { Ok(Self { kvs }) } @@ -61,4 +61,12 @@ impl Preferences for DefaultPreferences { fn set_completed_wizard(&self, value: bool) { self.set(HAS_COMPLETED_WIZARD_KEY, value); } + + fn should_display_welcome(&self) -> bool { + self.get(SHOULD_DISPLAY_WELCOME_KEY).unwrap_or(true) + } + + fn set_should_display_welcome(&self, value: bool) { + self.set(SHOULD_DISPLAY_WELCOME_KEY, value); + } } diff --git a/espanso/src/preferences/mod.rs b/espanso/src/preferences/mod.rs index bc86a1b..ca19f89 100644 --- a/espanso/src/preferences/mod.rs +++ b/espanso/src/preferences/mod.rs @@ -25,9 +25,12 @@ mod default; pub trait Preferences: Send + Sync + Clone { fn has_completed_wizard(&self) -> bool; fn set_completed_wizard(&self, value: bool); + + fn should_display_welcome(&self) -> bool; + fn set_should_display_welcome(&self, value: bool); } pub fn get_default(runtime_dir: &Path) -> Result { let kvs = espanso_kvs::get_persistent(runtime_dir)?; - default::DefaultPreferences::new(runtime_dir, kvs) + default::DefaultPreferences::new(kvs) } \ No newline at end of file diff --git a/espanso/src/res/windows/tray_explain_image.png b/espanso/src/res/windows/tray_explain_image.png new file mode 100644 index 0000000..1750b99 Binary files /dev/null and b/espanso/src/res/windows/tray_explain_image.png differ