Implement iPhone and Apple Watch preferences (#53)
This commit is contained in:
@@ -40,6 +40,7 @@ pub struct Config {
|
||||
clipboard_timeout: ClipboardTimeout,
|
||||
authentication_timeout: AuthenticationTimeout,
|
||||
biometric_unlock_enabled: bool,
|
||||
mobile_appearance: MobileAppearance,
|
||||
mobile_tab: MobileTab,
|
||||
mobile_home_refreshed_at: Option<i64>,
|
||||
watch_shared_totp_entries: BTreeSet<EntryPath>,
|
||||
@@ -60,6 +61,35 @@ pub struct ConfigSettings {
|
||||
authentication_timeout: Duration,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
||||
pub enum MobileAppearance {
|
||||
#[default]
|
||||
System,
|
||||
Light,
|
||||
Dark,
|
||||
}
|
||||
|
||||
impl MobileAppearance {
|
||||
fn from_config(value: &str) -> Result<Self, ConfigError> {
|
||||
match value {
|
||||
"system" => Ok(Self::System),
|
||||
"light" => Ok(Self::Light),
|
||||
"dark" => Ok(Self::Dark),
|
||||
_ => Err(ConfigError::InvalidField {
|
||||
field: "ui.mobile_appearance",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
const fn config_value(self) -> &'static str {
|
||||
match self {
|
||||
Self::System => "system",
|
||||
Self::Light => "light",
|
||||
Self::Dark => "dark",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigSettings {
|
||||
pub fn vault(&self) -> &Path {
|
||||
&self.vault
|
||||
@@ -133,6 +163,10 @@ impl Config {
|
||||
self.biometric_unlock_enabled
|
||||
}
|
||||
|
||||
pub fn mobile_appearance(&self) -> MobileAppearance {
|
||||
self.mobile_appearance
|
||||
}
|
||||
|
||||
pub fn mobile_tab(&self) -> MobileTab {
|
||||
self.mobile_tab
|
||||
}
|
||||
@@ -280,6 +314,66 @@ impl Config {
|
||||
validate_config(self.source.clone(), document, raw)?.persist()
|
||||
}
|
||||
|
||||
pub fn update_authentication_timeout(
|
||||
&self,
|
||||
timeout: AuthenticationTimeout,
|
||||
) -> Result<(), ConfigError> {
|
||||
let mut document = self.current_document()?;
|
||||
let root = document
|
||||
.as_table_mut()
|
||||
.ok_or_else(|| ConfigError::Malformed {
|
||||
path: self.source.clone(),
|
||||
})?;
|
||||
let security = root
|
||||
.entry("security")
|
||||
.or_insert_with(|| toml::Value::Table(toml::Table::new()))
|
||||
.as_table_mut()
|
||||
.ok_or(ConfigError::InvalidField { field: "security" })?;
|
||||
let seconds =
|
||||
i64::try_from(timeout.duration().as_secs()).map_err(|_| ConfigError::InvalidField {
|
||||
field: "security.inactivity_timeout_seconds",
|
||||
})?;
|
||||
security.insert(
|
||||
"inactivity_timeout_seconds".to_owned(),
|
||||
toml::Value::Integer(seconds),
|
||||
);
|
||||
let raw = document
|
||||
.clone()
|
||||
.try_into::<RawConfig>()
|
||||
.map_err(|_| ConfigError::Malformed {
|
||||
path: self.source.clone(),
|
||||
})?;
|
||||
validate_config(self.source.clone(), document, raw)?.persist()
|
||||
}
|
||||
|
||||
pub fn update_mobile_appearance(
|
||||
&self,
|
||||
appearance: MobileAppearance,
|
||||
) -> Result<(), ConfigError> {
|
||||
let mut document = self.current_document()?;
|
||||
let root = document
|
||||
.as_table_mut()
|
||||
.ok_or_else(|| ConfigError::Malformed {
|
||||
path: self.source.clone(),
|
||||
})?;
|
||||
let ui = root
|
||||
.entry("ui")
|
||||
.or_insert_with(|| toml::Value::Table(toml::Table::new()))
|
||||
.as_table_mut()
|
||||
.ok_or(ConfigError::InvalidField { field: "ui" })?;
|
||||
ui.insert(
|
||||
"mobile_appearance".to_owned(),
|
||||
toml::Value::String(appearance.config_value().to_owned()),
|
||||
);
|
||||
let raw = document
|
||||
.clone()
|
||||
.try_into::<RawConfig>()
|
||||
.map_err(|_| ConfigError::Malformed {
|
||||
path: self.source.clone(),
|
||||
})?;
|
||||
validate_config(self.source.clone(), document, raw)?.persist()
|
||||
}
|
||||
|
||||
pub fn update_git_identity(&self, identity: &GitIdentity) -> Result<(), ConfigError> {
|
||||
let mut document = self.current_document()?;
|
||||
let root = document
|
||||
@@ -952,6 +1046,7 @@ struct RawSecurity {
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct RawUi {
|
||||
selected_mobile_tab: Option<String>,
|
||||
mobile_appearance: Option<String>,
|
||||
home_remote_refreshed_at_unix_seconds: Option<i64>,
|
||||
#[serde(default)]
|
||||
watch_shared_totp_entries: Vec<String>,
|
||||
@@ -1032,6 +1127,13 @@ fn validate_config(
|
||||
field: "security.inactivity_timeout_seconds",
|
||||
})?;
|
||||
let biometric_unlock_enabled = raw.security.biometric_unlock_enabled.unwrap_or(false);
|
||||
let mobile_appearance = raw
|
||||
.ui
|
||||
.mobile_appearance
|
||||
.as_deref()
|
||||
.map(MobileAppearance::from_config)
|
||||
.transpose()?
|
||||
.unwrap_or_default();
|
||||
let mobile_tab = raw
|
||||
.ui
|
||||
.selected_mobile_tab
|
||||
@@ -1083,6 +1185,7 @@ fn validate_config(
|
||||
clipboard_timeout,
|
||||
authentication_timeout,
|
||||
biometric_unlock_enabled,
|
||||
mobile_appearance,
|
||||
mobile_tab,
|
||||
mobile_home_refreshed_at,
|
||||
watch_shared_totp_entries,
|
||||
@@ -1270,6 +1373,7 @@ fn validate_known_fields(value: &toml::Value, source: &Path) -> Result<(), Confi
|
||||
"ui",
|
||||
&[
|
||||
"selected_mobile_tab",
|
||||
"mobile_appearance",
|
||||
"home_remote_refreshed_at_unix_seconds",
|
||||
"watch_shared_totp_entries",
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user