diff --git a/src/ViewModels/LauncherPage.cs b/src/ViewModels/LauncherPage.cs
index db5e0241b..29e8f2757 100644
--- a/src/ViewModels/LauncherPage.cs
+++ b/src/ViewModels/LauncherPage.cs
@@ -107,9 +107,15 @@ public async Task ProcessPopupAsync()
public void CancelPopup()
{
- if (_popup == null || _popup.InProgress)
+ if (_popup == null)
return;
+ if (_popup.InProgress)
+ {
+ _popup.Cancel();
+ return;
+ }
+
_popup?.Cleanup();
Popup = null;
}
diff --git a/src/ViewModels/Popup.cs b/src/ViewModels/Popup.cs
index 9d800c50c..0213a4b39 100644
--- a/src/ViewModels/Popup.cs
+++ b/src/ViewModels/Popup.cs
@@ -34,7 +34,7 @@ public void OnReceiveCommandLog(string data)
ProgressDescription = desc;
}
- public void Cleanup()
+ public virtual void Cleanup()
{
_log?.Unsubscribe(this);
}
@@ -44,6 +44,18 @@ public virtual bool CanStartDirectly()
return true;
}
+ ///
+ /// Indicates the in-progress operation of this popup can be interrupted.
+ ///
+ public virtual bool CanCancel => false;
+
+ ///
+ /// Interrupts the in-progress operation of this popup.
+ ///
+ public virtual void Cancel()
+ {
+ }
+
public virtual Task Sure()
{
return null;
diff --git a/src/ViewModels/Push.cs b/src/ViewModels/Push.cs
index b4d9029a9..0a2d43dfb 100644
--- a/src/ViewModels/Push.cs
+++ b/src/ViewModels/Push.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
+using System.Threading;
using System.Threading.Tasks;
namespace SourceGit.ViewModels
@@ -190,6 +191,9 @@ public override async Task Sure()
{
using var lockWatcher = _repo.LockWatcher();
+ _cts?.Cancel();
+ _cts = new CancellationTokenSource();
+
var remoteBranchName = _selectedRemoteBranch.Name;
ProgressDescription = $"Push {_selectedLocalBranch.Name} -> {_selectedRemote.Name}/{remoteBranchName} ...";
@@ -204,12 +208,26 @@ public override async Task Sure()
PushAllTags,
_repo.Submodules.Count > 0 && CheckSubmodules,
_isSetTrackOptionVisible && _tracking,
- ForcePush).Use(log).RunAsync();
+ ForcePush).Use(log).WithCancellation(_cts.Token).RunAsync();
log.Complete();
return succ;
}
+ public override bool CanCancel => true;
+
+ public override void Cancel()
+ {
+ _cts?.Cancel();
+ }
+
+ public override void Cleanup()
+ {
+ base.Cleanup();
+ _cts?.Dispose();
+ _cts = null;
+ }
+
private void AutoSelectBranchByRemote()
{
if (_selectedRemote == null || _selectedLocalBranch == null)
@@ -266,5 +284,6 @@ private void AutoSelectBranchByRemote()
private Models.Branch _selectedRemoteBranch = null;
private bool _isSetTrackOptionVisible = false;
private bool _tracking = true;
+ private CancellationTokenSource _cts = null;
}
}
diff --git a/src/Views/LauncherPage.axaml b/src/Views/LauncherPage.axaml
index bcbecbeca..4b2075b97 100644
--- a/src/Views/LauncherPage.axaml
+++ b/src/Views/LauncherPage.axaml
@@ -113,8 +113,8 @@
+ CanCancel="{Binding CanCancel}"
+ IsVisible="{Binding InProgress}"/>
diff --git a/src/Views/PopupRunningStatus.axaml b/src/Views/PopupRunningStatus.axaml
index 6a0dbdb42..1deafc782 100644
--- a/src/Views/PopupRunningStatus.axaml
+++ b/src/Views/PopupRunningStatus.axaml
@@ -13,6 +13,15 @@
+
SetAndRaise(DescriptionProperty, ref _description, value);
}
+ public static readonly DirectProperty CanCancelProperty =
+ AvaloniaProperty.RegisterDirect(
+ nameof(CanCancel),
+ static o => o.CanCancel,
+ static (o, v) => o.CanCancel = v);
+
+ public bool CanCancel
+ {
+ get => _canCancel;
+ set => SetAndRaise(CanCancelProperty, ref _canCancel, value);
+ }
+
public PopupRunningStatus()
{
InitializeComponent();
@@ -52,6 +64,14 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang
}
}
+ private void OnCancelRequested(object sender, RoutedEventArgs e)
+ {
+ if (DataContext is ViewModels.Popup popup)
+ popup.Cancel();
+
+ e.Handled = true;
+ }
+
private void StartAnim()
{
Icon.Content = new Path() { Classes = { "waiting" } };
@@ -67,6 +87,7 @@ private void StopAnim()
}
private string _description = string.Empty;
+ private bool _canCancel = false;
private bool _isUnloading = false;
}
}