diff --git a/src/Commands/SaveDiscardOnTrash.cs b/src/Commands/SaveDiscardOnTrash.cs new file mode 100644 index 000000000..51d4ecd04 --- /dev/null +++ b/src/Commands/SaveDiscardOnTrash.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; + +namespace SourceGit.Commands +{ + public static class SaveDiscardOnTrash + { + public static async Task ProcessSaveDiscardOnTrash(string repo, List changes) + { + changes ??= await new QueryLocalChanges(repo).GetResultAsync().ConfigureAwait(false); + + string tempFolder = Path.GetTempPath(); + string fileName = $"discard_{DateTime.Now.Ticks}.patch"; + string fileNameTemp = Path.Combine(tempFolder, fileName); + + // Save the patch in the Temp Folder + var succ = await SaveChangesAsPatch.ProcessLocalChangesAsync(repo, changes, true, fileNameTemp); + if (succ) return false; + + // Move the file in the Trash + if(!Native.OS.MoveFileToTrash(fileNameTemp)) return false; + + return false; + } + } +} diff --git a/src/Native/Linux.cs b/src/Native/Linux.cs index 3f6de903c..684cdf7db 100644 --- a/src/Native/Linux.cs +++ b/src/Native/Linux.cs @@ -136,5 +136,10 @@ private string FindJetBrainsFleet() var path = $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}/JetBrains/Toolbox/apps/fleet/bin/Fleet"; return File.Exists(path) ? path : FindExecutable("fleet"); } + + public bool MoveFileToTrash(string file) + { + return true; + } } } diff --git a/src/Native/MacOS.cs b/src/Native/MacOS.cs index 8ee84cb59..1067ac957 100644 --- a/src/Native/MacOS.cs +++ b/src/Native/MacOS.cs @@ -105,5 +105,10 @@ public void OpenWithDefaultEditor(string file) { Process.Start("open", $"\"{file}\""); } + + public bool MoveFileToTrash(string file) + { + return true; + } } } diff --git a/src/Native/OS.cs b/src/Native/OS.cs index 3e616b185..8906ba246 100644 --- a/src/Native/OS.cs +++ b/src/Native/OS.cs @@ -20,6 +20,7 @@ public interface IBackend string FindGitExecutable(); string FindTerminal(Models.ShellOrTerminal shell); List FindExternalTools(); + bool MoveFileToTrash(string file); void OpenTerminal(string workdir); void OpenInFileManager(string path, bool select); @@ -162,6 +163,11 @@ public static void OpenBrowser(string url) _backend.OpenBrowser(url); } + public static bool MoveFileToTrash(string file) + { + return _backend.MoveFileToTrash(file); + } + public static void OpenTerminal(string workdir) { if (string.IsNullOrEmpty(ShellOrTerminal)) diff --git a/src/Native/Windows.cs b/src/Native/Windows.cs index caccc5e3c..15f78f8c6 100644 --- a/src/Native/Windows.cs +++ b/src/Native/Windows.cs @@ -33,6 +33,19 @@ internal struct MARGINS public int cyBottomHeight; } + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + internal struct SHFILEOPSTRUCT + { + public IntPtr hwnd; + public uint wFunc; + public string pFrom; + public string pTo; + public ushort fFlags; + public bool fAnyOperationsAborted; + public IntPtr hNameMappings; + public string lpszProgressTitle; + } + [DllImport("dwmapi.dll")] private static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins); @@ -48,6 +61,9 @@ internal struct MARGINS [DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = false)] private static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, int cild, IntPtr apidl, int dwFlags); + [DllImport("shell32.dll", CharSet = CharSet.Auto)] + private static extern int SHFileOperation(ref SHFILEOPSTRUCT FileOp); + [DllImport("user32.dll")] private static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect); @@ -253,6 +269,28 @@ public void OpenWithDefaultEditor(string file) Process.Start(start); } + public bool MoveFileToTrash(string file) + { + SHFILEOPSTRUCT fileOp = new SHFILEOPSTRUCT + { + wFunc = FO_DELETE, + pFrom = file + '\0', + pTo = null, + fFlags = (ushort)(FOF_ALLOWUNDO | FOF_NOCONFIRMATION), + fAnyOperationsAborted = false, + hNameMappings = IntPtr.Zero, + lpszProgressTitle = null + }; + + // Move the file in the Trash + bool result = SHFileOperation(ref fileOp) == 0; + + // If move ok delete the temp file + if (result) File.Delete(file); + + return result; + } + private void FixWindowFrameOnWin10(Window w) { // Schedule the DWM frame extension to run in the next render frame @@ -431,5 +469,9 @@ private string FindVSSolutionFile(DirectoryInfo dir, int leftDepth) return null; } + + private const uint FO_DELETE = 0x0003; // Delete operation + private const uint FOF_ALLOWUNDO = 0x0040; // Put in Trash + private const uint FOF_NOCONFIRMATION = 0x0010; // No confirmation } } diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 38a65f637..1779cc0a1 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -526,6 +526,7 @@ Date Format Language History Commits + Save discard in Trash Show author time instead of commit time in graph Show children in the commit details Show tags in commit graph diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index 10e9bc14b..24fe5cff8 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -472,6 +472,7 @@ Format de date Language Historique de commits + Enregistre les rejets dans la Corbeille Afficher l'heure de l'auteur au lieu de l'heure de validation dans le graphique Afficher les enfants dans les détails du commit Afficher les tags dans le graphique des commits diff --git a/src/ViewModels/Discard.cs b/src/ViewModels/Discard.cs index 1fcda9049..8f9795ce8 100644 --- a/src/ViewModels/Discard.cs +++ b/src/ViewModels/Discard.cs @@ -64,6 +64,9 @@ public override async Task Sure() var log = _repo.CreateLog("Discard all"); Use(log); + if (Preferences.Instance.DiscardChangedOnBin) + await Commands.SaveDiscardOnTrash.ProcessSaveDiscardOnTrash(_repo.FullPath, _changes); + if (Mode is DiscardAllMode all) await Commands.Discard.AllAsync(_repo.FullPath, all.IncludeIgnored, log); else diff --git a/src/ViewModels/Preferences.cs b/src/ViewModels/Preferences.cs index d7fe73f90..f3b588a13 100644 --- a/src/ViewModels/Preferences.cs +++ b/src/ViewModels/Preferences.cs @@ -158,6 +158,12 @@ public bool Check4UpdatesOnStartup set => SetProperty(ref _check4UpdatesOnStartup, value); } + public bool DiscardChangedOnBin + { + get => _discardChangedOnBin; + set => SetProperty(ref _discardChangedOnBin, value); + } + public bool ShowAuthorTimeInGraph { get => _showAuthorTimeInGraph; @@ -682,6 +688,7 @@ private bool RemoveInvalidRepositoriesRecursive(List collection) private bool _check4UpdatesOnStartup = true; private double _lastCheckUpdateTime = 0; private string _ignoreUpdateTag = string.Empty; + private bool _discardChangedOnBin = false; private bool _showTagsInGraph = true; private bool _useTwoColumnsLayoutInHistories = false; diff --git a/src/Views/Preferences.axaml b/src/Views/Preferences.axaml index bf5c29023..4728c2a95 100644 --- a/src/Views/Preferences.axaml +++ b/src/Views/Preferences.axaml @@ -46,7 +46,7 @@ - + + +