Add desktop HTTPS Git synchronization
This commit is contained in:
@@ -32,6 +32,10 @@ pub enum UiAction {
|
||||
CopyEntry,
|
||||
DeleteEntry,
|
||||
ToggleReveal,
|
||||
GitStatus,
|
||||
GitPull,
|
||||
GitPush,
|
||||
GitSync,
|
||||
Lock,
|
||||
Minimize,
|
||||
Help,
|
||||
@@ -68,6 +72,10 @@ impl UiAction {
|
||||
Self::CopyEntry => "copy-entry",
|
||||
Self::DeleteEntry => "delete-entry",
|
||||
Self::ToggleReveal => "toggle-reveal",
|
||||
Self::GitStatus => "git-status",
|
||||
Self::GitPull => "git-pull",
|
||||
Self::GitPush => "git-push",
|
||||
Self::GitSync => "git-sync",
|
||||
Self::Lock => "lock",
|
||||
Self::Minimize => "minimize",
|
||||
Self::Help => "help",
|
||||
@@ -129,6 +137,7 @@ pub struct ActionContext {
|
||||
pub focused_generatable: bool,
|
||||
pub entry_path: bool,
|
||||
pub selected_object: bool,
|
||||
pub git_running: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
@@ -228,6 +237,10 @@ pub const ACTIONS: &[ActionSpec] = &[
|
||||
"Reveal or Hide Field",
|
||||
None,
|
||||
),
|
||||
spec(UiAction::GitStatus, MenuGroup::Tools, "Git Status…", None),
|
||||
spec(UiAction::GitPull, MenuGroup::Tools, "Pull", None),
|
||||
spec(UiAction::GitPush, MenuGroup::Tools, "Push", None),
|
||||
spec(UiAction::GitSync, MenuGroup::Tools, "Synchronize", None),
|
||||
spec(UiAction::Lock, MenuGroup::Tools, "Lock", Some("⌘L")),
|
||||
spec(
|
||||
UiAction::Minimize,
|
||||
@@ -278,6 +291,9 @@ pub fn shortcut_label(action: UiAction) -> Option<String> {
|
||||
}
|
||||
|
||||
pub fn enabled(action: UiAction, context: ActionContext) -> bool {
|
||||
if context.git_running && !matches!(action, UiAction::Lock | UiAction::Minimize) {
|
||||
return false;
|
||||
}
|
||||
match action {
|
||||
UiAction::About | UiAction::Help => !context.modal_open,
|
||||
UiAction::Settings => {
|
||||
@@ -362,6 +378,13 @@ pub fn enabled(action: UiAction, context: ActionContext) -> bool {
|
||||
&& !context.switching_vault
|
||||
&& context.focused_sensitive
|
||||
}
|
||||
UiAction::GitStatus | UiAction::GitPull | UiAction::GitPush | UiAction::GitSync => {
|
||||
context.storage_ready
|
||||
&& !context.saving
|
||||
&& !context.switching_vault
|
||||
&& !context.git_running
|
||||
&& !context.modal_open
|
||||
}
|
||||
UiAction::Lock => context.unlocked,
|
||||
}
|
||||
}
|
||||
@@ -370,6 +393,9 @@ pub fn disabled_reason(action: UiAction, context: ActionContext) -> Option<&'sta
|
||||
if enabled(action, context) {
|
||||
return None;
|
||||
}
|
||||
if context.git_running && !matches!(action, UiAction::Lock | UiAction::Minimize) {
|
||||
return Some("Cancel or wait for the active Git operation");
|
||||
}
|
||||
Some(match action {
|
||||
UiAction::InitializeStore | UiAction::NewFolder | UiAction::NewEntry
|
||||
if !context.storage_ready =>
|
||||
@@ -471,6 +497,29 @@ pub fn disabled_reason(action: UiAction, context: ActionContext) -> Option<&'sta
|
||||
UiAction::ToggleReveal if !context.document_open => "Open an entry first",
|
||||
UiAction::ToggleReveal if !context.focused_sensitive => "Select a sensitive field first",
|
||||
UiAction::ToggleReveal => "Wait for vault validation",
|
||||
UiAction::GitStatus | UiAction::GitPull | UiAction::GitPush | UiAction::GitSync
|
||||
if !context.storage_ready =>
|
||||
{
|
||||
"Shared configuration is unavailable"
|
||||
}
|
||||
UiAction::GitStatus | UiAction::GitPull | UiAction::GitPush | UiAction::GitSync
|
||||
if context.saving =>
|
||||
{
|
||||
"Wait for the active save"
|
||||
}
|
||||
UiAction::GitStatus | UiAction::GitPull | UiAction::GitPush | UiAction::GitSync
|
||||
if context.switching_vault =>
|
||||
{
|
||||
"Wait for vault validation"
|
||||
}
|
||||
UiAction::GitStatus | UiAction::GitPull | UiAction::GitPush | UiAction::GitSync
|
||||
if context.git_running =>
|
||||
{
|
||||
"A Git operation is already running"
|
||||
}
|
||||
UiAction::GitStatus | UiAction::GitPull | UiAction::GitPush | UiAction::GitSync => {
|
||||
"Close the current screen first"
|
||||
}
|
||||
UiAction::Lock => "The password store is already locked",
|
||||
UiAction::CommandPalette => "Finish the current confirmation first",
|
||||
UiAction::Settings if !context.storage_ready => "Shared configuration is unavailable",
|
||||
@@ -512,6 +561,10 @@ pub const fn aliases(action: UiAction) -> &'static [&'static str] {
|
||||
UiAction::CopyEntry => &["duplicate entry", "copy folder", "pass cp"],
|
||||
UiAction::DeleteEntry => &["remove", "rm", "delete folder"],
|
||||
UiAction::ToggleReveal => &["show password", "hide password", "reveal field"],
|
||||
UiAction::GitStatus => &["repository status", "git history"],
|
||||
UiAction::GitPull => &["fetch", "download changes"],
|
||||
UiAction::GitPush => &["upload changes"],
|
||||
UiAction::GitSync => &["synchronize", "pull and push"],
|
||||
UiAction::Lock => &["secure", "log out", "relock"],
|
||||
UiAction::Minimize => &["hide window"],
|
||||
UiAction::Help => &["shortcuts", "documentation"],
|
||||
@@ -572,6 +625,7 @@ mod tests {
|
||||
focused_generatable: true,
|
||||
entry_path: true,
|
||||
selected_object: true,
|
||||
git_running: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -599,6 +653,14 @@ mod tests {
|
||||
assert!(enabled(UiAction::GeneratePassword, ready));
|
||||
assert!(!enabled(UiAction::CopyField, ready));
|
||||
assert!(enabled(UiAction::ToggleReveal, ready));
|
||||
for action in [
|
||||
UiAction::GitStatus,
|
||||
UiAction::GitPull,
|
||||
UiAction::GitPush,
|
||||
UiAction::GitSync,
|
||||
] {
|
||||
assert!(enabled(action, ready));
|
||||
}
|
||||
|
||||
let viewing = ActionContext {
|
||||
editing: false,
|
||||
@@ -631,6 +693,9 @@ mod tests {
|
||||
UiAction::MoveEntry,
|
||||
UiAction::CopyEntry,
|
||||
UiAction::DeleteEntry,
|
||||
UiAction::GitPull,
|
||||
UiAction::GitPush,
|
||||
UiAction::GitSync,
|
||||
] {
|
||||
assert!(
|
||||
enabled(action, locked),
|
||||
@@ -708,6 +773,19 @@ mod tests {
|
||||
),
|
||||
Some("Finish the current confirmation first")
|
||||
);
|
||||
|
||||
let git_running = ActionContext {
|
||||
git_running: true,
|
||||
..ready
|
||||
};
|
||||
assert!(enabled(UiAction::Lock, git_running));
|
||||
assert!(enabled(UiAction::Minimize, git_running));
|
||||
assert!(!enabled(UiAction::GitStatus, git_running));
|
||||
assert!(!enabled(UiAction::CloseWindow, git_running));
|
||||
assert_eq!(
|
||||
disabled_reason(UiAction::CloseWindow, git_running),
|
||||
Some("Cancel or wait for the active Git operation")
|
||||
);
|
||||
let modal = ActionContext {
|
||||
modal_open: true,
|
||||
..ready
|
||||
|
||||
Reference in New Issue
Block a user