From 876c3de1e09824e5d5daa10b4c90bcfcb1033eb0 Mon Sep 17 00:00:00 2001 From: Bert Verhelst Date: Mon, 12 Oct 2026 19:09:01 +0200 Subject: [PATCH 1/3] feat: add defaults for fetch pull and push, and dropdowns for options --- src/Models/RepositoryUIStates.cs | 18 +++++++ src/Resources/Icons.axaml | 1 + src/Resources/Locales/en_US.axaml | 3 ++ src/ViewModels/Fetch.cs | 50 +++++++++++++---- src/ViewModels/Popup.cs | 13 +++++ src/ViewModels/Pull.cs | 45 +++++++++++++--- src/ViewModels/Push.cs | 50 ++++++++++++++--- src/Views/LauncherPage.axaml | 81 ++++++++++++++++++---------- src/Views/LauncherPage.axaml.cs | 18 ++++++- src/Views/RepositoryToolbar.axaml | 38 +++++-------- src/Views/RepositoryToolbar.axaml.cs | 41 +++++++++++--- 11 files changed, 273 insertions(+), 85 deletions(-) diff --git a/src/Models/RepositoryUIStates.cs b/src/Models/RepositoryUIStates.cs index 0b35f8d618..693e9d9f5a 100644 --- a/src/Models/RepositoryUIStates.cs +++ b/src/Models/RepositoryUIStates.cs @@ -117,12 +117,30 @@ public bool PreferRebaseInsteadOfMerge set; } = true; + public DealWithLocalChanges? DealWithLocalChangesOnPull + { + get; + set; + } = null; + public bool CheckSubmodulesOnPush { get; set; } = true; + public bool SetTrackingOnPush + { + get; + set; + } = false; + + public bool NoVerifyOnPush + { + get; + set; + } = false; + public bool PushAllTags { get; diff --git a/src/Resources/Icons.axaml b/src/Resources/Icons.axaml index a410aef45f..ab784000e1 100644 --- a/src/Resources/Icons.axaml +++ b/src/Resources/Icons.axaml @@ -122,6 +122,7 @@ M853 256h-43v512h43c47 0 85-38 85-85v-341c0-47-38-85-85-85zM725 768V171h128V85h-341v85H640v85H171c-47 0-85 38-85 85v341c0 47 38 85 85 85h469V853h-128v85h341v-85H725v-86zm-469-171v-171h384v171H256z M960 146v91C960 318 759 384 512 384S64 318 64 238V146C64 66 265 0 512 0s448 66 448 146zM960 352v206C960 638 759 704 512 704S64 638 64 558V352c96 66 272 97 448 97S864 418 960 352zm0 320v206C960 958 759 1024 512 1024S64 958 64 878V672c96 66 272 97 448 97S864 738 960 672z M883 567l-128-128c-17-17-43-17-60 0l-128 128c-17 17-17 43 0 60 17 17 43 17 60 0l55-55V683c0 21-21 43-43 43H418c-13-38-43-64-77-77V375c51-17 85-64 85-119 0-73-60-128-128-128-73 0-128 55-128 128 0 55 34 102 85 119v269c-51 17-85 64-85 119 0 73 55 128 128 128 55 0 102-34 119-85H640c73 0 128-55 128-128v-111l55 55c9 9 17 13 30 13 13 0 21-4 30-13 17-13 17-43 0-55zM299 213c26 0 43 17 43 43 0 21-21 43-43 43-26 0-43-21-43-43 0-26 17-43 43-43zm0 597c-26 0-43-21-43-43 0-26 17-43 43-43s43 17 43 43c0 21-17 43-43 43zM725 384c-73 0-128-60-128-128 0-73 55-128 128-128s128 55 128 128c0 68-55 128-128 128zm0-171c-26 0-43 17-43 43s17 43 43 43 43-17 43-43-17-43-43-43z + M512 112A400 400 0 1 1 112 512H192A320 320 0 1 0 512 192V272L352 152L512 32Z M293 122v244h439V146l171 175V829a73 73 0 01-73 73h-98V536H293v366H195a73 73 0 01-73-73V195a73 73 0 0173-73h98zm366 512v268H366V634h293zm-49 49h-195v73h195v-73zm49-561v171H366V122h293z M0 551V472c0-11 9-19 19-19h984c11 0 19 9 19 19v79c0 11-9 19-19 19H19c-11 0-19-9-19-19zM114 154v240c0 11-9 19-19 19H19C9 413 0 404 0 394V79C0 35 35 0 79 0h315c11 0 19 9 19 19v75c0 11-9 19-19 19H154c-21 0-39 18-39 39zm795 0c0-22-17-39-39-39h-240c-11 0-19-9-19-19V19c0-11 9-19 19-19h315c43 0 79 35 79 79v315c0 11-9 19-19 19h-75c-11 0-19-9-19-19l-1-240zm0 716v-240c0-11 9-19 19-19h75c11 0 19 9 19 19v315c0 43-35 79-79 79h-315c-11 0-19-9-19-19v-75c0-11 9-19 19-19H870c21-1 39-18 39-40zm-795 0c0 21 18 39 39 39h240c11 0 19 9 19 19v75c0 11-9 19-19 19H79C35 1023 0 988 0 945v-315c0-11 9-19 19-19h75c11 0 19 9 19 19V870z M155 143h715v81H155V143zm358 94 358 369H662l1 278H363V605H155l358-369z diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 76ac9e4dcb..1522250dba 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -662,6 +662,8 @@ {0} months ago {0} years ago Yesterday + Reset defaults + Save as default Preferences AI Additional Prompt (Use `-` to list your requirements) @@ -850,6 +852,7 @@ First-parent only SHOW FLAGS Show lost commits + Show options... Show Submodules as Tree Show Tags as Tree SKIP diff --git a/src/ViewModels/Fetch.cs b/src/ViewModels/Fetch.cs index 330dd5d763..45ff5b02a9 100644 --- a/src/ViewModels/Fetch.cs +++ b/src/ViewModels/Fetch.cs @@ -19,11 +19,7 @@ public bool IsFetchAllRemoteVisible public bool FetchAllRemotes { get => _fetchAllRemotes; - set - { - if (SetProperty(ref _fetchAllRemotes, value) && IsFetchAllRemoteVisible) - _repo.UIStates.FetchAllRemotes = value; - } + set => SetProperty(ref _fetchAllRemotes, value); } public Models.Remote SelectedRemote @@ -34,14 +30,19 @@ public Models.Remote SelectedRemote public bool NoTags { - get => _repo.UIStates.FetchWithoutTags; - set => _repo.UIStates.FetchWithoutTags = value; + get => _noTags; + set => SetProperty(ref _noTags, value); } public bool Force { - get => _repo.UIStates.EnableForceOnFetch; - set => _repo.UIStates.EnableForceOnFetch = value; + get => _force; + set => SetProperty(ref _force, value); + } + + public override bool HasDefaultOptions + { + get => true; } public Fetch(Repository repo, Models.Remote preferredRemote = null) @@ -49,6 +50,8 @@ public Fetch(Repository repo, Models.Remote preferredRemote = null) _repo = repo; IsFetchAllRemoteVisible = repo.Remotes.Count > 1 && preferredRemote == null; _fetchAllRemotes = IsFetchAllRemoteVisible && _repo.UIStates.FetchAllRemotes; + _noTags = _repo.UIStates.FetchWithoutTags; + _force = _repo.UIStates.EnableForceOnFetch; CanTerminate = true; if (preferredRemote != null) @@ -66,6 +69,29 @@ public Fetch(Repository repo, Models.Remote preferredRemote = null) } } + public override void SaveOptionsAsDefault() + { + if (IsFetchAllRemoteVisible) + _repo.UIStates.FetchAllRemotes = _fetchAllRemotes; + + _repo.UIStates.FetchWithoutTags = _noTags; + _repo.UIStates.EnableForceOnFetch = _force; + _repo.UIStates.Save(); + } + + public override void ResetDefaultOptions() + { + var defaults = new Models.RepositoryUIStates(); + _repo.UIStates.FetchAllRemotes = defaults.FetchAllRemotes; + _repo.UIStates.FetchWithoutTags = defaults.FetchWithoutTags; + _repo.UIStates.EnableForceOnFetch = defaults.EnableForceOnFetch; + _repo.UIStates.Save(); + + FetchAllRemotes = IsFetchAllRemoteVisible && defaults.FetchAllRemotes; + NoTags = defaults.FetchWithoutTags; + Force = defaults.EnableForceOnFetch; + } + public override async Task Sure() { using var lockWatcher = _repo.LockWatcher(); @@ -74,8 +100,8 @@ public override async Task Sure() _repo.Histories.SelectedCommits.Count == 1 && _repo.Histories.SelectedCommits[0].IsCurrentHead; - var notags = _repo.UIStates.FetchWithoutTags; - var force = _repo.UIStates.EnableForceOnFetch; + var notags = _noTags; + var force = _force; var log = _repo.CreateLog("Fetch"); Use(log); @@ -130,6 +156,8 @@ public override void Terminate() private readonly Repository _repo = null; private bool _fetchAllRemotes = false; + private bool _noTags = false; + private bool _force = false; private CancellationTokenSource _cancellation = null; } } diff --git a/src/ViewModels/Popup.cs b/src/ViewModels/Popup.cs index 10bc44fe1b..ab3d055503 100644 --- a/src/ViewModels/Popup.cs +++ b/src/ViewModels/Popup.cs @@ -50,11 +50,24 @@ public void Cleanup() _log?.Unsubscribe(this); } + public virtual bool HasDefaultOptions + { + get => false; + } + public virtual bool CanStartDirectly() { return true; } + public virtual void SaveOptionsAsDefault() + { + } + + public virtual void ResetDefaultOptions() + { + } + public virtual Task Sure() { return null; diff --git a/src/ViewModels/Pull.cs b/src/ViewModels/Pull.cs index 7aaf1be4f4..ffe259716a 100644 --- a/src/ViewModels/Pull.cs +++ b/src/ViewModels/Pull.cs @@ -47,14 +47,19 @@ public bool HasLocalChanges public Models.DealWithLocalChanges DealWithLocalChanges { - get; - set; + get => _dealWithLocalChanges; + set => SetProperty(ref _dealWithLocalChanges, value); } public bool UseRebase { - get => _repo.UIStates.PreferRebaseInsteadOfMerge; - set => _repo.UIStates.PreferRebaseInsteadOfMerge = value; + get => _useRebase; + set => SetProperty(ref _useRebase, value); + } + + public override bool HasDefaultOptions + { + get => true; } public Pull(Repository repo, Models.Branch specifiedRemoteBranch) @@ -63,9 +68,8 @@ public Pull(Repository repo, Models.Branch specifiedRemoteBranch) Current = repo.CurrentBranch; CanTerminate = true; - DealWithLocalChanges = Preferences.Instance.UseStashAndReapplyByDefault ? - Models.DealWithLocalChanges.StashAndReapply : - Models.DealWithLocalChanges.DoNothing; + _dealWithLocalChanges = repo.UIStates.DealWithLocalChangesOnPull ?? GetPreferredDealWithLocalChanges(); + _useRebase = repo.UIStates.PreferRebaseInsteadOfMerge; if (specifiedRemoteBranch != null) { @@ -112,6 +116,24 @@ public Pull(Repository repo, Models.Branch specifiedRemoteBranch) } } + public override void SaveOptionsAsDefault() + { + _repo.UIStates.DealWithLocalChangesOnPull = _dealWithLocalChanges; + _repo.UIStates.PreferRebaseInsteadOfMerge = _useRebase; + _repo.UIStates.Save(); + } + + public override void ResetDefaultOptions() + { + var defaults = new Models.RepositoryUIStates(); + _repo.UIStates.DealWithLocalChangesOnPull = defaults.DealWithLocalChangesOnPull; + _repo.UIStates.PreferRebaseInsteadOfMerge = defaults.PreferRebaseInsteadOfMerge; + _repo.UIStates.Save(); + + DealWithLocalChanges = GetPreferredDealWithLocalChanges(); + UseRebase = defaults.PreferRebaseInsteadOfMerge; + } + public override async Task Sure() { using var lockWatcher = _repo.LockWatcher(); @@ -189,6 +211,13 @@ public override void Terminate() var _ = _cancellation?.CancelAsync(); } + private static Models.DealWithLocalChanges GetPreferredDealWithLocalChanges() + { + return Preferences.Instance.UseStashAndReapplyByDefault ? + Models.DealWithLocalChanges.StashAndReapply : + Models.DealWithLocalChanges.DoNothing; + } + private void PostRemoteSelected() { var remoteName = _selectedRemote.Name; @@ -214,6 +243,8 @@ private void PostRemoteSelected() private Models.Remote _selectedRemote = null; private List _remoteBranches = null; private Models.Branch _selectedBranch = null; + private Models.DealWithLocalChanges _dealWithLocalChanges = Models.DealWithLocalChanges.DoNothing; + private bool _useRebase = true; private CancellationTokenSource _cancellation = null; } } diff --git a/src/ViewModels/Push.cs b/src/ViewModels/Push.cs index ee7b660ac4..0274529d7d 100644 --- a/src/ViewModels/Push.cs +++ b/src/ViewModels/Push.cs @@ -87,14 +87,14 @@ public bool IsCheckSubmodulesVisible public bool CheckSubmodules { - get; - set; - } = true; + get => _checkSubmodules; + set => SetProperty(ref _checkSubmodules, value); + } public bool PushAllTags { - get => _repo.UIStates.PushAllTags; - set => _repo.UIStates.PushAllTags = value; + get => _pushAllTags; + set => SetProperty(ref _pushAllTags, value); } public bool ForcePush @@ -105,13 +105,22 @@ public bool ForcePush public bool NoVerify { - get; - set; + get => _noVerify; + set => SetProperty(ref _noVerify, value); + } + + public override bool HasDefaultOptions + { + get => true; } public Push(Repository repo, Models.Branch localBranch) { _repo = repo; + _tracking = repo.UIStates.SetTrackingOnPush; + _checkSubmodules = repo.UIStates.CheckSubmodulesOnPush; + _pushAllTags = repo.UIStates.PushAllTags; + _noVerify = repo.UIStates.NoVerifyOnPush; CanTerminate = true; // Gather all local branches and find current branch. @@ -162,6 +171,30 @@ public void PushToNewBranch(string name) SelectedRemoteBranch = fake; } + public override void SaveOptionsAsDefault() + { + _repo.UIStates.SetTrackingOnPush = _tracking; + _repo.UIStates.CheckSubmodulesOnPush = _checkSubmodules; + _repo.UIStates.PushAllTags = _pushAllTags; + _repo.UIStates.NoVerifyOnPush = _noVerify; + _repo.UIStates.Save(); + } + + public override void ResetDefaultOptions() + { + var defaults = new Models.RepositoryUIStates(); + _repo.UIStates.SetTrackingOnPush = defaults.SetTrackingOnPush; + _repo.UIStates.CheckSubmodulesOnPush = defaults.CheckSubmodulesOnPush; + _repo.UIStates.PushAllTags = defaults.PushAllTags; + _repo.UIStates.NoVerifyOnPush = defaults.NoVerifyOnPush; + _repo.UIStates.Save(); + + Tracking = defaults.SetTrackingOnPush; + CheckSubmodules = defaults.CheckSubmodulesOnPush; + PushAllTags = defaults.PushAllTags; + NoVerify = defaults.NoVerifyOnPush; + } + public override bool CanStartDirectly() { return !string.IsNullOrEmpty(_selectedRemoteBranch?.Head); @@ -357,6 +390,9 @@ private bool IsPreferredPushRemote(Models.Remote remote) private Models.Branch _selectedRemoteBranch = null; private bool _isSetTrackOptionVisible = false; private bool _tracking = false; + private bool _checkSubmodules = true; + private bool _pushAllTags = false; + private bool _noVerify = false; private CancellationTokenSource _cancellation = null; } } diff --git a/src/Views/LauncherPage.axaml b/src/Views/LauncherPage.axaml index 08107bfa90..359eadda3a 100644 --- a/src/Views/LauncherPage.axaml +++ b/src/Views/LauncherPage.axaml @@ -102,33 +102,60 @@ - - + + + + + + - + - + - + + + + - + + + + - + + + + From dd1cc9fd94528778d55189ee08d288d9e16a409e Mon Sep 17 00:00:00 2001 From: Bert Verhelst Date: Mon, 12 Oct 2026 19:40:01 +0200 Subject: [PATCH 3/3] fix: make check non transparent and center checkmark in circle --- src/Views/RepositoryToolbar.axaml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Views/RepositoryToolbar.axaml b/src/Views/RepositoryToolbar.axaml index 1e4f02b77b..381ce64726 100644 --- a/src/Views/RepositoryToolbar.axaml +++ b/src/Views/RepositoryToolbar.axaml @@ -31,8 +31,9 @@ + - + @@ -59,8 +60,9 @@ + - + @@ -87,8 +89,9 @@ + - +