feat(core): implement runtime Preferences module
This commit is contained in:
parent
cfe44fd861
commit
8fb3826298
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -427,6 +427,7 @@ dependencies = [
|
|||
"espanso-info",
|
||||
"espanso-inject",
|
||||
"espanso-ipc",
|
||||
"espanso-kvs",
|
||||
"espanso-mac-utils",
|
||||
"espanso-match",
|
||||
"espanso-migrate",
|
||||
|
@ -549,6 +550,18 @@ dependencies = [
|
|||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "espanso-kvs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempdir",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "espanso-mac-utils"
|
||||
version = "0.1.0"
|
||||
|
|
|
@ -15,4 +15,5 @@ members = [
|
|||
"espanso-modulo",
|
||||
"espanso-migrate",
|
||||
"espanso-mac-utils",
|
||||
"espanso-kvs",
|
||||
]
|
|
@ -34,8 +34,8 @@ dependencies=["create-bundle"]
|
|||
|
||||
[tasks.test]
|
||||
command = "cargo"
|
||||
args = ["test", "--workspace", "--exclude", "espanso-modulo", "--no-default-features"]
|
||||
args = ["test", "--workspace", "--exclude", "espanso-modulo", "--exclude", "espanso-ipc", "--no-default-features"]
|
||||
|
||||
[tasks.test-output]
|
||||
command = "cargo"
|
||||
args = ["test", "--workspace", "--exclude", "espanso-modulo", "--no-default-features", "--", "--nocapture"]
|
||||
args = ["test", "--workspace", "--exclude", "espanso-modulo", "--exclude", "espanso-ipc", "--no-default-features", "--", "--nocapture"]
|
|
@ -32,6 +32,7 @@ espanso-path = { path = "../espanso-path" }
|
|||
espanso-ipc = { path = "../espanso-ipc" }
|
||||
espanso-modulo = { path = "../espanso-modulo", optional = true }
|
||||
espanso-migrate = { path = "../espanso-migrate" }
|
||||
espanso-kvs = { path = "../espanso-kvs" }
|
||||
maplit = "1.0.2"
|
||||
simplelog = "0.9.0"
|
||||
log = "0.4.14"
|
||||
|
|
|
@ -17,9 +17,8 @@
|
|||
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use espanso_modulo::wizard::{MigrationResult, WizardHandlers, WizardOptions};
|
||||
|
||||
use self::util::MigrationError;
|
||||
use crate::preferences::Preferences;
|
||||
|
||||
use super::{CliModule, CliModuleArgs};
|
||||
|
||||
|
@ -41,10 +40,19 @@ pub fn new() -> CliModule {
|
|||
|
||||
#[cfg(feature = "modulo")]
|
||||
fn launcher_main(args: CliModuleArgs) -> i32 {
|
||||
use espanso_modulo::wizard::{MigrationResult, WizardHandlers, WizardOptions};
|
||||
|
||||
// TODO: should we create a non-gui wizard? We can also use it for the non-modulo versions of espanso
|
||||
|
||||
let paths = args.paths.expect("missing paths in launcher main");
|
||||
let icon_paths = crate::icon::load_icon_paths(&paths.runtime).expect("unable to load icon paths");
|
||||
|
||||
// TODO: should move wizard to "init" subcommand?
|
||||
let preferences =
|
||||
crate::preferences::get_default(&paths.runtime).expect("unable to initialize preferences");
|
||||
|
||||
let is_welcome_page_enabled = !preferences.has_completed_wizard();
|
||||
|
||||
let is_move_bundle_page_enabled = false; // TODO
|
||||
|
||||
let is_legacy_version_page_enabled = util::is_legacy_version_running(&paths.runtime);
|
||||
let runtime_dir_clone = paths.runtime.clone();
|
||||
|
@ -55,26 +63,20 @@ fn launcher_main(args: CliModuleArgs) -> i32 {
|
|||
let paths_clone = paths.clone();
|
||||
let backup_and_migrate_handler =
|
||||
Box::new(move || match util::migrate_configuration(&paths_clone) {
|
||||
Ok(_) => {
|
||||
MigrationResult::Success
|
||||
}
|
||||
Err(error) => {
|
||||
match error.downcast_ref::<MigrationError>() {
|
||||
Some(MigrationError::DirtyError) => {
|
||||
MigrationResult::DirtyFailure
|
||||
}
|
||||
Some(MigrationError::CleanError) => {
|
||||
MigrationResult::CleanFailure
|
||||
}
|
||||
_ => {
|
||||
MigrationResult::UnknownFailure
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(_) => MigrationResult::Success,
|
||||
Err(error) => match error.downcast_ref::<MigrationError>() {
|
||||
Some(MigrationError::DirtyError) => MigrationResult::DirtyFailure,
|
||||
Some(MigrationError::CleanError) => MigrationResult::CleanFailure,
|
||||
_ => MigrationResult::UnknownFailure,
|
||||
},
|
||||
});
|
||||
|
||||
// TODO: enable "Add to PATH" page only when NOT in portable mode
|
||||
// TODO: if the user clicks on "Continue" after unchecking the "ADD to PATH"
|
||||
// checkbox, we should remember (with the kvs) the choice and avoid asking again.
|
||||
let is_add_path_page_enabled = if cfg!(target_os = "macos") {
|
||||
// TODO: add actual check
|
||||
// TODO: consider also Windows case
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
@ -87,39 +89,46 @@ fn launcher_main(args: CliModuleArgs) -> i32 {
|
|||
false
|
||||
};
|
||||
|
||||
// TODO: show welcome page only the first time (we need a persistent key-value store)
|
||||
// TODO: show a "espanso is now running page at the end" (it should be triggered everytime
|
||||
// espanso is started, unless the user unchecks "show this message at startup")
|
||||
// This page could also be used when the user starts espanso, but an instance is already running.
|
||||
|
||||
espanso_modulo::wizard::show(WizardOptions {
|
||||
version: crate::VERSION.to_string(),
|
||||
is_welcome_page_enabled: true, // TODO
|
||||
is_move_bundle_page_enabled: false, // TODO
|
||||
is_legacy_version_page_enabled,
|
||||
is_migrate_page_enabled,
|
||||
is_add_path_page_enabled,
|
||||
is_accessibility_page_enabled,
|
||||
window_icon_path: icon_paths
|
||||
.wizard_icon
|
||||
.map(|path| path.to_string_lossy().to_string()),
|
||||
welcome_image_path: icon_paths
|
||||
.logo_no_background
|
||||
.map(|path| path.to_string_lossy().to_string()),
|
||||
accessibility_image_1_path: None, // TODO
|
||||
accessibility_image_2_path: None, // TODO
|
||||
handlers: WizardHandlers {
|
||||
is_legacy_version_running: Some(is_legacy_version_running_handler),
|
||||
backup_and_migrate: Some(backup_and_migrate_handler),
|
||||
add_to_path: None, // TODO
|
||||
enable_accessibility: None, // TODO
|
||||
is_accessibility_enabled: None, // TODO
|
||||
},
|
||||
});
|
||||
// Only show the wizard if a panel should be displayed
|
||||
if is_welcome_page_enabled
|
||||
|| is_move_bundle_page_enabled
|
||||
|| is_legacy_version_page_enabled
|
||||
|| is_migrate_page_enabled
|
||||
|| is_add_path_page_enabled
|
||||
|| is_accessibility_page_enabled
|
||||
{
|
||||
espanso_modulo::wizard::show(WizardOptions {
|
||||
version: crate::VERSION.to_string(),
|
||||
is_welcome_page_enabled,
|
||||
is_move_bundle_page_enabled,
|
||||
is_legacy_version_page_enabled,
|
||||
is_migrate_page_enabled,
|
||||
is_add_path_page_enabled,
|
||||
is_accessibility_page_enabled,
|
||||
window_icon_path: icon_paths
|
||||
.wizard_icon
|
||||
.map(|path| path.to_string_lossy().to_string()),
|
||||
welcome_image_path: icon_paths
|
||||
.logo_no_background
|
||||
.map(|path| path.to_string_lossy().to_string()),
|
||||
accessibility_image_1_path: None, // TODO
|
||||
accessibility_image_2_path: None, // TODO
|
||||
handlers: WizardHandlers {
|
||||
is_legacy_version_running: Some(is_legacy_version_running_handler),
|
||||
backup_and_migrate: Some(backup_and_migrate_handler),
|
||||
add_to_path: None, // TODO
|
||||
enable_accessibility: None, // TODO
|
||||
is_accessibility_enabled: None, // TODO
|
||||
},
|
||||
});
|
||||
|
||||
// TODO: enable "Add to PATH" page only when NOT in portable mode
|
||||
// TODO: if the user clicks on "Continue" after unchecking the "ADD to PATH"
|
||||
// checkbox, we should remember (with the kvs) the choice and avoid asking again.
|
||||
// TODO: check the wizard return status?
|
||||
preferences.set_completed_wizard(true);
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
@ -127,4 +136,6 @@ fn launcher_main(args: CliModuleArgs) -> i32 {
|
|||
#[cfg(not(feature = "modulo"))]
|
||||
fn launcher_main(_: CliModuleArgs) -> i32 {
|
||||
// TODO: handle what happens here
|
||||
|
||||
0
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ mod icon;
|
|||
mod ipc;
|
||||
mod lock;
|
||||
mod logging;
|
||||
mod preferences;
|
||||
mod util;
|
||||
|
||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
@ -289,6 +290,10 @@ fn main() {
|
|||
// TODO: explain that the register and unregister commands are only meaningful
|
||||
// when using the system daemon manager on macOS and Linux
|
||||
|
||||
// TODO: set the LSEnvironment variable as described here: https://stackoverflow.com/questions/12203377/combined-gui-and-command-line-os-x-app?rq=1
|
||||
// to detect if the executable was launched inside an AppBundle, and if so, launch the "launcher" handler
|
||||
// This should only apply when on macOS.
|
||||
|
||||
let matches = clap_instance.clone().get_matches();
|
||||
let log_level = match matches.occurrences_of("v") {
|
||||
0 | 1 => LevelFilter::Info,
|
||||
|
|
64
espanso/src/preferences/default.rs
Normal file
64
espanso/src/preferences/default.rs
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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";
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DefaultPreferences<KVSType: KVS> {
|
||||
kvs: KVSType,
|
||||
}
|
||||
|
||||
impl<KVSType: KVS> DefaultPreferences<KVSType> {
|
||||
pub fn new(runtime_dir: &Path, kvs: KVSType) -> Result<Self> {
|
||||
Ok(Self { kvs })
|
||||
}
|
||||
|
||||
fn get<T: DeserializeOwned>(&self, key: &str) -> Option<T> {
|
||||
let value = self
|
||||
.kvs
|
||||
.get(key)
|
||||
.expect(&format!("unable to read preference for key {}", key));
|
||||
value
|
||||
}
|
||||
|
||||
fn set<T: Serialize>(&self, key: &str, value: T) {
|
||||
self
|
||||
.kvs
|
||||
.set(key, value)
|
||||
.expect(&format!("unable to write preference for key {}", key))
|
||||
}
|
||||
}
|
||||
|
||||
impl<KVSType: KVS> Preferences for DefaultPreferences<KVSType> {
|
||||
fn has_completed_wizard(&self) -> bool {
|
||||
self.get(HAS_COMPLETED_WIZARD_KEY).unwrap_or(false)
|
||||
}
|
||||
|
||||
fn set_completed_wizard(&self, value: bool) {
|
||||
self.set(HAS_COMPLETED_WIZARD_KEY, value);
|
||||
}
|
||||
}
|
33
espanso/src/preferences/mod.rs
Normal file
33
espanso/src/preferences/mod.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::path::Path;
|
||||
use anyhow::Result;
|
||||
|
||||
mod default;
|
||||
|
||||
pub trait Preferences: Send + Sync {
|
||||
fn has_completed_wizard(&self) -> bool;
|
||||
fn set_completed_wizard(&self, value: bool);
|
||||
}
|
||||
|
||||
pub fn get_default(runtime_dir: &Path) -> Result<impl Preferences> {
|
||||
let kvs = espanso_kvs::get_persistent(runtime_dir)?;
|
||||
default::DefaultPreferences::new(runtime_dir, kvs)
|
||||
}
|
Loading…
Reference in New Issue
Block a user