From f986e59a9403d1da6e8b768fe382ed7800520d42 Mon Sep 17 00:00:00 2001 From: leo Date: Sat, 14 Dec 2024 20:25:25 +0800 Subject: [PATCH 001/441] fix: tag filter hidden behind the scroll bar (#815) Signed-off-by: leo --- src/Views/TagsView.axaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/TagsView.axaml b/src/Views/TagsView.axaml index 5dedb661..6e607edb 100644 --- a/src/Views/TagsView.axaml +++ b/src/Views/TagsView.axaml @@ -26,7 +26,7 @@ SelectionChanged="OnRowSelectionChanged"> - Date: Mon, 16 Dec 2024 09:29:06 +0800 Subject: [PATCH 002/441] version: Release 8.43 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index d72e21bd..50a1eb5b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.42 \ No newline at end of file +8.43 \ No newline at end of file From dd85760b7abf6b963ebab44c638ae312f25c0d09 Mon Sep 17 00:00:00 2001 From: Nils van Rijsinge Date: Mon, 16 Dec 2024 02:50:59 +0100 Subject: [PATCH 003/441] localization: add missing de_DE keys (#817) * localization: add missing de_DE keys BranchCM.MergeMultiBranches, CommitCM.MergeMultiple, MergeMultiple #793 CommitCM.Merge 2053ce033d1e24e9e6b74cecfcc0761fad899f6f CommitDetail.Files.Search 894f3e9b033f15df5f87f251299afa6ce9428227 Diff.UseBlockNavigation #703 FileCM.ResolveUsing 3b5d87391d11b27aff061cb57a32862046ee791f Hotkeys.Global.Clone bea2a39feb18cf4ef427f319f0436bd3f80546f5 InProgress.CherryPick.Head e1df5c52f10042523ba1d40483703bcbeeedf053 InProgress.Merge.Operating ef40e4b7387fb82d16984c5e4cc6a77559bd01e6 InProgress.Rebase.StoppedAt, Repository.Skip #790 InProgress.Revert.Head 93d9a044608c84fc8335f25269b1d5572c41b0e1 Merge.Source 2504a523987f0279afacef0b80b2ea00547d2145 WorkingCopy.CommitToEdit c1368212dfe08f3c0586cbefcace26c329c31d90 * localization: consistently use clone with 'k' for most other keys a more "germanized" version with a k is used rather than a c --- src/Resources/Locales/de_DE.axaml | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index 2045a229..ff8a1d97 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -61,6 +61,7 @@ Fetche ${0}$ in ${1}$ hinein... Git Flow - Abschließen ${0}$ Merge ${0}$ in ${1}$ hinein... + Merge ausgewählte {0} Branches in aktuellen hinein Pull ${0}$ Pull ${0}$ in ${1}$ hinein... Push ${0}$ @@ -113,6 +114,8 @@ SHA kopieren Benutzerdefinierte Aktion Interactives Rebase von ${0}$ auf diesen Commit + Merge in ${0}$ hinein + Merge ... Rebase von ${0}$ auf diesen Commit Reset ${0}$ auf diesen Commit Commit rückgängig machen @@ -124,6 +127,7 @@ Änderungen durchsuchen... DATEIEN LFS DATEI + Dateien durchsuchen... Submodule INFORMATION AUTOR @@ -249,6 +253,7 @@ Seiten wechseln Syntax Hervorhebung Zeilenumbruch + Aktiviere Block-Navigation Öffne in Merge Tool Alle Zeilen anzeigen Weniger Zeilen anzeigen @@ -280,6 +285,7 @@ Verwerfe {0} Dateien... Verwerfe Änderungen in ausgewählten Zeilen Öffne externes Merge Tool + Löse mit ${0}$ Als Patch speichern... Stagen {0} Dateien stagen @@ -358,6 +364,7 @@ Tastaturkürzel Referenz GLOBAL Aktuelles Popup schließen + Klone neues Repository Aktuellen Tab schließen Zum vorherigen Tab wechseln Zum nächsten Tab wechseln @@ -390,9 +397,13 @@ Initialisiere Repository Pfad: Cherry-Pick wird durchgeführt. + Verarbeite commit Merge request wird durchgeführt. + Verarbeite Rebase wird durchgeführt. + Angehalten bei Revert wird durchgeführt. + Reverte commit Interaktiver Rebase Ziel Branch: Auf: @@ -403,6 +414,11 @@ Branch mergen Ziel-Branch: Merge Option: + Quelle: + Merge (mehrere) + Alle Änderungen committen + Strategie: + Ziele: Bewege Repository Knoten Wähle Vorgänger-Knoten für: Name: @@ -459,7 +475,7 @@ Längenvorgabe für Commit-Nachrichten GIT Aktiviere Auto-CRLF - Clone Standardordner + Klon Standardordner Benutzer Email Globale Git Benutzer Email Installationspfad @@ -568,6 +584,7 @@ Autor & Committer Aktueller Branch Zeige Tags als Baum + ÜBERSPRINGEN Statistiken SUBMODULE SUBMODUL HINZUFÜGEN @@ -666,7 +683,7 @@ Öffne alle Repositories Öffne Repository Öffne Terminal - Clone Standardordner erneut nach Repositories durchsuchen + Klon Standardordner erneut nach Repositories durchsuchen Suche Repositories... Sortieren Änderungen @@ -681,6 +698,7 @@ COMMIT & PUSH Template/Historie Klick-Ereignis auslösen + Commit (Bearbeitung) Alle Änderungen stagen und committen Leerer Commit erkannt! Fortfahren (--allow-empty)? KONFLIKTE ERKANNT From e4cfca0ffdb85980b3221d30febea5997a48c384 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 16 Dec 2024 01:51:11 +0000 Subject: [PATCH 004/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 21 ++------------------- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 6916edbc..9f1d302a 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-100%25-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-97.50%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.78%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-95.00%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-95.56%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-96.81%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-97.92%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-100.00%25-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-100.00%25-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-100%25-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-100.00%25-brightgreen)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.78%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-95.00%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-95.56%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-96.81%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-97.92%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-100.00%25-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-100.00%25-brightgreen)](TRANSLATION.md) ## How to Use diff --git a/TRANSLATION.md b/TRANSLATION.md index 6e743f14..59ed0ff7 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,27 +1,10 @@ -### de_DE.axaml: 97.50% +### de_DE.axaml: 100.00%
Missing Keys -- Text.BranchCM.MergeMultiBranches -- Text.CommitCM.Merge -- Text.CommitCM.MergeMultiple -- Text.CommitDetail.Files.Search -- Text.Diff.UseBlockNavigation -- Text.FileCM.ResolveUsing -- Text.Hotkeys.Global.Clone -- Text.InProgress.CherryPick.Head -- Text.InProgress.Merge.Operating -- Text.InProgress.Rebase.StoppedAt -- Text.InProgress.Revert.Head -- Text.Merge.Source -- Text.MergeMultiple -- Text.MergeMultiple.CommitChanges -- Text.MergeMultiple.Strategy -- Text.MergeMultiple.Targets -- Text.Repository.Skip -- Text.WorkingCopy.CommitToEdit +
From 5425fa64fe46c5c025c09bcc9f7aa6662ce29661 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 16 Dec 2024 13:29:46 +0800 Subject: [PATCH 005/441] refactor: use another way to open tooltip of SHA after getting commit info (#810) --- src/Views/CommitBaseInfo.axaml.cs | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Views/CommitBaseInfo.axaml.cs b/src/Views/CommitBaseInfo.axaml.cs index 0b4c1f2d..79f65a4d 100644 --- a/src/Views/CommitBaseInfo.axaml.cs +++ b/src/Views/CommitBaseInfo.axaml.cs @@ -5,6 +5,7 @@ using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; +using Avalonia.Threading; namespace SourceGit.Views { @@ -124,7 +125,7 @@ namespace SourceGit.Views e.Handled = true; } - private async void OnSHAPointerEntered(object sender, PointerEventArgs e) + private void OnSHAPointerEntered(object sender, PointerEventArgs e) { if (DataContext is ViewModels.CommitDetail detail && sender is Control { DataContext: string sha } ctl) { @@ -132,14 +133,22 @@ namespace SourceGit.Views if (tooltip is Models.Commit commit && commit.SHA == sha) return; - var c = await Task.Run(() => detail.GetParent(sha)); - if (c != null && ctl.IsVisible && ctl.DataContext is string newSHA && newSHA == sha) + Task.Run(() => { - ToolTip.SetTip(ctl, c); + var c = detail.GetParent(sha); + if (c == null) return; - if (ctl.IsPointerOver) - ToolTip.SetIsOpen(ctl, true); - } + Dispatcher.UIThread.Invoke(() => + { + if (ctl.IsEffectivelyVisible && ctl.DataContext is string newSHA && newSHA == sha) + { + ToolTip.SetTip(ctl, c); + + if (ctl.IsPointerOver) + ToolTip.SetIsOpen(ctl, true); + } + }); + }); } e.Handled = true; From f418b72c64391b178ccb6a1ce46df1eaaae51f41 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 16 Dec 2024 15:47:33 +0800 Subject: [PATCH 006/441] feature: use `[$workspace] $repo_name ($repo_path)` as main window's title (#818) --- src/ViewModels/Launcher.cs | 48 +++++++++++++++++++++++++++++++++++--- src/Views/Launcher.axaml | 2 +- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index 8e4f7775..02844312 100644 --- a/src/ViewModels/Launcher.cs +++ b/src/ViewModels/Launcher.cs @@ -11,6 +11,12 @@ namespace SourceGit.ViewModels { public class Launcher : ObservableObject { + public string Title + { + get => _title; + private set => SetProperty(ref _title, value); + } + public AvaloniaList Pages { get; @@ -31,9 +37,10 @@ namespace SourceGit.ViewModels if (SetProperty(ref _activePage, value)) { PopupHost.Active = value; + UpdateTitle(); if (!_ignoreIndexChange && value is { Data: Repository repo }) - ActiveWorkspace.ActiveIdx = ActiveWorkspace.Repositories.IndexOf(repo.FullPath); + _activeWorkspace.ActiveIdx = _activeWorkspace.Repositories.IndexOf(repo.FullPath); } } } @@ -105,6 +112,9 @@ namespace SourceGit.ViewModels } _ignoreIndexChange = false; + + if (string.IsNullOrEmpty(_title)) + UpdateTitle(); } public void Quit(double width, double height) @@ -185,6 +195,7 @@ namespace SourceGit.ViewModels last.Node = new RepositoryNode() { Id = Guid.NewGuid().ToString() }; last.Data = Welcome.Instance; last.Popup = null; + UpdateTitle(); GC.Collect(); } @@ -193,7 +204,6 @@ namespace SourceGit.ViewModels App.Quit(0); } - _ignoreIndexChange = false; return; } @@ -308,7 +318,10 @@ namespace SourceGit.ViewModels page.Data = repo; } - ActivePage = page; + if (page != _activePage) + ActivePage = page; + else + UpdateTitle(); ActiveWorkspace.Repositories.Clear(); foreach (var p in Pages) @@ -530,8 +543,37 @@ namespace SourceGit.ViewModels page.Data = null; } + private void UpdateTitle() + { + if (_activeWorkspace == null) + return; + + var workspace = _activeWorkspace.Name; + if (_activePage is { Data: Repository repo }) + { + var node = _activePage.Node; + var name = node.Name; + var path = node.Id; + + if (!OperatingSystem.IsWindows()) + { + var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + var prefixLen = home.EndsWith('/') ? home.Length - 1 : home.Length; + if (path.StartsWith(home, StringComparison.Ordinal)) + path = "~" + path.Substring(prefixLen); + } + + Title = $"[{workspace}] {name} ({path})"; + } + else + { + Title = $"[{workspace}] Repositories"; + } + } + private Workspace _activeWorkspace = null; private LauncherPage _activePage = null; private bool _ignoreIndexChange = false; + private string _title = string.Empty; } } diff --git a/src/Views/Launcher.axaml b/src/Views/Launcher.axaml index ad5a7f34..d37cf928 100644 --- a/src/Views/Launcher.axaml +++ b/src/Views/Launcher.axaml @@ -10,7 +10,7 @@ x:DataType="vm:Launcher" x:Name="ThisControl" Icon="/App.ico" - Title="SourceGit" + Title="{Binding Title}" MinWidth="1024" MinHeight="600" WindowStartupLocation="CenterScreen"> From 707a227aca594b46475ad149a080a38a208352cf Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 17 Dec 2024 09:36:06 +0800 Subject: [PATCH 007/441] ux: make Welcome page responsive (#821) --- src/Views/Welcome.axaml | 265 ++++++++++++++++++++-------------------- 1 file changed, 132 insertions(+), 133 deletions(-) diff --git a/src/Views/Welcome.axaml b/src/Views/Welcome.axaml index 6f12c119..cdc892f4 100644 --- a/src/Views/Welcome.axaml +++ b/src/Views/Welcome.axaml @@ -9,149 +9,148 @@ x:Class="SourceGit.Views.Welcome" x:DataType="vm:Welcome"> - - - - - - - - - - - - + + + + + + + + - - - - + + + - - - - - - - + + + + - - - - - + + + + - - - - - - - - - + + - - - - - - + + + + + - + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + - - - - - + + +
+
+ From c768b1750e715091504fe9d866013f6a6d44ac22 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 17 Dec 2024 10:26:35 +0800 Subject: [PATCH 008/441] feature: use `-p:DisableUpdateDetection=true` to disable built-in update detection feature (#819) --- src/App.Commands.cs | 12 ++++++++++++ src/App.axaml | 2 +- src/App.axaml.cs | 2 ++ src/SourceGit.csproj | 4 ++++ src/Views/Launcher.axaml | 4 ++-- src/Views/Preference.axaml | 4 +++- 6 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/App.Commands.cs b/src/App.Commands.cs index 8a485029..18016a1c 100644 --- a/src/App.Commands.cs +++ b/src/App.Commands.cs @@ -25,6 +25,18 @@ namespace SourceGit private Action _action = null; } + public static bool IsCheckForUpdateCommandVisible + { + get + { + #if DISABLE_UPDATE_DETECTION + return false; + #else + return true; + #endif + } + } + public static readonly Command OpenPreferenceCommand = new Command(_ => OpenDialog(new Views.Preference())); public static readonly Command OpenHotkeysCommand = new Command(_ => OpenDialog(new Views.Hotkeys())); public static readonly Command OpenAppDataDirCommand = new Command(_ => Native.OS.OpenInFileManager(Native.OS.DataDir)); diff --git a/src/App.axaml b/src/App.axaml index 0f40031d..55aacb89 100644 --- a/src/App.axaml +++ b/src/App.axaml @@ -33,7 +33,7 @@ - + diff --git a/src/App.axaml.cs b/src/App.axaml.cs index 0615724a..3d1547c9 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -548,9 +548,11 @@ namespace SourceGit _launcher = new ViewModels.Launcher(startupRepo); desktop.MainWindow = new Views.Launcher() { DataContext = _launcher }; + #if !DISABLE_UPDATE_DETECTION var pref = ViewModels.Preference.Instance; if (pref.ShouldCheck4UpdateOnStartup()) Check4Update(); + #endif } private ViewModels.Launcher _launcher = null; diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj index 32f68d03..89893a39 100644 --- a/src/SourceGit.csproj +++ b/src/SourceGit.csproj @@ -26,6 +26,10 @@ link + + $(DefineConstants);DISABLE_UPDATE_DETECTION + + diff --git a/src/Views/Launcher.axaml b/src/Views/Launcher.axaml index d37cf928..a0691c4c 100644 --- a/src/Views/Launcher.axaml +++ b/src/Views/Launcher.axaml @@ -51,12 +51,12 @@ - + - + diff --git a/src/Views/Preference.axaml b/src/Views/Preference.axaml index 0ed598c2..6adbaca4 100644 --- a/src/Views/Preference.axaml +++ b/src/Views/Preference.axaml @@ -2,6 +2,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:s="using:SourceGit" xmlns:m="using:SourceGit.Models" xmlns:c="using:SourceGit.Converters" xmlns:vm="using:SourceGit.ViewModels" @@ -45,7 +46,7 @@ - + From 1c345df37db53e416d98887d860c919ef8c8311e Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 17 Dec 2024 11:24:59 +0800 Subject: [PATCH 009/441] ux: add some tooltips to checkboxes --- src/Resources/Locales/en_US.axaml | 2 +- src/Resources/Locales/zh_CN.axaml | 2 +- src/Resources/Locales/zh_TW.axaml | 2 +- src/Views/Apply.axaml | 3 ++- src/Views/Fetch.axaml | 9 ++++++--- src/Views/Pull.axaml | 6 ++++-- src/Views/Push.axaml | 12 ++++++++---- src/Views/StashChanges.axaml | 9 ++++++--- 8 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 65b4dd96..73e82074 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -273,7 +273,7 @@ Fast-Forward (without checkout) Fetch Fetch all remotes - Enable '--force' option + Override refs check Fetch without tags Remote: Fetch Remote Changes diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index f711cdee..e53af9a8 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -276,7 +276,7 @@ 快进(fast-forward,无需checkout) 拉取(fetch) 拉取所有的远程仓库 - 启用 --force 选项 + 覆盖REF检查 不拉取远程标签 远程仓库 : 拉取远程仓库内容 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 90444967..e96f68ad 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -276,7 +276,7 @@ 快進 (fast-forward,無需 checkout) 提取 (fetch) 提取所有的遠端存放庫 - 啟用 [--force] 選項 + 覆寫 REFs 檢查 不提取遠端標籤 遠端存放庫: 提取遠端存放庫內容 diff --git a/src/Views/Apply.axaml b/src/Views/Apply.axaml index c3cb420c..a5100cd6 100644 --- a/src/Views/Apply.axaml +++ b/src/Views/Apply.axaml @@ -54,7 +54,8 @@ + IsChecked="{Binding IgnoreWhiteSpace, Mode=TwoWay}" + ToolTip.Tip="--ignore-whitespace"/> diff --git a/src/Views/Fetch.axaml b/src/Views/Fetch.axaml index f9380ab0..67669380 100644 --- a/src/Views/Fetch.axaml +++ b/src/Views/Fetch.axaml @@ -34,15 +34,18 @@ + IsChecked="{Binding Force, Mode=TwoWay}" + ToolTip.Tip="--force"/> + IsChecked="{Binding FetchAllRemotes, Mode=TwoWay}" + ToolTip.Tip="--all"/> + IsChecked="{Binding NoTags, Mode=TwoWay}" + ToolTip.Tip="--no-tags"/> diff --git a/src/Views/Pull.axaml b/src/Views/Pull.axaml index f6aa245f..50615bc6 100644 --- a/src/Views/Pull.axaml +++ b/src/Views/Pull.axaml @@ -99,11 +99,13 @@ + IsChecked="{Binding NoTags, Mode=TwoWay}" + ToolTip.Tip="--no-tags"/> + IsChecked="{Binding UseRebase, Mode=TwoWay}" + ToolTip.Tip="--rebase"/> diff --git a/src/Views/Push.axaml b/src/Views/Push.axaml index 87921c88..6bc02cff 100644 --- a/src/Views/Push.axaml +++ b/src/Views/Push.axaml @@ -83,21 +83,25 @@ Height="32" Content="{DynamicResource Text.Push.Tracking}" IsChecked="{Binding Tracking, Mode=TwoWay}" - IsVisible="{Binding IsSetTrackOptionVisible}"/> + IsVisible="{Binding IsSetTrackOptionVisible}" + ToolTip.Tip="-u"/> + IsVisible="{Binding IsCheckSubmodulesVisible}" + ToolTip.Tip="--recurse-submodules=check"/> + IsChecked="{Binding PushAllTags, Mode=TwoWay}" + ToolTip.Tip="--tags"/> + IsChecked="{Binding ForcePush, Mode=TwoWay}" + ToolTip.Tip="--force-with-lease"/> diff --git a/src/Views/StashChanges.axaml b/src/Views/StashChanges.axaml index b3e6254a..772b09e6 100644 --- a/src/Views/StashChanges.axaml +++ b/src/Views/StashChanges.axaml @@ -27,18 +27,21 @@ Height="32" Content="{DynamicResource Text.Stash.IncludeUntracked}" IsChecked="{Binding IncludeUntracked, Mode=TwoWay}" - IsVisible="{Binding !HasSelectedFiles}"/> + IsVisible="{Binding !HasSelectedFiles}" + ToolTip.Tip="--include-untracked"/> + IsVisible="{Binding !HasSelectedFiles}" + ToolTip.Tip="--staged"/> + IsChecked="{Binding KeepIndex, Mode=TwoWay}" + ToolTip.Tip="--keep-index"/> Date: Tue, 17 Dec 2024 12:08:25 +0800 Subject: [PATCH 010/441] ux: new notification theme --- src/Views/LauncherPage.axaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/LauncherPage.axaml b/src/Views/LauncherPage.axaml index d09c2c0d..d40fd243 100644 --- a/src/Views/LauncherPage.axaml +++ b/src/Views/LauncherPage.axaml @@ -125,7 +125,7 @@ - + From 23326d179a875047db004cb76bd575db44a4c1bc Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 17 Dec 2024 14:39:18 +0800 Subject: [PATCH 011/441] refactor: commit hash detection in message --- src/Views/CommitMessagePresenter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/CommitMessagePresenter.cs b/src/Views/CommitMessagePresenter.cs index a767b395..0ae3d6cf 100644 --- a/src/Views/CommitMessagePresenter.cs +++ b/src/Views/CommitMessagePresenter.cs @@ -15,7 +15,7 @@ namespace SourceGit.Views { public partial class CommitMessagePresenter : SelectableTextBlock { - [GeneratedRegex(@"\b([0-9a-fA-F]{8,40})\b")] + [GeneratedRegex(@"\b([0-9a-fA-F]{10,40})\b")] private static partial Regex REG_SHA_FORMAT(); public static readonly StyledProperty MessageProperty = From 39dff8a93f8fc8df0adabf562a1cf9a7874d2d85 Mon Sep 17 00:00:00 2001 From: Martin Garstenauer Date: Wed, 18 Dec 2024 02:25:56 +0100 Subject: [PATCH 012/441] ux: change text selection brush to improve readability (#825) --- src/Resources/Styles.axaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Resources/Styles.axaml b/src/Resources/Styles.axaml index 2cc09e39..28eabbab 100644 --- a/src/Resources/Styles.axaml +++ b/src/Resources/Styles.axaml @@ -4,6 +4,7 @@ xmlns:vm="using:SourceGit.ViewModels" xmlns:c="using:SourceGit.Converters" xmlns:ae="using:AvaloniaEdit" + xmlns:aee="using:AvaloniaEdit.Editing" xmlns:aes="using:AvaloniaEdit.Search"> @@ -580,6 +581,19 @@ + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Views/LauncherTabsSelector.axaml.cs b/src/Views/LauncherTabsSelector.axaml.cs new file mode 100644 index 00000000..01c5fa0d --- /dev/null +++ b/src/Views/LauncherTabsSelector.axaml.cs @@ -0,0 +1,120 @@ +using System; + +using Avalonia; +using Avalonia.Collections; +using Avalonia.Controls; +using Avalonia.Interactivity; + +namespace SourceGit.Views +{ + public class LauncherTabSelectedEventArgs : RoutedEventArgs + { + public ViewModels.LauncherPage Page { get; } + + public LauncherTabSelectedEventArgs(ViewModels.LauncherPage page) + { + RoutedEvent = LauncherTabsSelector.PageSelectedEvent; + Page = page; + } + } + + public partial class LauncherTabsSelector : UserControl + { + public static readonly StyledProperty> PagesProperty = + AvaloniaProperty.Register>(nameof(Pages)); + + public AvaloniaList Pages + { + get => GetValue(PagesProperty); + set => SetValue(PagesProperty, value); + } + + public static readonly StyledProperty SearchFilterProperty = + AvaloniaProperty.Register(nameof(SearchFilter)); + + public string SearchFilter + { + get => GetValue(SearchFilterProperty); + set => SetValue(SearchFilterProperty, value); + } + + public static readonly RoutedEvent PageSelectedEvent = + RoutedEvent.Register(nameof(PageSelected), RoutingStrategies.Tunnel | RoutingStrategies.Bubble); + + public event EventHandler PageSelected + { + add { AddHandler(PageSelectedEvent, value); } + remove { RemoveHandler(PageSelectedEvent, value); } + } + + public AvaloniaList VisiblePages + { + get; + private set; + } + + public LauncherTabsSelector() + { + VisiblePages = new AvaloniaList(); + InitializeComponent(); + } + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + + if (change.Property == PagesProperty || change.Property == SearchFilterProperty) + UpdateVisiblePages(); + } + + private void OnClearSearchFilter(object sender, RoutedEventArgs e) + { + SearchFilter = string.Empty; + } + + private void OnPageSelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (sender is ListBox { SelectedItem : ViewModels.LauncherPage page }) + { + _isProcessingSelection = true; + RaiseEvent(new LauncherTabSelectedEventArgs(page)); + _isProcessingSelection = false; + } + + e.Handled = true; + } + + private void UpdateVisiblePages() + { + if (_isProcessingSelection) + return; + + VisiblePages.Clear(); + + if (Pages == null) + return; + + var filter = SearchFilter?.Trim() ?? ""; + if (string.IsNullOrEmpty(filter)) + { + foreach (var p in Pages) + VisiblePages.Add(p); + + return; + } + + foreach (var page in Pages) + { + if (!page.Node.IsRepository) + continue; + + if (page.Node.Name.Contains(filter, StringComparison.OrdinalIgnoreCase) || + page.Node.Id.Contains(filter, StringComparison.OrdinalIgnoreCase)) + VisiblePages.Add(page); + } + } + + private bool _isProcessingSelection = false; + } +} + From aebfffee003413b679ed7523c04c834764fe0a82 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 10 Feb 2025 20:51:36 +0800 Subject: [PATCH 211/441] fix: GUI stops refreshing after manually refresh while merge tool is open (#949) Signed-off-by: leo --- src/ViewModels/WorkingCopy.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index ecb3c0d6..7ac13dc2 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -431,10 +431,7 @@ namespace SourceGit.ViewModels { var toolType = Preferences.Instance.ExternalMergeToolType; var toolPath = Preferences.Instance.ExternalMergeToolPath; - - _repo.SetWatcherEnabled(false); await Task.Run(() => Commands.MergeTool.OpenForMerge(_repo.FullPath, toolType, toolPath, change.Path)); - _repo.SetWatcherEnabled(true); } public void ContinueMerge() From 821063e3ec196da97c75951d30c93088c127f91e Mon Sep 17 00:00:00 2001 From: Doodeletion <99095135+Doodeletion@users.noreply.github.com> Date: Tue, 11 Feb 2025 03:57:20 +0100 Subject: [PATCH 212/441] Swap selection start and end index if selection is created from bottom to top (#967) --- src/Views/TextDiffView.axaml.cs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 15a2a212..cc8fcfe5 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -970,8 +970,19 @@ namespace SourceGit.Views } var lines = GetLines(); - var startIdx = Math.Min(selection.StartPosition.Line - 1, lines.Count - 1); - var endIdx = Math.Min(selection.EndPosition.Line - 1, lines.Count - 1); + + var startPosition = selection.StartPosition; + var endPosition = selection.EndPosition; + + if (startPosition.Line > endPosition.Line + || startPosition.Line == endPosition.Line && startPosition.Column > endPosition.Column) + { + // swap start and end + (startPosition, endPosition) = (endPosition, startPosition); + } + + var startIdx = Math.Min(startPosition.Line - 1, lines.Count - 1); + var endIdx = Math.Min(endPosition.Line - 1, lines.Count - 1); if (startIdx == endIdx) { @@ -995,15 +1006,15 @@ namespace SourceGit.Views line.Type == Models.TextDiffLineType.None) continue; - if (i == startIdx && selection.StartPosition.Column > 1) + if (i == startIdx && startPosition.Column > 1) { - builder.AppendLine(line.Content.Substring(selection.StartPosition.Column - 1)); + builder.AppendLine(line.Content.Substring(startPosition.Column - 1)); continue; } - if (i == endIdx && selection.EndPosition.Column < line.Content.Length) + if (i == endIdx && endPosition.Column < line.Content.Length) { - builder.AppendLine(line.Content.Substring(0, selection.EndPosition.Column)); + builder.AppendLine(line.Content.Substring(0, endPosition.Column)); continue; } From 10fba08e430f6f67d6c1bca7abbf9338a546b9a4 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 11 Feb 2025 11:07:33 +0800 Subject: [PATCH 213/441] code_review: PR #949 Signed-off-by: leo --- src/Views/TextDiffView.axaml.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index cc8fcfe5..28fe81a8 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -973,13 +973,9 @@ namespace SourceGit.Views var startPosition = selection.StartPosition; var endPosition = selection.EndPosition; - - if (startPosition.Line > endPosition.Line - || startPosition.Line == endPosition.Line && startPosition.Column > endPosition.Column) - { - // swap start and end + + if (startPosition.Location > endPosition.Location) (startPosition, endPosition) = (endPosition, startPosition); - } var startIdx = Math.Min(startPosition.Line - 1, lines.Count - 1); var endIdx = Math.Min(endPosition.Line - 1, lines.Count - 1); From af20ab2448a2b46dfd687c0ff95a12716d2f9543 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 11 Feb 2025 14:34:14 +0800 Subject: [PATCH 214/441] feature: add `Wait for action done` option to control whether or not to wait for the custom action execution to complete (#951) Signed-off-by: leo --- src/Commands/ExecuteCustomAction.cs | 32 ++++++++++++++++++++++++++- src/Models/CustomAction.cs | 7 ++++++ src/Resources/Locales/en_US.axaml | 1 + src/Resources/Locales/zh_CN.axaml | 1 + src/Resources/Locales/zh_TW.axaml | 1 + src/ViewModels/ExecuteCustomAction.cs | 6 ++++- src/Views/RepositoryConfigure.axaml | 4 +++- 7 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/Commands/ExecuteCustomAction.cs b/src/Commands/ExecuteCustomAction.cs index a10f5387..3a77ec01 100644 --- a/src/Commands/ExecuteCustomAction.cs +++ b/src/Commands/ExecuteCustomAction.cs @@ -8,7 +8,37 @@ namespace SourceGit.Commands { public static class ExecuteCustomAction { - public static void Run(string repo, string file, string args, Action outputHandler) + public static void Run(string repo, string file, string args) + { + var start = new ProcessStartInfo(); + start.FileName = file; + start.Arguments = args; + start.UseShellExecute = false; + start.CreateNoWindow = true; + start.WorkingDirectory = repo; + + // Force using en_US.UTF-8 locale to avoid GCM crash + if (OperatingSystem.IsLinux()) + start.Environment.Add("LANG", "en_US.UTF-8"); + + // Fix macOS `PATH` env + if (OperatingSystem.IsMacOS() && !string.IsNullOrEmpty(Native.OS.CustomPathEnv)) + start.Environment.Add("PATH", Native.OS.CustomPathEnv); + + try + { + Process.Start(start); + } + catch (Exception e) + { + Dispatcher.UIThread.Invoke(() => + { + App.RaiseException(repo, e.Message); + }); + } + } + + public static void RunAndWait(string repo, string file, string args, Action outputHandler) { var start = new ProcessStartInfo(); start.FileName = file; diff --git a/src/Models/CustomAction.cs b/src/Models/CustomAction.cs index 8452a42d..bd56d6ae 100644 --- a/src/Models/CustomAction.cs +++ b/src/Models/CustomAction.cs @@ -34,9 +34,16 @@ namespace SourceGit.Models set => SetProperty(ref _arguments, value); } + public bool WaitForExit + { + get => _waitForExit; + set => SetProperty(ref _waitForExit, value); + } + private string _name = string.Empty; private CustomActionScope _scope = CustomActionScope.Repository; private string _executable = string.Empty; private string _arguments = string.Empty; + private bool _waitForExit = true; } } diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 018b54d7..40f95793 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -158,6 +158,7 @@ Scope: Commit Repository + Wait for action done Email Address Email address GIT diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 66d1f37e..ef31972a 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -161,6 +161,7 @@ 作用目标 : 选中的提交 仓库 + 等待操作执行完成 电子邮箱 邮箱地址 GIT配置 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index f8255947..506a618f 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -161,6 +161,7 @@ 執行範圍: 選取的提交 存放庫 + 等待自訂操作退出 電子郵件 電子郵件地址 Git 設定 diff --git a/src/ViewModels/ExecuteCustomAction.cs b/src/ViewModels/ExecuteCustomAction.cs index 920b9f43..848faaaf 100644 --- a/src/ViewModels/ExecuteCustomAction.cs +++ b/src/ViewModels/ExecuteCustomAction.cs @@ -28,7 +28,11 @@ namespace SourceGit.ViewModels return Task.Run(() => { - Commands.ExecuteCustomAction.Run(_repo.FullPath, CustomAction.Executable, _args, SetProgressDescription); + if (CustomAction.WaitForExit) + Commands.ExecuteCustomAction.RunAndWait(_repo.FullPath, CustomAction.Executable, _args, SetProgressDescription); + else + Commands.ExecuteCustomAction.Run(_repo.FullPath, CustomAction.Executable, _args); + CallUIThread(() => _repo.SetWatcherEnabled(true)); return true; }); diff --git a/src/Views/RepositoryConfigure.axaml b/src/Views/RepositoryConfigure.axaml index 5e9374f9..d9383743 100644 --- a/src/Views/RepositoryConfigure.axaml +++ b/src/Views/RepositoryConfigure.axaml @@ -341,7 +341,7 @@ - + @@ -439,6 +439,8 @@ + + From 37fed935894a08b073a0c02aeebe9c9083077ecd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Feb 2025 06:34:33 +0000 Subject: [PATCH 215/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 67ee5258..50f92a53 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-98.13%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-98.13%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.91%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-98.40%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-92.65%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-98.13%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-98.00%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-98.00%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.79%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-98.26%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-92.52%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-98.00%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index 9f7a1c80..f67ceacc 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,4 +1,4 @@ -### de_DE.axaml: 98.13% +### de_DE.axaml: 98.00%
@@ -11,6 +11,7 @@ - Text.ApplyStash.RestoreIndex - Text.ApplyStash.Stash - Text.Clone.RecurseSubmodules +- Text.Configure.CustomAction.WaitForExit - Text.CreateBranch.Name.WarnSpace - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup @@ -21,7 +22,7 @@
-### es_ES.axaml: 98.13% +### es_ES.axaml: 98.00%
@@ -34,6 +35,7 @@ - Text.ApplyStash.RestoreIndex - Text.ApplyStash.Stash - Text.Clone.RecurseSubmodules +- Text.Configure.CustomAction.WaitForExit - Text.CreateBranch.Name.WarnSpace - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup @@ -44,7 +46,7 @@
-### fr_FR.axaml: 92.91% +### fr_FR.axaml: 92.79%
@@ -57,6 +59,7 @@ - Text.ApplyStash.RestoreIndex - Text.ApplyStash.Stash - Text.Clone.RecurseSubmodules +- Text.Configure.CustomAction.WaitForExit - Text.CreateBranch.Name.WarnSpace - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup @@ -106,7 +109,7 @@
-### it_IT.axaml: 98.40% +### it_IT.axaml: 98.26%
@@ -119,6 +122,7 @@ - Text.ApplyStash.RestoreIndex - Text.ApplyStash.Stash - Text.Clone.RecurseSubmodules +- Text.Configure.CustomAction.WaitForExit - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup - Text.DeleteRepositoryNode.TipForRepository @@ -127,7 +131,7 @@
-### pt_BR.axaml: 92.65% +### pt_BR.axaml: 92.52%
@@ -145,6 +149,7 @@ - Text.CommitCM.MergeMultiple - Text.CommitDetail.Files.Search - Text.CommitDetail.Info.Children +- Text.Configure.CustomAction.WaitForExit - Text.Configure.IssueTracker.AddSampleGiteeIssue - Text.Configure.IssueTracker.AddSampleGiteePullRequest - Text.CreateBranch.Name.WarnSpace @@ -191,7 +196,7 @@
-### ru_RU.axaml: 98.13% +### ru_RU.axaml: 98.00%
@@ -204,6 +209,7 @@ - Text.ApplyStash.RestoreIndex - Text.ApplyStash.Stash - Text.Clone.RecurseSubmodules +- Text.Configure.CustomAction.WaitForExit - Text.CreateBranch.Name.WarnSpace - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup From 06df27780f46ad62b14a0305635546c1b6870528 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 11 Feb 2025 14:36:46 +0800 Subject: [PATCH 216/441] localization: update `Text.Configure.CustomAction.WaitForExit` for en_US Signed-off-by: leo --- src/Resources/Locales/en_US.axaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 40f95793..9aeaae50 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -158,7 +158,7 @@ Scope: Commit Repository - Wait for action done + Wait for action exit Email Address Email address GIT From 37e592638823681af941e99ccdb64a43cbdda7f4 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 11 Feb 2025 14:41:56 +0800 Subject: [PATCH 217/441] code_style: keep translation ordered Signed-off-by: leo --- src/Resources/Locales/de_DE.axaml | 2 +- src/Resources/Locales/en_US.axaml | 2 +- src/Resources/Locales/es_ES.axaml | 2 +- src/Resources/Locales/fr_FR.axaml | 2 +- src/Resources/Locales/it_IT.axaml | 2 +- src/Resources/Locales/pt_BR.axaml | 2 +- src/Resources/Locales/ru_RU.axaml | 2 +- src/Resources/Locales/zh_CN.axaml | 2 +- src/Resources/Locales/zh_TW.axaml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index fe961d14..e4cefbd4 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -565,6 +565,7 @@ Aufheben Im Graph ausblenden Im Graph filtern + Aktiviere '--first-parent' Option LAYOUT Horizontal Vertikal @@ -573,7 +574,6 @@ Topologie LOKALE BRANCHES Zum HEAD wechseln - Aktiviere '--first-parent' Option Erstelle Branch Nur aktuellen Branch im Graphen hervorheben Öffne in {0} diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 9aeaae50..83a9650f 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -574,6 +574,7 @@ Unset Hide in commit graph Filter in commit graph + Enable '--first-parent' Option LAYOUT Horizontal Vertical @@ -582,7 +583,6 @@ Topologically LOCAL BRANCHES Navigate to HEAD - Enable '--first-parent' Option Create Branch Only highlight current branch in graph Open in {0} diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index 3e926c63..a0f35814 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -566,6 +566,7 @@ Desestablecer Ocultar en el Gráfico de Commits Filtrar en el Gráfico de Commits + Habilitar Opción '--first-parent' DISPOSICIÓN Horizontal Vertical @@ -574,7 +575,6 @@ Topológicamente RAMAS LOCALES Navegar a HEAD - Habilitar Opción '--first-parent' Crear Rama Resaltar solo la rama actual en el gráfico Abrir en {0} diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index da20a5ee..b269424a 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -548,9 +548,9 @@ Activer l'option '--reflog' Ouvrir dans l'explorateur de fichiers Rechercher Branches/Tags/Submodules + Activer l'option '--first-parent' BRANCHES LOCALES Naviguer vers le HEAD - Activer l'option '--first-parent' Créer une branche Mettre la branche courante en surbrillance dans le graph Ouvrir dans {0} diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml index 95f7bd1d..1d0d353e 100644 --- a/src/Resources/Locales/it_IT.axaml +++ b/src/Resources/Locales/it_IT.axaml @@ -568,6 +568,7 @@ Non impostato Nascondi nel grafico dei commit Filtra nel grafico dei commit + Abilita opzione '--first-parent' LAYOUT Orizzontale Verticale @@ -576,7 +577,6 @@ Topologicamente BRANCH LOCALI Vai a HEAD - Abilita opzione '--first-parent' Crea Branch Evidenzia nel grafico solo il branch corrente Apri in {0} diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index dee8565b..a318cfa8 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -566,11 +566,11 @@ Desfazer Esconder no gráfico de commit Incluir no gráfico de commit + Habilitar opção '--first-parent' Data do Commit Topologicamente BRANCHES LOCAIS Navegar para HEAD - Habilitar opção '--first-parent' Criar Branch Abrir em {0} Abrir em Ferramentas Externas diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index 27a2d360..e9f03d5a 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -567,6 +567,7 @@ Скрыть в графе ревизии Фильтр в графе ревизии ОТФИЛЬТРОВАНО: + Включить опцию --first-parent РАСПОЛОЖЕНИЕ Горизонтально Вертикально @@ -575,7 +576,6 @@ Топологически ЛОКАЛЬНЫЕ ВЕТКИ Навигация по ГОЛОВЕ (HEAD) - Включить опцию --first-parent Создать ветку Выделять только текущую ветку на графике Открыть в {0} diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index ef31972a..c3932321 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -578,6 +578,7 @@ 不指定 在提交列表中隐藏 使用其对提交列表过滤 + 启用 --first-parent 过滤选项 布局方式 水平排布 竖直排布 @@ -586,7 +587,6 @@ 按拓扑排序 本地分支 定位HEAD - 启用 --first-parent 过滤选项 新建分支 提交路线图中仅高亮显示当前分支 在 {0} 中打开 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 506a618f..3e7382b8 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -577,6 +577,7 @@ 取消指定 在提交列表中隱藏 以其篩選提交列表 + 啟用 [--first-parent] 選項 佈局方式 橫向顯示 縱向顯示 @@ -585,7 +586,6 @@ 依拓撲排序 本機分支 回到 HEAD - 啟用 [--first-parent] 選項 新增分支 提交圖表中僅高亮顯示目前分支 在 {0} 中開啟 From 011a415949ebe23ef224878a0dd213b7be40b8e8 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 11 Feb 2025 15:15:27 +0800 Subject: [PATCH 218/441] enhance: add a button to clear all notifications (#950) Signed-off-by: leo --- src/Resources/Icons.axaml | 1 + src/Resources/Locales/en_US.axaml | 1 + src/Resources/Locales/zh_CN.axaml | 1 + src/Resources/Locales/zh_TW.axaml | 1 + src/ViewModels/LauncherPage.cs | 5 +++++ src/Views/LauncherPage.axaml | 20 ++++++++++++++++++-- 6 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/Resources/Icons.axaml b/src/Resources/Icons.axaml index efec7b2b..8e865660 100644 --- a/src/Resources/Icons.axaml +++ b/src/Resources/Icons.axaml @@ -12,6 +12,7 @@ M529 511c115 0 212 79 239 185h224a62 62 0 017 123l-7 0-224 0a247 247 0 01-479 0H65a62 62 0 01-7-123l7-0h224a247 247 0 01239-185zm0 124a124 124 0 100 247 124 124 0 000-247zm0-618c32 0 58 24 61 55l0 7V206c89 11 165 45 225 103a74 74 0 0122 45l0 9v87a62 62 0 01-123 7l-0-7v-65l-6-4c-43-33-97-51-163-53l-17-0c-74 0-133 18-180 54l-6 4v65a62 62 0 01-55 61l-7 0a62 62 0 01-61-55l-0-7V362c0-20 8-39 23-53 60-58 135-92 224-103V79c0-34 28-62 62-62z M512 926c-229 0-414-186-414-414S283 98 512 98s414 186 414 414-186 414-414 414zm0-73c189 0 341-153 341-341S701 171 512 171 171 323 171 512s153 341 341 341zm-6-192L284 439l52-52 171 171 171-171L728 439l-222 222z M512 57c251 0 455 204 455 455S763 967 512 967 57 763 57 512 261 57 512 57zm181 274c-11-11-29-11-40 0L512 472 371 331c-11-11-29-11-40 0-11 11-11 29 0 40L471 512 331 653c-11 11-11 29 0 40 11 11 29 11 40 0l141-141 141 141c11 11 29 11 40 0 11-11 11-29 0-40L552 512l141-141c11-11 11-29 0-40z + M591 907A85 85 0 01427 875h114a299 299 0 0050 32zM725 405c130 0 235 105 235 235s-105 235-235 235-235-105-235-235 105-235 235-235zM512 64a43 43 0 0143 43v24c126 17 229 107 264 225A298 298 0 00725 341l-4 0A235 235 0 00512 213l-5 0c-125 4-224 104-228 229l-0 6v167a211 211 0 01-26 101l-4 7-14 23h211a298 298 0 0050 85l-276-0a77 77 0 01-66-39c-13-22-14-50-2-73l2-4 22-36c10-17 16-37 17-57l0-7v-167C193 287 313 153 469 131V107a43 43 0 0139-43zm345 505L654 771a149 149 0 00202-202zM725 491a149 149 0 00-131 220l202-202A149 149 0 00725 491z M797 829a49 49 0 1049 49 49 49 0 00-49-49zm147-114A49 49 0 10992 764a49 49 0 00-49-49zM928 861a49 49 0 1049 49A49 49 0 00928 861zm-5-586L992 205 851 64l-71 71a67 67 0 00-94 0l235 235a67 67 0 000-94zm-853 128a32 32 0 00-32 50 1291 1291 0 0075 112L288 552c20 0 25 21 8 37l-93 86a1282 1282 0 00120 114l100-32c19-6 28 15 14 34l-40 55c26 19 53 36 82 53a89 89 0 00115-20 1391 1391 0 00256-485l-188-188s-306 224-595 198z M1280 704c0 141-115 256-256 256H288C129 960 0 831 0 672c0-126 80-232 192-272A327 327 0 01192 384c0-177 143-320 320-320 119 0 222 64 277 160C820 204 857 192 896 192c106 0 192 86 192 192 0 24-5 48-13 69C1192 477 1280 580 1280 704zm-493-128H656V352c0-18-14-32-32-32h-96c-18 0-32 14-32 32v224h-131c-29 0-43 34-23 55l211 211c12 12 33 12 45 0l211-211c20-20 6-55-23-55z M853 102H171C133 102 102 133 102 171v683C102 891 133 922 171 922h683C891 922 922 891 922 853V171C922 133 891 102 853 102zM390 600l-48 48L205 512l137-137 48 48L301 512l88 88zM465 819l-66-18L559 205l66 18L465 819zm218-171L634 600 723 512l-88-88 48-48L819 512 683 649z diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 83a9650f..70da2973 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -584,6 +584,7 @@ LOCAL BRANCHES Navigate to HEAD Create Branch + CLEAR NOTIFICATIONS Only highlight current branch in graph Open in {0} Open in External Tools diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index c3932321..005ef3a2 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -588,6 +588,7 @@ 本地分支 定位HEAD 新建分支 + 清空通知列表 提交路线图中仅高亮显示当前分支 在 {0} 中打开 使用外部工具打开 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 3e7382b8..fe0e4bac 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -587,6 +587,7 @@ 本機分支 回到 HEAD 新增分支 + 清空通知清單 提交圖表中僅高亮顯示目前分支 在 {0} 中開啟 使用外部工具開啟 diff --git a/src/ViewModels/LauncherPage.cs b/src/ViewModels/LauncherPage.cs index b8138aca..63cb52af 100644 --- a/src/ViewModels/LauncherPage.cs +++ b/src/ViewModels/LauncherPage.cs @@ -45,6 +45,11 @@ namespace SourceGit.ViewModels _data = repo; } + public void ClearNotifications() + { + Notifications.Clear(); + } + public void CopyPath() { if (_node.IsRepository) diff --git a/src/Views/LauncherPage.axaml b/src/Views/LauncherPage.axaml index ee4c77eb..81f504c1 100644 --- a/src/Views/LauncherPage.axaml +++ b/src/Views/LauncherPage.axaml @@ -53,7 +53,7 @@ PointerPressed="OnMaskClicked" IsVisible="{Binding Popup, Converter={x:Static ObjectConverters.IsNotNull}}"/> - + + + + - + From 1bfe1a275511a23f9a665da414ac892df66097e7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Feb 2025 07:15:47 +0000 Subject: [PATCH 219/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 50f92a53..623347bf 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-98.00%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-98.00%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.79%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-98.26%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-92.52%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-98.00%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-97.87%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.87%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.67%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-98.13%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-92.40%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-97.87%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index f67ceacc..d1e474d2 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,4 +1,4 @@ -### de_DE.axaml: 98.00% +### de_DE.axaml: 97.87%
@@ -16,13 +16,14 @@ - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup - Text.DeleteRepositoryNode.TipForRepository +- Text.Repository.Notifications.Clear - Text.Stash.AutoRestore - Text.Stash.AutoRestore.Tip - Text.WorkingCopy.SignOff
-### es_ES.axaml: 98.00% +### es_ES.axaml: 97.87%
@@ -40,13 +41,14 @@ - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup - Text.DeleteRepositoryNode.TipForRepository +- Text.Repository.Notifications.Clear - Text.Stash.AutoRestore - Text.Stash.AutoRestore.Tip - Text.WorkingCopy.SignOff
-### fr_FR.axaml: 92.79% +### fr_FR.axaml: 92.67%
@@ -90,6 +92,7 @@ - Text.Repository.HistoriesOrder - Text.Repository.HistoriesOrder.ByDate - Text.Repository.HistoriesOrder.Topo +- Text.Repository.Notifications.Clear - Text.Repository.Skip - Text.Repository.Tags.OrderByCreatorDate - Text.Repository.Tags.OrderByNameAsc @@ -109,7 +112,7 @@
-### it_IT.axaml: 98.26% +### it_IT.axaml: 98.13%
@@ -126,12 +129,13 @@ - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup - Text.DeleteRepositoryNode.TipForRepository +- Text.Repository.Notifications.Clear - Text.Stash.AutoRestore - Text.Stash.AutoRestore.Tip
-### pt_BR.axaml: 92.52% +### pt_BR.axaml: 92.40%
@@ -177,6 +181,7 @@ - Text.Repository.HistoriesLayout.Horizontal - Text.Repository.HistoriesLayout.Vertical - Text.Repository.HistoriesOrder +- Text.Repository.Notifications.Clear - Text.Repository.OnlyHighlightCurrentBranchInHistories - Text.Repository.Skip - Text.Repository.Tags.OrderByCreatorDate @@ -196,7 +201,7 @@
-### ru_RU.axaml: 98.00% +### ru_RU.axaml: 97.87%
@@ -214,6 +219,7 @@ - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup - Text.DeleteRepositoryNode.TipForRepository +- Text.Repository.Notifications.Clear - Text.Stash.AutoRestore - Text.Stash.AutoRestore.Tip - Text.WorkingCopy.SignOff From e9d16a5102351c107ca5cfc43785afc5663d9ef6 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 11 Feb 2025 16:58:10 +0800 Subject: [PATCH 220/441] project: upgrade `TextMateSharp` to `1.0.66` (#969) Signed-off-by: leo --- src/SourceGit.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj index af8fa5b1..624804f1 100644 --- a/src/SourceGit.csproj +++ b/src/SourceGit.csproj @@ -52,8 +52,8 @@ - - + + From 21cfd17cdb8c6467ff8704d67a820ec17f29dbcd Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 11 Feb 2025 18:57:54 +0800 Subject: [PATCH 221/441] fix: do NOT quit when try to input `@` via `Alt Gr+Q` with German ISO keyboard layout (#970) Signed-off-by: leo --- src/Views/Launcher.axaml.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Views/Launcher.axaml.cs b/src/Views/Launcher.axaml.cs index b5f09d79..e3140191 100644 --- a/src/Views/Launcher.axaml.cs +++ b/src/Views/Launcher.axaml.cs @@ -120,6 +120,13 @@ namespace SourceGit.Views return; } + // Ctrl+Q quits the application (macOS use hotkeys in system menu bar) + if (!OperatingSystem.IsMacOS() && e.KeyModifiers == KeyModifiers.Control && e.Key == Key.Q) + { + App.Quit(0); + return; + } + if (e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control)) { if (e.Key == Key.W) @@ -146,13 +153,6 @@ namespace SourceGit.Views return; } - if (e.Key == Key.Q) - { - App.Quit(0); - e.Handled = true; - return; - } - if ((OperatingSystem.IsMacOS() && e.KeyModifiers.HasFlag(KeyModifiers.Alt) && e.Key == Key.Right) || (!OperatingSystem.IsMacOS() && !e.KeyModifiers.HasFlag(KeyModifiers.Shift) && e.Key == Key.Tab)) { From eea55ec56fffc10032829662c43f36f5a14cd549 Mon Sep 17 00:00:00 2001 From: AquariusStar <48148723+AquariusStar@users.noreply.github.com> Date: Wed, 12 Feb 2025 05:51:06 +0300 Subject: [PATCH 222/441] localization: update russian localization (#971) --- src/Resources/Locales/ru_RU.axaml | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index e9f03d5a..a1c40764 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -22,7 +22,9 @@ Отслеживание ветки: Отслеживание внешней ветки OpenAI Ассистент + ПЕРЕСОЗДАТЬ Использовать OpenAI для создания сообщения о ревизии + ПРИМЕНИТЬ КАК СООБЩЕНИЕ РЕВИЗИИ Исправить Ошибка Выдает ошибки и отказывается применять исправление @@ -37,6 +39,10 @@ Предупреждать Выдавать предупреждения о нескольких таких ошибках, но применять Пробел: + Отложить + Удалить после применения + Восстановить изменения индекса + Отложенный: Архивировать... Сохранить архив в: Выберите путь к архивному файлу @@ -100,6 +106,7 @@ Локальное имя: Имя репозитория. (необязательно). Родительский каталог: + Инициализировать и обновить подмодуль Адрес репозитория: ЗАКРЫТЬ Редактор @@ -131,7 +138,7 @@ АВТОР ИЗМЕНЁННЫЙ ДОЧЕРНИЙ - ИСПОЛНИТЕЛЬ + РЕВИЗОР(ИСПОЛНИТЕЛЬ) Найти все ветки с этой ревизией ВЕТКИ С ЭТОЙ РЕВИЗИЕЙ Отображаются только первые 100 изменений. Смотрите все изменения на вкладке ИЗМЕНЕНИЯ. @@ -154,15 +161,16 @@ Диапазон: Ревизия Репозиторий + Ждать для выполения выхода Адрес электронной почты Адрес электронной почты GIT - Автоматическое скачивание изменений + Автоматическая загрузка изменений Минут(а/ы) Внешний репозиторий по умолчанию ОТСЛЕЖИВАНИЕ ПРОБЛЕМ - Добавить пример правила для тем в Gitee - Добавить пример правила запроса скачивания из Gitee + Добавить пример правила для тем в Gitea + Добавить пример правила запроса скачивания из Gitea Добавить пример правила для Git Добавить пример правила Jira Добавить пример правила выдачи GitLab @@ -203,6 +211,7 @@ Отложить и применить повторно Имя новой ветки: Введите имя ветки. + Пробелы будут заменены на тире. Создать локальную ветку Создать метку... Новая метка у: @@ -226,8 +235,11 @@ Вы пытаетесь удалить несколько веток одновременно. Обязательно перепроверьте, прежде чем предпринимать какие-либо действия! Удалить внешний репозиторий Внешний репозиторий: + Path: Цель: + Все дочерние элементы будут удалены из списка. Подтвердите удаление группы + Будет удалён из списка. На диске останется. Подтвердите удаление репозитория Удалить подмодуль Путь подмодуля: @@ -577,6 +589,7 @@ ЛОКАЛЬНЫЕ ВЕТКИ Навигация по ГОЛОВЕ (HEAD) Создать ветку + ОЧИСТКА УВЕДОМЛЕНИЙ Выделять только текущую ветку на графике Открыть в {0} Открыть в расширенном инструменте @@ -585,7 +598,7 @@ ДОБАВИТЬ ВНЕШНИЙ РЕПОЗИТОРИЙ Поиск ревизии Автор - исполнитель + Ревизор Файл Сообщение SHA @@ -645,6 +658,8 @@ Подготовленные так и неподготовленные изменения выбранных файлов будут сохранены!!! ЗАПУСК Отложить + Автоматически восстанавливать после откладывания + Ваши рабочие файлы остаются неизменными, но отложенные сохранятся. Включить неотслеживаемые файлы Хранить отложенные файлы Сообщение: @@ -660,7 +675,7 @@ ОТЛОЖЕННЫЕ Статистика РЕВИЗИИ - ИСПОЛНИТЕЛИ + РЕВИЗОРЫ(ИСПОЛНИТЕЛИ) МЕСЯЦ НЕДЕЛЯ РЕВИЗИИ: @@ -722,6 +737,7 @@ ВКЛЮЧИТЬ НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ НЕТ ПОСЛЕДНИХ ВХОДНЫХ СООБЩЕНИЙ НЕТ ШАБЛОНОВ РЕВИЗИИ + Завершение работы ПОДГОТОВЛЕННЫЕ СНЯТЬ ПОДГОТОВЛЕННЫЙ СНЯТЬ ВСЕ ПОДГОТОВЛЕННЫЕ From 19e72f86505233a694d0041c5dbf06170a256681 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 12 Feb 2025 02:51:20 +0000 Subject: [PATCH 223/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 19 ++----------------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 623347bf..eadd0cfd 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-97.87%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.87%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.67%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-98.13%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-92.40%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-97.87%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-97.87%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.87%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.67%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-98.13%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-92.40%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index d1e474d2..86da7846 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -201,28 +201,13 @@
-### ru_RU.axaml: 97.87% +### ru_RU.axaml: 100.00%
Missing Keys -- Text.AIAssistant.Regen -- Text.AIAssistant.Use -- Text.ApplyStash -- Text.ApplyStash.DropAfterApply -- Text.ApplyStash.RestoreIndex -- Text.ApplyStash.Stash -- Text.Clone.RecurseSubmodules -- Text.Configure.CustomAction.WaitForExit -- Text.CreateBranch.Name.WarnSpace -- Text.DeleteRepositoryNode.Path -- Text.DeleteRepositoryNode.TipForGroup -- Text.DeleteRepositoryNode.TipForRepository -- Text.Repository.Notifications.Clear -- Text.Stash.AutoRestore -- Text.Stash.AutoRestore.Tip -- Text.WorkingCopy.SignOff +
From 9757678dcf18de806828d23dbd1631b97602cce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20G=C3=B6ttfert?= <45085620+ChrisGoettfert@users.noreply.github.com> Date: Wed, 12 Feb 2025 03:59:00 +0100 Subject: [PATCH 224/441] localization: added missing german translations (#973) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christopher Göttfert --- src/Resources/Locales/de_DE.axaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index e4cefbd4..995c113b 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -22,7 +22,9 @@ Branch verfolgen: Remote-Branch verfolgen OpenAI Assistent + Neu generieren Verwende OpenAI, um Commit-Nachrichten zu generieren + Als Commit-Nachricht verwenden Patch Fehler Fehler werfen und anwenden des Patches verweigern @@ -37,6 +39,10 @@ Warnen Gibt eine Warnung für ein paar solcher Fehler aus, aber wendet es an Leerzeichen: + Stash anwenden + Nach dem Anwenden löschen + Änderungen des Index wiederherstellen + Stash: Archivieren... Speichere Archiv in: Wähle Archivpfad aus @@ -100,6 +106,7 @@ Lokaler Name: Repository-Name. Optional. Übergeordneter Ordner: + Submodule initialisieren und aktualisieren Repository URL: SCHLIESSEN Editor @@ -202,6 +209,7 @@ Stashen & wieder anwenden Neuer Branch-Name: Branch-Namen eingeben. + Leerzeichen werden durch Bindestriche ersetzt. Lokalen Branch erstellen Tag erstellen... Neuer Tag auf: @@ -225,8 +233,11 @@ Du versuchst mehrere Branches auf einmal zu löschen. Kontrolliere noch einmal vor dem Fortfahren! Remote löschen Remote: + Pfad: Ziel: Bestätige löschen von Gruppe + Alle Nachfolger werden aus der Liste entfernt. + Dadurch wird es nur aus der Liste entfernt, nicht von der Festplatte! Bestätige löschen von Repository Lösche Submodul Submodul Pfad: @@ -574,6 +585,7 @@ Topologie LOKALE BRANCHES Zum HEAD wechseln + Aktiviere '--first-parent' Option Erstelle Branch Nur aktuellen Branch im Graphen hervorheben Öffne in {0} @@ -641,6 +653,8 @@ Pfad zum privaten SSH Schlüssel START Stash + Automatisch wiederherstellen nach dem Stashen + Die Arbeitsdateien bleiben unverändert, aber ein Stash wird gespeichert. Inklusive nicht-verfolgter Dateien Behalte gestagte Dateien Name: @@ -720,6 +734,7 @@ NICHT-VERFOLGTE DATEIEN INKLUDIEREN KEINE BISHERIGEN COMMIT-NACHRICHTEN KEINE COMMIT TEMPLATES + SignOff GESTAGED UNSTAGEN ALLES UNSTAGEN From 21e4dcffd0e301e84045c17af1aa97490fbe0bb8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 12 Feb 2025 02:59:19 +0000 Subject: [PATCH 225/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 16 +--------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index eadd0cfd..f188bf25 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-97.87%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.87%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.67%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-98.13%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-92.40%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.73%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.87%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.67%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-98.13%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-92.40%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index 86da7846..71ef0acf 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,25 +1,11 @@ -### de_DE.axaml: 97.87% +### de_DE.axaml: 99.73%
Missing Keys -- Text.AIAssistant.Regen -- Text.AIAssistant.Use -- Text.ApplyStash -- Text.ApplyStash.DropAfterApply -- Text.ApplyStash.RestoreIndex -- Text.ApplyStash.Stash -- Text.Clone.RecurseSubmodules - Text.Configure.CustomAction.WaitForExit -- Text.CreateBranch.Name.WarnSpace -- Text.DeleteRepositoryNode.Path -- Text.DeleteRepositoryNode.TipForGroup -- Text.DeleteRepositoryNode.TipForRepository - Text.Repository.Notifications.Clear -- Text.Stash.AutoRestore -- Text.Stash.AutoRestore.Tip -- Text.WorkingCopy.SignOff
From 3302bdeb2607149c0ceaa3cadb0901516bea7617 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 12 Feb 2025 21:25:57 +0800 Subject: [PATCH 226/441] localization: remove duplicated keys in de_DE Signed-off-by: leo --- src/Resources/Locales/de_DE.axaml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index 995c113b..b6458822 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -585,7 +585,6 @@ Topologie LOKALE BRANCHES Zum HEAD wechseln - Aktiviere '--first-parent' Option Erstelle Branch Nur aktuellen Branch im Graphen hervorheben Öffne in {0} From c6aedf1193114b8fa94823aecf6c28235817ea16 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 12 Feb 2025 21:29:17 +0800 Subject: [PATCH 227/441] ux: right margin of main tab bar on macOS Signed-off-by: leo --- src/Views/Launcher.axaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Views/Launcher.axaml b/src/Views/Launcher.axaml index bfabf6e5..db5aeecb 100644 --- a/src/Views/Launcher.axaml +++ b/src/Views/Launcher.axaml @@ -86,10 +86,10 @@ - + - +
From 588879eb7f8689506179e02fea6402d6b5a8ed3b Mon Sep 17 00:00:00 2001 From: "Dmitrij D. Czarkoff" Date: Thu, 13 Feb 2025 02:41:08 +0000 Subject: [PATCH 228/441] feat: change worktree presentation (#978) Present the worktree name first, then relative path to the main repo. This is more aligned with Git's own UI, and works better with UI size constrains. --- src/Commands/Worktree.cs | 2 ++ src/Models/Worktree.cs | 9 +++++---- src/Views/RemoveWorktree.axaml | 4 ++-- src/Views/Repository.axaml | 4 ++-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Commands/Worktree.cs b/src/Commands/Worktree.cs index 27c0e28e..b73b8573 100644 --- a/src/Commands/Worktree.cs +++ b/src/Commands/Worktree.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; namespace SourceGit.Commands { @@ -26,6 +27,7 @@ namespace SourceGit.Commands if (line.StartsWith("worktree ", StringComparison.Ordinal)) { last = new Models.Worktree() { FullPath = line.Substring(9).Trim() }; + last.RelativePath = Path.GetRelativePath(WorkingDirectory, last.FullPath); worktrees.Add(last); } else if (line.StartsWith("bare", StringComparison.Ordinal)) diff --git a/src/Models/Worktree.cs b/src/Models/Worktree.cs index f9ba14e4..bc40e320 100644 --- a/src/Models/Worktree.cs +++ b/src/Models/Worktree.cs @@ -6,6 +6,7 @@ namespace SourceGit.Models { public string Branch { get; set; } = string.Empty; public string FullPath { get; set; } = string.Empty; + public string RelativePath { get; set; } = string.Empty; public string Head { get; set; } = string.Empty; public bool IsBare { get; set; } = false; public bool IsDetached { get; set; } = false; @@ -21,15 +22,15 @@ namespace SourceGit.Models get { if (IsDetached) - return $"(deteched HEAD at {Head.Substring(10)})"; + return $"deteched HEAD at {Head.Substring(10)}"; if (Branch.StartsWith("refs/heads/", System.StringComparison.Ordinal)) - return $"({Branch.Substring(11)})"; + return Branch.Substring(11); if (Branch.StartsWith("refs/remotes/", System.StringComparison.Ordinal)) - return $"({Branch.Substring(13)})"; + return Branch.Substring(13); - return $"({Branch})"; + return Branch; } } diff --git a/src/Views/RemoveWorktree.axaml b/src/Views/RemoveWorktree.axaml index 6d7ea914..364881d2 100644 --- a/src/Views/RemoveWorktree.axaml +++ b/src/Views/RemoveWorktree.axaml @@ -18,8 +18,8 @@ - - + + () diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index 74f628c6..4180a054 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -372,8 +372,8 @@ - - + + () From 9b07034846ea097f2628930ea43ce818ca0a35a1 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 13 Feb 2025 10:46:28 +0800 Subject: [PATCH 229/441] code_review: PR #978 * Remove unnecessary parentheses since the name of relative path uses secondary foreground color already Signed-off-by: leo --- src/Views/RemoveWorktree.axaml | 2 +- src/Views/Repository.axaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Views/RemoveWorktree.axaml b/src/Views/RemoveWorktree.axaml index 364881d2..736e6e40 100644 --- a/src/Views/RemoveWorktree.axaml +++ b/src/Views/RemoveWorktree.axaml @@ -19,7 +19,7 @@ - () +
diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index 4180a054..4d6bc64a 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -373,7 +373,7 @@ - () + From 9104060d79b0c4e5f316550cab8eca267e9e15ba Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 14 Feb 2025 10:43:08 +0800 Subject: [PATCH 230/441] feature: support add custom actions for selected branch (#980) Signed-off-by: leo --- src/Models/CustomAction.cs | 1 + src/Resources/Locales/en_US.axaml | 4 ++- src/Resources/Locales/zh_CN.axaml | 4 ++- src/Resources/Locales/zh_TW.axaml | 4 ++- src/ViewModels/ExecuteCustomAction.cs | 19 ++++++++++-- src/ViewModels/Repository.cs | 42 ++++++++++++++++++++++++++- src/Views/RepositoryConfigure.axaml | 21 ++++---------- 7 files changed, 73 insertions(+), 22 deletions(-) diff --git a/src/Models/CustomAction.cs b/src/Models/CustomAction.cs index bd56d6ae..a614961a 100644 --- a/src/Models/CustomAction.cs +++ b/src/Models/CustomAction.cs @@ -6,6 +6,7 @@ namespace SourceGit.Models { Repository, Commit, + Branch, } public class CustomAction : ObservableObject diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 70da2973..f8a06f08 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -56,6 +56,7 @@ Compare with HEAD Compare with Worktree Copy Branch Name + Custom Action Delete ${0}$... Delete selected {0} branches Discard all changes @@ -152,10 +153,11 @@ Template Content: CUSTOM ACTION Arguments: - ${REPO} - Repository's path; ${SHA} - Selected commit's SHA + ${REPO} - Repository's path; ${BRANCH} - Selected branch; ${SHA} - Selected commit's SHA Executable File: Name: Scope: + Branch Commit Repository Wait for action exit diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 005ef3a2..4db909c9 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -59,6 +59,7 @@ 与当前HEAD比较 与本地工作树比较 复制分支名 + 自定义操作 删除 ${0}$... 删除选中的 {0} 个分支 放弃所有更改 @@ -155,10 +156,11 @@ 模板内容 : 自定义操作 命令行参数 : - 请使用${REPO}代替仓库路径,${SHA}代替提交哈希 + 请使用${REPO}代替仓库路径,${BRANCH}代替选中的分支,${SHA}代替提交哈希 可执行文件路径 : 名称 : 作用目标 : + 选中的分支 选中的提交 仓库 等待操作执行完成 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index fe0e4bac..167565cf 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -59,6 +59,7 @@ 與目前 HEAD 比較 與本機工作區比較 複製分支名稱 + 自訂動作 刪除 ${0}$... 刪除所選的 {0} 個分支 捨棄所有變更 @@ -155,10 +156,11 @@ 範本內容: 自訂動作 指令參數: - 使用 ${REPO} 表示存放庫路徑、${SHA} 表示所選的提交編號 + 使用 ${REPO} 表示存放庫路徑、${BRANCH} 表示所選的分支、${SHA} 表示所選的提交編號 可執行檔案路徑: 名稱: 執行範圍: + 選取的分支 選取的提交 存放庫 等待自訂操作退出 diff --git a/src/ViewModels/ExecuteCustomAction.cs b/src/ViewModels/ExecuteCustomAction.cs index 848faaaf..8e34379f 100644 --- a/src/ViewModels/ExecuteCustomAction.cs +++ b/src/ViewModels/ExecuteCustomAction.cs @@ -10,13 +10,26 @@ namespace SourceGit.ViewModels private set; } - public ExecuteCustomAction(Repository repo, Models.CustomAction action, Models.Commit commit) + public ExecuteCustomAction(Repository repo, Models.CustomAction action) { _repo = repo; _args = action.Arguments.Replace("${REPO}", _repo.FullPath); - if (commit != null) - _args = _args.Replace("${SHA}", commit.SHA); + CustomAction = action; + View = new Views.ExecuteCustomAction() { DataContext = this }; + } + public ExecuteCustomAction(Repository repo, Models.CustomAction action, Models.Branch branch) + { + _repo = repo; + _args = action.Arguments.Replace("${REPO}", _repo.FullPath).Replace("${BRANCH}", branch.FriendlyName); + CustomAction = action; + View = new Views.ExecuteCustomAction() { DataContext = this }; + } + + public ExecuteCustomAction(Repository repo, Models.CustomAction action, Models.Commit commit) + { + _repo = repo; + _args = action.Arguments.Replace("${REPO}", _repo.FullPath).Replace("${SHA}", commit.SHA); CustomAction = action; View = new Views.ExecuteCustomAction() { DataContext = this }; } diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 44de8c35..6b96255f 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1439,7 +1439,7 @@ namespace SourceGit.ViewModels item.Click += (_, e) => { if (CanCreatePopup()) - ShowAndStartPopup(new ExecuteCustomAction(this, dup, null)); + ShowAndStartPopup(new ExecuteCustomAction(this, dup)); e.Handled = true; }; @@ -1698,6 +1698,7 @@ namespace SourceGit.ViewModels menu.Items.Add(createBranch); menu.Items.Add(createTag); menu.Items.Add(new MenuItem() { Header = "-" }); + TryToAddCustomActionsToBranchContextMenu(menu, branch); if (!IsBare) { @@ -1968,7 +1969,9 @@ namespace SourceGit.ViewModels menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(archive); menu.Items.Add(new MenuItem() { Header = "-" }); + TryToAddCustomActionsToBranchContextMenu(menu, branch); menu.Items.Add(copy); + return menu; } @@ -2319,6 +2322,43 @@ namespace SourceGit.ViewModels return null; } + private void TryToAddCustomActionsToBranchContextMenu(ContextMenu menu, Models.Branch branch) + { + var actions = new List(); + foreach (var action in Settings.CustomActions) + { + if (action.Scope == Models.CustomActionScope.Branch) + actions.Add(action); + } + + if (actions.Count == 0) + return; + + var custom = new MenuItem(); + custom.Header = App.Text("BranchCM.CustomAction"); + custom.Icon = App.CreateMenuIcon("Icons.Action"); + + foreach (var action in actions) + { + var dup = action; + var item = new MenuItem(); + item.Icon = App.CreateMenuIcon("Icons.Action"); + item.Header = dup.Name; + item.Click += (_, e) => + { + if (CanCreatePopup()) + ShowAndStartPopup(new ExecuteCustomAction(this, dup, branch)); + + e.Handled = true; + }; + + custom.Items.Add(item); + } + + menu.Items.Add(custom); + menu.Items.Add(new MenuItem() { Header = "-" }); + } + private void UpdateCurrentRevisionFilesForSearchSuggestion() { _revisionFiles.Clear(); diff --git a/src/Views/RepositoryConfigure.axaml b/src/Views/RepositoryConfigure.axaml index d9383743..6b7cdc12 100644 --- a/src/Views/RepositoryConfigure.axaml +++ b/src/Views/RepositoryConfigure.axaml @@ -5,7 +5,6 @@ xmlns:m="using:SourceGit.Models" xmlns:vm="using:SourceGit.ViewModels" xmlns:v="using:SourceGit.Views" - xmlns:ac="using:Avalonia.Controls.Converters" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="SourceGit.Views.RepositoryConfigure" x:DataType="vm:RepositoryConfigure" @@ -412,20 +411,12 @@ - - - - - - - - - + + + + + + From e39351b4a77e3f179340c4a1b61ed04087a9c3fc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 14 Feb 2025 02:43:26 +0000 Subject: [PATCH 231/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 25 ++++++++++++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f188bf25..3829cf54 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.73%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.87%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.67%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-98.13%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-92.40%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.47%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.61%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.42%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-97.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-92.15%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.73%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index 71ef0acf..84411404 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,15 +1,17 @@ -### de_DE.axaml: 99.73% +### de_DE.axaml: 99.47%
Missing Keys +- Text.BranchCM.CustomAction +- Text.Configure.CustomAction.Scope.Branch - Text.Configure.CustomAction.WaitForExit - Text.Repository.Notifications.Clear
-### es_ES.axaml: 97.87% +### es_ES.axaml: 97.61%
@@ -21,7 +23,9 @@ - Text.ApplyStash.DropAfterApply - Text.ApplyStash.RestoreIndex - Text.ApplyStash.Stash +- Text.BranchCM.CustomAction - Text.Clone.RecurseSubmodules +- Text.Configure.CustomAction.Scope.Branch - Text.Configure.CustomAction.WaitForExit - Text.CreateBranch.Name.WarnSpace - Text.DeleteRepositoryNode.Path @@ -34,7 +38,7 @@
-### fr_FR.axaml: 92.67% +### fr_FR.axaml: 92.42%
@@ -46,7 +50,9 @@ - Text.ApplyStash.DropAfterApply - Text.ApplyStash.RestoreIndex - Text.ApplyStash.Stash +- Text.BranchCM.CustomAction - Text.Clone.RecurseSubmodules +- Text.Configure.CustomAction.Scope.Branch - Text.Configure.CustomAction.WaitForExit - Text.CreateBranch.Name.WarnSpace - Text.DeleteRepositoryNode.Path @@ -98,7 +104,7 @@
-### it_IT.axaml: 98.13% +### it_IT.axaml: 97.87%
@@ -110,7 +116,9 @@ - Text.ApplyStash.DropAfterApply - Text.ApplyStash.RestoreIndex - Text.ApplyStash.Stash +- Text.BranchCM.CustomAction - Text.Clone.RecurseSubmodules +- Text.Configure.CustomAction.Scope.Branch - Text.Configure.CustomAction.WaitForExit - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup @@ -121,7 +129,7 @@
-### pt_BR.axaml: 92.40% +### pt_BR.axaml: 92.15%
@@ -133,12 +141,14 @@ - Text.ApplyStash.DropAfterApply - Text.ApplyStash.RestoreIndex - Text.ApplyStash.Stash +- Text.BranchCM.CustomAction - Text.BranchCM.MergeMultiBranches - Text.Clone.RecurseSubmodules - Text.CommitCM.Merge - Text.CommitCM.MergeMultiple - Text.CommitDetail.Files.Search - Text.CommitDetail.Info.Children +- Text.Configure.CustomAction.Scope.Branch - Text.Configure.CustomAction.WaitForExit - Text.Configure.IssueTracker.AddSampleGiteeIssue - Text.Configure.IssueTracker.AddSampleGiteePullRequest @@ -187,13 +197,14 @@
-### ru_RU.axaml: 100.00% +### ru_RU.axaml: 99.73%
Missing Keys - +- Text.BranchCM.CustomAction +- Text.Configure.CustomAction.Scope.Branch
From bc66e24407629efc0f9791fe14f3f05d9f1484e3 Mon Sep 17 00:00:00 2001 From: leo Date: Sat, 15 Feb 2025 17:43:32 +0800 Subject: [PATCH 232/441] project: upgrade `AvaloniaUI` to `11.2.4` Signed-off-by: leo --- src/SourceGit.csproj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj index 624804f1..7cceee7e 100644 --- a/src/SourceGit.csproj +++ b/src/SourceGit.csproj @@ -41,11 +41,11 @@ - - - - - + + + + + From 36178d5ecf00e650a59058d538d9ae2764f9b2d7 Mon Sep 17 00:00:00 2001 From: Chiahong <36815907+ChiahongHong@users.noreply.github.com> Date: Tue, 18 Feb 2025 09:26:44 +0800 Subject: [PATCH 233/441] localization: update zh_TW.axaml (#989) --- src/Resources/Locales/zh_TW.axaml | 38 +++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 167565cf..a3fe5c19 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -39,10 +39,10 @@ 警告 套用修補檔,輸出關於空白字元的警告 空白字元處理: - 套用擱置 - 在成功套用后捨棄擱置 - 恢復索引中已暫存的變更 - 已選擇擱置 : + 套用擱置變更 + 套用擱置變更後刪除 + 還原索引中已暫存的變更 (--index) + 已選擇擱置變更: 封存 (archive)... 封存檔案路徑: 選擇封存檔案的儲存路徑 @@ -107,7 +107,7 @@ 本機存放庫名稱: 本機存放庫目錄的名稱,選填。 父級目錄: - 初始化並複製子模組 + 初始化並更新子模組 遠端存放庫: 關閉 提交訊息編輯器 @@ -163,7 +163,7 @@ 選取的分支 選取的提交 存放庫 - 等待自訂操作退出 + 等待自訂動作執行結束 電子郵件 電子郵件地址 Git 設定 @@ -240,7 +240,7 @@ 目標: 所有子節點都會從清單中移除。 刪除群組確認 - 只會從清單中移除,而不會刪除磁碟中的檔案! + 只會從清單中移除,而不會刪除磁碟中的檔案! 刪除存放庫確認 刪除子模組確認 子模組路徑: @@ -265,7 +265,7 @@ 交換比對雙方 語法上色 自動換行 - 啟用基於變更區塊的導航 + 區塊切換上/下一個差異 使用外部合併工具檢視 顯示檔案的全部內容 減少可見的行數 @@ -412,7 +412,7 @@ 合併操作進行中。 正在處理 重定基底 (rebase) 操作進行中。 - 当前停止于 + 目前停止於 復原提交操作進行中。 正在復原提交 互動式重定基底 @@ -425,8 +425,8 @@ 合併分支 目標分支: 合併方式: - 合併目標: - 合併(多目標) + 合併來源: + 合併 (多個來源) 提交變更 合併策略: 目標列表: @@ -580,17 +580,17 @@ 在提交列表中隱藏 以其篩選提交列表 啟用 [--first-parent] 選項 - 佈局方式 + 版面配置 橫向顯示 縱向顯示 提交顯示順序 - 依提交時間排序 + 依時間排序 依拓撲排序 本機分支 回到 HEAD 新增分支 - 清空通知清單 - 提交圖表中僅高亮顯示目前分支 + 清除所有通知 + 在提交路線圖中僅對目前分支上色 在 {0} 中開啟 使用外部工具開啟 重新載入 @@ -616,7 +616,7 @@ 依名稱降序 排序 在終端機中開啟 - 在提交清單中使用相對時間 + 在提交列表中使用相對時間 工作區列表 新增工作區 清理 @@ -656,8 +656,8 @@ SSH 金鑰檔案 開 始 擱置變更 (stash) - 暫存後自動復原工作區 - 工作區檔案保持未修改,但暫存內容已儲存。 + 擱置變更後自動復原工作區 + 工作區檔案保持未修改,但擱置內容已儲存。 包含未追蹤的檔案 保留已暫存的變更 擱置變更訊息: @@ -729,7 +729,7 @@ 提交並推送 歷史輸入/範本 觸發點擊事件 - 提交(修改現有提交) + 提交 (修改原始提交) 自動暫存全部變更並提交 未包含任何檔案變更! 您是否仍要提交 (--allow-empty)? 檢測到衝突 From 7ae5100fcf210649e6a9f19189e88615dea1a4b7 Mon Sep 17 00:00:00 2001 From: Arun Date: Mon, 17 Feb 2025 17:25:51 -0800 Subject: [PATCH 234/441] chore: Convey the usage of monospace font only in text editor (#990) Signed-off-by: Arun (cherry picked from commit 7ec7de7b4a933a599cfffc79382a6edd13582c85) --- src/Resources/Locales/en_US.axaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index f8a06f08..cd266666 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -465,7 +465,7 @@ Default Editor Monospace Font - Only use monospace font in text editor + Use monospace font only in text editor Theme Theme Overrides Use fixed tab width in titlebar From 14f47a9007beab39a02fc10c08eb0736e4bdc116 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 18 Feb 2025 09:50:01 +0800 Subject: [PATCH 235/441] =?UTF-8?q?ux:=20style=20for=20current=20branch=20?= =?UTF-8?q?in=20branch=20tree=20(#991=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: leo --- src/ViewModels/BranchTreeNode.cs | 4 ++-- src/Views/BranchTree.axaml | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/ViewModels/BranchTreeNode.cs b/src/ViewModels/BranchTreeNode.cs index 698dc7ad..5c42f729 100644 --- a/src/ViewModels/BranchTreeNode.cs +++ b/src/ViewModels/BranchTreeNode.cs @@ -40,9 +40,9 @@ namespace SourceGit.ViewModels get => Backend is Models.Branch; } - public FontWeight NameFontWeight + public bool IsCurrent { - get => Backend is Models.Branch { IsCurrent: true } ? FontWeight.Bold : FontWeight.Regular; + get => Backend is Models.Branch { IsCurrent: true }; } public string Tooltip diff --git a/src/Views/BranchTree.axaml b/src/Views/BranchTree.axaml index 0ebcdf20..b7ac725b 100644 --- a/src/Views/BranchTree.axaml +++ b/src/Views/BranchTree.axaml @@ -57,11 +57,17 @@ IsExpanded="{Binding IsExpanded}"/> - + + + + + + + + Date: Tue, 18 Feb 2025 10:04:56 +0800 Subject: [PATCH 236/441] enhance: supports remove single histories filter (#987) Signed-off-by: leo --- src/ViewModels/Repository.cs | 9 +++++++++ src/Views/Repository.axaml | 6 +++++- src/Views/Repository.axaml.cs | 8 ++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 6b96255f..19e48b13 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -826,6 +826,15 @@ namespace SourceGit.ViewModels Task.Run(RefreshCommits); } + public void RemoveHistoriesFilter(Models.Filter filter) + { + if (_settings.HistoriesFilters.Remove(filter)) + { + HistoriesFilterMode = _settings.HistoriesFilters.Count > 0 ? _settings.HistoriesFilters[0].Mode : Models.FilterMode.None; + RefreshHistoriesFilters(true); + } + } + public void UpdateBranchNodeIsExpanded(BranchTreeNode node) { if (_settings == null || !string.IsNullOrWhiteSpace(_filter)) diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index 4d6bc64a..30180f7d 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -685,7 +685,11 @@ - + + + diff --git a/src/Views/Repository.axaml.cs b/src/Views/Repository.axaml.cs index bb359040..53bb2d53 100644 --- a/src/Views/Repository.axaml.cs +++ b/src/Views/Repository.axaml.cs @@ -519,5 +519,13 @@ namespace SourceGit.Views e.Handled = true; } + + private void OnRemoveSelectedHistoriesFilter(object sender, RoutedEventArgs e) + { + if (DataContext is ViewModels.Repository repo && sender is Button { DataContext: Models.Filter filter}) + repo.RemoveHistoriesFilter(filter); + + e.Handled = true; + } } } From d401e898a287b26cac19ca907bdc8be4dcfbf250 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 18 Feb 2025 10:58:30 +0800 Subject: [PATCH 237/441] version: Release 2025.05 Signed-off-by: leo --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 4ee298df..15689348 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2025.04 \ No newline at end of file +2025.05 \ No newline at end of file From af4645a4ade086672c43a99f23aa2f2e93223d41 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 18 Feb 2025 16:27:19 +0800 Subject: [PATCH 238/441] project: upgrade `LiveChartsCore.SkiaSharpView.Avalonia` to `2.0.0-rc5.4` Signed-off-by: leo --- src/SourceGit.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj index 7cceee7e..12e914f9 100644 --- a/src/SourceGit.csproj +++ b/src/SourceGit.csproj @@ -50,7 +50,7 @@ - + From 3d4a9b86b46f4ee09a1335532483d958edc5f0db Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 18 Feb 2025 16:54:00 +0800 Subject: [PATCH 239/441] ux: use bold font weight for current branch name (#997) Signed-off-by: leo --- src/Converters/BoolConverters.cs | 4 ++++ src/Views/BranchTree.axaml | 1 + 2 files changed, 5 insertions(+) diff --git a/src/Converters/BoolConverters.cs b/src/Converters/BoolConverters.cs index 2d738700..3563fb37 100644 --- a/src/Converters/BoolConverters.cs +++ b/src/Converters/BoolConverters.cs @@ -1,4 +1,5 @@ using Avalonia.Data.Converters; +using Avalonia.Media; namespace SourceGit.Converters { @@ -6,5 +7,8 @@ namespace SourceGit.Converters { public static readonly FuncValueConverter ToPageTabWidth = new FuncValueConverter(x => x ? 200 : double.NaN); + + public static readonly FuncValueConverter IsBoldToFontWeight = + new FuncValueConverter(x => x ? FontWeight.Bold : FontWeight.Normal); } } diff --git a/src/Views/BranchTree.axaml b/src/Views/BranchTree.axaml index b7ac725b..a01f3502 100644 --- a/src/Views/BranchTree.axaml +++ b/src/Views/BranchTree.axaml @@ -65,6 +65,7 @@ From 5d2cd8b2fa6cf94b972865bd73dae7c2c1eef278 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 18 Feb 2025 18:19:19 +0800 Subject: [PATCH 240/441] ux: new style for current branch (#998) Signed-off-by: leo --- src/Resources/Icons.axaml | 1 + src/Views/BranchTree.axaml | 17 +++++------------ src/Views/BranchTree.axaml.cs | 19 ++++++++++++------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/Resources/Icons.axaml b/src/Resources/Icons.axaml index 8e865660..b7d9c22e 100644 --- a/src/Resources/Icons.axaml +++ b/src/Resources/Icons.axaml @@ -8,6 +8,7 @@ M757 226a143 143 0 00-55 276 96 96 0 01-88 59h-191a187 187 0 00-96 27V312a143 143 0 10-96 0v399a143 143 0 10103 2 96 96 0 0188-59h191a191 191 0 00187-151 143 143 0 00-43-279zM280 130a48 48 0 110 96 48 48 0 010-96zm0 764a48 48 0 110-96 48 48 0 010 96zM757 417a48 48 0 110-96 48 48 0 010 96z M896 128h-64V64c0-35-29-64-64-64s-64 29-64 64v64h-64c-35 0-64 29-64 64s29 64 64 64h64v64c0 35 29 64 64 64s64-29 64-64V256h64c35 0 64-29 64-64s-29-64-64-64zm-204 307C673 481 628 512 576 512H448c-47 0-90 13-128 35V372C394 346 448 275 448 192c0-106-86-192-192-192S64 86 64 192c0 83 54 154 128 180v280c-74 26-128 97-128 180c0 106 86 192 192 192s192-86 192-192c0-67-34-125-84-159c22-20 52-33 84-33h128c122 0 223-85 249-199c-19 4-37 7-57 7c-26 0-51-5-76-13zM256 128c35 0 64 29 64 64s-29 64-64 64s-64-29-64-64s29-64 64-64zm0 768c-35 0-64-29-64-64s29-64 64-64s64 29 64 64s-29 64-64 64z M512 597m-1 0a1 1 0 103 0a1 1 0 10-3 0ZM810 393 732 315 448 600 293 444 214 522l156 156 78 78 362-362z + M512 32C246 32 32 250 32 512s218 480 480 480 480-218 480-480S774 32 512 32zm269 381L496 698c-26 26-61 26-83 0L243 528c-26-26-26-61 0-83s61-26 83 0l128 128 240-240c26-26 61-26 83 0 26 19 26 54 3 80z M747 467c29 0 56 4 82 12v-363c0-47-38-84-84-84H125c-47 0-84 38-84 84v707c0 47 38 84 84 84h375a287 287 0 01-43-152c0-160 129-289 289-289zm-531-250h438c19 0 34 15 34 34s-15 34-34 34H216c-19 0-34-15-34-34s15-34 34-34zm0 179h263c19 0 34 15 34 34s-15 34-34 34H216c-19 0-34-15-34-34s15-34 34-34zm131 247h-131c-19 0-34-15-34-34s15-34 34-34h131c19 0 34 15 34 34s-15 34-34 34zM747 521c-130 0-236 106-236 236S617 992 747 992s236-106 236-236S877 521 747 521zm11 386v-65h-130c-12 0-22-10-22-22s10-22 22-22h260l-130 108zm108-192H606l130-108v65h130c12 0 22 10 22 22s-10 22-22 22z M529 511c115 0 212 79 239 185h224a62 62 0 017 123l-7 0-224 0a247 247 0 01-479 0H65a62 62 0 01-7-123l7-0h224a247 247 0 01239-185zm0 124a124 124 0 100 247 124 124 0 000-247zm0-618c32 0 58 24 61 55l0 7V206c89 11 165 45 225 103a74 74 0 0122 45l0 9v87a62 62 0 01-123 7l-0-7v-65l-6-4c-43-33-97-51-163-53l-17-0c-74 0-133 18-180 54l-6 4v65a62 62 0 01-55 61l-7 0a62 62 0 01-61-55l-0-7V362c0-20 8-39 23-53 60-58 135-92 224-103V79c0-34 28-62 62-62z M512 926c-229 0-414-186-414-414S283 98 512 98s414 186 414 414-186 414-414 414zm0-73c189 0 341-153 341-341S701 171 512 171 171 323 171 512s153 341 341 341zm-6-192L284 439l52-52 171 171 171-171L728 439l-222 222z diff --git a/src/Views/BranchTree.axaml b/src/Views/BranchTree.axaml index a01f3502..6bff4d39 100644 --- a/src/Views/BranchTree.axaml +++ b/src/Views/BranchTree.axaml @@ -57,18 +57,11 @@ IsExpanded="{Binding IsExpanded}"/> - - - - - - - - + Date: Wed, 19 Feb 2025 10:35:34 +0800 Subject: [PATCH 241/441] enhance: tag push behavior while creating and deleting (#999) - Remember the state of `Push to all remotes after created` checkbox while creating tag - Remember the state of `Delete from remote repositories` checkbox while deleting tag - Change default state of `Delete from remote repositories` to `false` Signed-off-by: leo --- src/Models/RepositorySettings.cs | 12 ++++++++++++ src/ViewModels/CreateTag.cs | 13 +++++++------ src/ViewModels/DeleteTag.cs | 9 ++++----- src/Views/CreateTag.axaml | 2 +- src/Views/DeleteTag.axaml | 2 +- 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/Models/RepositorySettings.cs b/src/Models/RepositorySettings.cs index 556c99ea..44742fb8 100644 --- a/src/Models/RepositorySettings.cs +++ b/src/Models/RepositorySettings.cs @@ -104,6 +104,18 @@ namespace SourceGit.Models set; } = false; + public bool PushToRemoteWhenCreateTag + { + get; + set; + } = true; + + public bool PushToRemoteWhenDeleteTag + { + get; + set; + } = false; + public DealWithLocalChanges DealWithLocalChangesOnCreateBranch { get; diff --git a/src/ViewModels/CreateTag.cs b/src/ViewModels/CreateTag.cs index af9dcf99..a6d7255b 100644 --- a/src/ViewModels/CreateTag.cs +++ b/src/ViewModels/CreateTag.cs @@ -39,11 +39,11 @@ namespace SourceGit.ViewModels set; } = false; - public bool PushToAllRemotes + public bool PushToRemotes { - get; - set; - } = true; + get => _repo.Settings.PushToRemoteWhenCreateTag; + set => _repo.Settings.PushToRemoteWhenCreateTag = value; + } public CreateTag(Repository repo, Models.Branch branch) { @@ -82,6 +82,7 @@ namespace SourceGit.ViewModels _repo.SetWatcherEnabled(false); ProgressDescription = "Create tag..."; + var remotes = PushToRemotes ? _repo.Remotes : null; return Task.Run(() => { bool succ; @@ -90,9 +91,9 @@ namespace SourceGit.ViewModels else succ = Commands.Tag.Add(_repo.FullPath, _tagName, _basedOn); - if (succ && PushToAllRemotes) + if (succ && remotes != null) { - foreach (var remote in _repo.Remotes) + foreach (var remote in remotes) { SetProgressDescription($"Pushing tag to remote {remote.Name} ..."); new Commands.Push(_repo.FullPath, remote.Name, _tagName, false).Exec(); diff --git a/src/ViewModels/DeleteTag.cs b/src/ViewModels/DeleteTag.cs index 7b53e798..341eb4a2 100644 --- a/src/ViewModels/DeleteTag.cs +++ b/src/ViewModels/DeleteTag.cs @@ -10,17 +10,16 @@ namespace SourceGit.ViewModels private set; } - public bool ShouldPushToRemote + public bool PushToRemotes { - get; - set; + get => _repo.Settings.PushToRemoteWhenDeleteTag; + set => _repo.Settings.PushToRemoteWhenDeleteTag = value; } public DeleteTag(Repository repo, Models.Tag tag) { _repo = repo; Target = tag; - ShouldPushToRemote = true; View = new Views.DeleteTag() { DataContext = this }; } @@ -29,9 +28,9 @@ namespace SourceGit.ViewModels _repo.SetWatcherEnabled(false); ProgressDescription = $"Deleting tag '{Target.Name}' ..."; + var remotes = PushToRemotes ? _repo.Remotes : null; return Task.Run(() => { - var remotes = ShouldPushToRemote ? _repo.Remotes : null; var succ = Commands.Tag.Delete(_repo.FullPath, Target.Name, remotes); CallUIThread(() => { diff --git a/src/Views/CreateTag.axaml b/src/Views/CreateTag.axaml index 20b6798a..55b6052f 100644 --- a/src/Views/CreateTag.axaml +++ b/src/Views/CreateTag.axaml @@ -84,7 +84,7 @@ + IsChecked="{Binding PushToRemotes, Mode=TwoWay}"/> diff --git a/src/Views/DeleteTag.axaml b/src/Views/DeleteTag.axaml index 702a7f2a..23c19d35 100644 --- a/src/Views/DeleteTag.axaml +++ b/src/Views/DeleteTag.axaml @@ -23,7 +23,7 @@ + IsChecked="{Binding PushToRemotes, Mode=TwoWay}"/> From 69d107430a2473de5a2f4fb92b2c106929882f8f Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 19 Feb 2025 10:44:51 +0800 Subject: [PATCH 242/441] project: upgrade `OpenAI` and `Azure.AI.OpenAI` to `2.2.0-beta.2` Signed-off-by: leo --- src/SourceGit.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj index 12e914f9..4183511e 100644 --- a/src/SourceGit.csproj +++ b/src/SourceGit.csproj @@ -48,10 +48,10 @@ - + - + From c3eca0d7fdea2c28084db3732875becac6874c28 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 19 Feb 2025 18:01:16 +0800 Subject: [PATCH 243/441] refactor: OpenAI integration (#996) - Add `OpenAIResponse` to trim the `...` block - Add an `Enable Streaming` option to fix the issue that some services do not support streaming output Signed-off-by: leo --- src/Commands/GenerateCommitMessage.cs | 81 +++------------ src/Models/OpenAI.cs | 136 +++++++++++++++++++++++--- src/Resources/Locales/en_US.axaml | 1 + src/Resources/Locales/zh_CN.axaml | 1 + src/Resources/Locales/zh_TW.axaml | 7 +- src/Views/Preferences.axaml | 4 + 6 files changed, 145 insertions(+), 85 deletions(-) diff --git a/src/Commands/GenerateCommitMessage.cs b/src/Commands/GenerateCommitMessage.cs index 4b18a561..df61fdd2 100644 --- a/src/Commands/GenerateCommitMessage.cs +++ b/src/Commands/GenerateCommitMessage.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Text; -using System.Text.RegularExpressions; using System.Threading; using Avalonia.Threading; @@ -36,6 +35,8 @@ namespace SourceGit.Commands { try { + _onResponse?.Invoke("Waiting for pre-file analyzing to completed...\n\n"); + var responseBuilder = new StringBuilder(); var summaryBuilder = new StringBuilder(); foreach (var change in _changes) @@ -49,18 +50,17 @@ namespace SourceGit.Commands var rs = new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadToEnd(); if (rs.IsSuccess) { - var hasFirstValidChar = false; - var thinkingBuffer = new StringBuilder(); _service.Chat( _service.AnalyzeDiffPrompt, $"Here is the `git diff` output: {rs.StdOut}", _cancelToken, update => - ProcessChatResponse(update, ref hasFirstValidChar, thinkingBuffer, - (responseBuilder, text => - _onResponse?.Invoke( - $"Waiting for pre-file analyzing to completed...\n\n{text}")), - (summaryBuilder, null))); + { + responseBuilder.Append(update); + summaryBuilder.Append(update); + + _onResponse?.Invoke($"Waiting for pre-file analyzing to completed...\n\n{responseBuilder}"); + }); } responseBuilder.Append("\n"); @@ -74,15 +74,15 @@ namespace SourceGit.Commands var responseBody = responseBuilder.ToString(); var subjectBuilder = new StringBuilder(); - var hasSubjectFirstValidChar = false; - var subjectThinkingBuffer = new StringBuilder(); _service.Chat( _service.GenerateSubjectPrompt, $"Here are the summaries changes:\n{summaryBuilder}", _cancelToken, update => - ProcessChatResponse(update, ref hasSubjectFirstValidChar, subjectThinkingBuffer, - (subjectBuilder, text => _onResponse?.Invoke($"{text}\n\n{responseBody}")))); + { + subjectBuilder.Append(update); + _onResponse?.Invoke($"{subjectBuilder}\n\n{responseBody}"); + }); } catch (Exception e) { @@ -90,67 +90,10 @@ namespace SourceGit.Commands } } - private void ProcessChatResponse( - string update, - ref bool hasFirstValidChar, - StringBuilder thinkingBuffer, - params (StringBuilder builder, Action callback)[] outputs) - { - if (!hasFirstValidChar) - { - update = update.TrimStart(); - if (string.IsNullOrEmpty(update)) - return; - if (update.StartsWith("<", StringComparison.Ordinal)) - thinkingBuffer.Append(update); - hasFirstValidChar = true; - } - - if (thinkingBuffer.Length > 0) - thinkingBuffer.Append(update); - - if (thinkingBuffer.Length > 15) - { - var match = REG_COT.Match(thinkingBuffer.ToString()); - if (match.Success) - { - update = REG_COT.Replace(thinkingBuffer.ToString(), "").TrimStart(); - if (update.Length > 0) - { - foreach (var output in outputs) - output.builder.Append(update); - thinkingBuffer.Clear(); - } - return; - } - - match = REG_THINK_START.Match(thinkingBuffer.ToString()); - if (!match.Success) - { - foreach (var output in outputs) - output.builder.Append(thinkingBuffer); - thinkingBuffer.Clear(); - return; - } - } - - if (thinkingBuffer.Length == 0) - { - foreach (var output in outputs) - { - output.builder.Append(update); - output.callback?.Invoke(output.builder.ToString()); - } - } - } - private Models.OpenAIService _service; private string _repo; private List _changes; private CancellationToken _cancelToken; private Action _onResponse; - - private static readonly Regex REG_COT = new(@"^<(think|thought|thinking|thought_chain)>(.*?)", RegexOptions.Singleline); - private static readonly Regex REG_THINK_START = new(@"^<(think|thought|thinking|thought_chain)>", RegexOptions.Singleline); } } diff --git a/src/Models/OpenAI.cs b/src/Models/OpenAI.cs index a6648c11..264230c6 100644 --- a/src/Models/OpenAI.cs +++ b/src/Models/OpenAI.cs @@ -1,5 +1,8 @@ using System; using System.ClientModel; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; using System.Threading; using Azure.AI.OpenAI; using CommunityToolkit.Mvvm.ComponentModel; @@ -8,6 +11,91 @@ using OpenAI.Chat; namespace SourceGit.Models { + public partial class OpenAIResponse + { + public OpenAIResponse(Action onUpdate) + { + _onUpdate = onUpdate; + } + + public void Append(string text) + { + var buffer = text; + + if (_thinkTail.Length > 0) + { + _thinkTail.Append(buffer); + buffer = _thinkTail.ToString(); + _thinkTail.Clear(); + } + + buffer = REG_COT().Replace(buffer, ""); + + var startIdx = buffer.IndexOf('<', StringComparison.Ordinal); + if (startIdx >= 0) + { + if (startIdx > 0) + OnReceive(buffer.Substring(0, startIdx)); + + var endIdx = buffer.IndexOf(">", startIdx + 1, StringComparison.Ordinal); + if (endIdx <= startIdx) + { + if (buffer.Length - startIdx <= 15) + _thinkTail.Append(buffer.Substring(startIdx)); + else + OnReceive(buffer.Substring(startIdx)); + } + else if (endIdx < startIdx + 15) + { + var tag = buffer.Substring(startIdx + 1, endIdx - startIdx - 1); + if (_thinkTags.Contains(tag)) + _thinkTail.Append(buffer.Substring(startIdx)); + else + OnReceive(buffer.Substring(startIdx)); + } + else + { + OnReceive(buffer.Substring(startIdx)); + } + } + else + { + OnReceive(buffer); + } + } + + public void End() + { + if (_thinkTail.Length > 0) + { + OnReceive(_thinkTail.ToString()); + _thinkTail.Clear(); + } + } + + private void OnReceive(string text) + { + if (!_hasTrimmedStart) + { + text = text.TrimStart(); + if (string.IsNullOrEmpty(text)) + return; + + _hasTrimmedStart = true; + } + + _onUpdate.Invoke(text); + } + + [GeneratedRegex(@"<(think|thought|thinking|thought_chain)>.*?", RegexOptions.Singleline)] + private static partial Regex REG_COT(); + + private Action _onUpdate = null; + private StringBuilder _thinkTail = new StringBuilder(); + private HashSet _thinkTags = ["think", "thought", "thinking", "thought_chain"]; + private bool _hasTrimmedStart = false; + } + public class OpenAIService : ObservableObject { public string Name @@ -42,6 +130,12 @@ namespace SourceGit.Models set => SetProperty(ref _model, value); } + public bool Streaming + { + get => _streaming; + set => SetProperty(ref _streaming, value); + } + public string AnalyzeDiffPrompt { get => _analyzeDiffPrompt; @@ -89,32 +183,47 @@ namespace SourceGit.Models public void Chat(string prompt, string question, CancellationToken cancellation, Action onUpdate) { - Uri server = new(Server); - ApiKeyCredential key = new(ApiKey); - ChatClient client = null; - if (Server.Contains("openai.azure.com/", StringComparison.Ordinal)) + var server = new Uri(_server); + var key = new ApiKeyCredential(_apiKey); + var client = null as ChatClient; + if (_server.Contains("openai.azure.com/", StringComparison.Ordinal)) { var azure = new AzureOpenAIClient(server, key); - client = azure.GetChatClient(Model); + client = azure.GetChatClient(_model); } else { var openai = new OpenAIClient(key, new() { Endpoint = server }); - client = openai.GetChatClient(Model); + client = openai.GetChatClient(_model); } + var messages = new List(); + messages.Add(_model.Equals("o1-mini", StringComparison.Ordinal) ? new UserChatMessage(prompt) : new SystemChatMessage(prompt)); + messages.Add(new UserChatMessage(question)); + try { - var updates = client.CompleteChatStreaming([ - _model.Equals("o1-mini", StringComparison.Ordinal) ? new UserChatMessage(prompt) : new SystemChatMessage(prompt), - new UserChatMessage(question), - ], null, cancellation); + var rsp = new OpenAIResponse(onUpdate); - foreach (var update in updates) + if (_streaming) { - if (update.ContentUpdate.Count > 0) - onUpdate.Invoke(update.ContentUpdate[0].Text); + var updates = client.CompleteChatStreaming(messages, null, cancellation); + + foreach (var update in updates) + { + if (update.ContentUpdate.Count > 0) + rsp.Append(update.ContentUpdate[0].Text); + } } + else + { + var completion = client.CompleteChat(messages, null, cancellation); + + if (completion.Value.Content.Count > 0) + rsp.Append(completion.Value.Content[0].Text); + } + + rsp.End(); } catch { @@ -127,6 +236,7 @@ namespace SourceGit.Models private string _server; private string _apiKey; private string _model; + private bool _streaming = true; private string _analyzeDiffPrompt; private string _generateSubjectPrompt; } diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index cd266666..0da8b5ed 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -459,6 +459,7 @@ Model Name Server + Enable Streaming APPEARANCE Default Font Font Size diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 4db909c9..983775e7 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -462,6 +462,7 @@ 模型 配置名称 服务地址 + 启用流式输出 外观配置 缺省字体 字体大小 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index a3fe5c19..2a5ced45 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -456,12 +456,13 @@ {0} 年前 偏好設定 AI - 伺服器 + 分析變更差異提示詞 API 金鑰 + 產生提交訊息提示詞 模型 名稱 - 分析變更差異提示詞 - 產生提交訊息提示詞 + 伺服器 + 啟用串流輸出 外觀設定 預設字型 字型大小 diff --git a/src/Views/Preferences.axaml b/src/Views/Preferences.axaml index 1d282ad9..3bdd150a 100644 --- a/src/Views/Preferences.axaml +++ b/src/Views/Preferences.axaml @@ -616,6 +616,10 @@ Text="{Binding GenerateSubjectPrompt, Mode=TwoWay}" AcceptsReturn="true" TextWrapping="Wrap"/> + + From 68946d21400575332c784d8820ae247063865b1b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 19 Feb 2025 10:01:37 +0000 Subject: [PATCH 244/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3829cf54..aca5a594 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.47%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.61%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.42%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-97.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-92.15%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.73%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.34%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.48%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.30%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-97.74%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-92.03%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.60%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index 84411404..08b7c462 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,4 +1,4 @@ -### de_DE.axaml: 99.47% +### de_DE.axaml: 99.34%
@@ -7,11 +7,12 @@ - Text.BranchCM.CustomAction - Text.Configure.CustomAction.Scope.Branch - Text.Configure.CustomAction.WaitForExit +- Text.Preferences.AI.Streaming - Text.Repository.Notifications.Clear
-### es_ES.axaml: 97.61% +### es_ES.axaml: 97.48%
@@ -31,6 +32,7 @@ - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup - Text.DeleteRepositoryNode.TipForRepository +- Text.Preferences.AI.Streaming - Text.Repository.Notifications.Clear - Text.Stash.AutoRestore - Text.Stash.AutoRestore.Tip @@ -38,7 +40,7 @@
-### fr_FR.axaml: 92.42% +### fr_FR.axaml: 92.30%
@@ -67,6 +69,7 @@ - Text.MergeMultiple.CommitChanges - Text.MergeMultiple.Strategy - Text.MergeMultiple.Targets +- Text.Preferences.AI.Streaming - Text.Preferences.Appearance.FontSize - Text.Preferences.Appearance.FontSize.Default - Text.Preferences.Appearance.FontSize.Editor @@ -104,7 +107,7 @@
-### it_IT.axaml: 97.87% +### it_IT.axaml: 97.74%
@@ -123,13 +126,14 @@ - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup - Text.DeleteRepositoryNode.TipForRepository +- Text.Preferences.AI.Streaming - Text.Repository.Notifications.Clear - Text.Stash.AutoRestore - Text.Stash.AutoRestore.Tip
-### pt_BR.axaml: 92.15% +### pt_BR.axaml: 92.03%
@@ -169,6 +173,7 @@ - Text.MergeMultiple.CommitChanges - Text.MergeMultiple.Strategy - Text.MergeMultiple.Targets +- Text.Preferences.AI.Streaming - Text.Preferences.General.DateFormat - Text.Preferences.General.ShowChildren - Text.Preferences.Git.SSLVerify @@ -197,7 +202,7 @@
-### ru_RU.axaml: 99.73% +### ru_RU.axaml: 99.60%
@@ -205,6 +210,7 @@ - Text.BranchCM.CustomAction - Text.Configure.CustomAction.Scope.Branch +- Text.Preferences.AI.Streaming
From ce16ac63eb9ef3308209f42ee94ee974a2b42957 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 19 Feb 2025 19:22:21 +0800 Subject: [PATCH 245/441] enhance: submodule bookmark inherts from parent repo (#1001) Signed-off-by: leo --- src/ViewModels/Repository.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 19e48b13..6e8a5290 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1161,6 +1161,10 @@ namespace SourceGit.ViewModels public void OpenSubmodule(string submodule) { + var selfPage = GetOwnerPage(); + if (selfPage == null) + return; + var root = Path.GetFullPath(Path.Combine(_fullpath, submodule)); var normalizedPath = root.Replace("\\", "/"); @@ -1171,12 +1175,12 @@ namespace SourceGit.ViewModels { Id = normalizedPath, Name = Path.GetFileName(normalizedPath), - Bookmark = 0, + Bookmark = selfPage.Node.Bookmark, IsRepository = true, }; } - App.GetLauncer()?.OpenRepositoryInTab(node, null); + App.GetLauncer().OpenRepositoryInTab(node, null); } public void AddWorktree() From cbc2e46beb75edf05fb05935d87d8dfce36a539d Mon Sep 17 00:00:00 2001 From: Oleg Kosmakov <1533952+kosmakoff@users.noreply.github.com> Date: Thu, 20 Feb 2025 02:31:07 +0100 Subject: [PATCH 246/441] fix: Update unstaged filed counter when unstaged files change (#1007) * Add missing OnPropertyChanged in Cleanup * Force unstaged count to refresh --- src/ViewModels/WorkingCopy.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index 7ac13dc2..60fa93c3 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -214,9 +214,11 @@ namespace SourceGit.ViewModels OnPropertyChanged(nameof(SelectedStaged)); _visibleUnstaged.Clear(); - _unstaged.Clear(); OnPropertyChanged(nameof(VisibleUnstaged)); + _unstaged.Clear(); + OnPropertyChanged(nameof(Unstaged)); + _staged.Clear(); OnPropertyChanged(nameof(Staged)); @@ -305,6 +307,7 @@ namespace SourceGit.ViewModels _isLoadingData = true; HasUnsolvedConflicts = hasConflict; VisibleUnstaged = visibleUnstaged; + OnPropertyChanged(nameof(Unstaged)); Staged = staged; SelectedUnstaged = selectedUnstaged; SelectedStaged = selectedStaged; From 0e1dfba7ef9c94e43f0cf9a9dc8bfad33d3f8df7 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 20 Feb 2025 09:34:03 +0800 Subject: [PATCH 247/441] code_review: PR #1007 Signed-off-by: leo --- src/ViewModels/WorkingCopy.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index 60fa93c3..d87c54ec 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -109,7 +109,7 @@ namespace SourceGit.ViewModels if (_isLoadingData) return; - VisibleUnstaged = GetVisibleUnstagedChanges(); + VisibleUnstaged = GetVisibleUnstagedChanges(_unstaged); SelectedUnstaged = []; } } @@ -284,9 +284,7 @@ namespace SourceGit.ViewModels } } - _unstaged = unstaged; - - var visibleUnstaged = GetVisibleUnstagedChanges(); + var visibleUnstaged = GetVisibleUnstagedChanges(unstaged); var selectedUnstaged = new List(); foreach (var c in visibleUnstaged) { @@ -307,7 +305,7 @@ namespace SourceGit.ViewModels _isLoadingData = true; HasUnsolvedConflicts = hasConflict; VisibleUnstaged = visibleUnstaged; - OnPropertyChanged(nameof(Unstaged)); + Unstaged = unstaged; Staged = staged; SelectedUnstaged = selectedUnstaged; SelectedStaged = selectedStaged; @@ -1459,14 +1457,14 @@ namespace SourceGit.ViewModels } } - private List GetVisibleUnstagedChanges() + private List GetVisibleUnstagedChanges(List unstaged) { if (string.IsNullOrEmpty(_unstagedFilter)) - return _unstaged; + return unstaged; var visible = new List(); - foreach (var c in _unstaged) + foreach (var c in unstaged) { if (c.Path.Contains(_unstagedFilter, StringComparison.OrdinalIgnoreCase)) visible.Add(c); From 53f591bdad68afeb49a4c6d0b0ea8fc42b7a7323 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 20 Feb 2025 10:12:12 +0800 Subject: [PATCH 248/441] ux: add a warning icon when the tracking upstream of a local branch is gone (#1006) Co-authored-by: Davide Tentori --- src/Commands/QueryBranches.cs | 12 ++++++++++++ src/Models/Branch.cs | 1 + src/Resources/Locales/en_US.axaml | 1 + src/Resources/Locales/zh_CN.axaml | 1 + src/Resources/Locales/zh_TW.axaml | 1 + src/ViewModels/BranchTreeNode.cs | 8 +++++--- src/Views/BranchTree.axaml | 12 +++++++++++- 7 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/Commands/QueryBranches.cs b/src/Commands/QueryBranches.cs index 95f97214..44438cef 100644 --- a/src/Commands/QueryBranches.cs +++ b/src/Commands/QueryBranches.cs @@ -25,11 +25,22 @@ namespace SourceGit.Commands return branches; var lines = rs.StdOut.Split('\n', StringSplitOptions.RemoveEmptyEntries); + var remoteBranches = new HashSet(); foreach (var line in lines) { var b = ParseLine(line); if (b != null) + { branches.Add(b); + if (!b.IsLocal) + remoteBranches.Add(b.FullName); + } + } + + foreach (var b in branches) + { + if (b.IsLocal && !string.IsNullOrEmpty(b.Upstream)) + b.IsUpsteamGone = !remoteBranches.Contains(b.Upstream); } return branches; @@ -75,6 +86,7 @@ namespace SourceGit.Commands branch.Head = parts[1]; branch.IsCurrent = parts[2] == "*"; branch.Upstream = parts[3]; + branch.IsUpsteamGone = false; if (branch.IsLocal && !string.IsNullOrEmpty(parts[4]) && !parts[4].Equals("=", StringComparison.Ordinal)) branch.TrackStatus = new QueryTrackStatus(WorkingDirectory, branch.Name, branch.Upstream).Result(); diff --git a/src/Models/Branch.cs b/src/Models/Branch.cs index 0ba320c1..2d0ae5b2 100644 --- a/src/Models/Branch.cs +++ b/src/Models/Branch.cs @@ -34,6 +34,7 @@ namespace SourceGit.Models public string Upstream { get; set; } public BranchTrackStatus TrackStatus { get; set; } public string Remote { get; set; } + public bool IsUpsteamGone { get; set; } public string FriendlyName => IsLocal ? Name : $"{Remote}/{Name}"; } diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 0da8b5ed..dfc17dee 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -72,6 +72,7 @@ Rename ${0}$... Set Tracking Branch... Branch Compare + Invalid upstream! Bytes CANCEL Reset to This Revision diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 983775e7..115f917e 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -75,6 +75,7 @@ 重命名 ${0}$... 切换上游分支 ... 分支比较 + 跟踪的上游分支不存在或已删除! 字节 取 消 重置文件到该版本 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 2a5ced45..00933783 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -75,6 +75,7 @@ 重新命名 ${0}$... 切換上游分支... 分支比較 + 追蹤上游分支不存在或已刪除! 位元組 取 消 重設檔案為此版本 diff --git a/src/ViewModels/BranchTreeNode.cs b/src/ViewModels/BranchTreeNode.cs index 5c42f729..6c1d2e04 100644 --- a/src/ViewModels/BranchTreeNode.cs +++ b/src/ViewModels/BranchTreeNode.cs @@ -1,9 +1,6 @@ using System; using System.Collections.Generic; - using Avalonia; -using Avalonia.Media; - using CommunityToolkit.Mvvm.ComponentModel; namespace SourceGit.ViewModels @@ -45,6 +42,11 @@ namespace SourceGit.ViewModels get => Backend is Models.Branch { IsCurrent: true }; } + public bool ShowUpstreamGoneTip + { + get => Backend is Models.Branch { IsUpsteamGone: true }; + } + public string Tooltip { get => Backend is Models.Branch b ? b.FriendlyName : null; diff --git a/src/Views/BranchTree.axaml b/src/Views/BranchTree.axaml index 6bff4d39..0ac09e6c 100644 --- a/src/Views/BranchTree.axaml +++ b/src/Views/BranchTree.axaml @@ -61,7 +61,17 @@ Classes="primary" Text="{Binding Name}" FontWeight="{Binding IsCurrent, Converter={x:Static c:BoolConverters.IsBoldToFontWeight}}" - TextTrimming="CharacterEllipsis"/> + TextTrimming="CharacterEllipsis"/> + + + + + Date: Thu, 20 Feb 2025 02:14:51 +0000 Subject: [PATCH 249/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index aca5a594..784d0672 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.34%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.48%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.30%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-97.74%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-92.03%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.60%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.20%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.35%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.18%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-97.61%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.91%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.47%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index 08b7c462..53631bc1 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,10 +1,11 @@ -### de_DE.axaml: 99.34% +### de_DE.axaml: 99.20%
Missing Keys - Text.BranchCM.CustomAction +- Text.BranchUpstreamInvalid - Text.Configure.CustomAction.Scope.Branch - Text.Configure.CustomAction.WaitForExit - Text.Preferences.AI.Streaming @@ -12,7 +13,7 @@
-### es_ES.axaml: 97.48% +### es_ES.axaml: 97.35%
@@ -25,6 +26,7 @@ - Text.ApplyStash.RestoreIndex - Text.ApplyStash.Stash - Text.BranchCM.CustomAction +- Text.BranchUpstreamInvalid - Text.Clone.RecurseSubmodules - Text.Configure.CustomAction.Scope.Branch - Text.Configure.CustomAction.WaitForExit @@ -40,7 +42,7 @@
-### fr_FR.axaml: 92.30% +### fr_FR.axaml: 92.18%
@@ -53,6 +55,7 @@ - Text.ApplyStash.RestoreIndex - Text.ApplyStash.Stash - Text.BranchCM.CustomAction +- Text.BranchUpstreamInvalid - Text.Clone.RecurseSubmodules - Text.Configure.CustomAction.Scope.Branch - Text.Configure.CustomAction.WaitForExit @@ -107,7 +110,7 @@
-### it_IT.axaml: 97.74% +### it_IT.axaml: 97.61%
@@ -120,6 +123,7 @@ - Text.ApplyStash.RestoreIndex - Text.ApplyStash.Stash - Text.BranchCM.CustomAction +- Text.BranchUpstreamInvalid - Text.Clone.RecurseSubmodules - Text.Configure.CustomAction.Scope.Branch - Text.Configure.CustomAction.WaitForExit @@ -133,7 +137,7 @@
-### pt_BR.axaml: 92.03% +### pt_BR.axaml: 91.91%
@@ -147,6 +151,7 @@ - Text.ApplyStash.Stash - Text.BranchCM.CustomAction - Text.BranchCM.MergeMultiBranches +- Text.BranchUpstreamInvalid - Text.Clone.RecurseSubmodules - Text.CommitCM.Merge - Text.CommitCM.MergeMultiple @@ -202,13 +207,14 @@
-### ru_RU.axaml: 99.60% +### ru_RU.axaml: 99.47%
Missing Keys - Text.BranchCM.CustomAction +- Text.BranchUpstreamInvalid - Text.Configure.CustomAction.Scope.Branch - Text.Preferences.AI.Streaming From 507e502874a6dc6e3d4aa090519fc8a48e6c3e83 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 20 Feb 2025 10:18:46 +0800 Subject: [PATCH 250/441] fix: `Custom Action` height is not large enough to display all contents (#1004) Signed-off-by: leo --- src/Views/RepositoryConfigure.axaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/RepositoryConfigure.axaml b/src/Views/RepositoryConfigure.axaml index 6b7cdc12..61bc14e0 100644 --- a/src/Views/RepositoryConfigure.axaml +++ b/src/Views/RepositoryConfigure.axaml @@ -340,7 +340,7 @@ - + From 731f1055bcdc10da906eccd4345a43ba595896a3 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 20 Feb 2025 11:04:57 +0800 Subject: [PATCH 251/441] feat!: add `ptyxis` support (#1005) BREAKING CHANGE: Index of `Custom` shell/terminal Signed-off-by: leo --- src/Models/ShellOrTerminal.cs | 1 + src/Resources/Images/ShellIcons/ptyxis.png | Bin 0 -> 6930 bytes 2 files changed, 1 insertion(+) create mode 100644 src/Resources/Images/ShellIcons/ptyxis.png diff --git a/src/Models/ShellOrTerminal.cs b/src/Models/ShellOrTerminal.cs index 4f0222e8..3ada2cf9 100644 --- a/src/Models/ShellOrTerminal.cs +++ b/src/Models/ShellOrTerminal.cs @@ -57,6 +57,7 @@ namespace SourceGit.Models new ShellOrTerminal("mate-terminal", "MATE Terminal", "mate-terminal"), new ShellOrTerminal("foot", "Foot", "foot"), new ShellOrTerminal("wezterm", "WezTerm", "wezterm"), + new ShellOrTerminal("ptyxis", "Ptyxis", "ptyxis"), new ShellOrTerminal("custom", "Custom", ""), }; } diff --git a/src/Resources/Images/ShellIcons/ptyxis.png b/src/Resources/Images/ShellIcons/ptyxis.png new file mode 100644 index 0000000000000000000000000000000000000000..9202f6e115724d234fd1bf015abd705a475405a0 GIT binary patch literal 6930 zcmV+t8|~zYP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D8mCD_K~#8N?VEeB zWmjG2Kfkrsex28S-+rV!>7>&H0)zxm0-_0^j0ouHj9Q2yGm4B;fDTilC>YccsbWyE z#2OU~kP&Opp^8F59>q%_1c8u*q?0sB`jPIwkG}Vw*WPEp)>`w&KHceb-`h^61gRRn zw^r?Q);@dh_51F%zU#Mszjfg|_zoTue(=L@k1nkHwuMJ7thx~D!ir1brcd2sHm{(Ve}CGA=l`|v{;$73 zJpcQ3AN{ZGYIFSes$ag~{QB+imt${^Ua3;%`wm-1aL^ zzu_yt@yZ*&{KmID{|mRwpFMZ=hhH7t_~qaD_3!(~*Z;tyuX=1ay;y(pk2e4Md(VFN z!|Ye=R{8j9GoO3(FE7R=$H?3J?>^{V^p?Pz=Q~ty7+F4e?_nmDLy2ZN4EUh~*I-;T z*t~#M4&@ZC_S|*sA?_KRW@13cAxk>s*^hfXvo>H@RDArQuQPHb-+RR&u5K^kr3Uff z1z!mdoIb_+IHfXR;*eGpan1Z9kumsb8$}6&e27;$00%6pxO~p zJ0=|rklGUj=3IM~S6q8wAHBIQ;w<+ZInMEWPNUGwE<`;4=BKY|CGT3)t*7d-`|7K% z{Fz@n&s_BRUjRP#jt{Or>*v1zrDdXDII7E*iUZ|mY&L5v@+PNz#~}a@B&T* zr#yH?c4mUjEQm)$A)+YyBZ5u>0!3bt_j7Oxo7b3jj8lRWL3zdGOh%bIL>Ul8pbTk$ zgmO(!a3c6=vEo5#bQChI3w)p%Z1pjr=HL^rM8&49ML#9LJ>z4J$Y@6V?l^&GY%fcrmu`)cc^gKtW9&5&8kuqa7w z30iQIihO;5t7~jlAmY)XKG!hqgnTf@RTb7+ysv4^bs^D+ct9bdu|+{NlhEBe4`{q? znkJ%%IuVYVS{y1dBy(Lilo!RYmZeBBq6S_kk?eB z90Y<+j2OX*o9de&-hj2JL}OYp`N|NRRiHq3Lc(4|m_&>>MhLnQMjT!|;vYS6IdKRI zDn~vTfimtp%a4(72#YPGZ$k6k5Zm%_UvZ&+!BJJN(;(CNj-98D+6q9DF+2^ zBKXo_Gs~F=R!~+z+_cxqMaDA~LGd6)(VCy3J=-DQ9I|%LQI37}J~lVU=uYdx%g*8A zJ5Et61zLz_dWZ_hH^#Wqp-o8GX(K@hUU1TQoJNO~S%t41;uTID;8^Uox%s*$^W6sz zVbcudJ;j*}m)4Y{3AU*4IO@8g|D5AmU>)LXEpVxMpYF-+c2t2vbrL5 zHAh#@OeI$!(n!bPl$$nIH4~aNW8Py?I24V8^;jSmD7#mezQ?u%08n}A&G93RunwIl zddpqPY>f9MaVH??2I!WdOml2nQlu$fX(|P2HKC+t^~@G$h6CJrkK4IZervHK0Y)3L ztue(QM|qD@g13SW4Xv3L@k|>RD(boiQ z`w{F&07{6G7TNlU!O;z>eo4KV(Lb?*_X1wwYezLKuz5*)zKiM@y8C7kEmRvBD|a7d zUKw6|^Rv*tzQn`+^{```WU8ET(xyGzqZnsQh8c0vIyWrpeu*E|l!F457}`r+u03#o zmI;WGn5R7T2^@OdLDF=Lb#^*qOczbl&v=D6^~mvCj7vPRkrD@FqcKUhLm0)>nZu?Y zabSlv<;YTwN|Xbw;qqO}T)lTUGxHq?6lp!-fm5q^3C=k(=L?k=hgS}(n&Y<`I}%_O z2!d*yJSH1`+@ylclAal3i<;Wj)J091mk=r9cFa~aChA6%;z)~vjd8}&wRN1PS^5fS z8t=`EphJyGLZT$xxiQ~FZ2QccZ~e_*DrXHO8XF1{7_g3foMMXtv7Wl9X)h!wU(s6X zfCjH&Z8Bo)O49zA_0yZ&bH@?rv`7}aDAjnjWnN&58kC>{jqXNNlS#9(ys$CfWNb^o z=J6FBcN4<77VYH@$x@GKp-0qBaN_W$rfm#2ANnqy`?MSBwpxHNOmnuz6V}#;RHKq? zSP;z35G{1TC~R7jpPEo_)%X%9T;oJ-W|WhPS}DA5^x$8#Tmst@eg*L}{_M4rdRH5~ zqw!A!n-!E>1(DUV&9B z(oSUSr+OsoiE4c_9M!#aoa4(lDxdA##D=W+g# z;?LIm=C|k9ZC7@}js%EQCRqk&RR5y!8;xbC;gP z@7(ksS*{{5c5$nM@d|Kkuf+!N=Rsgm}SxaCY+B(EKl=Ud zf)|DNf-NlL)e#yH*Tlw>ZW|?ncQl@-lO|m5Jvc?WHK86?6q`Awuw1o&4^KLDIoBV$ zf*TGVV7}MGHy7hC;a==WfcI{?u7@Cw2~CVIgz@?a=W5yqmsvF_Kl}DKaM$SvanrtF z&^%+|D&G8@|HK~E!`Mg0V3&kW)@|AL#9%IphTfX zsI#2a!zYO180Q7=1Xp?NsG=U0l!F5A1rbf{z`7=AszvB;t}%abnL>N=y26S_iE!f7 z8lU+5SCAmWA~-j-We4m?fLM<&DzddrieW}I$*Cq2Orp_&!Fiz;=v}o$zg6<{fBZ&1 z_t0H9nkcP7ac%E1-u45p;i_;6ReSRFA^m$-86Vl?%$+CMy!$lmsMUy+1uWRCrXH5K zQHjeYxT1oxCQusVg?wd;(_cGGD+;j|0#Sro;|k9mUpvC*zH}Ev0kvxc)j6myLBNjc z@YMJGqA!eKUD=3}2!SyurKs_ECDS#%Bd9gm@hy@;&D(zd*Ld!s8wjS{dOQzg8~p0W z-ocUVG&SI?MQIHp_~~8FhPUfciOVgnEHQHlL;>D9ln8m65=0?UD+VAPjR=%SX@kvb zq9g`mAP`g>Vv?YVJnMkOsIMj!fA!I4|IY89XXeFuftx;ci&_5FXU+{aMz0eTUV$<2~>3-q_ z2~-nh?nSh^ZHmbRVnck{Je~c!>0P!=y4fe0pQW`tOSsS@T%M(K*)s9m3?___+EbsyB->?Rc6@v+Z;misYcsS7$f=9ved%H69+Ss83H8Rlp)hz6w;KCc*_+#n1i ztnwIRD7MBFXND-zC}Rkc5HmGAUmtPiuA@XoW2+ib3XuS(J)*!UO|>T&y#!!(QP1{#>t z5!cM^$LAGVz?BwqPrf!{baIm*Nl;;cRF=usfGSHdu_5bkQEc`p*ZZW$R$2e*y<`ub zq}@sYsIvl}*SOrG3J>Fo@yQL!G$(02_QZ%QHVU#+eL^qzsY|MYkT_1JuBmH^eRL6P z2`l*V8=udA`{`dIID1DAIga1`z@PJ1pZz<0XmG|utjQ)B-b2`K62 z5Oxwemo1R&n`7bH%SrYvQi;boOI4QCWkp@rSX(2JA)4zVkwJ$6Sn#6pS}>tzw6;Yt znh2KY<6WayJ7GrxocBZ~V%7)Dtmp8JGpyWtAN9CItVdY~&LOVx zx5X)vT=Vkle~4fDo*yUi>fFsozT{W_@~yo8_J1JWGlOXb6j_Ed3XH)8hH!C~nf<%T zhZF2zf+{^Kuc=P;S^eT+R=#)-KC7{{h05V34w=B#ku}P#9EDI@M_qZULB-1L4?yYh zUK&?=2kdy}N$>bMp9hYXcwY2_-%Cc#+92i5yY8bH7U#HYB*Bx^npZya$9VZu{|zw; znZ^@`Hs`hPej6XZ?~BAsJydA00?r7Xy^H8h2(dv028jadwGrcQoWy1om9s=qfJ&k! z4_Q0JmgISfLgSqy?!-t9c{V|Zs_BU$v^s69c)SR$N^!@l-np%2vOipn z%9l?D>5Gd&PCc$zUTAaZ8INZppD-FtICaNSj18up8{%5=%QycdKk?+7Nzh2+)X}dp zUi}xp%jX`vi+JxGVgv#~j0P{HyJ=s! zM6Es6*CaDBCJqoSP+Ri#5#y6*NY4x?Hbzt%L#Qo2&#|s1nvY3l+vMp4sT{f!qB;Sy zyXUY~K`|}}lxZ@_kw&!wf=)zL7x>zO15*oY|M0cnI^Wi_xR{lziFRFo?Nd58UVmFH zo-)k|dI4c4W;{&MPLo72BG7i4H@xr_yy&WD5Kgkoz|0f&(zyqFrqQBfp&n74Z3XzO+f$j2BeO5rMdIJy!&EXw{y?fD&n{Q?a%YPD{de};ivQciO~kHc*k#X@8CFQSC^SXi};Q~83F4_Pxk39 z&ru9B21hpugBa5Z2znu2dD2sTbluDz7==j;yRN|;iO>41- zww^cq@Xzu6SKL74_0)9FgPSY7{EuGGeS_nK3tgP@l#>dng31ryHV&V|fjaa;LFQye!*A8bbCJ0c0A!;Y+c7zH8#%r78>jOx0 zv=fX836qHV{foFuOoJD(^1@HQ;n1+&rQmhwSJU`e@GQfBDa8dqA2* z+2QpQyz)=p#ED`Zvou54i7AQ#tre|(bJ)7V+h$vx3`-_kBZ4r(*Ot7Ppdw8)*Cy%4 zWT!?{L!GNCg1F1^O8tnY+2z;kJKJlTX2@36VYCp!+Ws93F&5v zrinRJS;1(fPnl+fI>6?RDzAuoF*?x@8l+{2dkK?`5kliA#S0y}OEVB^1VviZhA3gRq)3oC0gj>74#oiLpy0=fl8sH0ErbSOPLkO#NlgC zT@`fqFA*(vAW;Ny%;3m6<(Ui}D#C??Xt_l+lQ2BCiG66meXslLZEd}%2b{&Oo3DG5 zGX{wby~P>AaGJaGf-PzW>5$JJ{tCApxr;pXL~|X`8YiCap}i<2WGh>kP_cB)9wy_Q z@#zs-1nt4s4y_I2%@Ni)dV3bh`zczVT|j%3(MS-W;(%zrMYPz#d2ppCTOX018K9gc zYK64g3B%I^bf<-C8+6YgZ9_EICh(fmfAghnd%(6L2;i)v#*ysmLdW0}jf4SSgu1TL z-3Z-_P%|;67dPij6T4F)XzQ4)Y!O5em9z9NTOjJj6vHv;U)nts7G$mH_9=E{E)k_4OkWd1$lM_yU`azE0dIVckDB}q`F%pMVWku~A z`rs_jy6rc9@j@H96ai(Hk<7P==2{RbRIE`ENL}NmQC$@pv@!U=V0xNpCO~U&YbmS$ zbUz`Qbag~EtSHkG(VC>yA_zmuNzsJ50)q-dW|rp&XJTw+q3}pmBfbfA3TGEvV3jAj zyvy?T~lp#u5L_wQKhor~W$yfSBJ|H#`ktnnSwEx3r-S+F(Uufr!Lm+v|Wp7%% z@c;xKJ>8^O^)u4d5n&WJ!A~#EE-@Ufy&ZzYP_C!+kFOF~h4O-}9o1lr@y+hCCI%>I ztsu~dR!AU7s4z*0NetP_CQ%rpLX9?p2@EV~jJ~F6IfW#UJ6)G}> zp(bA$F*>$|7>|h~OrSwEQ>ZO!ihP1X69f@~IlFbf39yRSIH{YcP^hRj#$@-d4ErDa z%FMZkpNAa@c=8|o%qO$9evXPliql)9-&iAkXbs~95ka(I1yCL*o?TD5g0S7?#Fy?P z@XeMt?Lo9ZH`1&$UH+_R5zTd3xb6V1r64j$q*0;5SmD@5Zbw)0$ResG zxuU0=HKl2n)eyH6g2fId2^l@OM*85H5A^@`)_?bC3mfb>1gibrFDDC&FX`-EO5CKT zTp3btW@z6eHpB~NntL~1F?hdbIqSc#irTi8U$2Z>DFXeyrjJQ_{Ie$ z!lguT>z$v!+s(9Y46OPX5VI_oxG~drF;n`!|9F0>L zCj?FrJB>ZoXXUf^WBQg*8+4$ti7@xX{glRGrq_n&9i!=e&wh@k=b~DOYDH9Q;z|z# zr#|2kb>rxNeeV7X?K_JdhrqWO!Zizfp7eqiMzjW>hEv+8|Ukf#&I;(= Date: Thu, 20 Feb 2025 11:12:29 +0800 Subject: [PATCH 252/441] enhance: prefer to use `Default Remote` in repository settings while fetching remote changes (#1008) Signed-off-by: leo --- src/ViewModels/Fetch.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/ViewModels/Fetch.cs b/src/ViewModels/Fetch.cs index d816d0b8..1094012e 100644 --- a/src/ViewModels/Fetch.cs +++ b/src/ViewModels/Fetch.cs @@ -38,7 +38,24 @@ namespace SourceGit.ViewModels { _repo = repo; _fetchAllRemotes = preferedRemote == null; - SelectedRemote = preferedRemote != null ? preferedRemote : _repo.Remotes[0]; + + if (preferedRemote != null) + { + SelectedRemote = preferedRemote; + } + else if (!string.IsNullOrEmpty(_repo.Settings.DefaultRemote)) + { + var def = _repo.Remotes.Find(r => r.Name == _repo.Settings.DefaultRemote); + if (def != null) + SelectedRemote = def; + else + SelectedRemote = _repo.Remotes[0]; + } + else + { + SelectedRemote = _repo.Remotes[0]; + } + View = new Views.Fetch() { DataContext = this }; } From b5feabfd37816ced5ecfa6eacb6fd820833e1651 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 20 Feb 2025 15:42:11 +0800 Subject: [PATCH 253/441] enhance: auto-set commit message while rebasing is inprogress (#1003) Signed-off-by: leo --- src/ViewModels/WorkingCopy.cs | 100 +++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 44 deletions(-) diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index d87c54ec..f1db3f3d 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -233,25 +233,10 @@ namespace SourceGit.ViewModels // Just force refresh selected changes. Dispatcher.UIThread.Invoke(() => { - if (_selectedUnstaged.Count == 1) - SetDetail(_selectedUnstaged[0], true); - else if (_selectedStaged.Count == 1) - SetDetail(_selectedStaged[0], false); - else - SetDetail(null, false); - - var inProgress = null as InProgressContext; - if (File.Exists(Path.Combine(_repo.GitDir, "CHERRY_PICK_HEAD"))) - inProgress = new CherryPickInProgress(_repo); - else if (Directory.Exists(Path.Combine(_repo.GitDir, "rebase-merge")) || Directory.Exists(Path.Combine(_repo.GitDir, "rebase-apply"))) - inProgress = new RebaseInProgress(_repo); - else if (File.Exists(Path.Combine(_repo.GitDir, "REVERT_HEAD"))) - inProgress = new RevertInProgress(_repo); - else if (File.Exists(Path.Combine(_repo.GitDir, "MERGE_HEAD"))) - inProgress = new MergeInProgress(_repo); - HasUnsolvedConflicts = _cached.Find(x => x.IsConflit) != null; - InProgressContext = inProgress; + + UpdateDetail(); + UpdateInProgressState(); }); return; @@ -311,32 +296,8 @@ namespace SourceGit.ViewModels SelectedStaged = selectedStaged; _isLoadingData = false; - if (selectedUnstaged.Count == 1) - SetDetail(selectedUnstaged[0], true); - else if (selectedStaged.Count == 1) - SetDetail(selectedStaged[0], false); - else - SetDetail(null, false); - - var inProgress = null as InProgressContext; - if (File.Exists(Path.Combine(_repo.GitDir, "CHERRY_PICK_HEAD"))) - inProgress = new CherryPickInProgress(_repo); - else if (Directory.Exists(Path.Combine(_repo.GitDir, "rebase-merge")) || Directory.Exists(Path.Combine(_repo.GitDir, "rebase-apply"))) - inProgress = new RebaseInProgress(_repo); - else if (File.Exists(Path.Combine(_repo.GitDir, "REVERT_HEAD"))) - inProgress = new RevertInProgress(_repo); - else if (File.Exists(Path.Combine(_repo.GitDir, "MERGE_HEAD"))) - inProgress = new MergeInProgress(_repo); - - InProgressContext = inProgress; - - // Try to load merge message from MERGE_MSG - if (string.IsNullOrEmpty(_commitMessage)) - { - var mergeMsgFile = Path.Combine(_repo.GitDir, "MERGE_MSG"); - if (File.Exists(mergeMsgFile)) - CommitMessage = File.ReadAllText(mergeMsgFile); - } + UpdateDetail(); + UpdateInProgressState(); }); } @@ -1488,6 +1449,57 @@ namespace SourceGit.ViewModels return rs; } + private void UpdateDetail() + { + if (_selectedUnstaged.Count == 1) + SetDetail(_selectedUnstaged[0], true); + else if (_selectedStaged.Count == 1) + SetDetail(_selectedStaged[0], false); + else + SetDetail(null, false); + } + + private void UpdateInProgressState() + { + if (string.IsNullOrEmpty(_commitMessage)) + { + var mergeMsgFile = Path.Combine(_repo.GitDir, "MERGE_MSG"); + if (File.Exists(mergeMsgFile)) + CommitMessage = File.ReadAllText(mergeMsgFile); + } + + if (File.Exists(Path.Combine(_repo.GitDir, "CHERRY_PICK_HEAD"))) + { + InProgressContext = new CherryPickInProgress(_repo); + } + else if (Directory.Exists(Path.Combine(_repo.GitDir, "rebase-merge")) || Directory.Exists(Path.Combine(_repo.GitDir, "rebase-apply"))) + { + var rebasing = new RebaseInProgress(_repo); + InProgressContext = rebasing; + + if (string.IsNullOrEmpty(_commitMessage)) + { + var rebaseMsgFile = Path.Combine(_repo.GitDir, "rebase-merge", "message"); + if (File.Exists(rebaseMsgFile)) + CommitMessage = File.ReadAllText(rebaseMsgFile); + else if (rebasing.StoppedAt != null) + CommitMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, rebasing.StoppedAt.SHA).Result(); + } + } + else if (File.Exists(Path.Combine(_repo.GitDir, "REVERT_HEAD"))) + { + InProgressContext = new RevertInProgress(_repo); + } + else if (File.Exists(Path.Combine(_repo.GitDir, "MERGE_HEAD"))) + { + InProgressContext = new MergeInProgress(_repo); + } + else + { + InProgressContext = null; + } + } + private async void StageChanges(List changes, Models.Change next) { if (changes.Count == 0) From 9da2c787dbf0dbac7cc26ce777672857d40e6066 Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 21 Feb 2025 09:44:51 +0800 Subject: [PATCH 254/441] enhance: supports to configure `fetch.prune` for selected repository (#995) Signed-off-by: leo --- src/ViewModels/RepositoryConfigure.cs | 9 +++++++++ src/Views/RepositoryConfigure.axaml | 8 ++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/ViewModels/RepositoryConfigure.cs b/src/ViewModels/RepositoryConfigure.cs index a7c04937..cf23b6d8 100644 --- a/src/ViewModels/RepositoryConfigure.cs +++ b/src/ViewModels/RepositoryConfigure.cs @@ -60,6 +60,12 @@ namespace SourceGit.ViewModels set => SetProperty(ref _httpProxy, value); } + public bool EnablePruneOnFetch + { + get; + set; + } + public bool EnableAutoFetch { get => _repo.Settings.EnableAutoFetch; @@ -153,6 +159,8 @@ namespace SourceGit.ViewModels GPGUserSigningKey = signingKey; if (_cached.TryGetValue("http.proxy", out var proxy)) HttpProxy = proxy; + if (_cached.TryGetValue("fetch.prune", out var prune)) + EnablePruneOnFetch = (prune == "true"); } public void ClearHttpProxy() @@ -286,6 +294,7 @@ namespace SourceGit.ViewModels SetIfChanged("tag.gpgsign", GPGTagSigningEnabled ? "true" : "false", "false"); SetIfChanged("user.signingkey", GPGUserSigningKey, ""); SetIfChanged("http.proxy", HttpProxy, ""); + SetIfChanged("fetch.prune", EnablePruneOnFetch ? "true" : "false", "false"); } private void SetIfChanged(string key, string value, string defValue) diff --git a/src/Views/RepositoryConfigure.axaml b/src/Views/RepositoryConfigure.axaml index 61bc14e0..f6a02c49 100644 --- a/src/Views/RepositoryConfigure.axaml +++ b/src/Views/RepositoryConfigure.axaml @@ -44,7 +44,7 @@ - + - + + + From 2b4fc64c73b126fd0d94b5562be53e25dcf7b24d Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 21 Feb 2025 10:26:14 +0800 Subject: [PATCH 255/441] fix: resolve conflict with deleted files does not work (#1009) Signed-off-by: leo --- src/Commands/Add.cs | 4 +- src/ViewModels/WorkingCopy.cs | 76 ++++++++++++++++++++++++++------- src/Views/TextDiffView.axaml.cs | 2 +- 3 files changed, 64 insertions(+), 18 deletions(-) diff --git a/src/Commands/Add.cs b/src/Commands/Add.cs index e1b55b68..b2aa803d 100644 --- a/src/Commands/Add.cs +++ b/src/Commands/Add.cs @@ -12,7 +12,7 @@ namespace SourceGit.Commands Args = includeUntracked ? "add ." : "add -u ."; } - public Add(string repo, List changes) + public Add(string repo, List changes) { WorkingDirectory = repo; Context = repo; @@ -22,7 +22,7 @@ namespace SourceGit.Commands foreach (var c in changes) { builder.Append(" \""); - builder.Append(c.Path); + builder.Append(c); builder.Append("\""); } Args = builder.ToString(); diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index f1db3f3d..ce2a2ac1 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -353,38 +353,80 @@ namespace SourceGit.ViewModels public async void UseTheirs(List changes) { + _repo.SetWatcherEnabled(false); + var files = new List(); + var needStage = new List(); + foreach (var change in changes) { - if (change.IsConflit) + if (!change.IsConflit) + continue; + + if (change.WorkTree == Models.ChangeState.Deleted) + { + var fullpath = Path.Combine(_repo.FullPath, change.Path); + if (File.Exists(fullpath)) + File.Delete(fullpath); + + needStage.Add(change.Path); + } + else + { files.Add(change.Path); + } } - _repo.SetWatcherEnabled(false); - var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseTheirs(files)); - if (succ) + if (files.Count > 0) { - await Task.Run(() => new Commands.Add(_repo.FullPath, changes).Exec()); + var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseTheirs(files)); + if (succ) + needStage.AddRange(files); } + + if (needStage.Count > 0) + await Task.Run(() => new Commands.Add(_repo.FullPath, needStage).Exec()); + _repo.MarkWorkingCopyDirtyManually(); _repo.SetWatcherEnabled(true); } public async void UseMine(List changes) { + _repo.SetWatcherEnabled(false); + var files = new List(); + var needStage = new List(); + foreach (var change in changes) { - if (change.IsConflit) + if (!change.IsConflit) + continue; + + if (change.Index == Models.ChangeState.Deleted) + { + var fullpath = Path.Combine(_repo.FullPath, change.Path); + if (File.Exists(fullpath)) + File.Delete(fullpath); + + needStage.Add(change.Path); + } + else + { files.Add(change.Path); + } } - _repo.SetWatcherEnabled(false); - var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseMine(files)); - if (succ) + if (files.Count > 0) { - await Task.Run(() => new Commands.Add(_repo.FullPath, changes).Exec()); + var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseMine(files)); + if (succ) + needStage.AddRange(files); } + + if (needStage.Count > 0) + await Task.Run(() => new Commands.Add(_repo.FullPath, needStage).Exec()); + _repo.MarkWorkingCopyDirtyManually(); _repo.SetWatcherEnabled(true); } @@ -1502,7 +1544,8 @@ namespace SourceGit.ViewModels private async void StageChanges(List changes, Models.Change next) { - if (changes.Count == 0) + var count = changes.Count; + if (count == 0) return; // Use `_selectedUnstaged` instead of `SelectedUnstaged` to avoid UI refresh. @@ -1510,7 +1553,7 @@ namespace SourceGit.ViewModels IsStaging = true; _repo.SetWatcherEnabled(false); - if (changes.Count == _unstaged.Count) + if (count == _unstaged.Count) { await Task.Run(() => new Commands.Add(_repo.FullPath, _repo.IncludeUntracked).Exec()); } @@ -1527,10 +1570,13 @@ namespace SourceGit.ViewModels } else { - for (int i = 0; i < changes.Count; i += 10) + var paths = new List(); + foreach (var c in changes) + paths.Add(c.Path); + + for (int i = 0; i < count; i += 10) { - var count = Math.Min(10, changes.Count - i); - var step = changes.GetRange(i, count); + var step = paths.GetRange(i, Math.Min(10, count - i)); await Task.Run(() => new Commands.Add(_repo.FullPath, step).Exec()); } } diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 28fe81a8..83bc47e3 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -1796,7 +1796,7 @@ namespace SourceGit.Views if (!selection.HasLeftChanges) { - new Commands.Add(repo.FullPath, [change]).Exec(); + new Commands.Add(repo.FullPath, [change.Path]).Exec(); } else { From 841276852a29c12f9da642e8d3c5f96b6cb7fce1 Mon Sep 17 00:00:00 2001 From: saxc Date: Fri, 21 Feb 2025 03:34:38 +0100 Subject: [PATCH 256/441] localization: add german translations (#1011) (cherry picked from commit fcc720480c85fe01120e555c22b6aec286ee717b) --- src/Resources/Locales/de_DE.axaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index b6458822..c16c90b5 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -59,6 +59,7 @@ Mit HEAD vergleichen Mit Worktree vergleichen Branch-Namen kopieren + Benutzerdefinierte Aktion Lösche ${0}$... Lösche alle ausgewählten {0} Branches Alle Änderungen verwerfen @@ -159,6 +160,7 @@ Ausführbare Datei: Name: Geltungsbereich: + Branch Commit Repository Email Adresse @@ -586,6 +588,7 @@ LOKALE BRANCHES Zum HEAD wechseln Erstelle Branch + BENACHRICHTIGUNGEN LÖSCHEN Nur aktuellen Branch im Graphen hervorheben Öffne in {0} Öffne in externen Tools @@ -710,7 +713,7 @@ Öffne alle Repositories Öffne Repository Öffne Terminal - Klon Standardordner erneut nach Repositories durchsuchen + Klon Standardordner erneut nach Repositories durchsuchen Suche Repositories... Sortieren Änderungen From b2ab62825ece1bb0111782f094266d1445c3a110 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 21 Feb 2025 02:48:21 +0000 Subject: [PATCH 257/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 784d0672..60c8543e 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.20%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.35%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.18%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-97.61%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.91%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.47%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.60%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.35%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.18%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-97.61%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.91%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.47%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index 53631bc1..c235ea6a 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,15 +1,12 @@ -### de_DE.axaml: 99.20% +### de_DE.axaml: 99.60%
Missing Keys -- Text.BranchCM.CustomAction - Text.BranchUpstreamInvalid -- Text.Configure.CustomAction.Scope.Branch - Text.Configure.CustomAction.WaitForExit - Text.Preferences.AI.Streaming -- Text.Repository.Notifications.Clear
From 9ab602788a7bfeaf05e382d876a145547cc3e73c Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Mon, 24 Feb 2025 10:28:00 +0900 Subject: [PATCH 258/441] docs: update README.md (#1014) comaptible -> compatible --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 60c8543e..256070e2 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ For **Linux** users: ## OpenAI -This software supports using OpenAI or other AI service that has an OpenAI comaptible HTTP API to generate commit message. You need configurate the service in `Preference` window. +This software supports using OpenAI or other AI service that has an OpenAI compatible HTTP API to generate commit message. You need configurate the service in `Preference` window. For `OpenAI`: From fa4caa218628169d5f34076732ffa9b35ed040fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20W?= <44604769+goran-w@users.noreply.github.com> Date: Mon, 24 Feb 2025 02:32:19 +0100 Subject: [PATCH 259/441] enhance: add first/last buttons for block-nav, no wrapping (#1015) (#1016) Added 2 new buttons (only visible in block-nav mode), with new icons and new (en_US) strings (First/Last Difference). Implemented these new buttons, and disabled the automatic wrap-around for the prev/next buttons in block-nav mode. --- src/Resources/Icons.axaml | 2 ++ src/Resources/Locales/en_US.axaml | 2 ++ src/ViewModels/BlockNavigation.cs | 28 ++++++++++++++-- src/Views/DiffView.axaml | 28 ++++++++++++++++ src/Views/DiffView.axaml.cs | 14 ++++++++ src/Views/TextDiffView.axaml.cs | 56 +++++++++++++++++++++++++++++++ 6 files changed, 127 insertions(+), 3 deletions(-) diff --git a/src/Resources/Icons.axaml b/src/Resources/Icons.axaml index b7d9c22e..9426d20a 100644 --- a/src/Resources/Icons.axaml +++ b/src/Resources/Icons.axaml @@ -5,6 +5,7 @@ M71 1024V0h661L953 219V1024H71zm808-731-220-219H145V951h735V293zM439 512h-220V219h220V512zm-74-219H292v146h74v-146zm0 512h74v73h-220v-73H292v-146H218V585h147v219zm294-366h74V512H512v-73h74v-146H512V219h147v219zm74 439H512V585h220v293zm-74-219h-74v146h74v-146z M128 256h192a64 64 0 110 128H128a64 64 0 110-128zm576 192h192a64 64 0 010 128h-192a64 64 0 010-128zm-576 192h192a64 64 0 010 128H128a64 64 0 010-128zm576 0h192a64 64 0 010 128h-192a64 64 0 010-128zm0-384h192a64 64 0 010 128h-192a64 64 0 010-128zM128 448h192a64 64 0 110 128H128a64 64 0 110-128zm384-320a64 64 0 0164 64v640a64 64 0 01-128 0V192a64 64 0 0164-64z M832 64H192c-18 0-32 14-32 32v832c0 18 14 32 32 32h640c18 0 32-14 32-32V96c0-18-14-32-32-32zM736 596 624 502 506 596V131h230v318z + M509 546 780 275 871 366 509 728 147 366 238 275zM509 728h-362v128h724v-128z M757 226a143 143 0 00-55 276 96 96 0 01-88 59h-191a187 187 0 00-96 27V312a143 143 0 10-96 0v399a143 143 0 10103 2 96 96 0 0188-59h191a191 191 0 00187-151 143 143 0 00-43-279zM280 130a48 48 0 110 96 48 48 0 010-96zm0 764a48 48 0 110-96 48 48 0 010 96zM757 417a48 48 0 110-96 48 48 0 010 96z M896 128h-64V64c0-35-29-64-64-64s-64 29-64 64v64h-64c-35 0-64 29-64 64s29 64 64 64h64v64c0 35 29 64 64 64s64-29 64-64V256h64c35 0 64-29 64-64s-29-64-64-64zm-204 307C673 481 628 512 576 512H448c-47 0-90 13-128 35V372C394 346 448 275 448 192c0-106-86-192-192-192S64 86 64 192c0 83 54 154 128 180v280c-74 26-128 97-128 180c0 106 86 192 192 192s192-86 192-192c0-67-34-125-84-159c22-20 52-33 84-33h128c122 0 223-85 249-199c-19 4-37 7-57 7c-26 0-51-5-76-13zM256 128c35 0 64 29 64 64s-29 64-64 64s-64-29-64-64s29-64 64-64zm0 768c-35 0-64-29-64-64s29-64 64-64s64 29 64 64s-29 64-64 64z M512 597m-1 0a1 1 0 103 0a1 1 0 10-3 0ZM810 393 732 315 448 600 293 444 214 522l156 156 78 78 362-362z @@ -119,6 +120,7 @@ M996 452 572 28A96 96 0 00504 0H96C43 0 0 43 0 96v408a96 96 0 0028 68l424 424c37 37 98 37 136 0l408-408c37-37 37-98 0-136zM224 320c-53 0-96-43-96-96s43-96 96-96 96 43 96 96-43 96-96 96zm1028 268L844 996c-37 37-98 37-136 0l-1-1L1055 647c34-34 53-79 53-127s-19-93-53-127L663 0h97a96 96 0 0168 28l424 424c37 37 37 98 0 136z M765 118 629 239l-16 137-186 160 54 59 183-168 144 4 136-129 47-43-175-12L827 67zM489 404c-66 0-124 55-124 125s54 121 124 121c66 0 120-55 120-121H489l23-121c-8-4-16-4-23-4zM695 525c0 114-93 207-206 207s-206-94-206-207 93-207 206-207c16 0 27 0 43 4l43-207c-27-4-54-8-85-8-229 0-416 188-416 419s187 419 416 419c225 0 408-180 416-403v-12l-210-4z M144 112h736c18 0 32 14 32 32v736c0 18-14 32-32 32H144c-18 0-32-14-32-32V144c0-18 14-32 32-32zm112 211v72a9 9 0 003 7L386 509 259 615a9 9 0 00-3 7v72a9 9 0 0015 7L493 516a9 9 0 000-14l-222-186a9 9 0 00-15 7zM522 624a10 10 0 00-10 10v60a10 10 0 0010 10h237a10 10 0 0010-10v-60a10 10 0 00-10-10H522z + M170 831 513 489 855 831 960 726 512 278 64 726 170 831zM512 278h448v-128h-896v128h448z M897 673v13c0 51-42 93-93 93h-10c-1 0-2 0-2 0H220c-23 0-42 19-42 42v13c0 23 19 42 42 42h552c14 0 26 12 26 26 0 14-12 26-26 26H220c-51 0-93-42-93-93v-13c0-51 42-93 93-93h20c1-0 2-0 2-0h562c23 0 42-19 42-42v-13c0-11-5-22-13-29-8-7-17-11-28-10H660c-14 0-26-12-26-26 0-14 12-26 26-26h144c24-1 47 7 65 24 18 17 29 42 29 67zM479 98c-112 0-203 91-203 203 0 44 14 85 38 118l132 208c15 24 50 24 66 0l133-209c23-33 37-73 37-117 0-112-91-203-203-203zm0 327c-68 0-122-55-122-122s55-122 122-122 122 55 122 122-55 122-122 122z M912 800a48 48 0 1 1 0 96h-416a48 48 0 1 1 0-96h416z m-704-704A112 112 0 0 1 256 309.184V480h80a48 48 0 0 1 0 96H256v224h81.664a48 48 0 1 1 0 96H256a96 96 0 0 1-96-96V309.248A112 112 0 0 1 208 96z m704 384a48 48 0 1 1 0 96h-416a48 48 0 0 1 0-96h416z m0-320a48 48 0 1 1 0 96h-416a48 48 0 0 1 0-96h416z M30 0 30 30 0 15z diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index dfc17dee..d2d64d5c 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -252,9 +252,11 @@ File Mode Changed Ignore Whitespace Change LFS OBJECT CHANGE + First Difference Next Difference NO CHANGES OR ONLY EOL CHANGES Previous Difference + Last Difference Save as Patch Show hidden symbols Side-By-Side Diff diff --git a/src/ViewModels/BlockNavigation.cs b/src/ViewModels/BlockNavigation.cs index 709338f8..9a5a926c 100644 --- a/src/ViewModels/BlockNavigation.cs +++ b/src/ViewModels/BlockNavigation.cs @@ -101,12 +101,12 @@ namespace SourceGit.ViewModels return (_current >= 0 && _current < Blocks.Count) ? Blocks[_current] : null; } - public Block GotoNext() + public Block GotoFirst() { if (Blocks.Count == 0) return null; - Current = (_current + 1) % Blocks.Count; + Current = 0; return Blocks[_current]; } @@ -115,7 +115,29 @@ namespace SourceGit.ViewModels if (Blocks.Count == 0) return null; - Current = _current == -1 ? Blocks.Count - 1 : (_current - 1 + Blocks.Count) % Blocks.Count; + if (_current == -1) + Current = 0; + else if (_current > 0) + Current = _current - 1; + return Blocks[_current]; + } + + public Block GotoNext() + { + if (Blocks.Count == 0) + return null; + + if (_current < Blocks.Count - 1) + Current = _current + 1; + return Blocks[_current]; + } + + public Block GotoLast() + { + if (Blocks.Count == 0) + return null; + + Current = Blocks.Count - 1; return Blocks[_current]; } diff --git a/src/Views/DiffView.axaml b/src/Views/DiffView.axaml index aa75c2a0..fccb949d 100644 --- a/src/Views/DiffView.axaml +++ b/src/Views/DiffView.axaml @@ -34,6 +34,20 @@ + + + + (); + textDiff?.GotoFirstChange(); + e.Handled = true; + } + private void OnGotoPrevChange(object _, RoutedEventArgs e) { var textDiff = this.FindDescendantOfType(); @@ -24,5 +31,12 @@ namespace SourceGit.Views textDiff?.GotoNextChange(); e.Handled = true; } + + private void OnGotoLastChange(object _, RoutedEventArgs e) + { + var textDiff = this.FindDescendantOfType(); + textDiff?.GotoLastChange(); + e.Handled = true; + } } } diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 83bc47e3..323fde03 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -543,6 +543,21 @@ namespace SourceGit.Views { } + public void GotoFirstChange() + { + var blockNavigation = BlockNavigation; + if (blockNavigation != null) + { + var prev = blockNavigation.GotoFirst(); + if (prev != null) + { + TextArea.Caret.Line = prev.Start; + ScrollToLine(prev.Start); + } + } + // NOTE: Not implemented (button hidden) for non-block navigation. + } + public void GotoPrevChange() { var blockNavigation = BlockNavigation; @@ -641,6 +656,21 @@ namespace SourceGit.Views } } + public void GotoLastChange() + { + var blockNavigation = BlockNavigation; + if (blockNavigation != null) + { + var next = blockNavigation.GotoLast(); + if (next != null) + { + TextArea.Caret.Line = next.Start; + ScrollToLine(next.Start); + } + } + // NOTE: Not implemented (button hidden) for non-block navigation. + } + public override void Render(DrawingContext context) { base.Render(context); @@ -1682,6 +1712,19 @@ namespace SourceGit.Views InitializeComponent(); } + public void GotoFirstChange() + { + var presenter = this.FindDescendantOfType(); + if (presenter == null) + return; + + presenter.GotoFirstChange(); + if (presenter is SingleSideTextDiffPresenter singleSide) + singleSide.ForceSyncScrollOffset(); + + BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty; + } + public void GotoPrevChange() { var presenter = this.FindDescendantOfType(); @@ -1708,6 +1751,19 @@ namespace SourceGit.Views BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty; } + public void GotoLastChange() + { + var presenter = this.FindDescendantOfType(); + if (presenter == null) + return; + + presenter.GotoLastChange(); + if (presenter is SingleSideTextDiffPresenter singleSide) + singleSide.ForceSyncScrollOffset(); + + BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty; + } + protected override void OnDataContextChanged(EventArgs e) { base.OnDataContextChanged(e); From 52a53cc6976df7ff153209ace0e78bb353e50d94 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 24 Feb 2025 01:32:32 +0000 Subject: [PATCH 260/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 34 ++++++++++++++++++++++++---------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 256070e2..a48af9bd 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.60%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.35%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-92.18%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-97.61%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.91%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.47%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.34%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.09%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.93%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-97.35%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.67%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.21%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-99.74%25-yellow)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-99.74%25-yellow)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index c235ea6a..4e96f0ac 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,4 +1,4 @@ -### de_DE.axaml: 99.60% +### de_DE.axaml: 99.34%
@@ -6,11 +6,13 @@ - Text.BranchUpstreamInvalid - Text.Configure.CustomAction.WaitForExit +- Text.Diff.First +- Text.Diff.Last - Text.Preferences.AI.Streaming
-### es_ES.axaml: 97.35% +### es_ES.axaml: 97.09%
@@ -31,6 +33,8 @@ - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup - Text.DeleteRepositoryNode.TipForRepository +- Text.Diff.First +- Text.Diff.Last - Text.Preferences.AI.Streaming - Text.Repository.Notifications.Clear - Text.Stash.AutoRestore @@ -39,7 +43,7 @@
-### fr_FR.axaml: 92.18% +### fr_FR.axaml: 91.93%
@@ -60,6 +64,8 @@ - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup - Text.DeleteRepositoryNode.TipForRepository +- Text.Diff.First +- Text.Diff.Last - Text.InProgress.CherryPick.Head - Text.InProgress.Merge.Operating - Text.InProgress.Rebase.StoppedAt @@ -107,7 +113,7 @@
-### it_IT.axaml: 97.61% +### it_IT.axaml: 97.35%
@@ -127,6 +133,8 @@ - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup - Text.DeleteRepositoryNode.TipForRepository +- Text.Diff.First +- Text.Diff.Last - Text.Preferences.AI.Streaming - Text.Repository.Notifications.Clear - Text.Stash.AutoRestore @@ -134,7 +142,7 @@
-### pt_BR.axaml: 91.91% +### pt_BR.axaml: 91.67%
@@ -162,6 +170,8 @@ - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup - Text.DeleteRepositoryNode.TipForRepository +- Text.Diff.First +- Text.Diff.Last - Text.Diff.UseBlockNavigation - Text.Fetch.Force - Text.FileCM.ResolveUsing @@ -204,7 +214,7 @@
-### ru_RU.axaml: 99.47% +### ru_RU.axaml: 99.21%
@@ -213,26 +223,30 @@ - Text.BranchCM.CustomAction - Text.BranchUpstreamInvalid - Text.Configure.CustomAction.Scope.Branch +- Text.Diff.First +- Text.Diff.Last - Text.Preferences.AI.Streaming
-### zh_CN.axaml: 100.00% +### zh_CN.axaml: 99.74%
Missing Keys - +- Text.Diff.First +- Text.Diff.Last
-### zh_TW.axaml: 100.00% +### zh_TW.axaml: 99.74%
Missing Keys - +- Text.Diff.First +- Text.Diff.Last
From 124bdc97f96a30ebcd0572671aed5db26bc6ee81 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 24 Feb 2025 09:37:34 +0800 Subject: [PATCH 261/441] localization: add missing keys for zh_CN and zh_TW Signed-off-by: leo --- src/Resources/Locales/en_US.axaml | 6 +++--- src/Resources/Locales/zh_CN.axaml | 2 ++ src/Resources/Locales/zh_TW.axaml | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index d2d64d5c..1a83a4da 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -250,13 +250,13 @@ OLD Copy File Mode Changed - Ignore Whitespace Change - LFS OBJECT CHANGE First Difference + Ignore Whitespace Change + Last Difference + LFS OBJECT CHANGE Next Difference NO CHANGES OR ONLY EOL CHANGES Previous Difference - Last Difference Save as Patch Show hidden symbols Side-By-Side Diff diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 115f917e..acfdefd2 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -253,7 +253,9 @@ 原始大小 复制 文件权限已变化 + 首个差异 忽略空白符号变化 + 最后一个差异 LFS对象变更 下一个差异 没有变更或仅有换行符差异 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 00933783..dd9092a4 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -253,7 +253,9 @@ 原始大小 複製 檔案權限已變更 + 第一個差異 忽略空白符號變化 + 最後一個差異 LFS 物件變更 下一個差異 沒有變更或僅有換行字元差異 From 74e5bcb7047d95e38ca116a1fe0ef2ef9c84242e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 24 Feb 2025 01:37:52 +0000 Subject: [PATCH 262/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a48af9bd..a82a43b1 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.34%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.09%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.93%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-97.35%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.67%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.21%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-99.74%25-yellow)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-99.74%25-yellow)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.34%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.09%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.93%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-97.35%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.67%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.21%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index 4e96f0ac..acecf990 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -229,24 +229,22 @@
-### zh_CN.axaml: 99.74% +### zh_CN.axaml: 100.00%
Missing Keys -- Text.Diff.First -- Text.Diff.Last +
-### zh_TW.axaml: 99.74% +### zh_TW.axaml: 100.00%
Missing Keys -- Text.Diff.First -- Text.Diff.Last +
From d4341c119554835d4885dd54ba15bd7fe153cf78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20J=2E=20Mart=C3=ADnez=20M=2E?= <56406225+jjesus-dev@users.noreply.github.com> Date: Sun, 23 Feb 2025 19:45:39 -0600 Subject: [PATCH 263/441] localization: add missing spanish translations (#1017) --- src/Resources/Locales/es_ES.axaml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index a0f35814..24170683 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -22,7 +22,9 @@ Rama de Seguimiento: Seguimiento de rama remota Asistente OpenAI + RE-GENERAR Usar OpenAI para generar mensaje de commit + APLICAR CÓMO MENSAJE DE COMMIT Aplicar Patch Error Genera errores y se niega a aplicar el patch @@ -37,6 +39,10 @@ Advertencia Genera advertencias para algunos de estos errores, pero aplica Espacios en Blanco: + Aplicar Stash + Borrar después de aplicar + Restaurar los cambios del índice + Stash: Archivar... Guardar Archivo en: Seleccionar ruta del archivo @@ -53,6 +59,7 @@ Comparar con HEAD Comparar con Worktree Copiar Nombre de Rama + Acción personalizada Eliminar ${0}$... Eliminar {0} ramas seleccionadas Descartar todos los cambios @@ -68,6 +75,7 @@ Renombrar ${0}$... Establecer Rama de Seguimiento... Comparar Ramas + ¡Upstream inválido! Bytes CANCELAR Resetear a Esta Revisión @@ -100,6 +108,7 @@ Nombre Local: Nombre del repositorio. Opcional. Carpeta Padre: + Inicializar y actualizar submodulos URL del Repositorio: CERRAR Editor @@ -152,8 +161,10 @@ Archivo Ejecutable: Nombre: Alcance: + Rama Commit Repositorio + Esperar la acción de salida Dirección de Email Dirección de email GIT @@ -202,6 +213,7 @@ Stash & Reaplicar Nombre de la Nueva Rama: Introduzca el nombre de la rama. + Los espacios serán reemplazados con guiones. Crear Rama Local Crear Etiqueta... Nueva Etiqueta En: @@ -225,8 +237,11 @@ Estás intentando eliminar múltiples ramas a la vez. ¡Asegúrate de revisar antes de tomar acción! Eliminar Remoto Remoto: + Ruta: Destino: + Todos los hijos serán removidos de la lista. Confirmar Eliminación de Grupo + ¡Esto solo lo removera de la lista, no del disco! Confirmar Eliminación de Repositorio Eliminar Submódulo Ruta del Submódulo: @@ -449,6 +464,7 @@ Modelo Nombre Servidor + Activar Transmisión APARIENCIA Fuente por defecto Tamaño de fuente @@ -576,6 +592,7 @@ RAMAS LOCALES Navegar a HEAD Crear Rama + LIMPIAR NOTIFICACIONES Resaltar solo la rama actual en el gráfico Abrir en {0} Abrir en Herramientas Externas @@ -642,6 +659,8 @@ Ruta de almacenamiento de la clave privada SSH INICIAR Stash + Restaurar automáticamente después del stashing + Tus archivos de trabajo permanecen sin cambios, pero se guarda un stash. Incluir archivos no rastreados Mantener archivos staged Mensaje: @@ -721,6 +740,7 @@ INCLUIR ARCHIVOS NO RASTREADOS NO HAY MENSAJES DE ENTRADA RECIENTES NO HAY PLANTILLAS DE COMMIT + Firmar STAGED UNSTAGE UNSTAGE TODO From 89e09d842d6f632e4c2cda52a6715983b44a2c28 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 24 Feb 2025 01:45:49 +0000 Subject: [PATCH 264/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 22 +--------------------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index a82a43b1..0990a39d 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.34%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.09%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.93%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-97.35%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.67%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.21%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.34%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-99.74%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.93%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-97.35%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.67%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.21%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index acecf990..04e121fc 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -12,34 +12,14 @@
-### es_ES.axaml: 97.09% +### es_ES.axaml: 99.74%
Missing Keys -- Text.AIAssistant.Regen -- Text.AIAssistant.Use -- Text.ApplyStash -- Text.ApplyStash.DropAfterApply -- Text.ApplyStash.RestoreIndex -- Text.ApplyStash.Stash -- Text.BranchCM.CustomAction -- Text.BranchUpstreamInvalid -- Text.Clone.RecurseSubmodules -- Text.Configure.CustomAction.Scope.Branch -- Text.Configure.CustomAction.WaitForExit -- Text.CreateBranch.Name.WarnSpace -- Text.DeleteRepositoryNode.Path -- Text.DeleteRepositoryNode.TipForGroup -- Text.DeleteRepositoryNode.TipForRepository - Text.Diff.First - Text.Diff.Last -- Text.Preferences.AI.Streaming -- Text.Repository.Notifications.Clear -- Text.Stash.AutoRestore -- Text.Stash.AutoRestore.Tip -- Text.WorkingCopy.SignOff
From 0b7805b2ee3489de0e4b6a3b62782301fa25012b Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 24 Feb 2025 09:49:30 +0800 Subject: [PATCH 265/441] version: Release 2025.06 Signed-off-by: leo --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 15689348..bb11b3b9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2025.05 \ No newline at end of file +2025.06 \ No newline at end of file From 1d037c7c572389bd91d50a22a1105b89bf4fd5c6 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 24 Feb 2025 21:24:53 +0800 Subject: [PATCH 266/441] feature: add context menu `Save As Patch...` for selected stash (#1018) Signed-off-by: leo --- src/Commands/SaveChangesAsPatch.cs | 13 +++++++++++ src/Resources/Locales/en_US.axaml | 1 + src/Resources/Locales/zh_CN.axaml | 1 + src/Resources/Locales/zh_TW.axaml | 1 + src/ViewModels/StashesPage.cs | 37 ++++++++++++++++++++++++++++++ 5 files changed, 53 insertions(+) diff --git a/src/Commands/SaveChangesAsPatch.cs b/src/Commands/SaveChangesAsPatch.cs index 461bbfb5..b10037a1 100644 --- a/src/Commands/SaveChangesAsPatch.cs +++ b/src/Commands/SaveChangesAsPatch.cs @@ -37,6 +37,19 @@ namespace SourceGit.Commands return true; } + public static bool ProcessStashChanges(string repo, List opts, string saveTo) + { + using (var sw = File.Create(saveTo)) + { + foreach (var opt in opts) + { + if (!ProcessSingleChange(repo, opt, sw)) + return false; + } + } + return true; + } + private static bool ProcessSingleChange(string repo, Models.DiffOption opt, FileStream writer) { var starter = new ProcessStartInfo(); diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 1a83a4da..6c397ea0 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -669,6 +669,7 @@ Apply Drop Pop + Save as Patch... Drop Stash Drop: STASHES diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index acfdefd2..09c46e95 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -673,6 +673,7 @@ 应用(apply) 删除(drop) 应用并删除(pop) + 另存为补丁... 丢弃贮藏确认 丢弃贮藏 : 贮藏列表 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index dd9092a4..0eb54676 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -672,6 +672,7 @@ 套用 (apply) 刪除 (drop) 套用並刪除 (pop) + 另存為修補檔 (patch)... 捨棄擱置變更確認 捨棄擱置變更: 擱置變更 diff --git a/src/ViewModels/StashesPage.cs b/src/ViewModels/StashesPage.cs index 4a3bf933..57b30fd3 100644 --- a/src/ViewModels/StashesPage.cs +++ b/src/ViewModels/StashesPage.cs @@ -4,6 +4,7 @@ using System.IO; using System.Threading.Tasks; using Avalonia.Controls; +using Avalonia.Platform.Storage; using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; @@ -157,9 +158,45 @@ namespace SourceGit.ViewModels ev.Handled = true; }; + var patch = new MenuItem(); + patch.Header = App.Text("StashCM.SaveAsPatch"); + patch.Icon = App.CreateMenuIcon("Icons.Diff"); + patch.Click += async (_, e) => + { + var storageProvider = App.GetStorageProvider(); + if (storageProvider == null) + return; + + var options = new FilePickerSaveOptions(); + options.Title = App.Text("StashCM.SaveAsPatch"); + options.DefaultExtension = ".patch"; + options.FileTypeChoices = [new FilePickerFileType("Patch File") { Patterns = ["*.patch"] }]; + + var storageFile = await storageProvider.SaveFilePickerAsync(options); + if (storageFile != null) + { + var opts = new List(); + foreach (var c in _changes) + { + if (_untrackedChanges.Contains(c.Path)) + opts.Add(new Models.DiffOption("4b825dc642cb6eb9a060e54bf8d69288fbee4904", _selectedStash.Parents[2], c)); + else + opts.Add(new Models.DiffOption(_selectedStash.Parents[0], _selectedStash.SHA, c)); + } + + var succ = await Task.Run(() => Commands.SaveChangesAsPatch.ProcessStashChanges(_repo.FullPath, opts, storageFile.Path.LocalPath)); + if (succ) + App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess")); + } + + e.Handled = true; + }; + var menu = new ContextMenu(); menu.Items.Add(apply); menu.Items.Add(drop); + menu.Items.Add(new MenuItem { Header = "-" }); + menu.Items.Add(patch); return menu; } From 1f35e837997148049b2365484b9bbea16ef5bd56 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 24 Feb 2025 13:25:13 +0000 Subject: [PATCH 267/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0990a39d..e89b071c 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.34%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-99.74%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.93%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-97.35%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.67%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.21%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.21%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-99.60%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.81%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-97.23%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.55%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.08%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index 04e121fc..024cd035 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,4 +1,4 @@ -### de_DE.axaml: 99.34% +### de_DE.axaml: 99.21%
@@ -9,10 +9,11 @@ - Text.Diff.First - Text.Diff.Last - Text.Preferences.AI.Streaming +- Text.StashCM.SaveAsPatch
-### es_ES.axaml: 99.74% +### es_ES.axaml: 99.60%
@@ -20,10 +21,11 @@ - Text.Diff.First - Text.Diff.Last +- Text.StashCM.SaveAsPatch
-### fr_FR.axaml: 91.93% +### fr_FR.axaml: 91.81%
@@ -88,12 +90,13 @@ - Text.SHALinkCM.NavigateTo - Text.Stash.AutoRestore - Text.Stash.AutoRestore.Tip +- Text.StashCM.SaveAsPatch - Text.WorkingCopy.CommitToEdit - Text.WorkingCopy.SignOff
-### it_IT.axaml: 97.35% +### it_IT.axaml: 97.23%
@@ -119,10 +122,11 @@ - Text.Repository.Notifications.Clear - Text.Stash.AutoRestore - Text.Stash.AutoRestore.Tip +- Text.StashCM.SaveAsPatch
-### pt_BR.axaml: 91.67% +### pt_BR.axaml: 91.55%
@@ -189,12 +193,13 @@ - Text.SHALinkCM.NavigateTo - Text.Stash.AutoRestore - Text.Stash.AutoRestore.Tip +- Text.StashCM.SaveAsPatch - Text.WorkingCopy.CommitToEdit - Text.WorkingCopy.SignOff
-### ru_RU.axaml: 99.21% +### ru_RU.axaml: 99.08%
@@ -206,6 +211,7 @@ - Text.Diff.First - Text.Diff.Last - Text.Preferences.AI.Streaming +- Text.StashCM.SaveAsPatch
From c6747f72f9fc712229b87783bc8d8a735f119647 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 25 Feb 2025 10:53:42 +0800 Subject: [PATCH 268/441] feature: auto-select first change in commit details panel and revision/branch compare panel (#1019) Signed-off-by: leo --- src/Models/OpenAI.cs | 2 +- src/ViewModels/CommitDetail.cs | 16 ++++---- src/ViewModels/Repository.cs | 6 +++ src/ViewModels/WorkingCopy.cs | 2 +- src/Views/BranchCompare.axaml | 1 + src/Views/ChangeCollectionView.axaml.cs | 53 +++++++++++++++++++++---- src/Views/CommitChanges.axaml | 1 + src/Views/LauncherTabsSelector.axaml.cs | 6 +-- src/Views/Repository.axaml.cs | 2 +- src/Views/RevisionCompare.axaml | 1 + src/Views/TextDiffView.axaml.cs | 2 +- 11 files changed, 71 insertions(+), 21 deletions(-) diff --git a/src/Models/OpenAI.cs b/src/Models/OpenAI.cs index 264230c6..76daacd0 100644 --- a/src/Models/OpenAI.cs +++ b/src/Models/OpenAI.cs @@ -36,7 +36,7 @@ namespace SourceGit.Models { if (startIdx > 0) OnReceive(buffer.Substring(0, startIdx)); - + var endIdx = buffer.IndexOf(">", startIdx + 1, StringComparison.Ordinal); if (endIdx <= startIdx) { diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index d90e97d6..702a757c 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -25,8 +25,15 @@ namespace SourceGit.ViewModels public int ActivePageIndex { - get => _activePageIndex; - set => SetProperty(ref _activePageIndex, value); + get => _repo.CommitDetailActivePageIndex; + set + { + if (_repo.CommitDetailActivePageIndex != value) + { + _repo.CommitDetailActivePageIndex = value; + OnPropertyChanged(); + } + } } public Models.Commit Commit @@ -617,11 +624,7 @@ namespace SourceGit.ViewModels _changes = null; _revisionFiles.Clear(); - FullMessage = string.Empty; SignInfo = null; - Changes = []; - VisibleChanges = null; - SelectedChanges = null; ViewRevisionFileContent = null; Children.Clear(); RevisionFileSearchFilter = string.Empty; @@ -821,7 +824,6 @@ namespace SourceGit.ViewModels }; private Repository _repo = null; - private int _activePageIndex = 0; private Models.Commit _commit = null; private string _fullMessage = string.Empty; private Models.CommitSignInfo _signInfo = null; diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 6e8a5290..104ff60b 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -453,6 +453,12 @@ namespace SourceGit.ViewModels private set => SetProperty(ref _isAutoFetching, value); } + public int CommitDetailActivePageIndex + { + get; + set; + } = 0; + public Repository(bool isBare, string path, string gitDir) { IsBare = isBare; diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index ce2a2ac1..afaf5868 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -1466,7 +1466,7 @@ namespace SourceGit.ViewModels return unstaged; var visible = new List(); - + foreach (var c in unstaged) { if (c.Path.Contains(_unstagedFilter, StringComparison.OrdinalIgnoreCase)) diff --git a/src/Views/BranchCompare.axaml b/src/Views/BranchCompare.axaml index 04b77306..f73860c5 100644 --- a/src/Views/BranchCompare.axaml +++ b/src/Views/BranchCompare.axaml @@ -134,6 +134,7 @@
diff --git a/src/Views/ChangeCollectionView.axaml.cs b/src/Views/ChangeCollectionView.axaml.cs index d6982dda..6ef79861 100644 --- a/src/Views/ChangeCollectionView.axaml.cs +++ b/src/Views/ChangeCollectionView.axaml.cs @@ -85,6 +85,15 @@ namespace SourceGit.Views set => SetValue(ChangesProperty, value); } + public static readonly StyledProperty AutoSelectFirstChangeProperty = + AvaloniaProperty.Register(nameof(AutoSelectFirstChange), false); + + public bool AutoSelectFirstChange + { + get => GetValue(AutoSelectFirstChangeProperty); + set => SetValue(AutoSelectFirstChangeProperty, value); + } + public static readonly StyledProperty> SelectedChangesProperty = AvaloniaProperty.Register>(nameof(SelectedChanges)); @@ -205,9 +214,9 @@ namespace SourceGit.Views base.OnPropertyChanged(change); if (change.Property == ViewModeProperty) - UpdateDataSource(false); - else if (change.Property == ChangesProperty) UpdateDataSource(true); + else if (change.Property == ChangesProperty) + UpdateDataSource(false); else if (change.Property == SelectedChangesProperty) UpdateSelection(); } @@ -292,9 +301,9 @@ namespace SourceGit.Views } } - private void UpdateDataSource(bool disableEvents) + private void UpdateDataSource(bool onlyViewModeChange) { - _disableSelectionChangingEvent = disableEvents; + _disableSelectionChangingEvent = !onlyViewModeChange; var changes = Changes; if (changes == null || changes.Count == 0) @@ -324,7 +333,19 @@ namespace SourceGit.Views MakeTreeRows(rows, tree.Tree); tree.Rows.AddRange(rows); - if (selected.Count > 0) + if (!onlyViewModeChange && AutoSelectFirstChange) + { + foreach (var row in tree.Rows) + { + if (row.Change != null) + { + tree.SelectedRows.Add(row); + SetCurrentValue(SelectedChangesProperty, [row.Change]); + break; + } + } + } + else if (selected.Count > 0) { var sets = new HashSet(); foreach (var c in selected) @@ -346,16 +367,34 @@ namespace SourceGit.Views { var grid = new ViewModels.ChangeCollectionAsGrid(); grid.Changes.AddRange(changes); - if (selected.Count > 0) + + if (!onlyViewModeChange && AutoSelectFirstChange) + { + grid.SelectedChanges.Add(changes[0]); + SetCurrentValue(SelectedChangesProperty, [changes[0]]); + } + else if (selected.Count > 0) + { grid.SelectedChanges.AddRange(selected); + } + Content = grid; } else { var list = new ViewModels.ChangeCollectionAsList(); list.Changes.AddRange(changes); - if (selected.Count > 0) + + if (!onlyViewModeChange && AutoSelectFirstChange) + { + list.SelectedChanges.Add(changes[0]); + SetCurrentValue(SelectedChangesProperty, [changes[0]]); + } + else if (selected.Count > 0) + { list.SelectedChanges.AddRange(selected); + } + Content = list; } diff --git a/src/Views/CommitChanges.axaml b/src/Views/CommitChanges.axaml index 377be944..2fac9365 100644 --- a/src/Views/CommitChanges.axaml +++ b/src/Views/CommitChanges.axaml @@ -49,6 +49,7 @@ ViewMode="{Binding Source={x:Static vm:Preferences.Instance}, Path=CommitChangeViewMode}" Changes="{Binding VisibleChanges}" SelectedChanges="{Binding SelectedChanges, Mode=TwoWay}" + AutoSelectFirstChange="True" ContextRequested="OnChangeContextRequested"/>
diff --git a/src/Views/LauncherTabsSelector.axaml.cs b/src/Views/LauncherTabsSelector.axaml.cs index 01c5fa0d..61d7a966 100644 --- a/src/Views/LauncherTabsSelector.axaml.cs +++ b/src/Views/LauncherTabsSelector.axaml.cs @@ -39,7 +39,7 @@ namespace SourceGit.Views } public static readonly RoutedEvent PageSelectedEvent = - RoutedEvent.Register(nameof(PageSelected), RoutingStrategies.Tunnel | RoutingStrategies.Bubble); + RoutedEvent.Register(nameof(PageSelected), RoutingStrategies.Tunnel | RoutingStrategies.Bubble); public event EventHandler PageSelected { @@ -74,7 +74,7 @@ namespace SourceGit.Views private void OnPageSelectionChanged(object sender, SelectionChangedEventArgs e) { - if (sender is ListBox { SelectedItem : ViewModels.LauncherPage page }) + if (sender is ListBox { SelectedItem: ViewModels.LauncherPage page }) { _isProcessingSelection = true; RaiseEvent(new LauncherTabSelectedEventArgs(page)); @@ -88,7 +88,7 @@ namespace SourceGit.Views { if (_isProcessingSelection) return; - + VisiblePages.Clear(); if (Pages == null) diff --git a/src/Views/Repository.axaml.cs b/src/Views/Repository.axaml.cs index 53bb2d53..2b3b7c30 100644 --- a/src/Views/Repository.axaml.cs +++ b/src/Views/Repository.axaml.cs @@ -522,7 +522,7 @@ namespace SourceGit.Views private void OnRemoveSelectedHistoriesFilter(object sender, RoutedEventArgs e) { - if (DataContext is ViewModels.Repository repo && sender is Button { DataContext: Models.Filter filter}) + if (DataContext is ViewModels.Repository repo && sender is Button { DataContext: Models.Filter filter }) repo.RemoveHistoriesFilter(filter); e.Handled = true; diff --git a/src/Views/RevisionCompare.axaml b/src/Views/RevisionCompare.axaml index 46b667ac..73703ff1 100644 --- a/src/Views/RevisionCompare.axaml +++ b/src/Views/RevisionCompare.axaml @@ -99,6 +99,7 @@ diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 323fde03..dccbb9b2 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -1006,7 +1006,7 @@ namespace SourceGit.Views if (startPosition.Location > endPosition.Location) (startPosition, endPosition) = (endPosition, startPosition); - + var startIdx = Math.Min(startPosition.Line - 1, lines.Count - 1); var endIdx = Math.Min(endPosition.Line - 1, lines.Count - 1); From 4d740f4731432e637ca1bb5f195ce9b307b4e805 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 25 Feb 2025 11:09:12 +0800 Subject: [PATCH 269/441] feature: auto-select the first change when selected stash changed (#1019) Signed-off-by: leo --- src/ViewModels/StashesPage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ViewModels/StashesPage.cs b/src/ViewModels/StashesPage.cs index 57b30fd3..9e220234 100644 --- a/src/ViewModels/StashesPage.cs +++ b/src/ViewModels/StashesPage.cs @@ -89,7 +89,7 @@ namespace SourceGit.ViewModels private set { if (SetProperty(ref _changes, value)) - SelectedChange = null; + SelectedChange = value is { Count: >0 } ? value[0] : null; } } From a0786bf9cc12f6e1b29078eed8357879e023098d Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 25 Feb 2025 14:37:03 +0800 Subject: [PATCH 270/441] fix: pulling with empty repository (no local branch) crashes this app (#1020) Signed-off-by: leo --- src/ViewModels/Repository.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 104ff60b..85b819c4 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -663,6 +663,12 @@ namespace SourceGit.ViewModels return; } + if (_currentBranch == null) + { + App.RaiseException(_fullpath, "Can NOT found current branch!!!"); + return; + } + var pull = new Pull(this, null); if (autoStart && pull.SelectedBranch != null) ShowAndStartPopup(pull); From 79306ad73bbd2b6f0872cbb32d348a0b105b50e4 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 25 Feb 2025 19:50:09 +0800 Subject: [PATCH 271/441] fix: `ptyxis` does not start with given working directory (#1005) Signed-off-by: leo --- src/Native/Linux.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Native/Linux.cs b/src/Native/Linux.cs index a24f1b65..fec110b2 100644 --- a/src/Native/Linux.cs +++ b/src/Native/Linux.cs @@ -65,13 +65,16 @@ namespace SourceGit.Native { var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); var cwd = string.IsNullOrEmpty(workdir) ? home : workdir; + var terminal = OS.ShellOrTerminal; var startInfo = new ProcessStartInfo(); startInfo.WorkingDirectory = cwd; - startInfo.FileName = OS.ShellOrTerminal; + startInfo.FileName = terminal; - if (OS.ShellOrTerminal.EndsWith("wezterm", StringComparison.OrdinalIgnoreCase)) + if (terminal.EndsWith("wezterm", StringComparison.OrdinalIgnoreCase)) startInfo.Arguments = $"start --cwd \"{cwd}\""; + else if (terminal.EndsWith("ptyxis", StringComparison.OrdinalIgnoreCase)) + startInfo.Arguments = $"--working-directory=\"{cwd}\""; try { From a7e254cac658ec288de30b490a1eaabbc4a3aa83 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 26 Feb 2025 09:50:54 +0800 Subject: [PATCH 272/441] fix: multiple bindings for `IsVisible` property of Button Signed-off-by: leo --- src/Views/DiffView.axaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Views/DiffView.axaml b/src/Views/DiffView.axaml index fccb949d..3644f8fc 100644 --- a/src/Views/DiffView.axaml +++ b/src/Views/DiffView.axaml @@ -37,7 +37,6 @@ + + - - - + + From b75676a7f8e350e27c9faf34b85e61e20707a589 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 4 Mar 2025 16:04:19 +0800 Subject: [PATCH 301/441] refactor: commit message - move issue tracker and commit hash links parsing to view models - parsing links async - make sure matched hash is a valid commit oid - disable `CHILDREN` row in submodule info panel Signed-off-by: leo --- src/Commands/IsCommitSHA.cs | 17 +++ ...cs => QueryCommitsForInteractiveRebase.cs} | 16 +- src/Models/Commit.cs | 6 +- src/Models/InteractiveRebase.cs | 6 + src/Models/RevisionFile.cs | 2 +- src/ViewModels/CommitDetail.cs | 142 +++++++++++------- src/ViewModels/DiffContext.cs | 8 +- src/ViewModels/FileHistories.cs | 12 +- src/ViewModels/InteractiveRebase.cs | 2 +- src/Views/CommitBaseInfo.axaml | 11 +- src/Views/CommitBaseInfo.axaml.cs | 33 ++-- src/Views/CommitDetail.axaml | 5 +- src/Views/CommitMessagePresenter.cs | 98 +++--------- src/Views/DiffView.axaml | 4 +- src/Views/RevisionFileContentViewer.axaml | 2 +- src/Views/RevisionFiles.axaml | 2 +- src/Views/RevisionFiles.axaml.cs | 11 +- 17 files changed, 191 insertions(+), 186 deletions(-) create mode 100644 src/Commands/IsCommitSHA.cs rename src/Commands/{QueryCommitsWithFullMessage.cs => QueryCommitsForInteractiveRebase.cs} (86%) diff --git a/src/Commands/IsCommitSHA.cs b/src/Commands/IsCommitSHA.cs new file mode 100644 index 00000000..1b0c50e3 --- /dev/null +++ b/src/Commands/IsCommitSHA.cs @@ -0,0 +1,17 @@ +namespace SourceGit.Commands +{ + public class IsCommitSHA : Command + { + public IsCommitSHA(string repo, string hash) + { + WorkingDirectory = repo; + Args = $"cat-file -t {hash}"; + } + + public bool Result() + { + var rs = ReadToEnd(); + return rs.IsSuccess && rs.StdOut.Trim().Equals("commit"); + } + } +} diff --git a/src/Commands/QueryCommitsWithFullMessage.cs b/src/Commands/QueryCommitsForInteractiveRebase.cs similarity index 86% rename from src/Commands/QueryCommitsWithFullMessage.cs rename to src/Commands/QueryCommitsForInteractiveRebase.cs index c15cdbe1..232d86e5 100644 --- a/src/Commands/QueryCommitsWithFullMessage.cs +++ b/src/Commands/QueryCommitsForInteractiveRebase.cs @@ -3,18 +3,18 @@ using System.Collections.Generic; namespace SourceGit.Commands { - public class QueryCommitsWithFullMessage : Command + public class QueryCommitsForInteractiveRebase : Command { - public QueryCommitsWithFullMessage(string repo, string args) + public QueryCommitsForInteractiveRebase(string repo, string on) { _boundary = $"----- BOUNDARY OF COMMIT {Guid.NewGuid()} -----"; WorkingDirectory = repo; Context = repo; - Args = $"log --date-order --no-show-signature --decorate=full --pretty=format:\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {args}"; + Args = $"log --date-order --no-show-signature --decorate=full --pretty=format:\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {on}..HEAD"; } - public List Result() + public List Result() { var rs = ReadToEnd(); if (!rs.IsSuccess) @@ -29,7 +29,7 @@ namespace SourceGit.Commands switch (nextPartIdx) { case 0: - _current = new Models.CommitWithMessage(); + _current = new Models.InteractiveCommit(); _current.Commit.SHA = line; _commits.Add(_current); break; @@ -52,7 +52,7 @@ namespace SourceGit.Commands _current.Commit.CommitterTime = ulong.Parse(line); break; default: - var boundary = rs.StdOut.IndexOf(_boundary, end + 1); + var boundary = rs.StdOut.IndexOf(_boundary, end + 1, StringComparison.Ordinal); if (boundary > end) { _current.Message = rs.StdOut.Substring(start, boundary - start - 1); @@ -88,8 +88,8 @@ namespace SourceGit.Commands _current.Commit.Parents.AddRange(data.Split(separator: ' ', options: StringSplitOptions.RemoveEmptyEntries)); } - private List _commits = new List(); - private Models.CommitWithMessage _current = null; + private List _commits = []; + private Models.InteractiveCommit _current = null; private string _boundary = ""; } } diff --git a/src/Models/Commit.cs b/src/Models/Commit.cs index f015130a..5c48b0c0 100644 --- a/src/Models/Commit.cs +++ b/src/Models/Commit.cs @@ -112,9 +112,9 @@ namespace SourceGit.Models } } - public class CommitWithMessage + public class CommitFullMessage { - public Commit Commit { get; set; } = new Commit(); - public string Message { get; set; } = ""; + public string Message { get; set; } = string.Empty; + public List Links { get; set; } = []; } } diff --git a/src/Models/InteractiveRebase.cs b/src/Models/InteractiveRebase.cs index 0980587a..691aadeb 100644 --- a/src/Models/InteractiveRebase.cs +++ b/src/Models/InteractiveRebase.cs @@ -12,6 +12,12 @@ namespace SourceGit.Models Drop, } + public class InteractiveCommit + { + public Commit Commit { get; set; } = new Commit(); + public string Message { get; set; } = string.Empty; + } + public class InteractiveRebaseJob { public string SHA { get; set; } = string.Empty; diff --git a/src/Models/RevisionFile.cs b/src/Models/RevisionFile.cs index f1f5265f..8cc1be2a 100644 --- a/src/Models/RevisionFile.cs +++ b/src/Models/RevisionFile.cs @@ -29,6 +29,6 @@ namespace SourceGit.Models public class RevisionSubmodule { public Commit Commit { get; set; } = null; - public string FullMessage { get; set; } = string.Empty; + public CommitFullMessage FullMessage { get; set; } = null; } } diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index 7c5aa28f..26fa37c1 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -5,7 +5,6 @@ using System.IO; using System.Text.RegularExpressions; using System.Threading.Tasks; -using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Media.Imaging; using Avalonia.Platform.Storage; @@ -46,7 +45,7 @@ namespace SourceGit.ViewModels } } - public string FullMessage + public Models.CommitFullMessage FullMessage { get => _fullMessage; private set => SetProperty(ref _fullMessage, value); @@ -85,11 +84,11 @@ namespace SourceGit.ViewModels } } - public AvaloniaList Children + public List Children { - get; - private set; - } = []; + get => _children; + private set => SetProperty(ref _children, value); + } public string SearchChangeFilter { @@ -109,17 +108,12 @@ namespace SourceGit.ViewModels set => SetProperty(ref _viewRevisionFileContent, value); } - public AvaloniaList WebLinks + public List WebLinks { get; private set; } = []; - public AvaloniaList IssueTrackerRules - { - get => _repo.Settings?.IssueTrackerRules; - } - public string RevisionFileSearchFilter { get => _revisionFileSearchFilter; @@ -127,25 +121,23 @@ namespace SourceGit.ViewModels { if (SetProperty(ref _revisionFileSearchFilter, value)) { - RevisionFileSearchSuggestion.Clear(); - if (!string.IsNullOrEmpty(value)) { - if (_revisionFiles.Count == 0) + if (_revisionFiles == null) { var sha = Commit.SHA; Task.Run(() => { var files = new Commands.QueryRevisionFileNames(_repo.FullPath, sha).Result(); + var filesList = new List(); + filesList.AddRange(files); Dispatcher.UIThread.Invoke(() => { if (sha == Commit.SHA) { - _revisionFiles.Clear(); - _revisionFiles.AddRange(files); - + _revisionFiles = filesList; if (!string.IsNullOrEmpty(_revisionFileSearchFilter)) UpdateRevisionFileSearchSuggestion(); } @@ -159,23 +151,17 @@ namespace SourceGit.ViewModels } else { - IsRevisionFileSearchSuggestionOpen = false; + RevisionFileSearchSuggestion = null; GC.Collect(); } } } } - public AvaloniaList RevisionFileSearchSuggestion + public List RevisionFileSearchSuggestion { - get; - private set; - } = []; - - public bool IsRevisionFileSearchSuggestionOpen - { - get => _isRevisionFileSearchSuggestionOpen; - set => SetProperty(ref _isRevisionFileSearchSuggestionOpen, value); + get => _revisionFileSearchSuggestion; + private set => SetProperty(ref _revisionFileSearchSuggestion, value); } public CommitDetail(Repository repo) @@ -212,23 +198,17 @@ namespace SourceGit.ViewModels { _repo = null; _commit = null; - - if (_changes != null) - _changes.Clear(); - if (_visibleChanges != null) - _visibleChanges.Clear(); - if (_selectedChanges != null) - _selectedChanges.Clear(); - + _changes = null; + _visibleChanges = null; + _selectedChanges = null; _signInfo = null; _searchChangeFilter = null; _diffContext = null; _viewRevisionFileContent = null; _cancelToken = null; - WebLinks.Clear(); - _revisionFiles.Clear(); - RevisionFileSearchSuggestion.Clear(); + _revisionFiles = null; + _revisionFileSearchSuggestion = null; } public void NavigateTo(string commitSHA) @@ -251,6 +231,11 @@ namespace SourceGit.ViewModels RevisionFileSearchFilter = string.Empty; } + public void CancelRevisionFileSuggestions() + { + RevisionFileSearchSuggestion = null; + } + public Models.Commit GetParent(string sha) { return new Commands.QuerySingleCommit(_repo.FullPath, sha).Result(); @@ -322,7 +307,12 @@ namespace SourceGit.ViewModels if (commit != null) { var body = new Commands.QueryCommitFullMessage(submoduleRoot, file.SHA).Result(); - var submodule = new Models.RevisionSubmodule() { Commit = commit, FullMessage = body }; + var submodule = new Models.RevisionSubmodule() + { + Commit = commit, + FullMessage = new Models.CommitFullMessage { Message = body } + }; + Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = submodule); } else @@ -332,7 +322,7 @@ namespace SourceGit.ViewModels ViewRevisionFileContent = new Models.RevisionSubmodule() { Commit = new Models.Commit() { SHA = file.SHA }, - FullMessage = string.Empty, + FullMessage = null, }; }); } @@ -622,23 +612,22 @@ namespace SourceGit.ViewModels private void Refresh() { _changes = null; - _revisionFiles.Clear(); + _revisionFiles = null; SignInfo = null; ViewRevisionFileContent = null; - Children.Clear(); + Children = null; RevisionFileSearchFilter = string.Empty; - IsRevisionFileSearchSuggestionOpen = false; - - GC.Collect(); + RevisionFileSearchSuggestion = null; if (_commit == null) return; Task.Run(() => { - var fullMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).Result(); - Dispatcher.UIThread.Invoke(() => FullMessage = fullMessage); + var message = new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).Result(); + var links = ParseLinksInMessage(message); + Dispatcher.UIThread.Invoke(() => FullMessage = new Models.CommitFullMessage { Message = message, Links = links }); }); Task.Run(() => @@ -694,6 +683,49 @@ namespace SourceGit.ViewModels }); } + private List ParseLinksInMessage(string message) + { + var links = new List(); + if (_repo.Settings.IssueTrackerRules is { Count: > 0 } rules) + { + foreach (var rule in rules) + rule.Matches(links, message); + } + + var shas = REG_SHA_FORMAT().Matches(message); + for (int i = 0; i < shas.Count; i++) + { + var sha = shas[i]; + if (!sha.Success) + continue; + + var hash = sha.Groups[1].Value; + var test = new Commands.IsCommitSHA(_repo.FullPath, hash).Result(); + if (!test) + continue; + + var start = sha.Index; + var len = sha.Length; + var intersect = false; + foreach (var link in links) + { + if (link.Intersect(start, len)) + { + intersect = true; + break; + } + } + + if (!intersect) + links.Add(new Models.Hyperlink(start, len, hash, true)); + } + + if (links.Count > 0) + links.Sort((l, r) => l.Start - r.Start); + + return links; + } + private void RefreshVisibleChanges() { if (_changes == null) @@ -813,11 +845,12 @@ namespace SourceGit.ViewModels break; } - RevisionFileSearchSuggestion.Clear(); - RevisionFileSearchSuggestion.AddRange(suggestion); - IsRevisionFileSearchSuggestionOpen = suggestion.Count > 0; + RevisionFileSearchSuggestion = suggestion; } + [GeneratedRegex(@"\b([0-9a-fA-F]{6,40})\b")] + private static partial Regex REG_SHA_FORMAT(); + [GeneratedRegex(@"^version https://git-lfs.github.com/spec/v\d+\r?\noid sha256:([0-9a-f]+)\r?\nsize (\d+)[\r\n]*$")] private static partial Regex REG_LFS_FORMAT(); @@ -828,8 +861,9 @@ namespace SourceGit.ViewModels private Repository _repo = null; private Models.Commit _commit = null; - private string _fullMessage = string.Empty; + private Models.CommitFullMessage _fullMessage = null; private Models.CommitSignInfo _signInfo = null; + private List _children = null; private List _changes = null; private List _visibleChanges = null; private List _selectedChanges = null; @@ -837,8 +871,8 @@ namespace SourceGit.ViewModels private DiffContext _diffContext = null; private object _viewRevisionFileContent = null; private Commands.Command.CancelToken _cancelToken = null; - private List _revisionFiles = []; + private List _revisionFiles = null; private string _revisionFileSearchFilter = string.Empty; - private bool _isRevisionFileSearchSuggestionOpen = false; + private List _revisionFileSearchSuggestion = null; } } diff --git a/src/ViewModels/DiffContext.cs b/src/ViewModels/DiffContext.cs index b10f4b62..6dd836bf 100644 --- a/src/ViewModels/DiffContext.cs +++ b/src/ViewModels/DiffContext.cs @@ -235,13 +235,17 @@ namespace SourceGit.ViewModels if (commit != null) { var body = new Commands.QueryCommitFullMessage(repo, sha).Result(); - return new Models.RevisionSubmodule() { Commit = commit, FullMessage = body }; + return new Models.RevisionSubmodule() + { + Commit = commit, + FullMessage = new Models.CommitFullMessage { Message = body } + }; } return new Models.RevisionSubmodule() { Commit = new Models.Commit() { SHA = sha }, - FullMessage = string.Empty, + FullMessage = null, }; } diff --git a/src/ViewModels/FileHistories.cs b/src/ViewModels/FileHistories.cs index 7e248274..417b816d 100644 --- a/src/ViewModels/FileHistories.cs +++ b/src/ViewModels/FileHistories.cs @@ -123,12 +123,20 @@ namespace SourceGit.ViewModels if (commit != null) { var message = new Commands.QueryCommitFullMessage(submoduleRoot, obj.SHA).Result(); - var module = new Models.RevisionSubmodule() { Commit = commit, FullMessage = message }; + var module = new Models.RevisionSubmodule() + { + Commit = commit, + FullMessage = new Models.CommitFullMessage { Message = message } + }; Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module)); } else { - var module = new Models.RevisionSubmodule() { Commit = new Models.Commit() { SHA = obj.SHA }, FullMessage = "" }; + var module = new Models.RevisionSubmodule() + { + Commit = new Models.Commit() { SHA = obj.SHA }, + FullMessage = null + }; Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module)); } }); diff --git a/src/ViewModels/InteractiveRebase.cs b/src/ViewModels/InteractiveRebase.cs index 9f28fbc7..2fd2d67c 100644 --- a/src/ViewModels/InteractiveRebase.cs +++ b/src/ViewModels/InteractiveRebase.cs @@ -118,7 +118,7 @@ namespace SourceGit.ViewModels Task.Run(() => { - var commits = new Commands.QueryCommitsWithFullMessage(repoPath, $"{on.SHA}..HEAD").Result(); + var commits = new Commands.QueryCommitsForInteractiveRebase(repoPath, on.SHA).Result(); var list = new List(); foreach (var c in commits) diff --git a/src/Views/CommitBaseInfo.axaml b/src/Views/CommitBaseInfo.axaml index c92a3612..4ff8f20f 100644 --- a/src/Views/CommitBaseInfo.axaml +++ b/src/Views/CommitBaseInfo.axaml @@ -95,8 +95,8 @@ - - + + @@ -133,8 +133,8 @@ - - + + @@ -187,8 +187,7 @@ diff --git a/src/Views/CommitBaseInfo.axaml.cs b/src/Views/CommitBaseInfo.axaml.cs index ce1a7cfd..8767db9f 100644 --- a/src/Views/CommitBaseInfo.axaml.cs +++ b/src/Views/CommitBaseInfo.axaml.cs @@ -1,7 +1,7 @@ +using System.Collections.Generic; using System.Threading.Tasks; using Avalonia; -using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; @@ -11,13 +11,13 @@ namespace SourceGit.Views { public partial class CommitBaseInfo : UserControl { - public static readonly StyledProperty MessageProperty = - AvaloniaProperty.Register(nameof(Message), string.Empty); + public static readonly StyledProperty FullMessageProperty = + AvaloniaProperty.Register(nameof(FullMessage)); - public string Message + public Models.CommitFullMessage FullMessage { - get => GetValue(MessageProperty); - set => SetValue(MessageProperty, value); + get => GetValue(FullMessageProperty); + set => SetValue(FullMessageProperty, value); } public static readonly StyledProperty SignInfoProperty = @@ -38,28 +38,19 @@ namespace SourceGit.Views set => SetValue(SupportsContainsInProperty, value); } - public static readonly StyledProperty> WebLinksProperty = - AvaloniaProperty.Register>(nameof(WebLinks)); + public static readonly StyledProperty> WebLinksProperty = + AvaloniaProperty.Register>(nameof(WebLinks)); - public AvaloniaList WebLinks + public List WebLinks { get => GetValue(WebLinksProperty); set => SetValue(WebLinksProperty, value); } - public static readonly StyledProperty> IssueTrackerRulesProperty = - AvaloniaProperty.Register>(nameof(IssueTrackerRules)); + public static readonly StyledProperty> ChildrenProperty = + AvaloniaProperty.Register>(nameof(Children)); - public AvaloniaList IssueTrackerRules - { - get => GetValue(IssueTrackerRulesProperty); - set => SetValue(IssueTrackerRulesProperty, value); - } - - public static readonly StyledProperty> ChildrenProperty = - AvaloniaProperty.Register>(nameof(Children)); - - public AvaloniaList Children + public List Children { get => GetValue(ChildrenProperty); set => SetValue(ChildrenProperty, value); diff --git a/src/Views/CommitDetail.axaml b/src/Views/CommitDetail.axaml index d0d52473..28b21eb7 100644 --- a/src/Views/CommitDetail.axaml +++ b/src/Views/CommitDetail.axaml @@ -20,12 +20,11 @@ + Children="{Binding Children}"/> diff --git a/src/Views/CommitMessagePresenter.cs b/src/Views/CommitMessagePresenter.cs index dc8a3bb7..002beda1 100644 --- a/src/Views/CommitMessagePresenter.cs +++ b/src/Views/CommitMessagePresenter.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; -using System.Text.RegularExpressions; using System.Threading.Tasks; using Avalonia; -using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Controls.Documents; using Avalonia.Input; @@ -13,27 +11,15 @@ using Avalonia.VisualTree; namespace SourceGit.Views { - public partial class CommitMessagePresenter : SelectableTextBlock + public class CommitMessagePresenter : SelectableTextBlock { - [GeneratedRegex(@"\b([0-9a-fA-F]{6,40})\b")] - private static partial Regex REG_SHA_FORMAT(); + public static readonly StyledProperty FullMessageProperty = + AvaloniaProperty.Register(nameof(FullMessage)); - public static readonly StyledProperty MessageProperty = - AvaloniaProperty.Register(nameof(Message)); - - public string Message + public Models.CommitFullMessage FullMessage { - get => GetValue(MessageProperty); - set => SetValue(MessageProperty, value); - } - - public static readonly StyledProperty> IssueTrackerRulesProperty = - AvaloniaProperty.Register>(nameof(IssueTrackerRules)); - - public AvaloniaList IssueTrackerRules - { - get => GetValue(IssueTrackerRulesProperty); - set => SetValue(IssueTrackerRulesProperty, value); + get => GetValue(FullMessageProperty); + set => SetValue(FullMessageProperty, value); } protected override Type StyleKeyOverride => typeof(SelectableTextBlock); @@ -42,69 +28,36 @@ namespace SourceGit.Views { base.OnPropertyChanged(change); - if (change.Property == MessageProperty || change.Property == IssueTrackerRulesProperty) + if (change.Property == FullMessageProperty) { Inlines!.Clear(); _inlineCommits.Clear(); - _matches = null; _lastHover = null; ClearHoveredIssueLink(); - var message = Message; + var message = FullMessage?.Message; if (string.IsNullOrEmpty(message)) return; - var matches = new List(); - if (IssueTrackerRules is { Count: > 0 } rules) - { - foreach (var rule in rules) - rule.Matches(matches, message); - } - - var shas = REG_SHA_FORMAT().Matches(message); - for (int i = 0; i < shas.Count; i++) - { - var sha = shas[i]; - if (!sha.Success) - continue; - - var start = sha.Index; - var len = sha.Length; - var intersect = false; - foreach (var match in matches) - { - if (match.Intersect(start, len)) - { - intersect = true; - break; - } - } - - if (!intersect) - matches.Add(new Models.Hyperlink(start, len, sha.Groups[1].Value, true)); - } - - if (matches.Count == 0) + var links = FullMessage?.Links; + if (links == null || links.Count == 0) { Inlines.Add(new Run(message)); return; } - matches.Sort((l, r) => l.Start - r.Start); - _matches = matches; - var inlines = new List(); var pos = 0; - foreach (var match in matches) + foreach (var link in links) { - if (match.Start > pos) - inlines.Add(new Run(message.Substring(pos, match.Start - pos))); + if (link.Start > pos) + inlines.Add(new Run(message.Substring(pos, link.Start - pos))); - var link = new Run(message.Substring(match.Start, match.Length)); - link.Classes.Add(match.IsCommitSHA ? "commit_link" : "issue_link"); - inlines.Add(link); + var run = new Run(message.Substring(link.Start, link.Length)); + run.Classes.Add(link.IsCommitSHA ? "commit_link" : "issue_link"); + inlines.Add(run); - pos = match.Start + match.Length; + pos = link.Start + link.Length; } if (pos < message.Length) @@ -134,7 +87,7 @@ namespace SourceGit.Views scrollViewer.LineDown(); } } - else if (_matches != null) + else if (FullMessage is { Links: { Count: > 0 } links }) { var point = e.GetPosition(this) - new Point(Padding.Left, Padding.Top); var x = Math.Min(Math.Max(point.X, 0), Math.Max(TextLayout.WidthIncludingTrailingWhitespace, 0)); @@ -142,25 +95,25 @@ namespace SourceGit.Views point = new Point(x, y); var pos = TextLayout.HitTestPoint(point).TextPosition; - foreach (var match in _matches) + foreach (var link in links) { - if (!match.Intersect(pos, 1)) + if (!link.Intersect(pos, 1)) continue; - if (match == _lastHover) + if (link == _lastHover) return; SetCurrentValue(CursorProperty, Cursor.Parse("Hand")); - _lastHover = match; - if (!match.IsCommitSHA) + _lastHover = link; + if (!link.IsCommitSHA) { - ToolTip.SetTip(this, match.Link); + ToolTip.SetTip(this, link.Link); ToolTip.SetIsOpen(this, true); } else { - ProcessHoverCommitLink(match); + ProcessHoverCommitLink(link); } return; @@ -361,7 +314,6 @@ namespace SourceGit.Views } } - private List _matches = null; private Models.Hyperlink _lastHover = null; private Dictionary _inlineCommits = new(); } diff --git a/src/Views/DiffView.axaml b/src/Views/DiffView.axaml index 3644f8fc..2842715c 100644 --- a/src/Views/DiffView.axaml +++ b/src/Views/DiffView.axaml @@ -257,7 +257,7 @@ - + @@ -271,7 +271,7 @@ - + diff --git a/src/Views/RevisionFileContentViewer.axaml b/src/Views/RevisionFileContentViewer.axaml index de8b3b75..f7599ba0 100644 --- a/src/Views/RevisionFileContentViewer.axaml +++ b/src/Views/RevisionFileContentViewer.axaml @@ -63,7 +63,7 @@ - + diff --git a/src/Views/RevisionFiles.axaml b/src/Views/RevisionFiles.axaml index 3d5cff38..6847b14b 100644 --- a/src/Views/RevisionFiles.axaml +++ b/src/Views/RevisionFiles.axaml @@ -44,7 +44,7 @@ + IsOpen="{Binding RevisionFileSearchSuggestion, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}"> 0) { SearchSuggestionBox.Focus(NavigationMethod.Tab); SearchSuggestionBox.SelectedIndex = 0; @@ -33,12 +33,7 @@ namespace SourceGit.Views } else if (e.Key == Key.Escape) { - if (vm.IsRevisionFileSearchSuggestionOpen) - { - vm.RevisionFileSearchSuggestion.Clear(); - vm.IsRevisionFileSearchSuggestionOpen = false; - } - + vm.CancelRevisionFileSuggestions(); e.Handled = true; } } @@ -57,7 +52,7 @@ namespace SourceGit.Views if (e.Key == Key.Escape) { - vm.RevisionFileSearchSuggestion.Clear(); + vm.CancelRevisionFileSuggestions(); e.Handled = true; } else if (e.Key == Key.Enter && SearchSuggestionBox.SelectedItem is string content) From 96538b9a6246ceebbb259cbdfd7abc3dc8239132 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 4 Mar 2025 16:26:14 +0800 Subject: [PATCH 302/441] fix: there's an extra line-ending while copy multiple lines from text diff view (#1049) Signed-off-by: leo --- src/Views/TextDiffView.axaml.cs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 958e803e..30034bc6 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -1032,18 +1032,32 @@ namespace SourceGit.Views line.Type == Models.TextDiffLineType.None) continue; + // The first selected line (partial selection) if (i == startIdx && startPosition.Column > 1) { builder.AppendLine(line.Content.Substring(startPosition.Column - 1)); continue; } - if (i == endIdx && endPosition.Column < line.Content.Length) + // The selection range is larger than original source. + if (i == lines.Count - 1 && i < endIdx) { - builder.AppendLine(line.Content.Substring(0, endPosition.Column - 1)); - continue; + builder.Append(line.Content); + break; } + // For the last line (selection range is within original source) + if (i == endIdx) + { + if (endPosition.Column < line.Content.Length) + builder.Append(line.Content.Substring(0, endPosition.Column - 1)); + else + builder.Append(line.Content); + + break; + } + + // Other lines. builder.AppendLine(line.Content); } From 25e6e261a626898942eeb981f75981caab307ff0 Mon Sep 17 00:00:00 2001 From: GadflyFang Date: Tue, 4 Mar 2025 16:33:43 +0800 Subject: [PATCH 303/441] refactor: Improve key modifier checks and AltGr detection (#1051) --- src/Views/Launcher.axaml.cs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Views/Launcher.axaml.cs b/src/Views/Launcher.axaml.cs index e3140191..b8c09b35 100644 --- a/src/Views/Launcher.axaml.cs +++ b/src/Views/Launcher.axaml.cs @@ -112,8 +112,19 @@ namespace SourceGit.Views // We should clear all unhandled key modifiers. _unhandledModifiers = KeyModifiers.None; + // Check for AltGr (which is detected as Ctrl+Alt) + bool isAltGr = e.KeyModifiers.HasFlag(KeyModifiers.Control) && + e.KeyModifiers.HasFlag(KeyModifiers.Alt); + + // Skip hotkey processing if AltGr is pressed + if (isAltGr) + { + base.OnKeyDown(e); + return; + } + // Ctrl+Shift+P opens preference dialog (macOS use hotkeys in system menu bar) - if (!OperatingSystem.IsMacOS() && e.KeyModifiers == (KeyModifiers.Control | KeyModifiers.Shift) && e.Key == Key.P) + if (!OperatingSystem.IsMacOS() && e is { KeyModifiers: (KeyModifiers.Control | KeyModifiers.Shift), Key: Key.P }) { App.OpenDialog(new Preferences()); e.Handled = true; @@ -243,13 +254,13 @@ namespace SourceGit.Views { _unhandledModifiers = e.KeyModifiers; - if (!_unhandledModifiers.HasFlag(KeyModifiers.Alt) && (e.Key == Key.LeftAlt || e.Key == Key.RightAlt)) + if (!_unhandledModifiers.HasFlag(KeyModifiers.Alt) && e.Key is Key.LeftAlt or Key.RightAlt) _unhandledModifiers |= KeyModifiers.Alt; - if (!_unhandledModifiers.HasFlag(KeyModifiers.Control) && (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)) + if (!_unhandledModifiers.HasFlag(KeyModifiers.Control) && e.Key is Key.LeftCtrl or Key.RightCtrl) _unhandledModifiers |= KeyModifiers.Control; - if (!_unhandledModifiers.HasFlag(KeyModifiers.Shift) && (e.Key == Key.LeftShift || e.Key == Key.RightShift)) + if (!_unhandledModifiers.HasFlag(KeyModifiers.Shift) && e.Key is Key.LeftShift or Key.RightShift) _unhandledModifiers |= KeyModifiers.Shift; } } From 68e96f428e650cf29bde1b27276cf63456fd5530 Mon Sep 17 00:00:00 2001 From: GadflyFang Date: Tue, 4 Mar 2025 16:34:51 +0800 Subject: [PATCH 304/441] fix: validate result not update #1052 (#1053) --- src/ViewModels/Pull.cs | 2 +- src/ViewModels/Push.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ViewModels/Pull.cs b/src/ViewModels/Pull.cs index 755b58f4..ff557792 100644 --- a/src/ViewModels/Pull.cs +++ b/src/ViewModels/Pull.cs @@ -35,7 +35,7 @@ namespace SourceGit.ViewModels public Models.Branch SelectedBranch { get => _selectedBranch; - set => SetProperty(ref _selectedBranch, value); + set => SetProperty(ref _selectedBranch, value, true); } public Models.DealWithLocalChanges PreAction diff --git a/src/ViewModels/Push.cs b/src/ViewModels/Push.cs index 1f18b38e..fb06c76e 100644 --- a/src/ViewModels/Push.cs +++ b/src/ViewModels/Push.cs @@ -18,7 +18,7 @@ namespace SourceGit.ViewModels get => _selectedLocalBranch; set { - if (SetProperty(ref _selectedLocalBranch, value)) + if (SetProperty(ref _selectedLocalBranch, value, true)) AutoSelectBranchByRemote(); } } @@ -39,7 +39,7 @@ namespace SourceGit.ViewModels get => _selectedRemote; set { - if (SetProperty(ref _selectedRemote, value)) + if (SetProperty(ref _selectedRemote, value, true)) AutoSelectBranchByRemote(); } } @@ -56,7 +56,7 @@ namespace SourceGit.ViewModels get => _selectedRemoteBranch; set { - if (SetProperty(ref _selectedRemoteBranch, value)) + if (SetProperty(ref _selectedRemoteBranch, value, true)) IsSetTrackOptionVisible = value != null && _selectedLocalBranch.Upstream != value.FullName; } } From 11af5d9b29ba0f994892e336f13e119fa9c9730b Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 4 Mar 2025 16:42:32 +0800 Subject: [PATCH 305/441] code_style: use `?:` operator instead of `if ... else` statement Signed-off-by: leo --- src/Views/TextDiffView.axaml.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 30034bc6..93d31668 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -1049,11 +1049,7 @@ namespace SourceGit.Views // For the last line (selection range is within original source) if (i == endIdx) { - if (endPosition.Column < line.Content.Length) - builder.Append(line.Content.Substring(0, endPosition.Column - 1)); - else - builder.Append(line.Content); - + builder.Append(endPosition.Column - 1 < line.Content.Length ? line.Content.Substring(0, endPosition.Column - 1) : line.Content); break; } From 2137ad9ec97c2c8aacb78773af2999a5d7f9d57b Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 4 Mar 2025 17:26:27 +0800 Subject: [PATCH 306/441] enhance: allow to configure editor tab width in preferences window (#1048) Signed-off-by: leo --- src/Resources/Locales/en_US.axaml | 1 + src/Resources/Locales/zh_CN.axaml | 1 + src/Resources/Locales/zh_TW.axaml | 1 + src/ViewModels/Preferences.cs | 7 ++++ src/Views/Blame.axaml | 1 + src/Views/Blame.axaml.cs | 19 +++++++++-- src/Views/Preferences.axaml | 35 ++++++++++++++------ src/Views/RevisionFileContentViewer.axaml | 1 + src/Views/RevisionFileContentViewer.axaml.cs | 26 +++++++++++++-- src/Views/TextDiffView.axaml | 3 ++ src/Views/TextDiffView.axaml.cs | 22 +++++++++--- 11 files changed, 98 insertions(+), 19 deletions(-) diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 5208a269..5df3ca71 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -464,6 +464,7 @@ Enable Streaming APPEARANCE Default Font + Editor Tab Width Font Size Default Editor diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 0e8b9f7d..72b434f9 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -467,6 +467,7 @@ 启用流式输出 外观配置 缺省字体 + 编辑器制表符宽度 字体大小 默认 代码编辑器 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index f4cfad08..bc9991f6 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -467,6 +467,7 @@ 啟用串流輸出 外觀設定 預設字型 + 編輯器制表符寬度 字型大小 預設 程式碼 diff --git a/src/ViewModels/Preferences.cs b/src/ViewModels/Preferences.cs index 5cd7c8a4..016fd4c4 100644 --- a/src/ViewModels/Preferences.cs +++ b/src/ViewModels/Preferences.cs @@ -111,6 +111,12 @@ namespace SourceGit.ViewModels set => SetProperty(ref _editorFontSize, value); } + public int EditorTabWidth + { + get => _editorTabWidth; + set => SetProperty(ref _editorTabWidth, value); + } + public LayoutInfo Layout { get => _layout; @@ -649,6 +655,7 @@ namespace SourceGit.ViewModels private bool _useSystemWindowFrame = false; private double _defaultFontSize = 13; private double _editorFontSize = 13; + private int _editorTabWidth = 4; private LayoutInfo _layout = new LayoutInfo(); private int _maxHistoryCommits = 20000; diff --git a/src/Views/Blame.axaml b/src/Views/Blame.axaml index 1ddb18fb..b700b580 100644 --- a/src/Views/Blame.axaml +++ b/src/Views/Blame.axaml @@ -58,6 +58,7 @@ Foreground="{DynamicResource Brush.FG1}" FontFamily="{DynamicResource Fonts.Monospace}" FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}" + TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}" BlameData="{Binding Data}"/> diff --git a/src/Views/Blame.axaml.cs b/src/Views/Blame.axaml.cs index 1784efc1..7e273998 100644 --- a/src/Views/Blame.axaml.cs +++ b/src/Views/Blame.axaml.cs @@ -260,6 +260,15 @@ namespace SourceGit.Views set => SetValue(BlameDataProperty, value); } + public static readonly StyledProperty TabWidthProperty = + AvaloniaProperty.Register(nameof(TabWidth), 4); + + public int TabWidth + { + get => GetValue(TabWidthProperty); + set => SetValue(TabWidthProperty, value); + } + protected override Type StyleKeyOverride => typeof(TextEditor); public BlameTextEditor() : base(new TextArea(), new TextDocument()) @@ -268,6 +277,10 @@ namespace SourceGit.Views ShowLineNumbers = false; WordWrap = false; + Options.IndentationSize = TabWidth; + Options.EnableHyperlinks = false; + Options.EnableEmailHyperlinks = false; + _textMate = Models.TextMateHelper.CreateForEditor(this); TextArea.LeftMargins.Add(new LineNumberMargin() { Margin = new Thickness(8, 0) }); @@ -280,8 +293,6 @@ namespace SourceGit.Views TextArea.TextView.ContextRequested += OnTextViewContextRequested; TextArea.TextView.VisualLinesChanged += OnTextViewVisualLinesChanged; TextArea.TextView.Margin = new Thickness(4, 0); - TextArea.TextView.Options.EnableHyperlinks = false; - TextArea.TextView.Options.EnableEmailHyperlinks = false; } public override void Render(DrawingContext context) @@ -350,6 +361,10 @@ namespace SourceGit.Views Text = string.Empty; } } + else if (change.Property == TabWidthProperty) + { + Options.IndentationSize = TabWidth; + } else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null) { Models.TextMateHelper.SetThemeByApp(_textMate); diff --git a/src/Views/Preferences.axaml b/src/Views/Preferences.axaml index 3bdd150a..12679e50 100644 --- a/src/Views/Preferences.axaml +++ b/src/Views/Preferences.axaml @@ -148,7 +148,7 @@ - + + Minimum="10" Maximum="18" Increment="0.5" + Height="28" + Padding="4" + BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}" + CornerRadius="3" + Value="{Binding DefaultFontSize, Mode=TwoWay}"> @@ -218,10 +218,23 @@ + + + + + - @@ -232,16 +245,16 @@ - - - diff --git a/src/Views/RevisionFileContentViewer.axaml.cs b/src/Views/RevisionFileContentViewer.axaml.cs index c74f2db2..16f4fc83 100644 --- a/src/Views/RevisionFileContentViewer.axaml.cs +++ b/src/Views/RevisionFileContentViewer.axaml.cs @@ -15,6 +15,15 @@ namespace SourceGit.Views { public class RevisionTextFileView : TextEditor { + public static readonly StyledProperty TabWidthProperty = + AvaloniaProperty.Register(nameof(TabWidth), 4); + + public int TabWidth + { + get => GetValue(TabWidthProperty); + set => SetValue(TabWidthProperty, value); + } + protected override Type StyleKeyOverride => typeof(TextEditor); public RevisionTextFileView() : base(new TextArea(), new TextDocument()) @@ -22,13 +31,16 @@ namespace SourceGit.Views IsReadOnly = true; ShowLineNumbers = true; WordWrap = false; + + Options.IndentationSize = TabWidth; + Options.EnableHyperlinks = false; + Options.EnableEmailHyperlinks = false; + HorizontalScrollBarVisibility = ScrollBarVisibility.Auto; VerticalScrollBarVisibility = ScrollBarVisibility.Auto; TextArea.LeftMargins[0].Margin = new Thickness(8, 0); TextArea.TextView.Margin = new Thickness(4, 0); - TextArea.TextView.Options.EnableHyperlinks = false; - TextArea.TextView.Options.EnableEmailHyperlinks = false; } protected override void OnLoaded(RoutedEventArgs e) @@ -69,6 +81,16 @@ namespace SourceGit.Views } } + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + + if (change.Property == TabWidthProperty) + { + Options.IndentationSize = TabWidth; + } + } + private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e) { var selected = SelectedText; diff --git a/src/Views/TextDiffView.axaml b/src/Views/TextDiffView.axaml index 3ea7af14..7ea6b44b 100644 --- a/src/Views/TextDiffView.axaml +++ b/src/Views/TextDiffView.axaml @@ -27,6 +27,7 @@ IndicatorForeground="{DynamicResource Brush.FG2}" FontFamily="{DynamicResource Fonts.Monospace}" FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}" + TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}" UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}" WordWrap="{Binding Source={x:Static vm:Preferences.Instance}, Path=EnableDiffViewWordWrap}" ShowHiddenSymbols="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowHiddenSymbolsInDiffView}" @@ -59,6 +60,7 @@ IndicatorForeground="{DynamicResource Brush.FG2}" FontFamily="{DynamicResource Fonts.Monospace}" FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}" + TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}" UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}" WordWrap="False" ShowHiddenSymbols="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowHiddenSymbolsInDiffView}" @@ -81,6 +83,7 @@ IndicatorForeground="{DynamicResource Brush.FG2}" FontFamily="{DynamicResource Fonts.Monospace}" FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}" + TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}" UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}" WordWrap="False" ShowHiddenSymbols="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowHiddenSymbolsInDiffView}" diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 93d31668..630be1b2 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -475,6 +475,15 @@ namespace SourceGit.Views set => SetValue(ShowHiddenSymbolsProperty, value); } + public static readonly StyledProperty TabWidthProperty = + AvaloniaProperty.Register(nameof(TabWidth), 4); + + public int TabWidth + { + get => GetValue(TabWidthProperty); + set => SetValue(TabWidthProperty, value); + } + public static readonly StyledProperty EnableChunkSelectionProperty = AvaloniaProperty.Register(nameof(EnableChunkSelection)); @@ -519,12 +528,13 @@ namespace SourceGit.Views ShowLineNumbers = false; BorderThickness = new Thickness(0); + Options.IndentationSize = TabWidth; + Options.EnableHyperlinks = false; + Options.EnableEmailHyperlinks = false; + _lineStyleTransformer = new LineStyleTransformer(this); TextArea.TextView.Margin = new Thickness(2, 0); - TextArea.TextView.Options.EnableHyperlinks = false; - TextArea.TextView.Options.EnableEmailHyperlinks = false; - TextArea.TextView.BackgroundRenderers.Add(new LineBackgroundRenderer(this)); TextArea.TextView.LineTransformers.Add(_lineStyleTransformer); } @@ -734,10 +744,14 @@ namespace SourceGit.Views } else if (change.Property == ShowHiddenSymbolsProperty) { - var val = change.NewValue is true; + var val = ShowHiddenSymbols; Options.ShowTabs = val; Options.ShowSpaces = val; } + else if (change.Property == TabWidthProperty) + { + Options.IndentationSize = TabWidth; + } else if (change.Property == FileNameProperty) { Models.TextMateHelper.SetGrammarByFileName(_textMate, FileName); From 5af856b9da238d552e8be47fbc002af7efae0742 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 4 Mar 2025 09:26:48 +0000 Subject: [PATCH 307/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index dae76783..849407b3 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.21%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-99.87%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.80%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-%E2%88%9A-brightgreen)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.53%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.07%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.08%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-99.74%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.68%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.41%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-98.94%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index 716ddd3a..8a7bd378 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,4 +1,4 @@ -### de_DE.axaml: 99.21% +### de_DE.axaml: 99.08%
@@ -9,21 +9,23 @@ - Text.Diff.First - Text.Diff.Last - Text.Preferences.AI.Streaming +- Text.Preferences.Appearance.EditorTabWidth - Text.StashCM.SaveAsPatch
-### es_ES.axaml: 99.87% +### es_ES.axaml: 99.74%
Missing Keys +- Text.Preferences.Appearance.EditorTabWidth - Text.StashCM.SaveAsPatch
-### fr_FR.axaml: 91.80% +### fr_FR.axaml: 91.68%
@@ -56,6 +58,7 @@ - Text.MergeMultiple.Strategy - Text.MergeMultiple.Targets - Text.Preferences.AI.Streaming +- Text.Preferences.Appearance.EditorTabWidth - Text.Preferences.Appearance.FontSize - Text.Preferences.Appearance.FontSize.Default - Text.Preferences.Appearance.FontSize.Editor @@ -94,17 +97,17 @@
-### it_IT.axaml: 100.00% +### it_IT.axaml: 99.87%
Missing Keys - +- Text.Preferences.Appearance.EditorTabWidth
-### pt_BR.axaml: 91.53% +### pt_BR.axaml: 91.41%
@@ -148,6 +151,7 @@ - Text.MergeMultiple.Strategy - Text.MergeMultiple.Targets - Text.Preferences.AI.Streaming +- Text.Preferences.Appearance.EditorTabWidth - Text.Preferences.General.DateFormat - Text.Preferences.General.ShowChildren - Text.Preferences.Git.SSLVerify @@ -177,7 +181,7 @@
-### ru_RU.axaml: 99.07% +### ru_RU.axaml: 98.94%
@@ -189,6 +193,7 @@ - Text.Diff.First - Text.Diff.Last - Text.Preferences.AI.Streaming +- Text.Preferences.Appearance.EditorTabWidth - Text.StashCM.SaveAsPatch
From e28f8611ef74bf259096b322d6c91531bc4ceeac Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 4 Mar 2025 17:39:07 +0800 Subject: [PATCH 308/441] ux: re-design the layout for `Interactive Rebase` window that tries to fix issue #1037 Signed-off-by: leo --- src/Views/InteractiveRebase.axaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Views/InteractiveRebase.axaml b/src/Views/InteractiveRebase.axaml index f031479b..a4c4dc8e 100644 --- a/src/Views/InteractiveRebase.axaml +++ b/src/Views/InteractiveRebase.axaml @@ -65,6 +65,7 @@ + @@ -77,7 +78,7 @@ - + Date: Tue, 4 Mar 2025 18:02:29 +0800 Subject: [PATCH 309/441] code_style: re-order `CommitDetail` properties Signed-off-by: leo --- src/ViewModels/CommitDetail.cs | 105 +++++++++++++++++---------------- 1 file changed, 54 insertions(+), 51 deletions(-) diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index 26fa37c1..21931181 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -16,12 +16,6 @@ namespace SourceGit.ViewModels { public partial class CommitDetail : ObservableObject { - public DiffContext DiffContext - { - get => _diffContext; - private set => SetProperty(ref _diffContext, value); - } - public int ActivePageIndex { get => _repo.CommitDetailActivePageIndex; @@ -57,6 +51,18 @@ namespace SourceGit.ViewModels private set => SetProperty(ref _signInfo, value); } + public List WebLinks + { + get; + private set; + } = []; + + public List Children + { + get => _children; + private set => SetProperty(ref _children, value); + } + public List Changes { get => _changes; @@ -84,10 +90,10 @@ namespace SourceGit.ViewModels } } - public List Children + public DiffContext DiffContext { - get => _children; - private set => SetProperty(ref _children, value); + get => _diffContext; + private set => SetProperty(ref _diffContext, value); } public string SearchChangeFilter @@ -108,53 +114,13 @@ namespace SourceGit.ViewModels set => SetProperty(ref _viewRevisionFileContent, value); } - public List WebLinks - { - get; - private set; - } = []; - public string RevisionFileSearchFilter { get => _revisionFileSearchFilter; set { if (SetProperty(ref _revisionFileSearchFilter, value)) - { - if (!string.IsNullOrEmpty(value)) - { - if (_revisionFiles == null) - { - var sha = Commit.SHA; - - Task.Run(() => - { - var files = new Commands.QueryRevisionFileNames(_repo.FullPath, sha).Result(); - var filesList = new List(); - filesList.AddRange(files); - - Dispatcher.UIThread.Invoke(() => - { - if (sha == Commit.SHA) - { - _revisionFiles = filesList; - if (!string.IsNullOrEmpty(_revisionFileSearchFilter)) - UpdateRevisionFileSearchSuggestion(); - } - }); - }); - } - else - { - UpdateRevisionFileSearchSuggestion(); - } - } - else - { - RevisionFileSearchSuggestion = null; - GC.Collect(); - } - } + RefreshRevisionSearchSuggestion(); } } @@ -832,7 +798,44 @@ namespace SourceGit.ViewModels menu.Items.Add(new MenuItem() { Header = "-" }); } - private void UpdateRevisionFileSearchSuggestion() + private void RefreshRevisionSearchSuggestion() + { + if (!string.IsNullOrEmpty(_revisionFileSearchFilter)) + { + if (_revisionFiles == null) + { + var sha = Commit.SHA; + + Task.Run(() => + { + var files = new Commands.QueryRevisionFileNames(_repo.FullPath, sha).Result(); + var filesList = new List(); + filesList.AddRange(files); + + Dispatcher.UIThread.Invoke(() => + { + if (sha == Commit.SHA) + { + _revisionFiles = filesList; + if (!string.IsNullOrEmpty(_revisionFileSearchFilter)) + CalcRevisionFileSearchSuggestion(); + } + }); + }); + } + else + { + CalcRevisionFileSearchSuggestion(); + } + } + else + { + RevisionFileSearchSuggestion = null; + GC.Collect(); + } + } + + private void CalcRevisionFileSearchSuggestion() { var suggestion = new List(); foreach (var file in _revisionFiles) From 792e61b24f8ed6b18dc6d77d7125312baca99a77 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 4 Mar 2025 18:23:13 +0800 Subject: [PATCH 310/441] ux: re-design the layout for `Interactive Rebase` window that tries to fix issue #1037 Signed-off-by: leo --- src/Views/InteractiveRebase.axaml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Views/InteractiveRebase.axaml b/src/Views/InteractiveRebase.axaml index a4c4dc8e..b4499ddc 100644 --- a/src/Views/InteractiveRebase.axaml +++ b/src/Views/InteractiveRebase.axaml @@ -60,7 +60,7 @@ SelectedItem="{Binding SelectedItem, Mode=OneWayToSource}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto"> - + - + - + - + - + - + - - + + - + From 71d0b69eee5d48f0118d0c8bd8029a7bf73497bc Mon Sep 17 00:00:00 2001 From: GadflyFang Date: Tue, 4 Mar 2025 19:51:36 +0800 Subject: [PATCH 311/441] fix: prevent kill apt process by accident (#1054) --- build/resources/deb/DEBIAN/preinst | 8 ++++---- build/resources/deb/DEBIAN/prerm | 9 ++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/build/resources/deb/DEBIAN/preinst b/build/resources/deb/DEBIAN/preinst index edcf9088..a93f8090 100755 --- a/build/resources/deb/DEBIAN/preinst +++ b/build/resources/deb/DEBIAN/preinst @@ -12,10 +12,10 @@ set -e case "$1" in install|upgrade) # Check if SourceGit is running and stop it - if pidof -q sourcegit || pgrep -f sourcegit > /dev/null; then - echo "SourceGit is running, stopping it..." - killall sourcegit 2>/dev/null || pkill -f sourcegit 2>/dev/null || true - # Wait for SourceGit to exit + if pgrep -f '/opt/sourcegit/sourcegit' > /dev/null; then + echo "Stopping running SourceGit instance..." + pkill -f '/opt/sourcegit/sourcegit' || true + # Give the process a moment to terminate sleep 1 fi ;; diff --git a/build/resources/deb/DEBIAN/prerm b/build/resources/deb/DEBIAN/prerm index 8ecd4b8d..c2c9e4f0 100755 --- a/build/resources/deb/DEBIAN/prerm +++ b/build/resources/deb/DEBIAN/prerm @@ -15,11 +15,10 @@ set -e case "$1" in remove|upgrade|deconfigure) - # Check if SourceGit is running and stop it - if pidof -q sourcegit || pgrep -f sourcegit > /dev/null; then - echo "SourceGit is running, stopping it before removal..." - killall sourcegit 2>/dev/null || pkill -f sourcegit 2>/dev/null || true - # Wait for SourceGit to exit + if pgrep -f '/opt/sourcegit/sourcegit' > /dev/null; then + echo "Stopping running SourceGit instance..." + pkill -f '/opt/sourcegit/sourcegit' || true + # Give the process a moment to terminate sleep 1 fi ;; From 5e898a809e0b8171a4349371690f5ce491a486ba Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 5 Mar 2025 09:30:38 +0800 Subject: [PATCH 312/441] enhance: check commit hash after intersect testing Signed-off-by: leo --- src/ViewModels/CommitDetail.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index 21931181..32827db3 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -665,11 +665,6 @@ namespace SourceGit.ViewModels if (!sha.Success) continue; - var hash = sha.Groups[1].Value; - var test = new Commands.IsCommitSHA(_repo.FullPath, hash).Result(); - if (!test) - continue; - var start = sha.Index; var len = sha.Length; var intersect = false; @@ -682,7 +677,12 @@ namespace SourceGit.ViewModels } } - if (!intersect) + if (intersect) + continue; + + var hash = sha.Groups[1].Value; + var isCommitSHA = new Commands.IsCommitSHA(_repo.FullPath, hash).Result(); + if (isCommitSHA) links.Add(new Models.Hyperlink(start, len, hash, true)); } From 269903503fe77029ec8db1e16121a3b6e830027d Mon Sep 17 00:00:00 2001 From: GadflyFang Date: Wed, 5 Mar 2025 09:36:32 +0800 Subject: [PATCH 313/441] feat: Add commit Tooltip in Blame (#1055) Fixes #993 --- src/ViewModels/Blame.cs | 5 ++++ src/Views/Blame.axaml | 19 ++++++++++++-- src/Views/Blame.axaml.cs | 45 ++++++++++++++++++++++++++------- src/Views/TextDiffView.axaml.cs | 8 +++--- 4 files changed, 62 insertions(+), 15 deletions(-) diff --git a/src/ViewModels/Blame.cs b/src/ViewModels/Blame.cs index 253626bc..7ee39550 100644 --- a/src/ViewModels/Blame.cs +++ b/src/ViewModels/Blame.cs @@ -57,6 +57,11 @@ namespace SourceGit.ViewModels } } + public Models.Commit GetCommitInfo(string commitSHA) + { + return new Commands.QuerySingleCommit(_repo, commitSHA).Result(); + } + private readonly string _repo; private Models.BlameData _data = null; } diff --git a/src/Views/Blame.axaml b/src/Views/Blame.axaml index b700b580..4d050bb5 100644 --- a/src/Views/Blame.axaml +++ b/src/Views/Blame.axaml @@ -2,6 +2,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:m="using:SourceGit.Models" xmlns:vm="using:SourceGit.ViewModels" xmlns:v="using:SourceGit.Views" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" @@ -59,8 +60,22 @@ FontFamily="{DynamicResource Fonts.Monospace}" FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}" TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}" - BlameData="{Binding Data}"/> - + BlameData="{Binding Data}"> + + + + + + + + + + + + + + + + { + var commit = blame.GetCommitInfo(info.CommitSHA); + if (commit == null) + return; + + Dispatcher.UIThread.Invoke(() => + { + if (IsEffectivelyVisible && IsPointerOver) + { + ToolTip.SetTip(this, commit); + ToolTip.SetIsOpen(this, true); + } + }); + }); + } + return; } } - } - Cursor = Cursor.Default; + Cursor = Cursor.Default; + ToolTip.SetIsOpen(this, false); + } } protected override void OnPointerPressed(PointerPressedEventArgs e) @@ -230,9 +257,9 @@ namespace SourceGit.Views private readonly BlameTextEditor _editor = null; } - public class VerticalSeperatorMargin : AbstractMargin + public class VerticalSeparatorMargin : AbstractMargin { - public VerticalSeperatorMargin(BlameTextEditor editor) + public VerticalSeparatorMargin(BlameTextEditor editor) { _editor = editor; } @@ -284,9 +311,9 @@ namespace SourceGit.Views _textMate = Models.TextMateHelper.CreateForEditor(this); TextArea.LeftMargins.Add(new LineNumberMargin() { Margin = new Thickness(8, 0) }); - TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this)); + TextArea.LeftMargins.Add(new VerticalSeparatorMargin(this)); TextArea.LeftMargins.Add(new CommitInfoMargin(this) { Margin = new Thickness(8, 0) }); - TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this)); + TextArea.LeftMargins.Add(new VerticalSeparatorMargin(this)); TextArea.Caret.PositionChanged += OnTextAreaCaretPositionChanged; TextArea.LayoutUpdated += OnTextAreaLayoutUpdated; TextArea.PointerWheelChanged += OnTextAreaPointerWheelChanged; diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 630be1b2..925c7622 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -60,7 +60,7 @@ namespace SourceGit.Views public class ThemedTextDiffPresenter : TextEditor { - public class VerticalSeperatorMargin : AbstractMargin + public class VerticalSeparatorMargin : AbstractMargin { public override void Render(DrawingContext context) { @@ -1085,9 +1085,9 @@ namespace SourceGit.Views public CombinedTextDiffPresenter() : base(new TextArea(), new TextDocument()) { TextArea.LeftMargins.Add(new LineNumberMargin(false, true)); - TextArea.LeftMargins.Add(new VerticalSeperatorMargin()); + TextArea.LeftMargins.Add(new VerticalSeparatorMargin()); TextArea.LeftMargins.Add(new LineNumberMargin(false, false)); - TextArea.LeftMargins.Add(new VerticalSeperatorMargin()); + TextArea.LeftMargins.Add(new VerticalSeparatorMargin()); TextArea.LeftMargins.Add(new LineModifyTypeMargin()); } @@ -1286,7 +1286,7 @@ namespace SourceGit.Views public SingleSideTextDiffPresenter() : base(new TextArea(), new TextDocument()) { TextArea.LeftMargins.Add(new LineNumberMargin(true, false)); - TextArea.LeftMargins.Add(new VerticalSeperatorMargin()); + TextArea.LeftMargins.Add(new VerticalSeparatorMargin()); TextArea.LeftMargins.Add(new LineModifyTypeMargin()); } From fb8d4a2542063a76cff6d41b8fc2ad02de3afa0c Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 5 Mar 2025 09:54:23 +0800 Subject: [PATCH 314/441] code_review: PR #1055 - since the author and time are already shown in the blame view, use the full message as tooltip is better. - cache the commit message in `ViewModels.Blame` since the `Tooltip` of control may change. - querying commit message synchronously (it's very fast) to avoid similar issues in commit details panel. Signed-off-by: leo --- src/ViewModels/Blame.cs | 13 ++++++++++--- src/Views/Blame.axaml | 17 +---------------- src/Views/Blame.axaml.cs | 30 ++++++------------------------ 3 files changed, 17 insertions(+), 43 deletions(-) diff --git a/src/ViewModels/Blame.cs b/src/ViewModels/Blame.cs index 7ee39550..7cfa8eac 100644 --- a/src/ViewModels/Blame.cs +++ b/src/ViewModels/Blame.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Threading.Tasks; using Avalonia.Threading; @@ -57,12 +58,18 @@ namespace SourceGit.ViewModels } } - public Models.Commit GetCommitInfo(string commitSHA) + public string GetCommitMessage(string sha) { - return new Commands.QuerySingleCommit(_repo, commitSHA).Result(); + if (_commitMessages.TryGetValue(sha, out var msg)) + return msg; + + msg = new Commands.QueryCommitFullMessage(_repo, sha).Result(); + _commitMessages[sha] = msg; + return msg; } private readonly string _repo; private Models.BlameData _data = null; + private Dictionary _commitMessages = new Dictionary(); } } diff --git a/src/Views/Blame.axaml b/src/Views/Blame.axaml index 4d050bb5..d5c3fd22 100644 --- a/src/Views/Blame.axaml +++ b/src/Views/Blame.axaml @@ -2,7 +2,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:m="using:SourceGit.Models" xmlns:vm="using:SourceGit.ViewModels" xmlns:v="using:SourceGit.Views" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" @@ -60,21 +59,7 @@ FontFamily="{DynamicResource Fonts.Monospace}" FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}" TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}" - BlameData="{Binding Data}"> - - - - - - - - - - - - - - + BlameData="{Binding Data}"/> - { - var commit = blame.GetCommitInfo(info.CommitSHA); - if (commit == null) - return; - - Dispatcher.UIThread.Invoke(() => - { - if (IsEffectivelyVisible && IsPointerOver) - { - ToolTip.SetTip(this, commit); - ToolTip.SetIsOpen(this, true); - } - }); - }); + var msg = blame.GetCommitMessage(info.CommitSHA); + ToolTip.SetTip(this, msg); + ToolTip.SetIsOpen(this, true); } return; From 991ebe40824f9d42b4fabff69c2a30b1e00e98e9 Mon Sep 17 00:00:00 2001 From: Gadfly Date: Wed, 5 Mar 2025 09:55:55 +0800 Subject: [PATCH 315/441] ci: set ubuntu:20.04 (#1056) --- .github/workflows/build.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d4117364..bcb32580 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,14 +19,25 @@ jobs: os: macos-latest runtime: osx-arm64 - name : Linux - os: ubuntu-20.04 + os: ubuntu-latest runtime: linux-x64 + container: ubuntu:20.04 - name : Linux (arm64) - os: ubuntu-20.04 + os: ubuntu-latest runtime: linux-arm64 + container: ubuntu:20.04 name: Build ${{ matrix.name }} runs-on: ${{ matrix.os }} + container: ${{ matrix.container || '' }} steps: + - name: Install common CLI tools + if: ${{ startsWith(matrix.runtime, 'linux-') }} + run: | + export DEBIAN_FRONTEND=noninteractive + ln -fs /usr/share/zoneinfo/Etc/UTC /etc/localtime + apt-get update + apt-get install -y sudo + sudo apt-get install -y curl wget git unzip zip libicu66 tzdata clang - name: Checkout sources uses: actions/checkout@v4 - name: Setup .NET @@ -47,7 +58,7 @@ jobs: if: ${{ matrix.runtime == 'linux-arm64' }} run: | sudo apt-get update - sudo apt-get install clang llvm gcc-aarch64-linux-gnu zlib1g-dev:arm64 + sudo apt-get install -y llvm gcc-aarch64-linux-gnu zlib1g-dev:arm64 - name: Build run: dotnet build -c Release - name: Publish From 81bbe11345522e6ace161747e294c77c3a6f1a81 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 5 Mar 2025 17:06:45 +0800 Subject: [PATCH 316/441] code_style: rename some variables in `ParseLinksInMessage` Signed-off-by: leo --- src/ViewModels/CommitDetail.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index 32827db3..a4f3f595 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -658,15 +658,15 @@ namespace SourceGit.ViewModels rule.Matches(links, message); } - var shas = REG_SHA_FORMAT().Matches(message); - for (int i = 0; i < shas.Count; i++) + var matches = REG_SHA_FORMAT().Matches(message); + for (int i = 0; i < matches.Count; i++) { - var sha = shas[i]; - if (!sha.Success) + var match = matches[i]; + if (!match.Success) continue; - var start = sha.Index; - var len = sha.Length; + var start = match.Index; + var len = match.Length; var intersect = false; foreach (var link in links) { @@ -680,10 +680,10 @@ namespace SourceGit.ViewModels if (intersect) continue; - var hash = sha.Groups[1].Value; - var isCommitSHA = new Commands.IsCommitSHA(_repo.FullPath, hash).Result(); + var sha = match.Groups[1].Value; + var isCommitSHA = new Commands.IsCommitSHA(_repo.FullPath, sha).Result(); if (isCommitSHA) - links.Add(new Models.Hyperlink(start, len, hash, true)); + links.Add(new Models.Hyperlink(start, len, sha, true)); } if (links.Count > 0) From 78c0d8d3344c3315a5a8b022fb893124c703d71a Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 6 Mar 2025 10:37:50 +0800 Subject: [PATCH 317/441] fix: both `--tags` and `--no-tags` are used in `git pull` command Signed-off-by: leo --- src/Commands/Pull.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Commands/Pull.cs b/src/Commands/Pull.cs index a4efa4b6..35a6289a 100644 --- a/src/Commands/Pull.cs +++ b/src/Commands/Pull.cs @@ -11,10 +11,11 @@ namespace SourceGit.Commands Context = repo; TraitErrorAsOutput = true; SSHKey = new Config(repo).Get($"remote.{remote}.sshkey"); - Args = "pull --verbose --progress --tags "; + Args = "pull --verbose --progress "; if (useRebase) - Args += "--rebase "; + Args += "--rebase=true "; + if (noTags) Args += "--no-tags "; From aa0d4b42969271dbc9f42edaadac4d521e09f634 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 6 Mar 2025 11:50:22 +0800 Subject: [PATCH 318/441] ux: adjust column width of commit hash and time after font size changed (#994) Signed-off-by: leo --- src/Views/Histories.axaml | 10 +++++----- src/Views/InteractiveRebase.axaml | 22 +++++++++++++++++++--- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/Views/Histories.axaml b/src/Views/Histories.axaml index 5cde532f..40b2636f 100644 --- a/src/Views/Histories.axaml +++ b/src/Views/Histories.axaml @@ -24,7 +24,7 @@ - + - - + + @@ -121,8 +121,8 @@ - - + + diff --git a/src/Views/InteractiveRebase.axaml b/src/Views/InteractiveRebase.axaml index b4499ddc..1ef2b6cd 100644 --- a/src/Views/InteractiveRebase.axaml +++ b/src/Views/InteractiveRebase.axaml @@ -59,7 +59,8 @@ SelectionMode="Single" SelectedItem="{Binding SelectedItem, Mode=OneWayToSource}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" - ScrollViewer.VerticalScrollBarVisibility="Auto"> + ScrollViewer.VerticalScrollBarVisibility="Auto" + Grid.IsSharedSizeScope="True"> + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + diff --git a/src/Views/Preferences.axaml.cs b/src/Views/Preferences.axaml.cs index 8f9917be..324d2375 100644 --- a/src/Views/Preferences.axaml.cs +++ b/src/Views/Preferences.axaml.cs @@ -103,6 +103,15 @@ namespace SourceGit.Views set => SetValue(SelectedOpenAIServiceProperty, value); } + public static readonly StyledProperty SelectedCustomActionProperty = + AvaloniaProperty.Register(nameof(SelectedCustomAction)); + + public Models.CustomAction SelectedCustomAction + { + get => GetValue(SelectedCustomActionProperty); + set => SetValue(SelectedCustomActionProperty, value); + } + public Preferences() { var pref = ViewModels.Preferences.Instance; @@ -368,6 +377,40 @@ namespace SourceGit.Views e.Handled = true; } + private void OnAddCustomAction(object sender, RoutedEventArgs e) + { + var action = new Models.CustomAction() { Name = "Unnamed Action (Global)" }; + ViewModels.Preferences.Instance.CustomActions.Add(action); + SelectedCustomAction = action; + + e.Handled = true; + } + + private async void SelectExecutableForCustomAction(object sender, RoutedEventArgs e) + { + var options = new FilePickerOpenOptions() + { + FileTypeFilter = [new FilePickerFileType("Executable file(script)") { Patterns = ["*.*"] }], + AllowMultiple = false, + }; + + var selected = await StorageProvider.OpenFilePickerAsync(options); + if (selected.Count == 1 && sender is Button { DataContext: Models.CustomAction action }) + action.Executable = selected[0].Path.LocalPath; + + e.Handled = true; + } + + private void OnRemoveSelectedCustomAction(object sender, RoutedEventArgs e) + { + if (SelectedCustomAction == null) + return; + + ViewModels.Preferences.Instance.CustomActions.Remove(SelectedCustomAction); + SelectedCustomAction = null; + e.Handled = true; + } + private void UpdateGitVersion() { GitVersion = Native.OS.GitVersionString; From cf8cff6b64eb78c96800ce5dbf46e75ebe2e9903 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 10 Mar 2025 21:30:04 +0800 Subject: [PATCH 341/441] code_style: add `ViewModels.Repository.GetCustomAction(scope)` Signed-off-by: leo --- src/ViewModels/Histories.cs | 12 +-------- src/ViewModels/Repository.cs | 47 ++++++++++++++++-------------------- 2 files changed, 22 insertions(+), 37 deletions(-) diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index 301cbb3c..707e8c43 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -694,17 +694,7 @@ namespace SourceGit.ViewModels menu.Items.Add(archive); menu.Items.Add(new MenuItem() { Header = "-" }); - var actions = new List(); - foreach (var action in Preferences.Instance.CustomActions) - { - if (action.Scope == Models.CustomActionScope.Commit) - actions.Add(action); - } - foreach (var action in _repo.Settings.CustomActions) - { - if (action.Scope == Models.CustomActionScope.Commit) - actions.Add(action); - } + var actions = _repo.GetCustomActions(Models.CustomActionScope.Commit); if (actions.Count > 0) { var custom = new MenuItem(); diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 5d2778c9..96d0b36c 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -943,6 +943,25 @@ namespace SourceGit.ViewModels _workingCopy?.AbortMerge(); } + public List GetCustomActions(Models.CustomActionScope scope) + { + var actions = new List(); + + foreach (var act in Preferences.Instance.CustomActions) + { + if (act.Scope == scope) + actions.Add(act); + } + + foreach (var act in _settings.CustomActions) + { + if (act.Scope == scope) + actions.Add(act); + } + + return actions; + } + public void RefreshBranches() { var branches = new Commands.QueryBranches(_fullpath).Result(); @@ -1443,22 +1462,10 @@ namespace SourceGit.ViewModels public ContextMenu CreateContextMenuForCustomAction() { - var actions = new List(); - foreach (var action in Preferences.Instance.CustomActions) - { - if (action.Scope == Models.CustomActionScope.Repository) - actions.Add(action); - } - - foreach (var action in _settings.CustomActions) - { - if (action.Scope == Models.CustomActionScope.Repository) - actions.Add(action); - } - var menu = new ContextMenu(); menu.Placement = PlacementMode.BottomEdgeAlignedLeft; + var actions = GetCustomActions(Models.CustomActionScope.Repository); if (actions.Count > 0) { foreach (var action in actions) @@ -2355,19 +2362,7 @@ namespace SourceGit.ViewModels private void TryToAddCustomActionsToBranchContextMenu(ContextMenu menu, Models.Branch branch) { - var actions = new List(); - foreach (var action in Preferences.Instance.CustomActions) - { - if (action.Scope == Models.CustomActionScope.Branch) - actions.Add(action); - } - - foreach (var action in Settings.CustomActions) - { - if (action.Scope == Models.CustomActionScope.Branch) - actions.Add(action); - } - + var actions = GetCustomActions(Models.CustomActionScope.Branch); if (actions.Count == 0) return; From f496d15f70a7ae5395170f6289bce511129baeff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B8=D1=85=D0=B0=D0=B8=D0=BB=20=D0=A3=D1=81=D0=BE?= =?UTF-8?q?=D1=86=D0=BA=D0=B8=D0=B9?= Date: Mon, 10 Mar 2025 20:15:29 +0300 Subject: [PATCH 342/441] update russian localization --- src/Resources/Locales/ru_RU.axaml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index b15a769b..ff24912e 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -11,9 +11,9 @@ • Исходный код можно найти по адресу Бесплатный графический клиент Git с исходным кодом Добавить рабочий каталог - Что проверить: - Существующую ветку - Создать новую ветку + Переключиться на: + ветку из списка + создать новую ветку Расположение: Путь к рабочему каталогу (поддерживается относительный путь) Имя ветки: @@ -126,7 +126,7 @@ Сбросить ${0}$ сюда Отменить ревизию Изменить комментарий - Сохранить как patch-файл... + Сохранить как заплатки... Объединить с предыдущей ревизией Объединить все следующие ревизии с этим ИЗМЕНЕНИЯ @@ -167,7 +167,7 @@ Адрес электронной почты Адрес электронной почты GIT - Автоматическая загрузка изменений + Автозагрузка изменений Минут(а/ы) Внешний репозиторий по умолчанию ОТСЛЕЖИВАНИЕ ПРОБЛЕМ @@ -218,15 +218,15 @@ Создать метку... Новая метка у: GPG подпись - Сообщение с меткой: + Сообщение с меткой: Необязательно. Имя метки: Рекомендуемый формат: v1.0.0-alpha Выложить на все внешние репозитории после создания Создать новую метку Вид: - Аннотированный - Лёгкий + С примечаниями + Простой Удерживайте Ctrl, чтобы начать сразу Вырезать Удалить ветку @@ -237,7 +237,7 @@ Вы пытаетесь удалить несколько веток одновременно. Обязательно перепроверьте, прежде чем предпринимать какие-либо действия! Удалить внешний репозиторий Внешний репозиторий: - Path: + Путь: Цель: Все дочерние элементы будут удалены из списка. Подтвердите удаление группы @@ -262,7 +262,7 @@ НИКАКИХ ИЗМЕНЕНИЙ ИЛИ МЕНЯЕТСЯ ТОЛЬКО EOL Предыдущее различие Сохранить как заплатку - Различие бок о бок + Различие рядом ПОДМОДУЛЬ НОВЫЙ Обмен @@ -553,7 +553,7 @@ Редактировать внешний репозиторий Имя: Имя внешнего репозитория - Адрес репозитория: + Адрес: Адрес внешнего репозитория git Копировать адрес Удалить... @@ -693,8 +693,8 @@ Копировать относительный путь Извлечение вложенных подмодулей Открыть подмодуль репозитория - Относительный путь: - Относительный каталог для хранения подмодуля. + Каталог: + Относительный путь для хранения подмодуля. Удалить подмодуль ОК Копировать имя метки From 5f2bd8ad943c3fb5af83d95ec2e1bb0483653b87 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 11 Mar 2025 09:27:32 +0800 Subject: [PATCH 343/441] ux: layout for `Preferences` window Signed-off-by: leo --- src/Views/Preferences.axaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/Preferences.axaml b/src/Views/Preferences.axaml index 236deb1f..7bc83b10 100644 --- a/src/Views/Preferences.axaml +++ b/src/Views/Preferences.axaml @@ -422,7 +422,7 @@ - + From 54d49a9edafbec871f4c862011bedbcf21b7e51e Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 11 Mar 2025 09:36:13 +0800 Subject: [PATCH 344/441] fix: app crashes when close a repository on read-only drive (#1080) Signed-off-by: leo --- src/ViewModels/Repository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 96d0b36c..31de381a 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -518,7 +518,7 @@ namespace SourceGit.ViewModels { File.WriteAllText(Path.Combine(_gitDir, "sourcegit.settings"), settingsSerialized); } - catch (DirectoryNotFoundException) + catch { // Ignore } From f23e3478e625362bc23fc428757139e57d270fea Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 11 Mar 2025 11:41:37 +0800 Subject: [PATCH 345/441] fix: do not save preference in design mode Signed-off-by: leo --- src/Views/ConfigureWorkspace.axaml.cs | 4 +++- src/Views/Launcher.axaml.cs | 4 +++- src/Views/Preferences.axaml.cs | 6 +++++- src/Views/RepositoryConfigure.axaml.cs | 4 +++- src/Views/WorkingCopy.axaml.cs | 1 - 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Views/ConfigureWorkspace.axaml.cs b/src/Views/ConfigureWorkspace.axaml.cs index 012c2e85..9e458f6f 100644 --- a/src/Views/ConfigureWorkspace.axaml.cs +++ b/src/Views/ConfigureWorkspace.axaml.cs @@ -11,8 +11,10 @@ namespace SourceGit.Views protected override void OnClosing(WindowClosingEventArgs e) { - ViewModels.Preferences.Instance.Save(); base.OnClosing(e); + + if (!Design.IsDesignMode) + ViewModels.Preferences.Instance.Save(); } } } diff --git a/src/Views/Launcher.axaml.cs b/src/Views/Launcher.axaml.cs index b8c09b35..9ccec78c 100644 --- a/src/Views/Launcher.axaml.cs +++ b/src/Views/Launcher.axaml.cs @@ -273,8 +273,10 @@ namespace SourceGit.Views protected override void OnClosing(WindowClosingEventArgs e) { - (DataContext as ViewModels.Launcher)?.Quit(Width, Height); base.OnClosing(e); + + if (!Design.IsDesignMode && DataContext is ViewModels.Launcher launcher) + launcher.Quit(Width, Height); } private void OnOpenWorkspaceMenu(object sender, RoutedEventArgs e) diff --git a/src/Views/Preferences.axaml.cs b/src/Views/Preferences.axaml.cs index 324d2375..73b2e995 100644 --- a/src/Views/Preferences.axaml.cs +++ b/src/Views/Preferences.axaml.cs @@ -169,6 +169,11 @@ namespace SourceGit.Views protected override void OnClosing(WindowClosingEventArgs e) { + base.OnClosing(e); + + if (Design.IsDesignMode) + return; + var config = new Commands.Config(null).ListAll(); SetIfChanged(config, "user.name", DefaultUser, ""); SetIfChanged(config, "user.email", DefaultEmail, ""); @@ -199,7 +204,6 @@ namespace SourceGit.Views } ViewModels.Preferences.Instance.Save(); - base.OnClosing(e); } private async void SelectThemeOverrideFile(object _, RoutedEventArgs e) diff --git a/src/Views/RepositoryConfigure.axaml.cs b/src/Views/RepositoryConfigure.axaml.cs index 3faba5ee..455731aa 100644 --- a/src/Views/RepositoryConfigure.axaml.cs +++ b/src/Views/RepositoryConfigure.axaml.cs @@ -13,8 +13,10 @@ namespace SourceGit.Views protected override void OnClosing(WindowClosingEventArgs e) { - (DataContext as ViewModels.RepositoryConfigure)?.Save(); base.OnClosing(e); + + if (!Design.IsDesignMode && DataContext is ViewModels.RepositoryConfigure configure) + configure.Save(); } private async void SelectExecutableForCustomAction(object sender, RoutedEventArgs e) diff --git a/src/Views/WorkingCopy.axaml.cs b/src/Views/WorkingCopy.axaml.cs index dfaad858..4ae4d779 100644 --- a/src/Views/WorkingCopy.axaml.cs +++ b/src/Views/WorkingCopy.axaml.cs @@ -1,7 +1,6 @@ using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; -using Avalonia.VisualTree; namespace SourceGit.Views { From 471452646b48c58b6bf64a069e777ba6fe0d9afa Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 11 Mar 2025 16:53:51 +0800 Subject: [PATCH 346/441] refactor: use `System.Threading.CancellationToken` instead of `SourceGit.Commands.Command.CancelToken` to cancel fetching information of selected commit Signed-off-by: leo --- src/Commands/Command.cs | 48 ++++++++++++++-------------------- src/ViewModels/CommitDetail.cs | 35 ++++++++++++++----------- 2 files changed, 40 insertions(+), 43 deletions(-) diff --git a/src/Commands/Command.cs b/src/Commands/Command.cs index a3e6673b..cedaf674 100644 --- a/src/Commands/Command.cs +++ b/src/Commands/Command.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Text.RegularExpressions; +using System.Threading; using Avalonia.Threading; @@ -10,11 +11,6 @@ namespace SourceGit.Commands { public partial class Command { - public class CancelToken - { - public bool Requested { get; set; } = false; - } - public class ReadToEndResult { public bool IsSuccess { get; set; } = false; @@ -30,7 +26,7 @@ namespace SourceGit.Commands } public string Context { get; set; } = string.Empty; - public CancelToken Cancel { get; set; } = null; + public CancellationToken CancellationToken { get; set; } = CancellationToken.None; public string WorkingDirectory { get; set; } = null; public EditorType Editor { get; set; } = EditorType.CoreEditor; // Only used in Exec() mode public string SSHKey { get; set; } = string.Empty; @@ -43,36 +39,15 @@ namespace SourceGit.Commands var start = CreateGitStartInfo(); var errs = new List(); var proc = new Process() { StartInfo = start }; - var isCancelled = false; proc.OutputDataReceived += (_, e) => { - if (Cancel != null && Cancel.Requested) - { - isCancelled = true; - proc.CancelErrorRead(); - proc.CancelOutputRead(); - if (!proc.HasExited) - proc.Kill(true); - return; - } - if (e.Data != null) OnReadline(e.Data); }; proc.ErrorDataReceived += (_, e) => { - if (Cancel != null && Cancel.Requested) - { - isCancelled = true; - proc.CancelErrorRead(); - proc.CancelOutputRead(); - if (!proc.HasExited) - proc.Kill(true); - return; - } - if (string.IsNullOrEmpty(e.Data)) { errs.Add(string.Empty); @@ -97,9 +72,25 @@ namespace SourceGit.Commands errs.Add(e.Data); }; + var dummy = null as Process; try { proc.Start(); + + // It not safe, please only use `CancellationToken` in readonly commands. + if (CancellationToken.CanBeCanceled) + { + dummy = proc; + CancellationToken.Register(() => + { + if (dummy is { HasExited: false }) + { + dummy.CancelErrorRead(); + dummy.CancelOutputRead(); + dummy.Kill(); + } + }); + } } catch (Exception e) { @@ -113,10 +104,11 @@ namespace SourceGit.Commands proc.BeginErrorReadLine(); proc.WaitForExit(); + dummy = null; int exitCode = proc.ExitCode; proc.Close(); - if (!isCancelled && exitCode != 0) + if (!CancellationToken.IsCancellationRequested && exitCode != 0) { if (RaiseError) { diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index 456e99f8..c6ef8367 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text.RegularExpressions; +using System.Threading; using System.Threading.Tasks; using Avalonia.Controls; @@ -171,7 +172,7 @@ namespace SourceGit.ViewModels _searchChangeFilter = null; _diffContext = null; _viewRevisionFileContent = null; - _cancelToken = null; + _cancellationSource = null; WebLinks.Clear(); _revisionFiles = null; _revisionFileSearchSuggestion = null; @@ -589,32 +590,36 @@ namespace SourceGit.ViewModels if (_commit == null) return; + if (_cancellationSource is { IsCancellationRequested: false }) + _cancellationSource.Cancel(); + + _cancellationSource = new CancellationTokenSource(); + var token = _cancellationSource.Token; + Task.Run(() => { var message = new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).Result(); var links = ParseLinksInMessage(message); - Dispatcher.UIThread.Invoke(() => FullMessage = new Models.CommitFullMessage { Message = message, Links = links }); + + if (!token.IsCancellationRequested) + Dispatcher.UIThread.Invoke(() => FullMessage = new Models.CommitFullMessage { Message = message, Links = links }); }); Task.Run(() => { var signInfo = new Commands.QueryCommitSignInfo(_repo.FullPath, _commit.SHA, !_repo.HasAllowedSignersFile).Result(); - Dispatcher.UIThread.Invoke(() => SignInfo = signInfo); + if (!token.IsCancellationRequested) + Dispatcher.UIThread.Invoke(() => SignInfo = signInfo); }); - if (_cancelToken != null) - _cancelToken.Requested = true; - - _cancelToken = new Commands.Command.CancelToken(); - if (Preferences.Instance.ShowChildren) { Task.Run(() => { var max = Preferences.Instance.MaxHistoryCommits; - var cmdChildren = new Commands.QueryCommitChildren(_repo.FullPath, _commit.SHA, max) { Cancel = _cancelToken }; - var children = cmdChildren.Result(); - if (!cmdChildren.Cancel.Requested) + var cmd = new Commands.QueryCommitChildren(_repo.FullPath, _commit.SHA, max) { CancellationToken = token }; + var children = cmd.Result(); + if (!token.IsCancellationRequested) Dispatcher.UIThread.Post(() => Children = children); }); } @@ -622,8 +627,8 @@ namespace SourceGit.ViewModels Task.Run(() => { var parent = _commit.Parents.Count == 0 ? "4b825dc642cb6eb9a060e54bf8d69288fbee4904" : _commit.Parents[0]; - var cmdChanges = new Commands.CompareRevisions(_repo.FullPath, parent, _commit.SHA) { Cancel = _cancelToken }; - var changes = cmdChanges.Result(); + var cmd = new Commands.CompareRevisions(_repo.FullPath, parent, _commit.SHA) { CancellationToken = token }; + var changes = cmd.Result(); var visible = changes; if (!string.IsNullOrWhiteSpace(_searchChangeFilter)) { @@ -635,7 +640,7 @@ namespace SourceGit.ViewModels } } - if (!cmdChanges.Cancel.Requested) + if (!token.IsCancellationRequested) { Dispatcher.UIThread.Post(() => { @@ -873,7 +878,7 @@ namespace SourceGit.ViewModels private string _searchChangeFilter = string.Empty; private DiffContext _diffContext = null; private object _viewRevisionFileContent = null; - private Commands.Command.CancelToken _cancelToken = null; + private CancellationTokenSource _cancellationSource = null; private List _revisionFiles = null; private string _revisionFileSearchFilter = string.Empty; private List _revisionFileSearchSuggestion = null; From 2fc03025eef98c6641e8045232256691675ce7db Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 11 Mar 2025 19:52:50 +0800 Subject: [PATCH 347/441] fix: file suggestion popup did not show while searching commit by file path Signed-off-by: leo --- src/ViewModels/Repository.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 31de381a..ebf9210e 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -321,7 +321,7 @@ namespace SourceGit.ViewModels set { if (SetProperty(ref _searchCommitFilter, value) && - _searchCommitFilterType == 3 && + _searchCommitFilterType == 4 && !string.IsNullOrEmpty(value) && value.Length >= 2 && _revisionFiles.Count > 0) @@ -2395,14 +2395,14 @@ namespace SourceGit.ViewModels { _revisionFiles.Clear(); - if (_searchCommitFilterType == 3) + if (_searchCommitFilterType == 4) { Task.Run(() => { var files = new Commands.QueryRevisionFileNames(_fullpath, "HEAD").Result(); Dispatcher.UIThread.Invoke(() => { - if (_searchCommitFilterType != 3) + if (_searchCommitFilterType != 4) return; _revisionFiles.AddRange(files); From 91c5c96afc3a070ca8b491a3e992ef5dbcb70d54 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 11 Mar 2025 20:05:05 +0800 Subject: [PATCH 348/441] fix: accessing `dummy` in multi-threads throws exception Signed-off-by: leo --- src/Commands/Command.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/Commands/Command.cs b/src/Commands/Command.cs index cedaf674..5197de11 100644 --- a/src/Commands/Command.cs +++ b/src/Commands/Command.cs @@ -73,6 +73,7 @@ namespace SourceGit.Commands }; var dummy = null as Process; + var dummyProcLock = new object(); try { proc.Start(); @@ -83,11 +84,10 @@ namespace SourceGit.Commands dummy = proc; CancellationToken.Register(() => { - if (dummy is { HasExited: false }) + lock (dummyProcLock) { - dummy.CancelErrorRead(); - dummy.CancelOutputRead(); - dummy.Kill(); + if (dummy is { HasExited: false }) + dummy.Kill(); } }); } @@ -104,7 +104,14 @@ namespace SourceGit.Commands proc.BeginErrorReadLine(); proc.WaitForExit(); - dummy = null; + if (dummy != null) + { + lock (dummyProcLock) + { + dummy = null; + } + } + int exitCode = proc.ExitCode; proc.Close(); From fa4d9d24e9ab5f1dfd8bf8f75fadddd8b903a23c Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 11 Mar 2025 20:22:32 +0800 Subject: [PATCH 349/441] enhance: hide suggestion popups when window is deactived (#963) Signed-off-by: leo --- src/Views/Repository.axaml | 10 ++++++++-- src/Views/RevisionFiles.axaml | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index 30180f7d..bfa5a5e1 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -421,8 +421,14 @@ + HorizontalOffset="-8" VerticalAlignment="-8"> + + + + + + + + HorizontalOffset="-8" VerticalAlignment="-8"> + + + + + + + Date: Tue, 11 Mar 2025 20:55:39 +0800 Subject: [PATCH 350/441] refactor: rewrite searching commit by file path Signed-off-by: leo --- src/ViewModels/Repository.cs | 112 +++++++++++++++------------------- src/Views/Repository.axaml | 4 +- src/Views/Repository.axaml.cs | 13 +--- 3 files changed, 53 insertions(+), 76 deletions(-) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index ebf9210e..9e10390a 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -271,14 +271,13 @@ namespace SourceGit.ViewModels { SearchedCommits = new List(); SearchCommitFilter = string.Empty; - SearchCommitFilterSuggestion.Clear(); - IsSearchCommitSuggestionOpen = false; - _revisionFiles.Clear(); + MatchedFilesForSearching = null; + _worktreeFiles = null; if (value) { SelectedViewIndex = 0; - UpdateCurrentRevisionFilesForSearchSuggestion(); + CalcWorktreeFilesForSearching(); } } } @@ -307,7 +306,7 @@ namespace SourceGit.ViewModels { if (SetProperty(ref _searchCommitFilterType, value)) { - UpdateCurrentRevisionFilesForSearchSuggestion(); + CalcWorktreeFilesForSearching(); if (!string.IsNullOrEmpty(_searchCommitFilter)) StartSearchCommits(); @@ -320,47 +319,22 @@ namespace SourceGit.ViewModels get => _searchCommitFilter; set { - if (SetProperty(ref _searchCommitFilter, value) && - _searchCommitFilterType == 4 && - !string.IsNullOrEmpty(value) && - value.Length >= 2 && - _revisionFiles.Count > 0) + if (SetProperty(ref _searchCommitFilter, value)) { - var suggestion = new List(); - foreach (var file in _revisionFiles) - { - if (file.Contains(value, StringComparison.OrdinalIgnoreCase) && file.Length != value.Length) - { - suggestion.Add(file); - if (suggestion.Count > 100) - break; - } - } - - SearchCommitFilterSuggestion.Clear(); - SearchCommitFilterSuggestion.AddRange(suggestion); - IsSearchCommitSuggestionOpen = SearchCommitFilterSuggestion.Count > 0; - } - else if (SearchCommitFilterSuggestion.Count > 0) - { - SearchCommitFilterSuggestion.Clear(); - IsSearchCommitSuggestionOpen = false; + if (_searchCommitFilterType == 4 && value is { Length: > 2 }) + CalcMatchedFilesForSearching(); + else if (_matchedFilesForSearching is { }) + MatchedFilesForSearching = null; } } } - public bool IsSearchCommitSuggestionOpen + public List MatchedFilesForSearching { - get => _isSearchCommitSuggestionOpen; - set => SetProperty(ref _isSearchCommitSuggestionOpen, value); + get => _matchedFilesForSearching; + private set => SetProperty(ref _matchedFilesForSearching, value); } - public AvaloniaList SearchCommitFilterSuggestion - { - get; - private set; - } = new AvaloniaList(); - public List SearchedCommits { get => _searchedCommits; @@ -551,8 +525,8 @@ namespace SourceGit.ViewModels _visibleSubmodules.Clear(); _searchedCommits.Clear(); - _revisionFiles.Clear(); - SearchCommitFilterSuggestion.Clear(); + _worktreeFiles = null; + _matchedFilesForSearching = null; } public bool CanCreatePopup() @@ -723,6 +697,11 @@ namespace SourceGit.ViewModels SearchCommitFilter = string.Empty; } + public void ClearMatchedFilesForSearching() + { + MatchedFilesForSearching = null; + } + public void StartSearchCommits() { if (_histories == null) @@ -730,8 +709,7 @@ namespace SourceGit.ViewModels IsSearchLoadingVisible = true; SearchResultSelectedCommit = null; - IsSearchCommitSuggestionOpen = false; - SearchCommitFilterSuggestion.Clear(); + MatchedFilesForSearching = null; Task.Run(() => { @@ -2391,9 +2369,9 @@ namespace SourceGit.ViewModels menu.Items.Add(new MenuItem() { Header = "-" }); } - private void UpdateCurrentRevisionFilesForSearchSuggestion() + private void CalcWorktreeFilesForSearching() { - _revisionFiles.Clear(); + _worktreeFiles = null; if (_searchCommitFilterType == 4) { @@ -2405,30 +2383,36 @@ namespace SourceGit.ViewModels if (_searchCommitFilterType != 4) return; - _revisionFiles.AddRange(files); + _worktreeFiles = new List(); + foreach (var f in files) + _worktreeFiles.Add(f); - if (!string.IsNullOrEmpty(_searchCommitFilter) && _searchCommitFilter.Length > 2 && _revisionFiles.Count > 0) - { - var suggestion = new List(); - foreach (var file in _revisionFiles) - { - if (file.Contains(_searchCommitFilter, StringComparison.OrdinalIgnoreCase) && file.Length != _searchCommitFilter.Length) - { - suggestion.Add(file); - if (suggestion.Count > 100) - break; - } - } - - SearchCommitFilterSuggestion.Clear(); - SearchCommitFilterSuggestion.AddRange(suggestion); - IsSearchCommitSuggestionOpen = SearchCommitFilterSuggestion.Count > 0; - } + if (_searchCommitFilter is { Length: > 2 }) + CalcMatchedFilesForSearching(); }); }); } } + private void CalcMatchedFilesForSearching() + { + if (_worktreeFiles == null || _worktreeFiles.Count == 0) + return; + + var matched = new List(); + foreach (var file in _worktreeFiles) + { + if (file.Contains(_searchCommitFilter, StringComparison.OrdinalIgnoreCase) && file.Length != _searchCommitFilter.Length) + { + matched.Add(file); + if (matched.Count > 100) + break; + } + } + + MatchedFilesForSearching = matched; + } + private void AutoFetchImpl(object sender) { if (!_settings.EnableAutoFetch || _isAutoFetching) @@ -2475,13 +2459,13 @@ namespace SourceGit.ViewModels private bool _isSearching = false; private bool _isSearchLoadingVisible = false; - private bool _isSearchCommitSuggestionOpen = false; private int _searchCommitFilterType = 3; private bool _onlySearchCommitsInCurrentBranch = false; private string _searchCommitFilter = string.Empty; private List _searchedCommits = new List(); private Models.Commit _searchResultSelectedCommit = null; - private List _revisionFiles = new List(); + private List _worktreeFiles = null; + private List _matchedFilesForSearching = null; private string _filter = string.Empty; private object _lockRemotes = new object(); diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index bfa5a5e1..9caac015 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -424,7 +424,7 @@ HorizontalOffset="-8" VerticalAlignment="-8"> - + @@ -434,7 +434,7 @@ diff --git a/src/Views/Repository.axaml.cs b/src/Views/Repository.axaml.cs index 2b3b7c30..00218a85 100644 --- a/src/Views/Repository.axaml.cs +++ b/src/Views/Repository.axaml.cs @@ -134,7 +134,7 @@ namespace SourceGit.Views } else if (e.Key == Key.Down) { - if (repo.IsSearchCommitSuggestionOpen) + if (repo.MatchedFilesForSearching is { Count: > 0 }) { SearchSuggestionBox.Focus(NavigationMethod.Tab); SearchSuggestionBox.SelectedIndex = 0; @@ -144,12 +144,7 @@ namespace SourceGit.Views } else if (e.Key == Key.Escape) { - if (repo.IsSearchCommitSuggestionOpen) - { - repo.SearchCommitFilterSuggestion.Clear(); - repo.IsSearchCommitSuggestionOpen = false; - } - + repo.ClearMatchedFilesForSearching(); e.Handled = true; } } @@ -369,9 +364,7 @@ namespace SourceGit.Views if (e.Key == Key.Escape) { - repo.IsSearchCommitSuggestionOpen = false; - repo.SearchCommitFilterSuggestion.Clear(); - + repo.ClearMatchedFilesForSearching(); e.Handled = true; } else if (e.Key == Key.Enter && SearchSuggestionBox.SelectedItem is string content) From f5d6e1264d6e587c3ac6b90a9df3e0df30650f9e Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 11 Mar 2025 23:01:34 +0800 Subject: [PATCH 351/441] refactor: use `List` instead of `AvaloniaList` since it is not used for bindings Signed-off-by: leo --- src/ViewModels/Repository.cs | 10 ++++++---- src/ViewModels/WorkingCopy.cs | 32 ++++++++++++++------------------ 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 9e10390a..59ab6a1b 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -6,7 +6,6 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Media; using Avalonia.Media.Imaging; @@ -1221,23 +1220,26 @@ namespace SourceGit.ViewModels App.GetLauncer()?.OpenRepositoryInTab(node, null); } - public AvaloniaList GetPreferedOpenAIServices() + public List GetPreferedOpenAIServices() { var services = Preferences.Instance.OpenAIServices; if (services == null || services.Count == 0) return []; if (services.Count == 1) - return services; + return [services[0]]; var prefered = _settings.PreferedOpenAIService; + var all = new List(); foreach (var service in services) { if (service.Name.Equals(prefered, StringComparison.Ordinal)) return [service]; + + all.Add(service); } - return services; + return all; } public ContextMenu CreateContextMenuForGitFlow() diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index 35db11b9..f9ddb288 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -1452,28 +1452,24 @@ namespace SourceGit.ViewModels App.OpenDialog(dialog); return null; } - else + + var menu = new ContextMenu() { Placement = PlacementMode.TopEdgeAlignedLeft }; + foreach (var service in services) { - var menu = new ContextMenu() { Placement = PlacementMode.TopEdgeAlignedLeft }; - - foreach (var service in services) + var dup = service; + var item = new MenuItem(); + item.Header = service.Name; + item.Click += (_, e) => { - var dup = service; + var dialog = new Views.AIAssistant(dup, _repo.FullPath, this, _staged); + App.OpenDialog(dialog); + e.Handled = true; + }; - var item = new MenuItem(); - item.Header = service.Name; - item.Click += (_, e) => - { - var dialog = new Views.AIAssistant(dup, _repo.FullPath, this, _staged); - App.OpenDialog(dialog); - e.Handled = true; - }; - - menu.Items.Add(item); - } - - return menu; + menu.Items.Add(item); } + + return menu; } private List GetVisibleUnstagedChanges(List unstaged) From 231f3bf6688485be75a5295f5307e115889e5296 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 12 Mar 2025 10:11:00 +0800 Subject: [PATCH 352/441] enhance: use `--ancestry-path=` to reduce unnecessary outpus while querying children commits Signed-off-by: leo --- src/Commands/QueryCommitChildren.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Commands/QueryCommitChildren.cs b/src/Commands/QueryCommitChildren.cs index d1bced52..6a6ed909 100644 --- a/src/Commands/QueryCommitChildren.cs +++ b/src/Commands/QueryCommitChildren.cs @@ -9,7 +9,7 @@ namespace SourceGit.Commands WorkingDirectory = repo; Context = repo; _commit = commit; - Args = $"rev-list -{max} --parents --branches --remotes ^{commit}"; + Args = $"rev-list -{max} --parents --branches --remotes --ancestry-path={commit} ^{commit}"; } public List Result() From ee7ccc0391ee5e7e03f5f8d9cf496804170cda4a Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 12 Mar 2025 11:05:19 +0800 Subject: [PATCH 353/441] refactor: re-write commit searching (part 2) Signed-off-by: leo --- src/Models/Commit.cs | 1 + src/ViewModels/Histories.cs | 12 ++-- src/ViewModels/Repository.cs | 132 +++++++++++++++++------------------ src/Views/Repository.axaml | 2 +- 4 files changed, 73 insertions(+), 74 deletions(-) diff --git a/src/Models/Commit.cs b/src/Models/Commit.cs index 5c48b0c0..72ce54bd 100644 --- a/src/Models/Commit.cs +++ b/src/Models/Commit.cs @@ -8,6 +8,7 @@ namespace SourceGit.Models { public enum CommitSearchMethod { + BySHA = 0, ByAuthor, ByCommitter, ByMessage, diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index 707e8c43..0e67915c 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -148,14 +148,14 @@ namespace SourceGit.ViewModels { if (commits.Count == 0) { - _repo.SearchResultSelectedCommit = null; + _repo.SelectedSearchedCommit = null; DetailContext = null; } else if (commits.Count == 1) { var commit = (commits[0] as Models.Commit)!; - if (_repo.SearchResultSelectedCommit == null || _repo.SearchResultSelectedCommit.SHA != commit.SHA) - _repo.SearchResultSelectedCommit = _repo.SearchedCommits.Find(x => x.SHA == commit.SHA); + if (_repo.SelectedSearchedCommit == null || _repo.SelectedSearchedCommit.SHA != commit.SHA) + _repo.SelectedSearchedCommit = _repo.SearchedCommits.Find(x => x.SHA == commit.SHA); AutoSelectedCommit = commit; NavigationId = _navigationId + 1; @@ -173,7 +173,7 @@ namespace SourceGit.ViewModels } else if (commits.Count == 2) { - _repo.SearchResultSelectedCommit = null; + _repo.SelectedSearchedCommit = null; var end = commits[0] as Models.Commit; var start = commits[1] as Models.Commit; @@ -181,7 +181,7 @@ namespace SourceGit.ViewModels } else { - _repo.SearchResultSelectedCommit = null; + _repo.SelectedSearchedCommit = null; DetailContext = commits.Count; } } @@ -599,7 +599,7 @@ namespace SourceGit.ViewModels var head = _commits.Find(x => x.SHA == current.Head); if (head == null) { - _repo.SearchResultSelectedCommit = null; + _repo.SelectedSearchedCommit = null; head = new Commands.QuerySingleCommit(_repo.FullPath, current.Head).Result(); if (head != null) DetailContext = new RevisionCompare(_repo.FullPath, commit, head); diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 59ab6a1b..c7557356 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -268,16 +268,19 @@ namespace SourceGit.ViewModels { if (SetProperty(ref _isSearching, value)) { - SearchedCommits = new List(); - SearchCommitFilter = string.Empty; - MatchedFilesForSearching = null; - _worktreeFiles = null; - if (value) { SelectedViewIndex = 0; CalcWorktreeFilesForSearching(); } + else + { + SearchedCommits = new List(); + SelectedSearchedCommit = null; + SearchCommitFilter = string.Empty; + MatchedFilesForSearching = null; + _worktreeFiles = null; + } } } } @@ -306,7 +309,6 @@ namespace SourceGit.ViewModels if (SetProperty(ref _searchCommitFilterType, value)) { CalcWorktreeFilesForSearching(); - if (!string.IsNullOrEmpty(_searchCommitFilter)) StartSearchCommits(); } @@ -318,13 +320,8 @@ namespace SourceGit.ViewModels get => _searchCommitFilter; set { - if (SetProperty(ref _searchCommitFilter, value)) - { - if (_searchCommitFilterType == 4 && value is { Length: > 2 }) - CalcMatchedFilesForSearching(); - else if (_matchedFilesForSearching is { }) - MatchedFilesForSearching = null; - } + if (SetProperty(ref _searchCommitFilter, value) && IsSearchingCommitsByFilePath()) + CalcMatchedFilesForSearching(); } } @@ -340,6 +337,16 @@ namespace SourceGit.ViewModels set => SetProperty(ref _searchedCommits, value); } + public Models.Commit SelectedSearchedCommit + { + get => _selectedSearchedCommit; + set + { + if (SetProperty(ref _selectedSearchedCommit, value) && value != null) + NavigateToCommit(value.SHA); + } + } + public bool IsLocalBranchGroupExpanded { get => _settings.IsLocalBranchesExpandedInSideBar; @@ -410,16 +417,6 @@ namespace SourceGit.ViewModels get => _workingCopy?.InProgressContext; } - public Models.Commit SearchResultSelectedCommit - { - get => _searchResultSelectedCommit; - set - { - if (SetProperty(ref _searchResultSelectedCommit, value) && value != null) - NavigateToCommit(value.SHA); - } - } - public bool IsAutoFetching { get => _isAutoFetching; @@ -523,6 +520,7 @@ namespace SourceGit.ViewModels _submodules.Clear(); _visibleSubmodules.Clear(); _searchedCommits.Clear(); + _selectedSearchedCommit = null; _worktreeFiles = null; _matchedFilesForSearching = null; @@ -707,32 +705,22 @@ namespace SourceGit.ViewModels return; IsSearchLoadingVisible = true; - SearchResultSelectedCommit = null; + SelectedSearchedCommit = null; MatchedFilesForSearching = null; Task.Run(() => { - var visible = new List(); + var visible = null as List; + var method = (Models.CommitSearchMethod)_searchCommitFilterType; - switch (_searchCommitFilterType) + if (method == Models.CommitSearchMethod.BySHA) { - case 0: - var commit = new Commands.QuerySingleCommit(_fullpath, _searchCommitFilter).Result(); - if (commit != null) - visible.Add(commit); - break; - case 1: - visible = new Commands.QueryCommits(_fullpath, _searchCommitFilter, Models.CommitSearchMethod.ByAuthor, _onlySearchCommitsInCurrentBranch).Result(); - break; - case 2: - visible = new Commands.QueryCommits(_fullpath, _searchCommitFilter, Models.CommitSearchMethod.ByCommitter, _onlySearchCommitsInCurrentBranch).Result(); - break; - case 3: - visible = new Commands.QueryCommits(_fullpath, _searchCommitFilter, Models.CommitSearchMethod.ByMessage, _onlySearchCommitsInCurrentBranch).Result(); - break; - case 4: - visible = new Commands.QueryCommits(_fullpath, _searchCommitFilter, Models.CommitSearchMethod.ByFile, _onlySearchCommitsInCurrentBranch).Result(); - break; + var commit = new Commands.QuerySingleCommit(_fullpath, _searchCommitFilter).Result(); + visible = commit == null ? [] : [commit]; + } + else + { + visible = new Commands.QueryCommits(_fullpath, _searchCommitFilter, method, _onlySearchCommitsInCurrentBranch).Result(); } Dispatcher.UIThread.Invoke(() => @@ -1636,7 +1624,7 @@ namespace SourceGit.ViewModels compareWithWorktree.Icon = App.CreateMenuIcon("Icons.Compare"); compareWithWorktree.Click += (_, _) => { - SearchResultSelectedCommit = null; + SelectedSearchedCommit = null; if (_histories != null) { @@ -1918,7 +1906,7 @@ namespace SourceGit.ViewModels compareWithWorktree.Icon = App.CreateMenuIcon("Icons.Compare"); compareWithWorktree.Click += (_, _) => { - SearchResultSelectedCommit = null; + SelectedSearchedCommit = null; if (_histories != null) { @@ -2371,35 +2359,45 @@ namespace SourceGit.ViewModels menu.Items.Add(new MenuItem() { Header = "-" }); } + private bool IsSearchingCommitsByFilePath() + { + return _isSearching && _searchCommitFilterType == (int)Models.CommitSearchMethod.ByFile; + } + private void CalcWorktreeFilesForSearching() { - _worktreeFiles = null; - - if (_searchCommitFilterType == 4) + if (!IsSearchingCommitsByFilePath()) { - Task.Run(() => - { - var files = new Commands.QueryRevisionFileNames(_fullpath, "HEAD").Result(); - Dispatcher.UIThread.Invoke(() => - { - if (_searchCommitFilterType != 4) - return; - - _worktreeFiles = new List(); - foreach (var f in files) - _worktreeFiles.Add(f); - - if (_searchCommitFilter is { Length: > 2 }) - CalcMatchedFilesForSearching(); - }); - }); + _worktreeFiles = null; + MatchedFilesForSearching = null; + GC.Collect(); + return; } + + Task.Run(() => + { + var files = new Commands.QueryRevisionFileNames(_fullpath, "HEAD").Result(); + Dispatcher.UIThread.Invoke(() => + { + if (!IsSearchingCommitsByFilePath()) + return; + + _worktreeFiles = new List(); + foreach (var f in files) + _worktreeFiles.Add(f); + + CalcMatchedFilesForSearching(); + }); + }); } private void CalcMatchedFilesForSearching() { - if (_worktreeFiles == null || _worktreeFiles.Count == 0) + if (_worktreeFiles == null || _worktreeFiles.Count == 0 || _searchCommitFilter.Length < 3) + { + MatchedFilesForSearching = null; return; + } var matched = new List(); foreach (var file in _worktreeFiles) @@ -2461,11 +2459,11 @@ namespace SourceGit.ViewModels private bool _isSearching = false; private bool _isSearchLoadingVisible = false; - private int _searchCommitFilterType = 3; + private int _searchCommitFilterType = (int)Models.CommitSearchMethod.ByMessage; private bool _onlySearchCommitsInCurrentBranch = false; private string _searchCommitFilter = string.Empty; private List _searchedCommits = new List(); - private Models.Commit _searchResultSelectedCommit = null; + private Models.Commit _selectedSearchedCommit = null; private List _worktreeFiles = null; private List _matchedFilesForSearching = null; diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index 9caac015..1d94e9b2 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -504,7 +504,7 @@ Margin="0,8,0,0" ItemsSource="{Binding SearchedCommits}" SelectionMode="Single" - SelectedItem="{Binding SearchResultSelectedCommit, Mode=TwoWay}" + SelectedItem="{Binding SelectedSearchedCommit, Mode=TwoWay}" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}" Background="{DynamicResource Brush.Contents}" From bb2284c4c91d4c95ddbc3bb0d5c0d3c951b2e756 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 12 Mar 2025 11:53:24 +0800 Subject: [PATCH 354/441] refactor: re-write commit searching (part 3) Signed-off-by: leo --- src/Commands/QueryRevisionFileNames.cs | 16 +++++++++++----- src/ViewModels/CommitDetail.cs | 5 +---- src/ViewModels/Repository.cs | 12 +++--------- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/Commands/QueryRevisionFileNames.cs b/src/Commands/QueryRevisionFileNames.cs index d2d69614..c6fd7373 100644 --- a/src/Commands/QueryRevisionFileNames.cs +++ b/src/Commands/QueryRevisionFileNames.cs @@ -1,4 +1,6 @@ -namespace SourceGit.Commands +using System.Collections.Generic; + +namespace SourceGit.Commands { public class QueryRevisionFileNames : Command { @@ -9,13 +11,17 @@ Args = $"ls-tree -r -z --name-only {revision}"; } - public string[] Result() + public List Result() { var rs = ReadToEnd(); - if (rs.IsSuccess) - return rs.StdOut.Split('\0', System.StringSplitOptions.RemoveEmptyEntries); + if (!rs.IsSuccess) + return []; - return []; + var lines = rs.StdOut.Split('\0', System.StringSplitOptions.RemoveEmptyEntries); + var outs = new List(); + foreach (var line in lines) + outs.Add(line); + return outs; } } } diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index c6ef8367..34ac8308 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -814,14 +814,11 @@ namespace SourceGit.ViewModels Task.Run(() => { var files = new Commands.QueryRevisionFileNames(_repo.FullPath, sha).Result(); - var filesList = new List(); - filesList.AddRange(files); - Dispatcher.UIThread.Invoke(() => { if (sha == Commit.SHA) { - _revisionFiles = filesList; + _revisionFiles = files; if (!string.IsNullOrEmpty(_revisionFileSearchFilter)) CalcRevisionFileSearchSuggestion(); } diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index c7557356..97c52d8e 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -2376,17 +2376,11 @@ namespace SourceGit.ViewModels Task.Run(() => { - var files = new Commands.QueryRevisionFileNames(_fullpath, "HEAD").Result(); + _worktreeFiles = new Commands.QueryRevisionFileNames(_fullpath, "HEAD").Result(); Dispatcher.UIThread.Invoke(() => { - if (!IsSearchingCommitsByFilePath()) - return; - - _worktreeFiles = new List(); - foreach (var f in files) - _worktreeFiles.Add(f); - - CalcMatchedFilesForSearching(); + if (IsSearchingCommitsByFilePath()) + CalcMatchedFilesForSearching(); }); }); } From 0476a825efffa277e751eeb8352ed9c93d41f1c5 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 12 Mar 2025 14:58:59 +0800 Subject: [PATCH 355/441] code_style: move some code from `Histories.axaml` to separate files Signed-off-by: leo --- src/Views/CommitGraph.cs | 228 +++++++++ src/Views/CommitStatusIndicator.cs | 90 ++++ src/Views/CommitSubjectPresenter.cs | 189 ++++++++ src/Views/CommitTimeTextBlock.cs | 163 +++++++ src/Views/Histories.axaml | 12 +- src/Views/Histories.axaml.cs | 695 ++-------------------------- 6 files changed, 705 insertions(+), 672 deletions(-) create mode 100644 src/Views/CommitGraph.cs create mode 100644 src/Views/CommitStatusIndicator.cs create mode 100644 src/Views/CommitSubjectPresenter.cs create mode 100644 src/Views/CommitTimeTextBlock.cs diff --git a/src/Views/CommitGraph.cs b/src/Views/CommitGraph.cs new file mode 100644 index 00000000..015eaca5 --- /dev/null +++ b/src/Views/CommitGraph.cs @@ -0,0 +1,228 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Media; +using Avalonia.VisualTree; + +namespace SourceGit.Views +{ + public class CommitGraph : Control + { + public static readonly StyledProperty GraphProperty = + AvaloniaProperty.Register(nameof(Graph)); + + public Models.CommitGraph Graph + { + get => GetValue(GraphProperty); + set => SetValue(GraphProperty, value); + } + + public static readonly StyledProperty DotBrushProperty = + AvaloniaProperty.Register(nameof(DotBrush), Brushes.Transparent); + + public IBrush DotBrush + { + get => GetValue(DotBrushProperty); + set => SetValue(DotBrushProperty, value); + } + + public static readonly StyledProperty OnlyHighlightCurrentBranchProperty = + AvaloniaProperty.Register(nameof(OnlyHighlightCurrentBranch), true); + + public bool OnlyHighlightCurrentBranch + { + get => GetValue(OnlyHighlightCurrentBranchProperty); + set => SetValue(OnlyHighlightCurrentBranchProperty, value); + } + + static CommitGraph() + { + AffectsRender(GraphProperty, DotBrushProperty, OnlyHighlightCurrentBranchProperty); + } + + public override void Render(DrawingContext context) + { + base.Render(context); + + var graph = Graph; + if (graph == null) + return; + + var histories = this.FindAncestorOfType(); + if (histories == null) + return; + + var list = histories.CommitListContainer; + if (list == null) + return; + + // Calculate drawing area. + double width = Bounds.Width - 273 - histories.AuthorNameColumnWidth.Value; + double height = Bounds.Height; + double startY = list.Scroll?.Offset.Y ?? 0; + double endY = startY + height + 28; + + // Apply scroll offset and clip. + using (context.PushClip(new Rect(0, 0, width, height))) + using (context.PushTransform(Matrix.CreateTranslation(0, -startY))) + { + // Draw contents + DrawCurves(context, graph, startY, endY); + DrawAnchors(context, graph, startY, endY); + } + } + + private void DrawCurves(DrawingContext context, Models.CommitGraph graph, double top, double bottom) + { + var grayedPen = new Pen(new SolidColorBrush(Colors.Gray, 0.4), Models.CommitGraph.Pens[0].Thickness); + var onlyHighlightCurrentBranch = OnlyHighlightCurrentBranch; + + if (onlyHighlightCurrentBranch) + { + foreach (var link in graph.Links) + { + if (link.IsMerged) + continue; + if (link.End.Y < top) + continue; + if (link.Start.Y > bottom) + break; + + var geo = new StreamGeometry(); + using (var ctx = geo.Open()) + { + ctx.BeginFigure(link.Start, false); + ctx.QuadraticBezierTo(link.Control, link.End); + } + + context.DrawGeometry(null, grayedPen, geo); + } + } + + foreach (var line in graph.Paths) + { + var last = line.Points[0]; + var size = line.Points.Count; + + if (line.Points[size - 1].Y < top) + continue; + if (last.Y > bottom) + break; + + var geo = new StreamGeometry(); + var pen = Models.CommitGraph.Pens[line.Color]; + + using (var ctx = geo.Open()) + { + var started = false; + var ended = false; + for (int i = 1; i < size; i++) + { + var cur = line.Points[i]; + if (cur.Y < top) + { + last = cur; + continue; + } + + if (!started) + { + ctx.BeginFigure(last, false); + started = true; + } + + if (cur.Y > bottom) + { + cur = new Point(cur.X, bottom); + ended = true; + } + + if (cur.X > last.X) + { + ctx.QuadraticBezierTo(new Point(cur.X, last.Y), cur); + } + else if (cur.X < last.X) + { + if (i < size - 1) + { + var midY = (last.Y + cur.Y) / 2; + ctx.CubicBezierTo(new Point(last.X, midY + 4), new Point(cur.X, midY - 4), cur); + } + else + { + ctx.QuadraticBezierTo(new Point(last.X, cur.Y), cur); + } + } + else + { + ctx.LineTo(cur); + } + + if (ended) + break; + last = cur; + } + } + + if (!line.IsMerged && onlyHighlightCurrentBranch) + context.DrawGeometry(null, grayedPen, geo); + else + context.DrawGeometry(null, pen, geo); + } + + foreach (var link in graph.Links) + { + if (onlyHighlightCurrentBranch && !link.IsMerged) + continue; + if (link.End.Y < top) + continue; + if (link.Start.Y > bottom) + break; + + var geo = new StreamGeometry(); + using (var ctx = geo.Open()) + { + ctx.BeginFigure(link.Start, false); + ctx.QuadraticBezierTo(link.Control, link.End); + } + + context.DrawGeometry(null, Models.CommitGraph.Pens[link.Color], geo); + } + } + + private void DrawAnchors(DrawingContext context, Models.CommitGraph graph, double top, double bottom) + { + var dotFill = DotBrush; + var dotFillPen = new Pen(dotFill, 2); + var grayedPen = new Pen(Brushes.Gray, Models.CommitGraph.Pens[0].Thickness); + var onlyHighlightCurrentBranch = OnlyHighlightCurrentBranch; + + foreach (var dot in graph.Dots) + { + if (dot.Center.Y < top) + continue; + if (dot.Center.Y > bottom) + break; + + var pen = Models.CommitGraph.Pens[dot.Color]; + if (!dot.IsMerged && onlyHighlightCurrentBranch) + pen = grayedPen; + + switch (dot.Type) + { + case Models.CommitGraph.DotType.Head: + context.DrawEllipse(dotFill, pen, dot.Center, 6, 6); + context.DrawEllipse(pen.Brush, null, dot.Center, 3, 3); + break; + case Models.CommitGraph.DotType.Merge: + context.DrawEllipse(pen.Brush, null, dot.Center, 6, 6); + context.DrawLine(dotFillPen, new Point(dot.Center.X, dot.Center.Y - 3), new Point(dot.Center.X, dot.Center.Y + 3)); + context.DrawLine(dotFillPen, new Point(dot.Center.X - 3, dot.Center.Y), new Point(dot.Center.X + 3, dot.Center.Y)); + break; + default: + context.DrawEllipse(dotFill, pen, dot.Center, 3, 3); + break; + } + } + } + } +} diff --git a/src/Views/CommitStatusIndicator.cs b/src/Views/CommitStatusIndicator.cs new file mode 100644 index 00000000..c2f4184e --- /dev/null +++ b/src/Views/CommitStatusIndicator.cs @@ -0,0 +1,90 @@ +using System; + +using Avalonia; +using Avalonia.Controls; +using Avalonia.Media; + +namespace SourceGit.Views +{ + public class CommitStatusIndicator : Control + { + public static readonly StyledProperty CurrentBranchProperty = + AvaloniaProperty.Register(nameof(CurrentBranch)); + + public Models.Branch CurrentBranch + { + get => GetValue(CurrentBranchProperty); + set => SetValue(CurrentBranchProperty, value); + } + + public static readonly StyledProperty AheadBrushProperty = + AvaloniaProperty.Register(nameof(AheadBrush)); + + public IBrush AheadBrush + { + get => GetValue(AheadBrushProperty); + set => SetValue(AheadBrushProperty, value); + } + + public static readonly StyledProperty BehindBrushProperty = + AvaloniaProperty.Register(nameof(BehindBrush)); + + public IBrush BehindBrush + { + get => GetValue(BehindBrushProperty); + set => SetValue(BehindBrushProperty, value); + } + + enum Status + { + Normal, + Ahead, + Behind, + } + + public override void Render(DrawingContext context) + { + if (_status == Status.Normal) + return; + + context.DrawEllipse(_status == Status.Ahead ? AheadBrush : BehindBrush, null, new Rect(0, 0, 5, 5)); + } + + protected override Size MeasureOverride(Size availableSize) + { + if (DataContext is Models.Commit commit && CurrentBranch is not null) + { + var sha = commit.SHA; + var track = CurrentBranch.TrackStatus; + + if (track.Ahead.Contains(sha)) + _status = Status.Ahead; + else if (track.Behind.Contains(sha)) + _status = Status.Behind; + else + _status = Status.Normal; + } + else + { + _status = Status.Normal; + } + + return _status == Status.Normal ? new Size(0, 0) : new Size(9, 5); + } + + protected override void OnDataContextChanged(EventArgs e) + { + base.OnDataContextChanged(e); + InvalidateMeasure(); + } + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + if (change.Property == CurrentBranchProperty) + InvalidateMeasure(); + } + + private Status _status = Status.Normal; + } +} diff --git a/src/Views/CommitSubjectPresenter.cs b/src/Views/CommitSubjectPresenter.cs new file mode 100644 index 00000000..32f6838d --- /dev/null +++ b/src/Views/CommitSubjectPresenter.cs @@ -0,0 +1,189 @@ +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using Avalonia; +using Avalonia.Collections; +using Avalonia.Controls; +using Avalonia.Controls.Documents; +using Avalonia.Input; +using Avalonia.Media; +using Avalonia.Media.TextFormatting; + +namespace SourceGit.Views +{ + public partial class CommitSubjectPresenter : TextBlock + { + public static readonly StyledProperty SubjectProperty = + AvaloniaProperty.Register(nameof(Subject)); + + public string Subject + { + get => GetValue(SubjectProperty); + set => SetValue(SubjectProperty, value); + } + + public static readonly StyledProperty> IssueTrackerRulesProperty = + AvaloniaProperty.Register>(nameof(IssueTrackerRules)); + + public AvaloniaList IssueTrackerRules + { + get => GetValue(IssueTrackerRulesProperty); + set => SetValue(IssueTrackerRulesProperty, value); + } + + protected override Type StyleKeyOverride => typeof(TextBlock); + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + + if (change.Property == SubjectProperty || change.Property == IssueTrackerRulesProperty) + { + Inlines!.Clear(); + _matches = null; + ClearHoveredIssueLink(); + + var subject = Subject; + if (string.IsNullOrEmpty(subject)) + return; + + var keywordMatch = REG_KEYWORD_FORMAT1().Match(subject); + if (!keywordMatch.Success) + keywordMatch = REG_KEYWORD_FORMAT2().Match(subject); + + var rules = IssueTrackerRules ?? []; + var matches = new List(); + foreach (var rule in rules) + rule.Matches(matches, subject); + + if (matches.Count == 0) + { + if (keywordMatch.Success) + { + Inlines.Add(new Run(subject.Substring(0, keywordMatch.Length)) { FontWeight = FontWeight.Bold }); + Inlines.Add(new Run(subject.Substring(keywordMatch.Length))); + } + else + { + Inlines.Add(new Run(subject)); + } + return; + } + + matches.Sort((l, r) => l.Start - r.Start); + _matches = matches; + + var inlines = new List(); + var pos = 0; + foreach (var match in matches) + { + if (match.Start > pos) + { + if (keywordMatch.Success && pos < keywordMatch.Length) + { + if (keywordMatch.Length < match.Start) + { + inlines.Add(new Run(subject.Substring(pos, keywordMatch.Length - pos)) { FontWeight = FontWeight.Bold }); + inlines.Add(new Run(subject.Substring(keywordMatch.Length, match.Start - keywordMatch.Length))); + } + else + { + inlines.Add(new Run(subject.Substring(pos, match.Start - pos)) { FontWeight = FontWeight.Bold }); + } + } + else + { + inlines.Add(new Run(subject.Substring(pos, match.Start - pos))); + } + } + + var link = new Run(subject.Substring(match.Start, match.Length)); + link.Classes.Add("issue_link"); + inlines.Add(link); + + pos = match.Start + match.Length; + } + + if (pos < subject.Length) + { + if (keywordMatch.Success && pos < keywordMatch.Length) + { + inlines.Add(new Run(subject.Substring(pos, keywordMatch.Length - pos)) { FontWeight = FontWeight.Bold }); + inlines.Add(new Run(subject.Substring(keywordMatch.Length))); + } + else + { + inlines.Add(new Run(subject.Substring(pos))); + } + } + + Inlines.AddRange(inlines); + } + } + + protected override void OnPointerMoved(PointerEventArgs e) + { + base.OnPointerMoved(e); + + if (_matches != null) + { + var point = e.GetPosition(this) - new Point(Padding.Left, Padding.Top); + var x = Math.Min(Math.Max(point.X, 0), Math.Max(TextLayout.WidthIncludingTrailingWhitespace, 0)); + var y = Math.Min(Math.Max(point.Y, 0), Math.Max(TextLayout.Height, 0)); + point = new Point(x, y); + + var textPosition = TextLayout.HitTestPoint(point).TextPosition; + foreach (var match in _matches) + { + if (!match.Intersect(textPosition, 1)) + continue; + + if (match == _lastHover) + return; + + _lastHover = match; + SetCurrentValue(CursorProperty, Cursor.Parse("Hand")); + ToolTip.SetTip(this, match.Link); + ToolTip.SetIsOpen(this, true); + e.Handled = true; + return; + } + + ClearHoveredIssueLink(); + } + } + + protected override void OnPointerPressed(PointerPressedEventArgs e) + { + base.OnPointerPressed(e); + + if (_lastHover != null) + Native.OS.OpenBrowser(_lastHover.Link); + } + + protected override void OnPointerExited(PointerEventArgs e) + { + base.OnPointerExited(e); + ClearHoveredIssueLink(); + } + + private void ClearHoveredIssueLink() + { + if (_lastHover != null) + { + ToolTip.SetTip(this, null); + SetCurrentValue(CursorProperty, Cursor.Parse("Arrow")); + _lastHover = null; + } + } + + [GeneratedRegex(@"^\[[\w\s]+\]")] + private static partial Regex REG_KEYWORD_FORMAT1(); + + [GeneratedRegex(@"^\S+([\<\(][\w\s_\-\*,]+[\>\)])?\!?\s?:\s")] + private static partial Regex REG_KEYWORD_FORMAT2(); + + private List _matches = null; + private Models.Hyperlink _lastHover = null; + } +} diff --git a/src/Views/CommitTimeTextBlock.cs b/src/Views/CommitTimeTextBlock.cs new file mode 100644 index 00000000..6947f7f2 --- /dev/null +++ b/src/Views/CommitTimeTextBlock.cs @@ -0,0 +1,163 @@ +using System; + +using Avalonia; +using Avalonia.Controls; +using Avalonia.Interactivity; +using Avalonia.Threading; + +namespace SourceGit.Views +{ + public class CommitTimeTextBlock : TextBlock + { + public static readonly StyledProperty ShowAsDateTimeProperty = + AvaloniaProperty.Register(nameof(ShowAsDateTime), true); + + public bool ShowAsDateTime + { + get => GetValue(ShowAsDateTimeProperty); + set => SetValue(ShowAsDateTimeProperty, value); + } + + public static readonly StyledProperty DateTimeFormatProperty = + AvaloniaProperty.Register(nameof(DateTimeFormat), 0); + + public int DateTimeFormat + { + get => GetValue(DateTimeFormatProperty); + set => SetValue(DateTimeFormatProperty, value); + } + + public static readonly StyledProperty UseAuthorTimeProperty = + AvaloniaProperty.Register(nameof(UseAuthorTime), true); + + public bool UseAuthorTime + { + get => GetValue(UseAuthorTimeProperty); + set => SetValue(UseAuthorTimeProperty, value); + } + + protected override Type StyleKeyOverride => typeof(TextBlock); + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + + if (change.Property == UseAuthorTimeProperty) + { + SetCurrentValue(TextProperty, GetDisplayText()); + } + else if (change.Property == ShowAsDateTimeProperty) + { + SetCurrentValue(TextProperty, GetDisplayText()); + + if (ShowAsDateTime) + StopTimer(); + else + StartTimer(); + } + else if (change.Property == DateTimeFormatProperty) + { + if (ShowAsDateTime) + SetCurrentValue(TextProperty, GetDisplayText()); + } + } + + protected override void OnLoaded(RoutedEventArgs e) + { + base.OnLoaded(e); + + if (!ShowAsDateTime) + StartTimer(); + } + + protected override void OnUnloaded(RoutedEventArgs e) + { + base.OnUnloaded(e); + StopTimer(); + } + + protected override void OnDataContextChanged(EventArgs e) + { + base.OnDataContextChanged(e); + SetCurrentValue(TextProperty, GetDisplayText()); + } + + private void StartTimer() + { + if (_refreshTimer != null) + return; + + _refreshTimer = DispatcherTimer.Run(() => + { + Dispatcher.UIThread.Invoke(() => + { + var text = GetDisplayText(); + if (!text.Equals(Text, StringComparison.Ordinal)) + Text = text; + }); + + return true; + }, TimeSpan.FromSeconds(10)); + } + + private void StopTimer() + { + if (_refreshTimer != null) + { + _refreshTimer.Dispose(); + _refreshTimer = null; + } + } + + private string GetDisplayText() + { + var commit = DataContext as Models.Commit; + if (commit == null) + return string.Empty; + + if (ShowAsDateTime) + return UseAuthorTime ? commit.AuthorTimeStr : commit.CommitterTimeStr; + + var timestamp = UseAuthorTime ? commit.AuthorTime : commit.CommitterTime; + var now = DateTime.Now; + var localTime = DateTime.UnixEpoch.AddSeconds(timestamp).ToLocalTime(); + var span = now - localTime; + if (span.TotalMinutes < 1) + return App.Text("Period.JustNow"); + + if (span.TotalHours < 1) + return App.Text("Period.MinutesAgo", (int)span.TotalMinutes); + + if (span.TotalDays < 1) + return App.Text("Period.HoursAgo", (int)span.TotalHours); + + var lastDay = now.AddDays(-1).Date; + if (localTime >= lastDay) + return App.Text("Period.Yesterday"); + + if ((localTime.Year == now.Year && localTime.Month == now.Month) || span.TotalDays < 28) + { + var diffDay = now.Date - localTime.Date; + return App.Text("Period.DaysAgo", (int)diffDay.TotalDays); + } + + var lastMonth = now.AddMonths(-1).Date; + if (localTime.Year == lastMonth.Year && localTime.Month == lastMonth.Month) + return App.Text("Period.LastMonth"); + + if (localTime.Year == now.Year || localTime > now.AddMonths(-11)) + { + var diffMonth = (12 + now.Month - localTime.Month) % 12; + return App.Text("Period.MonthsAgo", diffMonth); + } + + var diffYear = now.Year - localTime.Year; + if (diffYear == 1) + return App.Text("Period.LastYear"); + + return App.Text("Period.YearsAgo", diffYear); + } + + private IDisposable _refreshTimer = null; + } +} diff --git a/src/Views/Histories.axaml b/src/Views/Histories.axaml index 40b2636f..583e17c1 100644 --- a/src/Views/Histories.axaml +++ b/src/Views/Histories.axaml @@ -10,18 +10,18 @@ x:Class="SourceGit.Views.Histories" x:DataType="vm:Histories" x:Name="ThisControl"> - - + + - + - + - + @@ -264,5 +264,5 @@ - + diff --git a/src/Views/Histories.axaml.cs b/src/Views/Histories.axaml.cs index 8b5142ad..62c283e5 100644 --- a/src/Views/Histories.axaml.cs +++ b/src/Views/Histories.axaml.cs @@ -1,24 +1,18 @@ using System; -using System.Collections.Generic; using System.Text; -using System.Text.RegularExpressions; using Avalonia; using Avalonia.Collections; using Avalonia.Controls; -using Avalonia.Controls.Documents; using Avalonia.Input; -using Avalonia.Interactivity; -using Avalonia.Media; -using Avalonia.Threading; using Avalonia.VisualTree; namespace SourceGit.Views { - public class LayoutableGrid : Grid + public class HistoriesLayout : Grid { public static readonly StyledProperty UseHorizontalProperty = - AvaloniaProperty.Register(nameof(UseHorizontal)); + AvaloniaProperty.Register(nameof(UseHorizontal)); public bool UseHorizontal { @@ -28,17 +22,20 @@ namespace SourceGit.Views protected override Type StyleKeyOverride => typeof(Grid); - static LayoutableGrid() - { - UseHorizontalProperty.Changed.AddClassHandler((o, _) => o.RefreshLayout()); - } - public override void ApplyTemplate() { base.ApplyTemplate(); RefreshLayout(); } + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + + if (change.Property == UseHorizontalProperty) + RefreshLayout(); + } + private void RefreshLayout() { if (UseHorizontal) @@ -74,639 +71,6 @@ namespace SourceGit.Views } } - public class CommitStatusIndicator : Control - { - public static readonly StyledProperty CurrentBranchProperty = - AvaloniaProperty.Register(nameof(CurrentBranch)); - - public Models.Branch CurrentBranch - { - get => GetValue(CurrentBranchProperty); - set => SetValue(CurrentBranchProperty, value); - } - - public static readonly StyledProperty AheadBrushProperty = - AvaloniaProperty.Register(nameof(AheadBrush)); - - public IBrush AheadBrush - { - get => GetValue(AheadBrushProperty); - set => SetValue(AheadBrushProperty, value); - } - - public static readonly StyledProperty BehindBrushProperty = - AvaloniaProperty.Register(nameof(BehindBrush)); - - public IBrush BehindBrush - { - get => GetValue(BehindBrushProperty); - set => SetValue(BehindBrushProperty, value); - } - - enum Status - { - Normal, - Ahead, - Behind, - } - - public override void Render(DrawingContext context) - { - if (_status == Status.Normal) - return; - - context.DrawEllipse(_status == Status.Ahead ? AheadBrush : BehindBrush, null, new Rect(0, 0, 5, 5)); - } - - protected override Size MeasureOverride(Size availableSize) - { - if (DataContext is Models.Commit commit && CurrentBranch is not null) - { - var sha = commit.SHA; - var track = CurrentBranch.TrackStatus; - - if (track.Ahead.Contains(sha)) - _status = Status.Ahead; - else if (track.Behind.Contains(sha)) - _status = Status.Behind; - else - _status = Status.Normal; - } - else - { - _status = Status.Normal; - } - - return _status == Status.Normal ? new Size(0, 0) : new Size(9, 5); - } - - protected override void OnDataContextChanged(EventArgs e) - { - base.OnDataContextChanged(e); - InvalidateMeasure(); - } - - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) - { - base.OnPropertyChanged(change); - if (change.Property == CurrentBranchProperty) - InvalidateMeasure(); - } - - private Status _status = Status.Normal; - } - - public partial class CommitSubjectPresenter : TextBlock - { - public static readonly StyledProperty SubjectProperty = - AvaloniaProperty.Register(nameof(Subject)); - - public string Subject - { - get => GetValue(SubjectProperty); - set => SetValue(SubjectProperty, value); - } - - public static readonly StyledProperty> IssueTrackerRulesProperty = - AvaloniaProperty.Register>(nameof(IssueTrackerRules)); - - public AvaloniaList IssueTrackerRules - { - get => GetValue(IssueTrackerRulesProperty); - set => SetValue(IssueTrackerRulesProperty, value); - } - - protected override Type StyleKeyOverride => typeof(TextBlock); - - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) - { - base.OnPropertyChanged(change); - - if (change.Property == SubjectProperty || change.Property == IssueTrackerRulesProperty) - { - Inlines!.Clear(); - _matches = null; - ClearHoveredIssueLink(); - - var subject = Subject; - if (string.IsNullOrEmpty(subject)) - return; - - var keywordMatch = REG_KEYWORD_FORMAT1().Match(subject); - if (!keywordMatch.Success) - keywordMatch = REG_KEYWORD_FORMAT2().Match(subject); - - var rules = IssueTrackerRules ?? []; - var matches = new List(); - foreach (var rule in rules) - rule.Matches(matches, subject); - - if (matches.Count == 0) - { - if (keywordMatch.Success) - { - Inlines.Add(new Run(subject.Substring(0, keywordMatch.Length)) { FontWeight = FontWeight.Bold }); - Inlines.Add(new Run(subject.Substring(keywordMatch.Length))); - } - else - { - Inlines.Add(new Run(subject)); - } - return; - } - - matches.Sort((l, r) => l.Start - r.Start); - _matches = matches; - - var inlines = new List(); - var pos = 0; - foreach (var match in matches) - { - if (match.Start > pos) - { - if (keywordMatch.Success && pos < keywordMatch.Length) - { - if (keywordMatch.Length < match.Start) - { - inlines.Add(new Run(subject.Substring(pos, keywordMatch.Length - pos)) { FontWeight = FontWeight.Bold }); - inlines.Add(new Run(subject.Substring(keywordMatch.Length, match.Start - keywordMatch.Length))); - } - else - { - inlines.Add(new Run(subject.Substring(pos, match.Start - pos)) { FontWeight = FontWeight.Bold }); - } - } - else - { - inlines.Add(new Run(subject.Substring(pos, match.Start - pos))); - } - } - - var link = new Run(subject.Substring(match.Start, match.Length)); - link.Classes.Add("issue_link"); - inlines.Add(link); - - pos = match.Start + match.Length; - } - - if (pos < subject.Length) - { - if (keywordMatch.Success && pos < keywordMatch.Length) - { - inlines.Add(new Run(subject.Substring(pos, keywordMatch.Length - pos)) { FontWeight = FontWeight.Bold }); - inlines.Add(new Run(subject.Substring(keywordMatch.Length))); - } - else - { - inlines.Add(new Run(subject.Substring(pos))); - } - } - - Inlines.AddRange(inlines); - } - } - - protected override void OnPointerMoved(PointerEventArgs e) - { - base.OnPointerMoved(e); - - if (_matches != null) - { - var point = e.GetPosition(this) - new Point(Padding.Left, Padding.Top); - var x = Math.Min(Math.Max(point.X, 0), Math.Max(TextLayout.WidthIncludingTrailingWhitespace, 0)); - var y = Math.Min(Math.Max(point.Y, 0), Math.Max(TextLayout.Height, 0)); - point = new Point(x, y); - - var textPosition = TextLayout.HitTestPoint(point).TextPosition; - foreach (var match in _matches) - { - if (!match.Intersect(textPosition, 1)) - continue; - - if (match == _lastHover) - return; - - _lastHover = match; - SetCurrentValue(CursorProperty, Cursor.Parse("Hand")); - ToolTip.SetTip(this, match.Link); - ToolTip.SetIsOpen(this, true); - e.Handled = true; - return; - } - - ClearHoveredIssueLink(); - } - } - - protected override void OnPointerPressed(PointerPressedEventArgs e) - { - base.OnPointerPressed(e); - - if (_lastHover != null) - Native.OS.OpenBrowser(_lastHover.Link); - } - - protected override void OnPointerExited(PointerEventArgs e) - { - base.OnPointerExited(e); - ClearHoveredIssueLink(); - } - - private void ClearHoveredIssueLink() - { - if (_lastHover != null) - { - ToolTip.SetTip(this, null); - SetCurrentValue(CursorProperty, Cursor.Parse("Arrow")); - _lastHover = null; - } - } - - [GeneratedRegex(@"^\[[\w\s]+\]")] - private static partial Regex REG_KEYWORD_FORMAT1(); - - [GeneratedRegex(@"^\S+([\<\(][\w\s_\-\*,]+[\>\)])?\!?\s?:\s")] - private static partial Regex REG_KEYWORD_FORMAT2(); - - private List _matches = null; - private Models.Hyperlink _lastHover = null; - } - - public class CommitTimeTextBlock : TextBlock - { - public static readonly StyledProperty ShowAsDateTimeProperty = - AvaloniaProperty.Register(nameof(ShowAsDateTime), true); - - public bool ShowAsDateTime - { - get => GetValue(ShowAsDateTimeProperty); - set => SetValue(ShowAsDateTimeProperty, value); - } - - public static readonly StyledProperty DateTimeFormatProperty = - AvaloniaProperty.Register(nameof(DateTimeFormat), 0); - - public int DateTimeFormat - { - get => GetValue(DateTimeFormatProperty); - set => SetValue(DateTimeFormatProperty, value); - } - - public static readonly StyledProperty UseAuthorTimeProperty = - AvaloniaProperty.Register(nameof(UseAuthorTime), true); - - public bool UseAuthorTime - { - get => GetValue(UseAuthorTimeProperty); - set => SetValue(UseAuthorTimeProperty, value); - } - - protected override Type StyleKeyOverride => typeof(TextBlock); - - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) - { - base.OnPropertyChanged(change); - - if (change.Property == UseAuthorTimeProperty) - { - SetCurrentValue(TextProperty, GetDisplayText()); - } - else if (change.Property == ShowAsDateTimeProperty) - { - SetCurrentValue(TextProperty, GetDisplayText()); - - if (ShowAsDateTime) - StopTimer(); - else - StartTimer(); - } - else if (change.Property == DateTimeFormatProperty) - { - if (ShowAsDateTime) - SetCurrentValue(TextProperty, GetDisplayText()); - } - } - - protected override void OnLoaded(RoutedEventArgs e) - { - base.OnLoaded(e); - - if (!ShowAsDateTime) - StartTimer(); - } - - protected override void OnUnloaded(RoutedEventArgs e) - { - base.OnUnloaded(e); - StopTimer(); - } - - protected override void OnDataContextChanged(EventArgs e) - { - base.OnDataContextChanged(e); - SetCurrentValue(TextProperty, GetDisplayText()); - } - - private void StartTimer() - { - if (_refreshTimer != null) - return; - - _refreshTimer = DispatcherTimer.Run(() => - { - Dispatcher.UIThread.Invoke(() => - { - var text = GetDisplayText(); - if (!text.Equals(Text, StringComparison.Ordinal)) - Text = text; - }); - - return true; - }, TimeSpan.FromSeconds(10)); - } - - private void StopTimer() - { - if (_refreshTimer != null) - { - _refreshTimer.Dispose(); - _refreshTimer = null; - } - } - - private string GetDisplayText() - { - var commit = DataContext as Models.Commit; - if (commit == null) - return string.Empty; - - if (ShowAsDateTime) - return UseAuthorTime ? commit.AuthorTimeStr : commit.CommitterTimeStr; - - var timestamp = UseAuthorTime ? commit.AuthorTime : commit.CommitterTime; - var now = DateTime.Now; - var localTime = DateTime.UnixEpoch.AddSeconds(timestamp).ToLocalTime(); - var span = now - localTime; - if (span.TotalMinutes < 1) - return App.Text("Period.JustNow"); - - if (span.TotalHours < 1) - return App.Text("Period.MinutesAgo", (int)span.TotalMinutes); - - if (span.TotalDays < 1) - return App.Text("Period.HoursAgo", (int)span.TotalHours); - - var lastDay = now.AddDays(-1).Date; - if (localTime >= lastDay) - return App.Text("Period.Yesterday"); - - if ((localTime.Year == now.Year && localTime.Month == now.Month) || span.TotalDays < 28) - { - var diffDay = now.Date - localTime.Date; - return App.Text("Period.DaysAgo", (int)diffDay.TotalDays); - } - - var lastMonth = now.AddMonths(-1).Date; - if (localTime.Year == lastMonth.Year && localTime.Month == lastMonth.Month) - return App.Text("Period.LastMonth"); - - if (localTime.Year == now.Year || localTime > now.AddMonths(-11)) - { - var diffMonth = (12 + now.Month - localTime.Month) % 12; - return App.Text("Period.MonthsAgo", diffMonth); - } - - var diffYear = now.Year - localTime.Year; - if (diffYear == 1) - return App.Text("Period.LastYear"); - - return App.Text("Period.YearsAgo", diffYear); - } - - private IDisposable _refreshTimer = null; - } - - public class CommitGraph : Control - { - public static readonly StyledProperty GraphProperty = - AvaloniaProperty.Register(nameof(Graph)); - - public Models.CommitGraph Graph - { - get => GetValue(GraphProperty); - set => SetValue(GraphProperty, value); - } - - public static readonly StyledProperty DotBrushProperty = - AvaloniaProperty.Register(nameof(DotBrush), Brushes.Transparent); - - public IBrush DotBrush - { - get => GetValue(DotBrushProperty); - set => SetValue(DotBrushProperty, value); - } - - public static readonly StyledProperty OnlyHighlightCurrentBranchProperty = - AvaloniaProperty.Register(nameof(OnlyHighlightCurrentBranch), true); - - public bool OnlyHighlightCurrentBranch - { - get => GetValue(OnlyHighlightCurrentBranchProperty); - set => SetValue(OnlyHighlightCurrentBranchProperty, value); - } - - static CommitGraph() - { - AffectsRender(GraphProperty, DotBrushProperty, OnlyHighlightCurrentBranchProperty); - } - - public override void Render(DrawingContext context) - { - base.Render(context); - - var graph = Graph; - if (graph == null) - return; - - var histories = this.FindAncestorOfType(); - if (histories == null) - return; - - var list = histories.CommitListContainer; - if (list == null) - return; - - // Calculate drawing area. - double width = Bounds.Width - 273 - histories.AuthorNameColumnWidth.Value; - double height = Bounds.Height; - double startY = list.Scroll?.Offset.Y ?? 0; - double endY = startY + height + 28; - - // Apply scroll offset and clip. - using (context.PushClip(new Rect(0, 0, width, height))) - using (context.PushTransform(Matrix.CreateTranslation(0, -startY))) - { - // Draw contents - DrawCurves(context, graph, startY, endY); - DrawAnchors(context, graph, startY, endY); - } - } - - private void DrawCurves(DrawingContext context, Models.CommitGraph graph, double top, double bottom) - { - var grayedPen = new Pen(new SolidColorBrush(Colors.Gray, 0.4), Models.CommitGraph.Pens[0].Thickness); - var onlyHighlightCurrentBranch = OnlyHighlightCurrentBranch; - - if (onlyHighlightCurrentBranch) - { - foreach (var link in graph.Links) - { - if (link.IsMerged) - continue; - if (link.End.Y < top) - continue; - if (link.Start.Y > bottom) - break; - - var geo = new StreamGeometry(); - using (var ctx = geo.Open()) - { - ctx.BeginFigure(link.Start, false); - ctx.QuadraticBezierTo(link.Control, link.End); - } - - context.DrawGeometry(null, grayedPen, geo); - } - } - - foreach (var line in graph.Paths) - { - var last = line.Points[0]; - var size = line.Points.Count; - - if (line.Points[size - 1].Y < top) - continue; - if (last.Y > bottom) - break; - - var geo = new StreamGeometry(); - var pen = Models.CommitGraph.Pens[line.Color]; - - using (var ctx = geo.Open()) - { - var started = false; - var ended = false; - for (int i = 1; i < size; i++) - { - var cur = line.Points[i]; - if (cur.Y < top) - { - last = cur; - continue; - } - - if (!started) - { - ctx.BeginFigure(last, false); - started = true; - } - - if (cur.Y > bottom) - { - cur = new Point(cur.X, bottom); - ended = true; - } - - if (cur.X > last.X) - { - ctx.QuadraticBezierTo(new Point(cur.X, last.Y), cur); - } - else if (cur.X < last.X) - { - if (i < size - 1) - { - var midY = (last.Y + cur.Y) / 2; - ctx.CubicBezierTo(new Point(last.X, midY + 4), new Point(cur.X, midY - 4), cur); - } - else - { - ctx.QuadraticBezierTo(new Point(last.X, cur.Y), cur); - } - } - else - { - ctx.LineTo(cur); - } - - if (ended) - break; - last = cur; - } - } - - if (!line.IsMerged && onlyHighlightCurrentBranch) - context.DrawGeometry(null, grayedPen, geo); - else - context.DrawGeometry(null, pen, geo); - } - - foreach (var link in graph.Links) - { - if (onlyHighlightCurrentBranch && !link.IsMerged) - continue; - if (link.End.Y < top) - continue; - if (link.Start.Y > bottom) - break; - - var geo = new StreamGeometry(); - using (var ctx = geo.Open()) - { - ctx.BeginFigure(link.Start, false); - ctx.QuadraticBezierTo(link.Control, link.End); - } - - context.DrawGeometry(null, Models.CommitGraph.Pens[link.Color], geo); - } - } - - private void DrawAnchors(DrawingContext context, Models.CommitGraph graph, double top, double bottom) - { - var dotFill = DotBrush; - var dotFillPen = new Pen(dotFill, 2); - var grayedPen = new Pen(Brushes.Gray, Models.CommitGraph.Pens[0].Thickness); - var onlyHighlightCurrentBranch = OnlyHighlightCurrentBranch; - - foreach (var dot in graph.Dots) - { - if (dot.Center.Y < top) - continue; - if (dot.Center.Y > bottom) - break; - - var pen = Models.CommitGraph.Pens[dot.Color]; - if (!dot.IsMerged && onlyHighlightCurrentBranch) - pen = grayedPen; - - switch (dot.Type) - { - case Models.CommitGraph.DotType.Head: - context.DrawEllipse(dotFill, pen, dot.Center, 6, 6); - context.DrawEllipse(pen.Brush, null, dot.Center, 3, 3); - break; - case Models.CommitGraph.DotType.Merge: - context.DrawEllipse(pen.Brush, null, dot.Center, 6, 6); - context.DrawLine(dotFillPen, new Point(dot.Center.X, dot.Center.Y - 3), new Point(dot.Center.X, dot.Center.Y + 3)); - context.DrawLine(dotFillPen, new Point(dot.Center.X - 3, dot.Center.Y), new Point(dot.Center.X + 3, dot.Center.Y)); - break; - default: - context.DrawEllipse(dotFill, pen, dot.Center, 3, 3); - break; - } - } - } - } - public partial class Histories : UserControl { public static readonly StyledProperty AuthorNameColumnWidthProperty = @@ -754,36 +118,34 @@ namespace SourceGit.Views set => SetValue(NavigationIdProperty, value); } - static Histories() - { - NavigationIdProperty.Changed.AddClassHandler((h, _) => - { - if (h.DataContext == null) - return; - - // Force scroll selected item (current head) into view. see issue #58 - var list = h.CommitListContainer; - if (list != null && list.SelectedItems.Count == 1) - list.ScrollIntoView(list.SelectedIndex); - }); - - AuthorNameColumnWidthProperty.Changed.AddClassHandler((h, _) => - { - h.CommitGraph.InvalidateVisual(); - }); - } - public Histories() { InitializeComponent(); } + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + + if (change.Property == NavigationIdProperty) + { + if (DataContext is ViewModels.Histories) + { + var list = CommitListContainer; + if (list != null && list.SelectedItems.Count == 1) + list.ScrollIntoView(list.SelectedIndex); + } + } + } + private void OnCommitListLayoutUpdated(object _1, EventArgs _2) { var y = CommitListContainer.Scroll?.Offset.Y ?? 0; - if (y != _lastScrollY) + var authorNameColumnWidth = AuthorNameColumnWidth.Value; + if (y != _lastScrollY || authorNameColumnWidth != _lastAuthorNameColumnWidth) { _lastScrollY = y; + _lastAuthorNameColumnWidth = authorNameColumnWidth; CommitGraph.InvalidateVisual(); } } @@ -863,5 +225,6 @@ namespace SourceGit.Views } private double _lastScrollY = 0; + private double _lastAuthorNameColumnWidth = 0; } } From 77d8afe056963fe23f78b15660948fcbb8bd1c91 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 12 Mar 2025 15:10:43 +0800 Subject: [PATCH 356/441] refactor: reduce the times to call `RefreshLayout` Signed-off-by: leo --- src/Views/Histories.axaml.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Views/Histories.axaml.cs b/src/Views/Histories.axaml.cs index 62c283e5..f7055dfa 100644 --- a/src/Views/Histories.axaml.cs +++ b/src/Views/Histories.axaml.cs @@ -22,9 +22,8 @@ namespace SourceGit.Views protected override Type StyleKeyOverride => typeof(Grid); - public override void ApplyTemplate() + public HistoriesLayout() { - base.ApplyTemplate(); RefreshLayout(); } From eaa322dfabd9b91eb4afe360a68645b874f16ed8 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 12 Mar 2025 17:57:31 +0800 Subject: [PATCH 357/441] enhance: re-design commit search result display (#1083) Signed-off-by: leo --- src/Models/Commit.cs | 1 + src/Views/Repository.axaml | 49 ++++++++++++++++++++++---------------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/Models/Commit.cs b/src/Models/Commit.cs index 72ce54bd..0bad8376 100644 --- a/src/Models/Commit.cs +++ b/src/Models/Commit.cs @@ -36,6 +36,7 @@ namespace SourceGit.Models public string AuthorTimeStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime); public string CommitterTimeStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime); public string AuthorTimeShortStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateOnly); + public string CommitterTimeShortStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateOnly); public bool IsMerged { get; set; } = false; public bool IsCommitterVisible => !Author.Equals(Committer) || AuthorTime != CommitterTime; diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index 1d94e9b2..c8bbde5f 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -482,13 +482,13 @@ Padding="4,0" Background="Transparent" BorderThickness="0" - SelectedIndex="{Binding SearchCommitFilterType, Mode=TwoWay}"> + SelectedIndex="{Binding SearchCommitFilterType, Mode=TwoWay}"> - - - - - + + + + + @@ -496,12 +496,13 @@ Margin="4,0,0,0" IsChecked="{Binding OnlySearchCommitsInCurrentBranch, Mode=TwoWay}" IsVisible="{Binding SearchCommitFilterType, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"> - +
+ ScrollViewer.VerticalScrollBarVisibility="Auto" + Grid.IsSharedSizeScope="True"> @@ -527,18 +530,22 @@ - - - - - - - - - - - - + + + + + + + + + + From e4f5c34e0cbe62345e370e723d47b00aacddc626 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 12 Mar 2025 17:58:57 +0800 Subject: [PATCH 358/441] code_style: remove whitespaces Signed-off-by: leo --- src/Views/Repository.axaml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index c8bbde5f..b16447fa 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -86,7 +86,7 @@ - + - + + VerticalContentAlignment="Center"> - @@ -428,7 +428,7 @@ - + + SelectedIndex="{Binding SearchCommitFilterType, Mode=TwoWay}"> @@ -562,7 +562,7 @@ - + - + @@ -649,7 +649,7 @@ - + From f07832c38553cf35b4f7bc521290cc16507e954d Mon Sep 17 00:00:00 2001 From: Morgan Courbet Date: Wed, 12 Mar 2025 15:37:28 +0100 Subject: [PATCH 359/441] docs: fix typo in README.md (cherry picked from commit 59fd2aaab144aa8313ecbfcb5457457359fa0c4f) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4086a641..399916c9 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ For **Windows** users: ``` > [!NOTE] > `winget` will install this software as a commandline tool. You need run `SourceGit` from console or `Win+R` at the first time. Then you can add it to the taskbar. -* You can install the latest stable by `scoope` with follow commands: +* You can install the latest stable by `scoop` with follow commands: ```shell scoop bucket add extras scoop install sourcegit From 7331167be2ca09e0fc9378934fad18c48062d329 Mon Sep 17 00:00:00 2001 From: Gadfly Date: Thu, 13 Mar 2025 09:38:08 +0800 Subject: [PATCH 360/441] fix: schedule DWM frame extension to next render frame on Windows 10 (#1087) The DwmExtendFrameIntoClientArea call needs to be posted to the next render frame to ensure the window handle is fully initialized and avoid potential race conditions. --- src/Native/Windows.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Native/Windows.cs b/src/Native/Windows.cs index 11b6bd13..eb354f10 100644 --- a/src/Native/Windows.cs +++ b/src/Native/Windows.cs @@ -8,6 +8,7 @@ using System.Text; using Avalonia; using Avalonia.Controls; +using Avalonia.Threading; namespace SourceGit.Native { @@ -214,12 +215,17 @@ namespace SourceGit.Native private void FixWindowFrameOnWin10(Window w) { - var platformHandle = w.TryGetPlatformHandle(); - if (platformHandle == null) - return; + // Schedule the DWM frame extension to run in the next render frame + // to ensure proper timing with the window initialization sequence + Dispatcher.UIThread.InvokeAsync(() => + { + var platformHandle = w.TryGetPlatformHandle(); + if (platformHandle == null) + return; - var margins = new MARGINS { cxLeftWidth = 1, cxRightWidth = 1, cyTopHeight = 1, cyBottomHeight = 1 }; - DwmExtendFrameIntoClientArea(platformHandle.Handle, ref margins); + var margins = new MARGINS { cxLeftWidth = 1, cxRightWidth = 1, cyTopHeight = 1, cyBottomHeight = 1 }; + DwmExtendFrameIntoClientArea(platformHandle.Handle, ref margins); + }, DispatcherPriority.Render); } #region EXTERNAL_EDITOR_FINDER From e430e847ff957e23c9e146197f6ce8690730645e Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 13 Mar 2025 09:49:25 +0800 Subject: [PATCH 361/441] enhance: auto convert spaces with dashes while renaming a branch (#1088) Signed-off-by: leo --- src/ViewModels/RenameBranch.cs | 21 ++++++++++++++++----- src/Views/CreateBranch.axaml | 12 ++---------- src/Views/RenameBranch.axaml | 10 +++++++++- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/ViewModels/RenameBranch.cs b/src/ViewModels/RenameBranch.cs index bd0b4664..0679a5b5 100644 --- a/src/ViewModels/RenameBranch.cs +++ b/src/ViewModels/RenameBranch.cs @@ -12,7 +12,7 @@ namespace SourceGit.ViewModels } [Required(ErrorMessage = "Branch name is required!!!")] - [RegularExpression(@"^[\w\-/\.#]+$", ErrorMessage = "Bad branch name format!")] + [RegularExpression(@"^[\w \-/\.#]+$", ErrorMessage = "Bad branch name format!")] [CustomValidation(typeof(RenameBranch), nameof(ValidateBranchName))] public string Name { @@ -32,9 +32,10 @@ namespace SourceGit.ViewModels { if (ctx.ObjectInstance is RenameBranch rename) { + var fixedName = rename.FixName(name); foreach (var b in rename._repo.Branches) { - if (b.IsLocal && b != rename.Target && b.Name == name) + if (b.IsLocal && b != rename.Target && b.Name == fixedName) { return new ValidationResult("A branch with same name already exists!!!"); } @@ -46,7 +47,8 @@ namespace SourceGit.ViewModels public override Task Sure() { - if (_name == Target.Name) + var fixedName = FixName(_name); + if (fixedName == Target.Name) return null; _repo.SetWatcherEnabled(false); @@ -55,7 +57,7 @@ namespace SourceGit.ViewModels return Task.Run(() => { var oldName = Target.FullName; - var succ = Commands.Branch.Rename(_repo.FullPath, Target.Name, _name); + var succ = Commands.Branch.Rename(_repo.FullPath, Target.Name, fixedName); CallUIThread(() => { if (succ) @@ -65,7 +67,7 @@ namespace SourceGit.ViewModels if (filter.Type == Models.FilterType.LocalBranch && filter.Pattern.Equals(oldName, StringComparison.Ordinal)) { - filter.Pattern = $"refs/heads/{_name}"; + filter.Pattern = $"refs/heads/{fixedName}"; break; } } @@ -78,6 +80,15 @@ namespace SourceGit.ViewModels }); } + private string FixName(string name) + { + if (!name.Contains(' ')) + return name; + + var parts = name.Split(' ', StringSplitOptions.RemoveEmptyEntries); + return string.Join("-", parts); + } + private readonly Repository _repo; private string _name; } diff --git a/src/Views/CreateBranch.axaml b/src/Views/CreateBranch.axaml index ec56ff20..b757bd78 100644 --- a/src/Views/CreateBranch.axaml +++ b/src/Views/CreateBranch.axaml @@ -14,15 +14,7 @@ - - - - - - - - - + - + @@ -11,7 +12,7 @@ - + + + + + + From 0e261cffd20a39847f4a6377715eecb7a8c307aa Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 13 Mar 2025 10:21:54 +0800 Subject: [PATCH 362/441] refactor: rewrite the way to deal with uncommitted local changes when checkout/pull/create branch (#1085) Signed-off-by: leo --- src/Models/DealWithLocalChanges.cs | 9 ------ src/Resources/Locales/de_DE.axaml | 3 -- src/Resources/Locales/en_US.axaml | 3 -- src/Resources/Locales/es_ES.axaml | 3 -- src/Resources/Locales/fr_FR.axaml | 3 -- src/Resources/Locales/it_IT.axaml | 3 -- src/Resources/Locales/pt_BR.axaml | 3 -- src/Resources/Locales/ru_RU.axaml | 3 -- src/Resources/Locales/zh_CN.axaml | 3 -- src/Resources/Locales/zh_TW.axaml | 3 -- src/ViewModels/Checkout.cs | 17 ++++++----- src/ViewModels/CheckoutCommit.cs | 20 ++++++------- src/ViewModels/CreateBranch.cs | 19 +++++++----- src/ViewModels/Pull.cs | 16 +++++----- src/Views/Checkout.axaml | 22 +++++--------- src/Views/Checkout.axaml.cs | 47 ------------------------------ src/Views/CheckoutCommit.axaml | 12 ++++---- src/Views/CreateBranch.axaml | 18 ++++-------- src/Views/CreateBranch.axaml.cs | 47 ------------------------------ src/Views/Pull.axaml | 22 +++++--------- src/Views/Pull.axaml.cs | 47 ------------------------------ 21 files changed, 63 insertions(+), 260 deletions(-) delete mode 100644 src/Models/DealWithLocalChanges.cs diff --git a/src/Models/DealWithLocalChanges.cs b/src/Models/DealWithLocalChanges.cs deleted file mode 100644 index f308a90c..00000000 --- a/src/Models/DealWithLocalChanges.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace SourceGit.Models -{ - public enum DealWithLocalChanges - { - DoNothing, - StashAndReaply, - Discard, - } -} diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index 1d0ca895..759e3a53 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -90,7 +90,6 @@ Branch: Lokale Änderungen: Verwerfen - Nichts tun Stashen & wieder anwenden Cherry Pick Quelle an Commit-Nachricht anhängen @@ -206,7 +205,6 @@ Erstellten Branch auschecken Lokale Änderungen: Verwerfen - Nichts tun Stashen & wieder anwenden Neuer Branch-Name: Branch-Namen eingeben. @@ -517,7 +515,6 @@ Lokaler Branch: Lokale Änderungen: Verwerfen - Nichts tun Stashen & wieder anwenden Ohne Tags fetchen Remote: diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 5df3ca71..90125de8 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -88,7 +88,6 @@ Branch: Local Changes: Discard - Do Nothing Stash & Reapply Cherry Pick Append source to commit message @@ -205,7 +204,6 @@ Check out the created branch Local Changes: Discard - Do Nothing Stash & Reapply New Branch Name: Enter branch name. @@ -520,7 +518,6 @@ Into: Local Changes: Discard - Do Nothing Stash & Reapply Fetch without tags Remote: diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index 4073f512..bcf09e1a 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -91,7 +91,6 @@ Rama: Cambios Locales: Descartar - No Hacer Nada Stash & Reaplicar Cherry Pick Añadir fuente al mensaje de commit @@ -208,7 +207,6 @@ Checkout de la rama creada Cambios Locales: Descartar - No Hacer Nada Stash & Reaplicar Nombre de la Nueva Rama: Introduzca el nombre de la rama. @@ -524,7 +522,6 @@ En: Cambios Locales: Descartar - No Hacer Nada Stash & Reaplicar Fetch sin etiquetas Remoto: diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index 59fe00a8..76405b21 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -83,7 +83,6 @@ Branche : Changements locaux : Annuler - Ne rien faire Mettre en stash et réappliquer Cherry-Pick de ce commit Ajouter la source au message de commit @@ -198,7 +197,6 @@ Récupérer la branche créée Changements locaux : Rejeter - Ne rien faire Stash & Réappliquer Nom de la nouvelle branche : Entrez le nom de la branche. @@ -492,7 +490,6 @@ Dans : Changements locaux : Rejeter - Ne rien faire Stash & Réappliquer Fetch sans les tags Dépôt distant : diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml index 6e99decf..f944689c 100644 --- a/src/Resources/Locales/it_IT.axaml +++ b/src/Resources/Locales/it_IT.axaml @@ -91,7 +91,6 @@ Branch: Modifiche Locali: Scarta - Non fare nulla Stasha e Ripristina Cherry Pick Aggiungi sorgente al messaggio di commit @@ -208,7 +207,6 @@ Checkout del Branch Creato Modifiche Locali: Scarta - Non Fare Nulla Stasha e Ripristina Nome Nuovo Branch: Inserisci il nome del branch. @@ -523,7 +521,6 @@ In: Modifiche Locali: Scarta - Non fare nulla Stasha e Riapplica Recupera senza tag Remoto: diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index 78445bfb..ebff746c 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -107,7 +107,6 @@ Branch: Alterações Locais: Descartar - Nada Stash & Reaplicar Cherry-Pick Adicionar origem à mensagem de commit @@ -215,7 +214,6 @@ Checar o branch criado Alterações Locais: Descartar - Não Fazer Nada Guardar & Reaplicar Nome do Novo Branch: Insira o nome do branch. @@ -506,7 +504,6 @@ Para: Alterações Locais: Descartar - Não Fazer Nada Guardar & Reaplicar Buscar sem tags Remoto: diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index ff24912e..6815bbeb 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -91,7 +91,6 @@ Ветка: Локальные изменения: Отклонить - Ничего не делать Отложить и примненить повторно Частичный выбор Добавить источник для ревизии сообщения @@ -209,7 +208,6 @@ Проверить созданную ветку Локальные изменения: Отклонить - Ничего не делать Отложить и применить повторно Имя новой ветки: Введите имя ветки. @@ -524,7 +522,6 @@ В: Локальные изменения: Отклонить - Ничего не делать Отложить и применить повторно Забрать без меток Внешний репозиторий: diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 72b434f9..cf796805 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -91,7 +91,6 @@ 目标分支 : 未提交更改 : 丢弃更改 - 不做处理 贮藏并自动恢复 挑选提交 提交信息中追加来源信息 @@ -208,7 +207,6 @@ 完成后切换到新分支 未提交更改 : 丢弃更改 - 不做处理 贮藏并自动恢复 新分支名 : 填写分支名称。 @@ -524,7 +522,6 @@ 本地分支 : 未提交更改 : 丢弃更改 - 不做处理 贮藏并自动恢复 不拉取远程标签 远程 : diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index bc9991f6..539001bd 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -91,7 +91,6 @@ 目標分支: 未提交變更: 捨棄變更 - 不做處理 擱置變更並自動復原 揀選提交 提交資訊中追加來源資訊 @@ -208,7 +207,6 @@ 完成後切換到新分支 未提交變更: 捨棄變更 - 不做處理 擱置變更並自動復原 新分支名稱: 輸入分支名稱。 @@ -523,7 +521,6 @@ 本機分支: 未提交變更: 捨棄變更 - 不做處理 擱置變更並自動復原 不拉取遠端標籤 遠端: diff --git a/src/ViewModels/Checkout.cs b/src/ViewModels/Checkout.cs index 9376741d..3334eba4 100644 --- a/src/ViewModels/Checkout.cs +++ b/src/ViewModels/Checkout.cs @@ -9,16 +9,17 @@ namespace SourceGit.ViewModels get; } - public Models.DealWithLocalChanges PreAction + public bool DiscardLocalChanges { get; set; - } = Models.DealWithLocalChanges.DoNothing; + } public Checkout(Repository repo, string branch) { _repo = repo; Branch = branch; + DiscardLocalChanges = false; View = new Views.Checkout() { DataContext = this }; } @@ -33,7 +34,12 @@ namespace SourceGit.ViewModels var needPopStash = false; if (changes > 0) { - if (PreAction == Models.DealWithLocalChanges.StashAndReaply) + if (DiscardLocalChanges) + { + SetProgressDescription("Discard local changes ..."); + Commands.Discard.All(_repo.FullPath, false); + } + else { SetProgressDescription("Stash local changes ..."); var succ = new Commands.Stash(_repo.FullPath).Push("CHECKOUT_AUTO_STASH"); @@ -45,11 +51,6 @@ namespace SourceGit.ViewModels needPopStash = true; } - else if (PreAction == Models.DealWithLocalChanges.Discard) - { - SetProgressDescription("Discard local changes ..."); - Commands.Discard.All(_repo.FullPath, false); - } } SetProgressDescription("Checkout branch ..."); diff --git a/src/ViewModels/CheckoutCommit.cs b/src/ViewModels/CheckoutCommit.cs index ddc0a0c6..1876a425 100644 --- a/src/ViewModels/CheckoutCommit.cs +++ b/src/ViewModels/CheckoutCommit.cs @@ -9,16 +9,17 @@ namespace SourceGit.ViewModels get; } - public bool AutoStash + public bool DiscardLocalChanges { - get => _autoStash; - set => SetProperty(ref _autoStash, value); + get; + set; } public CheckoutCommit(Repository repo, Models.Commit commit) { _repo = repo; Commit = commit; + DiscardLocalChanges = false; View = new Views.CheckoutCommit() { DataContext = this }; } @@ -33,7 +34,12 @@ namespace SourceGit.ViewModels var needPopStash = false; if (changes > 0) { - if (AutoStash) + if (DiscardLocalChanges) + { + SetProgressDescription("Discard local changes ..."); + Commands.Discard.All(_repo.FullPath, false); + } + else { SetProgressDescription("Stash local changes ..."); var succ = new Commands.Stash(_repo.FullPath).Push("CHECKOUT_AUTO_STASH"); @@ -45,11 +51,6 @@ namespace SourceGit.ViewModels needPopStash = true; } - else - { - SetProgressDescription("Discard local changes ..."); - Commands.Discard.All(_repo.FullPath, false); - } } SetProgressDescription("Checkout commit ..."); @@ -67,6 +68,5 @@ namespace SourceGit.ViewModels } private readonly Repository _repo = null; - private bool _autoStash = true; } } diff --git a/src/ViewModels/CreateBranch.cs b/src/ViewModels/CreateBranch.cs index 01bff031..37db0065 100644 --- a/src/ViewModels/CreateBranch.cs +++ b/src/ViewModels/CreateBranch.cs @@ -19,11 +19,11 @@ namespace SourceGit.ViewModels get; } - public Models.DealWithLocalChanges PreAction + public bool DiscardLocalChanges { get; set; - } = Models.DealWithLocalChanges.DoNothing; + } public bool CheckoutAfterCreated { @@ -47,6 +47,7 @@ namespace SourceGit.ViewModels } BasedOn = branch; + DiscardLocalChanges = false; View = new Views.CreateBranch() { DataContext = this }; } @@ -56,6 +57,7 @@ namespace SourceGit.ViewModels _baseOnRevision = commit.SHA; BasedOn = commit; + DiscardLocalChanges = false; View = new Views.CreateBranch() { DataContext = this }; } @@ -65,6 +67,7 @@ namespace SourceGit.ViewModels _baseOnRevision = tag.SHA; BasedOn = tag; + DiscardLocalChanges = false; View = new Views.CreateBranch() { DataContext = this }; } @@ -98,7 +101,12 @@ namespace SourceGit.ViewModels var needPopStash = false; if (changes > 0) { - if (PreAction == Models.DealWithLocalChanges.StashAndReaply) + if (DiscardLocalChanges) + { + SetProgressDescription("Discard local changes..."); + Commands.Discard.All(_repo.FullPath, false); + } + else { SetProgressDescription("Stash local changes"); succ = new Commands.Stash(_repo.FullPath).Push("CREATE_BRANCH_AUTO_STASH"); @@ -110,11 +118,6 @@ namespace SourceGit.ViewModels needPopStash = true; } - else if (PreAction == Models.DealWithLocalChanges.Discard) - { - SetProgressDescription("Discard local changes..."); - Commands.Discard.All(_repo.FullPath, false); - } } SetProgressDescription($"Create new branch '{fixedName}'"); diff --git a/src/ViewModels/Pull.cs b/src/ViewModels/Pull.cs index ff557792..62d68834 100644 --- a/src/ViewModels/Pull.cs +++ b/src/ViewModels/Pull.cs @@ -38,11 +38,11 @@ namespace SourceGit.ViewModels set => SetProperty(ref _selectedBranch, value, true); } - public Models.DealWithLocalChanges PreAction + public bool DiscardLocalChanges { get; set; - } = Models.DealWithLocalChanges.DoNothing; + } public bool UseRebase { @@ -124,7 +124,12 @@ namespace SourceGit.ViewModels var needPopStash = false; if (changes > 0) { - if (PreAction == Models.DealWithLocalChanges.StashAndReaply) + if (DiscardLocalChanges) + { + SetProgressDescription("Discard local changes ..."); + Commands.Discard.All(_repo.FullPath, false); + } + else { SetProgressDescription("Stash local changes..."); var succ = new Commands.Stash(_repo.FullPath).Push("PULL_AUTO_STASH"); @@ -136,11 +141,6 @@ namespace SourceGit.ViewModels needPopStash = true; } - else if (PreAction == Models.DealWithLocalChanges.Discard) - { - SetProgressDescription("Discard local changes ..."); - Commands.Discard.All(_repo.FullPath, false); - } } bool rs; diff --git a/src/Views/Checkout.axaml b/src/Views/Checkout.axaml index eb1c9de0..3cdfd94e 100644 --- a/src/Views/Checkout.axaml +++ b/src/Views/Checkout.axaml @@ -18,7 +18,7 @@ - + - - + - - + Content="{DynamicResource Text.CreateBranch.LocalChanges.StashAndReply}" + IsChecked="{Binding !DiscardLocalChanges, Mode=TwoWay}"/> + diff --git a/src/Views/Checkout.axaml.cs b/src/Views/Checkout.axaml.cs index da6e6b31..f8398a1d 100644 --- a/src/Views/Checkout.axaml.cs +++ b/src/Views/Checkout.axaml.cs @@ -1,5 +1,4 @@ using Avalonia.Controls; -using Avalonia.Interactivity; namespace SourceGit.Views { @@ -9,51 +8,5 @@ namespace SourceGit.Views { InitializeComponent(); } - - protected override void OnLoaded(RoutedEventArgs e) - { - base.OnLoaded(e); - - var vm = DataContext as ViewModels.Checkout; - if (vm == null) - return; - - switch (vm.PreAction) - { - case Models.DealWithLocalChanges.DoNothing: - RadioDoNothing.IsChecked = true; - break; - case Models.DealWithLocalChanges.StashAndReaply: - RadioStashAndReply.IsChecked = true; - break; - default: - RadioDiscard.IsChecked = true; - break; - } - } - - private void OnLocalChangeActionIsCheckedChanged(object sender, RoutedEventArgs e) - { - var vm = DataContext as ViewModels.Checkout; - if (vm == null) - return; - - if (RadioDoNothing.IsChecked == true) - { - if (vm.PreAction != Models.DealWithLocalChanges.DoNothing) - vm.PreAction = Models.DealWithLocalChanges.DoNothing; - return; - } - - if (RadioStashAndReply.IsChecked == true) - { - if (vm.PreAction != Models.DealWithLocalChanges.StashAndReaply) - vm.PreAction = Models.DealWithLocalChanges.StashAndReaply; - return; - } - - if (vm.PreAction != Models.DealWithLocalChanges.Discard) - vm.PreAction = Models.DealWithLocalChanges.Discard; - } } } diff --git a/src/Views/CheckoutCommit.axaml b/src/Views/CheckoutCommit.axaml index 3ee3943f..9b418823 100644 --- a/src/Views/CheckoutCommit.axaml +++ b/src/Views/CheckoutCommit.axaml @@ -30,16 +30,16 @@ + Margin="0,0,8,0" + IsChecked="{Binding !DiscardLocalChanges, Mode=TwoWay}"/> + GroupName="LocalChanges"/> - - - - + Content="{DynamicResource Text.CreateBranch.LocalChanges.StashAndReply}" + IsChecked="{Binding !DiscardLocalChanges, Mode=TwoWay}"/> + diff --git a/src/Views/CreateBranch.axaml.cs b/src/Views/CreateBranch.axaml.cs index 6499e1c7..6626871b 100644 --- a/src/Views/CreateBranch.axaml.cs +++ b/src/Views/CreateBranch.axaml.cs @@ -1,5 +1,4 @@ using Avalonia.Controls; -using Avalonia.Interactivity; namespace SourceGit.Views { @@ -9,51 +8,5 @@ namespace SourceGit.Views { InitializeComponent(); } - - protected override void OnLoaded(RoutedEventArgs e) - { - base.OnLoaded(e); - - var vm = DataContext as ViewModels.CreateBranch; - if (vm == null) - return; - - switch (vm.PreAction) - { - case Models.DealWithLocalChanges.DoNothing: - RadioDoNothing.IsChecked = true; - break; - case Models.DealWithLocalChanges.StashAndReaply: - RadioStashAndReply.IsChecked = true; - break; - default: - RadioDiscard.IsChecked = true; - break; - } - } - - private void OnLocalChangeActionIsCheckedChanged(object sender, RoutedEventArgs e) - { - var vm = DataContext as ViewModels.CreateBranch; - if (vm == null) - return; - - if (RadioDoNothing.IsChecked == true) - { - if (vm.PreAction != Models.DealWithLocalChanges.DoNothing) - vm.PreAction = Models.DealWithLocalChanges.DoNothing; - return; - } - - if (RadioStashAndReply.IsChecked == true) - { - if (vm.PreAction != Models.DealWithLocalChanges.StashAndReaply) - vm.PreAction = Models.DealWithLocalChanges.StashAndReaply; - return; - } - - if (vm.PreAction != Models.DealWithLocalChanges.Discard) - vm.PreAction = Models.DealWithLocalChanges.Discard; - } } } diff --git a/src/Views/Pull.axaml b/src/Views/Pull.axaml index 3e1f96d9..67121826 100644 --- a/src/Views/Pull.axaml +++ b/src/Views/Pull.axaml @@ -22,7 +22,7 @@ - + - - - + Content="{DynamicResource Text.Pull.LocalChanges.StashAndReply}" + IsChecked="{Binding !DiscardLocalChanges, Mode=TwoWay}"/> + - + diff --git a/src/Views/Pull.axaml.cs b/src/Views/Pull.axaml.cs index 3003f02c..c6b4923e 100644 --- a/src/Views/Pull.axaml.cs +++ b/src/Views/Pull.axaml.cs @@ -1,5 +1,4 @@ using Avalonia.Controls; -using Avalonia.Interactivity; namespace SourceGit.Views { @@ -9,51 +8,5 @@ namespace SourceGit.Views { InitializeComponent(); } - - protected override void OnLoaded(RoutedEventArgs e) - { - base.OnLoaded(e); - - var vm = DataContext as ViewModels.Pull; - if (vm == null) - return; - - switch (vm.PreAction) - { - case Models.DealWithLocalChanges.DoNothing: - RadioDoNothing.IsChecked = true; - break; - case Models.DealWithLocalChanges.StashAndReaply: - RadioStashAndReply.IsChecked = true; - break; - default: - RadioDiscard.IsChecked = true; - break; - } - } - - private void OnLocalChangeActionIsCheckedChanged(object sender, RoutedEventArgs e) - { - var vm = DataContext as ViewModels.Pull; - if (vm == null) - return; - - if (RadioDoNothing.IsChecked == true) - { - if (vm.PreAction != Models.DealWithLocalChanges.DoNothing) - vm.PreAction = Models.DealWithLocalChanges.DoNothing; - return; - } - - if (RadioStashAndReply.IsChecked == true) - { - if (vm.PreAction != Models.DealWithLocalChanges.StashAndReaply) - vm.PreAction = Models.DealWithLocalChanges.StashAndReaply; - return; - } - - if (vm.PreAction != Models.DealWithLocalChanges.Discard) - vm.PreAction = Models.DealWithLocalChanges.Discard; - } } } From 519bdf1ddc1bb7bba6fb0187d1d9d208797115e6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 13 Mar 2025 02:22:09 +0000 Subject: [PATCH 363/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 399916c9..cc37aae9 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.08%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-%E2%88%9A-brightgreen)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.68%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.41%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.07%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-%E2%88%9A-brightgreen)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.64%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.38%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index a5abbbba..155e031a 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,4 +1,4 @@ -### de_DE.axaml: 99.08% +### de_DE.axaml: 99.07%
@@ -24,7 +24,7 @@
-### fr_FR.axaml: 91.68% +### fr_FR.axaml: 91.64%
@@ -106,7 +106,7 @@
-### pt_BR.axaml: 91.41% +### pt_BR.axaml: 91.38%
From b9b684a83d58740d2bd802e08ad83746fcb97359 Mon Sep 17 00:00:00 2001 From: Gadfly Date: Thu, 13 Mar 2025 15:05:30 +0800 Subject: [PATCH 364/441] fix: improve font string processing in SetFonts method (#1092) --- src/App.axaml.cs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/App.axaml.cs b/src/App.axaml.cs index 25e32323..504981f7 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -181,6 +181,9 @@ namespace SourceGit app._fontsOverrides = null; } + defaultFont = ProcessFontString(defaultFont); + monospaceFont = ProcessFontString(monospaceFont); + var resDic = new ResourceDictionary(); if (!string.IsNullOrEmpty(defaultFont)) resDic.Add("Fonts.Default", new FontFamily(defaultFont)); @@ -437,6 +440,28 @@ namespace SourceGit return true; } + private static string ProcessFontString(string input) + { + if (string.IsNullOrEmpty(input)) return string.Empty; + + var parts = input.Split(','); + var result = new StringBuilder(); + var isFirst = true; + + foreach (var part in parts) + { + var trimmed = part.Trim(); + if (!string.IsNullOrEmpty(trimmed)) + { + if (!isFirst) result.Append(','); + result.Append(trimmed); + isFirst = false; + } + } + + return result.ToString(); + } + private bool TryLaunchAsCoreEditor(IClassicDesktopStyleApplicationLifetime desktop) { var args = desktop.Args; From 9560496c7bf9cec50f98f19d8b37dbe98d71fcf9 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 13 Mar 2025 15:17:20 +0800 Subject: [PATCH 365/441] code_review: PR #1092 - Remove `SourceGit.ViewModels.Preference.FixFontFamilyName` (it is not necessary any more) - Use `string.Join` instead of `StringBuilder` to make the logic more clear Signed-off-by: leo --- src/App.axaml.cs | 24 +++++++++------------ src/ViewModels/Preferences.cs | 40 ++++------------------------------- 2 files changed, 14 insertions(+), 50 deletions(-) diff --git a/src/App.axaml.cs b/src/App.axaml.cs index 504981f7..79eeda4e 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -181,8 +181,8 @@ namespace SourceGit app._fontsOverrides = null; } - defaultFont = ProcessFontString(defaultFont); - monospaceFont = ProcessFontString(monospaceFont); + defaultFont = FixFontFamilyName(defaultFont); + monospaceFont = FixFontFamilyName(monospaceFont); var resDic = new ResourceDictionary(); if (!string.IsNullOrEmpty(defaultFont)) @@ -440,26 +440,22 @@ namespace SourceGit return true; } - private static string ProcessFontString(string input) + private static string FixFontFamilyName(string input) { - if (string.IsNullOrEmpty(input)) return string.Empty; + if (string.IsNullOrEmpty(input)) + return string.Empty; var parts = input.Split(','); - var result = new StringBuilder(); - var isFirst = true; + var trimmed = new List(); foreach (var part in parts) { - var trimmed = part.Trim(); - if (!string.IsNullOrEmpty(trimmed)) - { - if (!isFirst) result.Append(','); - result.Append(trimmed); - isFirst = false; - } + var t = part.Trim(); + if (!string.IsNullOrEmpty(t)) + trimmed.Add(t); } - return result.ToString(); + return trimmed.Count > 0 ? string.Join(',', trimmed) : string.Empty; } private bool TryLaunchAsCoreEditor(IClassicDesktopStyleApplicationLifetime desktop) diff --git a/src/ViewModels/Preferences.cs b/src/ViewModels/Preferences.cs index dae90517..0b1d841e 100644 --- a/src/ViewModels/Preferences.cs +++ b/src/ViewModels/Preferences.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using Avalonia.Collections; @@ -66,9 +65,8 @@ namespace SourceGit.ViewModels get => _defaultFontFamily; set { - var name = FixFontFamilyName(value); - if (SetProperty(ref _defaultFontFamily, name) && !_isLoading) - App.SetFonts(_defaultFontFamily, _monospaceFontFamily, _onlyUseMonoFontInEditor); + if (SetProperty(ref _defaultFontFamily, value) && !_isLoading) + App.SetFonts(value, _monospaceFontFamily, _onlyUseMonoFontInEditor); } } @@ -77,9 +75,8 @@ namespace SourceGit.ViewModels get => _monospaceFontFamily; set { - var name = FixFontFamilyName(value); - if (SetProperty(ref _monospaceFontFamily, name) && !_isLoading) - App.SetFonts(_defaultFontFamily, _monospaceFontFamily, _onlyUseMonoFontInEditor); + if (SetProperty(ref _monospaceFontFamily, value) && !_isLoading) + App.SetFonts(_defaultFontFamily, value, _onlyUseMonoFontInEditor); } } @@ -620,35 +617,6 @@ namespace SourceGit.ViewModels return changed; } - private string FixFontFamilyName(string name) - { - var trimmed = name.Trim(); - if (string.IsNullOrEmpty(trimmed)) - return string.Empty; - - var builder = new StringBuilder(); - var lastIsSpace = false; - for (int i = 0; i < trimmed.Length; i++) - { - var c = trimmed[i]; - if (char.IsWhiteSpace(c)) - { - if (lastIsSpace) - continue; - - lastIsSpace = true; - } - else - { - lastIsSpace = false; - } - - builder.Append(c); - } - - return builder.ToString(); - } - private static Preferences _instance = null; private static bool _isLoading = false; From 67f4330dd4799c4358be3852a566207aae30cb3f Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 13 Mar 2025 15:23:43 +0800 Subject: [PATCH 366/441] code_style: arrange methods in `App.axaml.cs` Signed-off-by: leo --- src/App.axaml.cs | 90 ++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/App.axaml.cs b/src/App.axaml.cs index 79eeda4e..f59d35db 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -77,6 +77,31 @@ namespace SourceGit Native.OS.SetupApp(builder); return builder; } + + private static void LogException(Exception ex) + { + if (ex == null) + return; + + var builder = new StringBuilder(); + builder.Append($"Crash::: {ex.GetType().FullName}: {ex.Message}\n\n"); + builder.Append("----------------------------\n"); + builder.Append($"Version: {Assembly.GetExecutingAssembly().GetName().Version}\n"); + builder.Append($"OS: {Environment.OSVersion}\n"); + builder.Append($"Framework: {AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName}\n"); + builder.Append($"Source: {ex.Source}\n"); + builder.Append($"Thread Name: {Thread.CurrentThread.Name ?? "Unnamed"}\n"); + builder.Append($"User: {Environment.UserName}\n"); + builder.Append($"App Start Time: {Process.GetCurrentProcess().StartTime}\n"); + builder.Append($"Exception Time: {DateTime.Now}\n"); + builder.Append($"Memory Usage: {Process.GetCurrentProcess().PrivateMemorySize64 / 1024 / 1024} MB\n"); + builder.Append($"---------------------------\n\n"); + builder.Append(ex); + + var time = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"); + var file = Path.Combine(Native.OS.DataDir, $"crash_{time}.log"); + File.WriteAllText(file, builder.ToString()); + } #endregion #region Utility Functions @@ -181,8 +206,8 @@ namespace SourceGit app._fontsOverrides = null; } - defaultFont = FixFontFamilyName(defaultFont); - monospaceFont = FixFontFamilyName(monospaceFont); + defaultFont = app.FixFontFamilyName(defaultFont); + monospaceFont = app.FixFontFamilyName(monospaceFont); var resDic = new ResourceDictionary(); if (!string.IsNullOrEmpty(defaultFont)) @@ -328,31 +353,6 @@ namespace SourceGit } #endregion - private static void LogException(Exception ex) - { - if (ex == null) - return; - - var builder = new StringBuilder(); - builder.Append($"Crash::: {ex.GetType().FullName}: {ex.Message}\n\n"); - builder.Append("----------------------------\n"); - builder.Append($"Version: {Assembly.GetExecutingAssembly().GetName().Version}\n"); - builder.Append($"OS: {Environment.OSVersion}\n"); - builder.Append($"Framework: {AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName}\n"); - builder.Append($"Source: {ex.Source}\n"); - builder.Append($"Thread Name: {Thread.CurrentThread.Name ?? "Unnamed"}\n"); - builder.Append($"User: {Environment.UserName}\n"); - builder.Append($"App Start Time: {Process.GetCurrentProcess().StartTime}\n"); - builder.Append($"Exception Time: {DateTime.Now}\n"); - builder.Append($"Memory Usage: {Process.GetCurrentProcess().PrivateMemorySize64 / 1024 / 1024} MB\n"); - builder.Append($"---------------------------\n\n"); - builder.Append(ex); - - var time = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"); - var file = Path.Combine(Native.OS.DataDir, $"crash_{time}.log"); - File.WriteAllText(file, builder.ToString()); - } - private static bool TryLaunchAsRebaseTodoEditor(string[] args, out int exitCode) { exitCode = -1; @@ -440,24 +440,6 @@ namespace SourceGit return true; } - private static string FixFontFamilyName(string input) - { - if (string.IsNullOrEmpty(input)) - return string.Empty; - - var parts = input.Split(','); - var trimmed = new List(); - - foreach (var part in parts) - { - var t = part.Trim(); - if (!string.IsNullOrEmpty(t)) - trimmed.Add(t); - } - - return trimmed.Count > 0 ? string.Join(',', trimmed) : string.Empty; - } - private bool TryLaunchAsCoreEditor(IClassicDesktopStyleApplicationLifetime desktop) { var args = desktop.Args; @@ -567,6 +549,24 @@ namespace SourceGit }); } + private string FixFontFamilyName(string input) + { + if (string.IsNullOrEmpty(input)) + return string.Empty; + + var parts = input.Split(','); + var trimmed = new List(); + + foreach (var part in parts) + { + var t = part.Trim(); + if (!string.IsNullOrEmpty(t)) + trimmed.Add(t); + } + + return trimmed.Count > 0 ? string.Join(',', trimmed) : string.Empty; + } + private ViewModels.Launcher _launcher = null; private ResourceDictionary _activeLocale = null; private ResourceDictionary _themeOverrides = null; From 9645b65db669af8fa2b5b24df0e2765d0d576182 Mon Sep 17 00:00:00 2001 From: Michael Pakhantsov Date: Fri, 14 Mar 2025 03:26:59 +0200 Subject: [PATCH 367/441] Explicitly provided fully qualified reference for the git branch, becase can be exists a tag and a branch with identical names (#1093) Fix push command for branch deletion Updated the `push` command to use `--delete refs/heads/{name}` instead of `--delete {name}` for clearer branch reference when deleting a remote branch. Co-authored-by: Michael Pakhantsov --- src/Commands/Branch.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Commands/Branch.cs b/src/Commands/Branch.cs index 391aeeb2..d56dfa97 100644 --- a/src/Commands/Branch.cs +++ b/src/Commands/Branch.cs @@ -62,7 +62,7 @@ if (exists) { cmd.SSHKey = new Config(repo).Get($"remote.{remote}.sshkey"); - cmd.Args = $"push {remote} --delete {name}"; + cmd.Args = $"push {remote} --delete refs/heads/{name}"; } else { From c8bee2f6ba9f611e125126b7729a91ebdb2b7d31 Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 14 Mar 2025 09:36:34 +0800 Subject: [PATCH 368/441] code_review: PR #1093 Merge deleting branch and tag on remote into `SourceGit.Commands.Push(repo, remote, refname, isDelete)` Signed-off-by: leo --- src/Commands/Branch.cs | 17 +++++------------ src/Commands/Push.cs | 4 ++-- src/Commands/Tag.cs | 4 +--- src/ViewModels/CreateTag.cs | 2 +- src/ViewModels/PushTag.cs | 7 ++++--- 5 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/Commands/Branch.cs b/src/Commands/Branch.cs index d56dfa97..2dc8a98d 100644 --- a/src/Commands/Branch.cs +++ b/src/Commands/Branch.cs @@ -54,21 +54,14 @@ public static bool DeleteRemote(string repo, string remote, string name) { + bool exists = new Remote(repo).HasBranch(remote, name); + if (exists) + return new Push(repo, remote, $"refs/heads/{name}", true).Exec(); + var cmd = new Command(); cmd.WorkingDirectory = repo; cmd.Context = repo; - - bool exists = new Remote(repo).HasBranch(remote, name); - if (exists) - { - cmd.SSHKey = new Config(repo).Get($"remote.{remote}.sshkey"); - cmd.Args = $"push {remote} --delete refs/heads/{name}"; - } - else - { - cmd.Args = $"branch -D -r {remote}/{name}"; - } - + cmd.Args = $"branch -D -r {remote}/{name}"; return cmd.Exec(); } } diff --git a/src/Commands/Push.cs b/src/Commands/Push.cs index 69b859ab..dc81f606 100644 --- a/src/Commands/Push.cs +++ b/src/Commands/Push.cs @@ -26,7 +26,7 @@ namespace SourceGit.Commands Args += $"{remote} {local}:{remoteBranch}"; } - public Push(string repo, string remote, string tag, bool isDelete) + public Push(string repo, string remote, string refname, bool isDelete) { WorkingDirectory = repo; Context = repo; @@ -36,7 +36,7 @@ namespace SourceGit.Commands if (isDelete) Args += "--delete "; - Args += $"{remote} refs/tags/{tag}"; + Args += $"{remote} {refname}"; } protected override void OnReadline(string line) diff --git a/src/Commands/Tag.cs b/src/Commands/Tag.cs index fa11e366..23dbb11c 100644 --- a/src/Commands/Tag.cs +++ b/src/Commands/Tag.cs @@ -48,9 +48,7 @@ namespace SourceGit.Commands if (remotes != null) { foreach (var r in remotes) - { - new Push(repo, r.Name, name, true).Exec(); - } + new Push(repo, r.Name, $"refs/tags/{name}", true).Exec(); } return true; diff --git a/src/ViewModels/CreateTag.cs b/src/ViewModels/CreateTag.cs index a6d7255b..86ae7118 100644 --- a/src/ViewModels/CreateTag.cs +++ b/src/ViewModels/CreateTag.cs @@ -96,7 +96,7 @@ namespace SourceGit.ViewModels foreach (var remote in remotes) { SetProgressDescription($"Pushing tag to remote {remote.Name} ..."); - new Commands.Push(_repo.FullPath, remote.Name, _tagName, false).Exec(); + new Commands.Push(_repo.FullPath, remote.Name, $"refs/tags/{_tagName}", false).Exec(); } } diff --git a/src/ViewModels/PushTag.cs b/src/ViewModels/PushTag.cs index 54673fbe..de2941d2 100644 --- a/src/ViewModels/PushTag.cs +++ b/src/ViewModels/PushTag.cs @@ -43,13 +43,14 @@ namespace SourceGit.ViewModels return Task.Run(() => { - bool succ = true; + var succ = true; + var tag = $"refs/tags/{Target.Name}"; if (_pushAllRemotes) { foreach (var remote in _repo.Remotes) { SetProgressDescription($"Pushing tag to remote {remote.Name} ..."); - succ = new Commands.Push(_repo.FullPath, remote.Name, Target.Name, false).Exec(); + succ = new Commands.Push(_repo.FullPath, remote.Name, tag, false).Exec(); if (!succ) break; } @@ -57,7 +58,7 @@ namespace SourceGit.ViewModels else { SetProgressDescription($"Pushing tag to remote {SelectedRemote.Name} ..."); - succ = new Commands.Push(_repo.FullPath, SelectedRemote.Name, Target.Name, false).Exec(); + succ = new Commands.Push(_repo.FullPath, SelectedRemote.Name, tag, false).Exec(); } CallUIThread(() => _repo.SetWatcherEnabled(true)); From c3e1fb93b6fcd42b5156c999371e1f4f61537fb5 Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 14 Mar 2025 10:54:09 +0800 Subject: [PATCH 369/441] refactor: fix maxOS `PATH` env Signed-off-by: leo --- src/Commands/Command.cs | 4 ---- src/Commands/ExecuteCustomAction.cs | 8 -------- src/Native/MacOS.cs | 15 ++++++++++++++- src/Native/OS.cs | 6 ------ 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/Commands/Command.cs b/src/Commands/Command.cs index 5197de11..0fef1235 100644 --- a/src/Commands/Command.cs +++ b/src/Commands/Command.cs @@ -198,10 +198,6 @@ namespace SourceGit.Commands start.Environment.Add("LC_ALL", "C"); } - // Fix macOS `PATH` env - if (OperatingSystem.IsMacOS() && !string.IsNullOrEmpty(Native.OS.CustomPathEnv)) - start.Environment.Add("PATH", Native.OS.CustomPathEnv); - // Force using this app as git editor. switch (Editor) { diff --git a/src/Commands/ExecuteCustomAction.cs b/src/Commands/ExecuteCustomAction.cs index 894637a5..000c8fd1 100644 --- a/src/Commands/ExecuteCustomAction.cs +++ b/src/Commands/ExecuteCustomAction.cs @@ -17,10 +17,6 @@ namespace SourceGit.Commands start.CreateNoWindow = true; start.WorkingDirectory = repo; - // Fix macOS `PATH` env - if (OperatingSystem.IsMacOS() && !string.IsNullOrEmpty(Native.OS.CustomPathEnv)) - start.Environment.Add("PATH", Native.OS.CustomPathEnv); - try { Process.Start(start); @@ -44,10 +40,6 @@ namespace SourceGit.Commands start.StandardErrorEncoding = Encoding.UTF8; start.WorkingDirectory = repo; - // Fix macOS `PATH` env - if (OperatingSystem.IsMacOS() && !string.IsNullOrEmpty(Native.OS.CustomPathEnv)) - start.Environment.Add("PATH", Native.OS.CustomPathEnv); - var proc = new Process() { StartInfo = start }; var builder = new StringBuilder(); diff --git a/src/Native/MacOS.cs b/src/Native/MacOS.cs index 633ef5eb..123b160b 100644 --- a/src/Native/MacOS.cs +++ b/src/Native/MacOS.cs @@ -18,9 +18,22 @@ namespace SourceGit.Native DisableDefaultApplicationMenuItems = true, }); + // Fix `PATH` env on macOS. + var path = Environment.GetEnvironmentVariable("PATH"); + if (string.IsNullOrEmpty(path)) + path = "/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"; + else if (!path.Contains("/opt/homebrew/", StringComparison.Ordinal)) + path = "/opt/homebrew/bin:/opt/homebrew/sbin:" + path; + var customPathFile = Path.Combine(OS.DataDir, "PATH"); if (File.Exists(customPathFile)) - OS.CustomPathEnv = File.ReadAllText(customPathFile).Trim(); + { + var env = File.ReadAllText(customPathFile).Trim(); + if (!string.IsNullOrEmpty(env)) + path = env; + } + + Environment.SetEnvironmentVariable("PATH", path); } public string FindGitExecutable() diff --git a/src/Native/OS.cs b/src/Native/OS.cs index 3a688654..f11d1e7f 100644 --- a/src/Native/OS.cs +++ b/src/Native/OS.cs @@ -31,12 +31,6 @@ namespace SourceGit.Native private set; } = string.Empty; - public static string CustomPathEnv - { - get; - set; - } = string.Empty; - public static string GitExecutable { get => _gitExecutable; From db504241eae8fc93813b4eca2ddbdab3c52306b8 Mon Sep 17 00:00:00 2001 From: Asurada <43401755+ousugo@users.noreply.github.com> Date: Fri, 14 Mar 2025 16:57:03 +0800 Subject: [PATCH 370/441] feat: add translation for "1 hour ago" in multiple languages (#1096) --- src/Resources/Locales/de_DE.axaml | 1 + src/Resources/Locales/en_US.axaml | 1 + src/Resources/Locales/es_ES.axaml | 1 + src/Resources/Locales/fr_FR.axaml | 1 + src/Resources/Locales/it_IT.axaml | 1 + src/Resources/Locales/pt_BR.axaml | 1 + src/Resources/Locales/ru_RU.axaml | 1 + src/Resources/Locales/zh_CN.axaml | 1 + src/Resources/Locales/zh_TW.axaml | 1 + src/Views/CommitTimeTextBlock.cs | 5 ++++- 10 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index 759e3a53..aff8ffc5 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -443,6 +443,7 @@ Einfügen Gerade eben Vor {0} Minuten + Vor 1 Stunde Vor {0} Stunden Gestern Vor {0} Tagen diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 90125de8..818bd9bb 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -444,6 +444,7 @@ Paste Just now {0} minutes ago + 1 hour ago {0} hours ago Yesterday {0} days ago diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index bcf09e1a..e909a14e 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -447,6 +447,7 @@ Pegar Justo ahora Hace {0} minutos + Hace 1 hora Hace {0} horas Ayer Hace {0} días diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index 76405b21..aecea9ad 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -422,6 +422,7 @@ Coller A l'instant il y a {0} minutes + il y a 1 heure il y a {0} heures Hier il y a {0} jours diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml index f944689c..4dcc8771 100644 --- a/src/Resources/Locales/it_IT.axaml +++ b/src/Resources/Locales/it_IT.axaml @@ -448,6 +448,7 @@ Incolla Proprio ora {0} minuti fa + 1 ora fa {0} ore fa Ieri {0} giorni fa diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index ebff746c..b146bf0e 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -435,6 +435,7 @@ Colar Agora mesmo {0} minutos atrás + 1 hora atrás {0} horas atrás Ontem {0} dias atrás diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index 6815bbeb..07fb7c94 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -448,6 +448,7 @@ Вставить Сейчас {0} минут назад + 1 час назад {0} часов назад Вчера {0} дней назад diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index cf796805..2d160ad2 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -447,6 +447,7 @@ 粘贴 刚刚 {0}分钟前 + 1小时前 {0}小时前 昨天 {0}天前 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 539001bd..e50a600d 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -447,6 +447,7 @@ 貼上 剛剛 {0} 分鐘前 + 1 小時前 {0} 小時前 昨天 {0} 天前 diff --git a/src/Views/CommitTimeTextBlock.cs b/src/Views/CommitTimeTextBlock.cs index 6947f7f2..db63e8a6 100644 --- a/src/Views/CommitTimeTextBlock.cs +++ b/src/Views/CommitTimeTextBlock.cs @@ -129,7 +129,10 @@ namespace SourceGit.Views return App.Text("Period.MinutesAgo", (int)span.TotalMinutes); if (span.TotalDays < 1) - return App.Text("Period.HoursAgo", (int)span.TotalHours); + { + var hours = (int)span.TotalHours; + return hours == 1 ? App.Text("Period.HourAgo") : App.Text("Period.HoursAgo", hours); + } var lastDay = now.AddDays(-1).Date; if (localTime >= lastDay) From a46e52582fd9f8e5930fe76bec86386380d4cf7a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 14 Mar 2025 08:57:15 +0000 Subject: [PATCH 371/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cc37aae9..c932ec8a 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.07%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-%E2%88%9A-brightgreen)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.64%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.38%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.07%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-%E2%88%9A-brightgreen)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.66%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.39%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index 155e031a..e3f9d2a1 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -24,7 +24,7 @@
-### fr_FR.axaml: 91.64% +### fr_FR.axaml: 91.66%
@@ -106,7 +106,7 @@
-### pt_BR.axaml: 91.38% +### pt_BR.axaml: 91.39%
From 66517fd4bf1ed05bd91a1002cfc9d9a508559131 Mon Sep 17 00:00:00 2001 From: Gadfly Date: Sun, 16 Mar 2025 11:23:42 +0800 Subject: [PATCH 372/441] enhance: add tooltips to various UI elements for better accessibility (#1097) * enhance: add tooltips to various UI elements for better accessibility * refactor: simplify user string conversion --- src/Models/User.cs | 5 +++++ src/Views/ChangeCollectionView.axaml | 13 ++++++++++--- src/Views/DiffView.axaml | 2 +- src/Views/Histories.axaml | 11 +++++++++-- src/Views/RevisionFiles.axaml | 2 +- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/Models/User.cs b/src/Models/User.cs index 850bcf2f..066ab747 100644 --- a/src/Models/User.cs +++ b/src/Models/User.cs @@ -43,6 +43,11 @@ namespace SourceGit.Models return _caches.GetOrAdd(data, key => new User(key)); } + public override string ToString() + { + return $"{Name} <{Email}>"; + } + private static ConcurrentDictionary _caches = new ConcurrentDictionary(); private readonly int _hash; } diff --git a/src/Views/ChangeCollectionView.axaml b/src/Views/ChangeCollectionView.axaml index 6ce3d033..2b0f5bfa 100644 --- a/src/Views/ChangeCollectionView.axaml +++ b/src/Views/ChangeCollectionView.axaml @@ -39,7 +39,8 @@ + DoubleTapped="OnRowDoubleTapped" + ToolTip.Tip="{Binding FullPath}"> - + - + - + diff --git a/src/Views/Histories.axaml b/src/Views/Histories.axaml index 583e17c1..afe2c1b7 100644 --- a/src/Views/Histories.axaml +++ b/src/Views/Histories.axaml @@ -126,7 +126,11 @@ - + - + - + From 84979b20b330144a0dea8ea41ae48986943e079c Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 09:32:31 +0800 Subject: [PATCH 373/441] ux: force using `VertialAlignment="Center"` for sign info of commit (#1098) Signed-off-by: leo --- src/Views/CommitBaseInfo.axaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Views/CommitBaseInfo.axaml b/src/Views/CommitBaseInfo.axaml index 4ff8f20f..692d04b8 100644 --- a/src/Views/CommitBaseInfo.axaml +++ b/src/Views/CommitBaseInfo.axaml @@ -80,10 +80,10 @@ - - - - + + + + From 34f86189895c74e7ddd798ead684782f4263ff49 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 09:37:40 +0800 Subject: [PATCH 374/441] version: Release 2025.09 Signed-off-by: leo --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index a75bd422..23993bfb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2025.08 \ No newline at end of file +2025.09 \ No newline at end of file From 7caa03a09bbc7770cbf85ba8d16f23a9aa077864 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 09:57:52 +0800 Subject: [PATCH 375/441] project: upgrade `AvaloniaEdit` to `11.2.0` Signed-off-by: leo --- src/SourceGit.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj index 34e4eab2..3578d59f 100644 --- a/src/SourceGit.csproj +++ b/src/SourceGit.csproj @@ -46,8 +46,8 @@ - - + + From 450dadf76ce582b3f1e59dd56f822d7c1f194c86 Mon Sep 17 00:00:00 2001 From: Gadfly Date: Mon, 17 Mar 2025 10:12:44 +0800 Subject: [PATCH 376/441] feat: Add JSP grammar support and improve TextMateHelper file type handling (#1100) - Extend grammar support by allowing multiple file extensions per grammar and adding JSP file type handling. - Add a new JSON grammar file for JavaServer Pages (JSP) syntax highlighting. --- src/Models/TextMateHelper.cs | 22 +- src/Resources/Grammars/jsp.json | 1206 +++++++++++++++++++++++++++++++ 2 files changed, 1218 insertions(+), 10 deletions(-) create mode 100644 src/Resources/Grammars/jsp.json diff --git a/src/Models/TextMateHelper.cs b/src/Models/TextMateHelper.cs index 0eb5e489..b7efae72 100644 --- a/src/Models/TextMateHelper.cs +++ b/src/Models/TextMateHelper.cs @@ -21,10 +21,11 @@ namespace SourceGit.Models { private static readonly ExtraGrammar[] s_extraGrammars = [ - new ExtraGrammar("source.toml", ".toml", "toml.json"), - new ExtraGrammar("source.kotlin", ".kotlin", "kotlin.json"), - new ExtraGrammar("source.hx", ".hx", "haxe.json"), - new ExtraGrammar("source.hxml", ".hxml", "hxml.json"), + new ExtraGrammar("source.toml", [".toml"], "toml.json"), + new ExtraGrammar("source.kotlin", [".kotlin", ".kt", ".kts"], "kotlin.json"), + new ExtraGrammar("source.hx", [".hx"], "haxe.json"), + new ExtraGrammar("source.hxml", [".hxml"], "hxml.json"), + new ExtraGrammar("text.html.jsp", [".jsp", ".jspf", ".tag"], "jsp.json"), ]; public static string GetScope(string file, RegistryOptions reg) @@ -36,13 +37,14 @@ namespace SourceGit.Models extension = ".xml"; else if (extension == ".command") extension = ".sh"; - else if (extension == ".kt" || extension == ".kts") - extension = ".kotlin"; foreach (var grammar in s_extraGrammars) { - if (grammar.Extension.Equals(extension, StringComparison.OrdinalIgnoreCase)) - return grammar.Scope; + foreach (var ext in grammar.Extensions) + { + if (ext.Equals(extension, StringComparison.OrdinalIgnoreCase)) + return grammar.Scope; + } } return reg.GetScopeByExtension(extension); @@ -71,10 +73,10 @@ namespace SourceGit.Models return reg.GetGrammar(scopeName); } - private record ExtraGrammar(string Scope, string Extension, string File) + private record ExtraGrammar(string Scope, List Extensions, string File) { public readonly string Scope = Scope; - public readonly string Extension = Extension; + public readonly List Extensions = Extensions; public readonly string File = File; } } diff --git a/src/Resources/Grammars/jsp.json b/src/Resources/Grammars/jsp.json new file mode 100644 index 00000000..f0067748 --- /dev/null +++ b/src/Resources/Grammars/jsp.json @@ -0,0 +1,1206 @@ +{ + "information_for_contributors": [ + "This file has been copied from https://github.com/J0hnMilt0n/vscode-jsp/blob/b33b7e4d47f3b5f4b82e93dfcadd180149153d02/syntaxes/jsp.tmLanguage.json" + ], + "fileTypes": [ + "jsp", + "jspf", + "tag" + ], + "injections": { + "text.html.jsp - (meta.embedded.block.jsp | meta.embedded.line.jsp | meta.tag | comment), meta.tag string.quoted": { + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#declaration" + }, + { + "include": "#expression" + }, + { + "include": "#el_expression" + }, + { + "include": "#tags" + }, + { + "begin": "(^\\s*)(?=<%(?=\\s))", + "beginCaptures": { + "0": { + "name": "punctuation.whitespace.embedded.leading.erb" + } + }, + "end": "(?!\\G)(\\s*$\\n)?", + "endCaptures": { + "0": { + "name": "punctuation.whitespace.embedded.trailing.erb" + } + }, + "patterns": [ + { + "include": "#scriptlet" + } + ] + }, + { + "include": "#scriptlet" + } + ] + } + }, + "keyEquivalent": "^~J", + "name": "JavaServer Pages", + "patterns": [ + { + "include": "#xml_tags" + }, + { + "include": "text.html.basic" + } + ], + "repository": { + "comment": { + "begin": "<%--", + "captures": { + "0": { + "name": "punctuation.definition.comment.jsp" + } + }, + "end": "--%>", + "name": "comment.block.jsp" + }, + "declaration": { + "begin": "<%!", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.jsp" + } + }, + "contentName": "source.java", + "end": "(%)>", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.jsp" + }, + "1": { + "name": "source.java" + } + }, + "name": "meta.embedded.line.declaration.jsp", + "patterns": [ + { + "include": "source.java" + } + ] + }, + "el_expression": { + "begin": "\\$\\{", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.jsp" + } + }, + "contentName": "source.java", + "end": "(\\})", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.jsp" + }, + "1": { + "name": "source.java" + } + }, + "name": "meta.embedded.line.el_expression.jsp", + "patterns": [ + { + "include": "source.java" + } + ] + }, + "expression": { + "begin": "<%=", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.jsp" + } + }, + "contentName": "source.java", + "end": "(%)>", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.jsp" + }, + "1": { + "name": "source.java" + } + }, + "name": "meta.embedded.line.expression.jsp", + "patterns": [ + { + "include": "source.java" + } + ] + }, + "scriptlet": { + "begin": "<%", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.jsp" + } + }, + "contentName": "source.java", + "end": "(%)>", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.jsp" + }, + "1": { + "name": "source.java" + } + }, + "name": "meta.embedded.block.scriptlet.jsp", + "patterns": [ + { + "match": "\\{", + "name": "punctuation.section.scope.begin.java" + }, + { + "match": "\\}", + "name": "punctuation.section.scope.end.java" + }, + { + "include": "source.java" + } + ] + }, + "tags": { + "begin": "(<%@)\\s*(?=(attribute|include|page|tag|taglib|variable)\\s)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.jsp" + } + }, + "end": "%>", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.tag.template.include.jsp", + "patterns": [ + { + "begin": "\\G(attribute)(?=\\s)", + "captures": { + "1": { + "name": "keyword.control.attribute.jsp" + } + }, + "end": "(?=%>)", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(name|required|fragment|rtexprvalue|type|description)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "\\G(include)(?=\\s)", + "captures": { + "1": { + "name": "keyword.control.include.jsp" + } + }, + "end": "(?=%>)", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(file)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "\\G(page)(?=\\s)", + "captures": { + "1": { + "name": "keyword.control.page.jsp" + } + }, + "end": "(?=%>)", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(language|extends|import|session|buffer|autoFlush|isThreadSafe|info|errorPage|isErrorPage|contentType|pageEncoding|isElIgnored)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "\\G(tag)(?=\\s)", + "captures": { + "1": { + "name": "keyword.control.tag.jsp" + } + }, + "end": "(?=%>)", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(display-name|body-content|dynamic-attributes|small-icon|large-icon|description|example|language|import|pageEncoding|isELIgnored)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "\\G(taglib)(?=\\s)", + "captures": { + "1": { + "name": "keyword.control.taglib.jsp" + } + }, + "end": "(?=%>)", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(uri|tagdir|prefix)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "\\G(variable)(?=\\s)", + "captures": { + "1": { + "name": "keyword.control.variable.jsp" + } + }, + "end": "(?=%>)", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(name-given|alias|variable-class|declare|scope|description)(=)((\")[^\"]*(\"))" + } + ] + } + ] + }, + "xml_tags": { + "patterns": [ + { + "begin": "(^\\s*)(?=)", + "beginCaptures": { + "0": { + "name": "punctuation.whitespace.embedded.leading.erb" + } + }, + "end": "(?!\\G)(\\s*$\\n)?", + "endCaptures": { + "0": { + "name": "punctuation.whitespace.embedded.trailing.erb" + } + }, + "patterns": [ + { + "include": "#embedded" + } + ] + }, + { + "include": "#embedded" + }, + { + "include": "#directive" + }, + { + "include": "#actions" + } + ], + "repository": { + "actions": { + "patterns": [ + { + "begin": "(", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.tag.template.attribute.jsp", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(name|trim)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "captures": { + "1": { + "name": "punctuation.definition.tag.begin.jsp" + }, + "2": { + "name": "entity.name.tag.jsp" + }, + "3": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "match": "()", + "name": "meta.tag.template.body.jsp" + }, + { + "begin": "(", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.tag.template.element.jsp", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(name)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "(<)(jsp:doBody)\\b", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.jsp" + }, + "2": { + "name": "entity.name.tag.jsp" + } + }, + "end": "/>", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.tag.template.dobody.jsp", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(var|varReader|scope)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "(", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.tag.template.forward.jsp", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(page)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "(<)(jsp:param)\\b", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.jsp" + }, + "2": { + "name": "entity.name.tag.jsp" + } + }, + "end": "/>", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.tag.template.param.jsp", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(name|value)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "(<)(jsp:getProperty)\\b", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.jsp" + }, + "2": { + "name": "entity.name.tag.jsp" + } + }, + "end": "/>", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.tag.template.getproperty.jsp", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(name|property)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "(", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.tag.template.include.jsp", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(page|flush)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "(<)(jsp:invoke)\\b", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.jsp" + }, + "2": { + "name": "entity.name.tag.jsp" + } + }, + "end": "/>", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.tag.template.invoke.jsp", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(fragment|var|varReader|scope)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "(<)(jsp:output)\\b", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.jsp" + }, + "2": { + "name": "entity.name.tag.jsp" + } + }, + "end": "/>", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.tag.template.output.jsp", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(omit-xml-declaration|doctype-root-element|doctype-system|doctype-public)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "(", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.tag.template.plugin.jsp", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(type|code|codebase|name|archive|align|height|hspace|jreversion|nspluginurl|iepluginurl)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "captures": { + "1": { + "name": "punctuation.definition.tag.begin.jsp" + }, + "2": { + "name": "entity.name.tag.jsp" + }, + "3": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "end": ">", + "match": "()", + "name": "meta.tag.template.fallback.jsp" + }, + { + "begin": "(", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.tag.template.root.jsp", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(xmlns|version|xmlns:taglibPrefix)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "(<)(jsp:setProperty)\\b", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.jsp" + }, + "2": { + "name": "entity.name.tag.jsp" + } + }, + "end": "/>", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.tag.template.setproperty.jsp", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(name|property|value)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "captures": { + "1": { + "name": "punctuation.definition.tag.begin.jsp" + }, + "2": { + "name": "entity.name.tag.jsp" + }, + "3": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "end": ">", + "match": "()", + "name": "meta.tag.template.text.jsp" + }, + { + "begin": "(", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.tag.template.usebean.jsp", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(id|scope|class|type|beanName)(=)((\")[^\"]*(\"))" + } + ] + } + ] + }, + "directive": { + "begin": "(<)(jsp:directive\\.(?=(attribute|include|page|tag|variable)\\s))", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.jsp" + }, + "2": { + "name": "entity.name.tag.jsp" + } + }, + "end": "/>", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.tag.template.$3.jsp", + "patterns": [ + { + "begin": "\\G(attribute)(?=\\s)", + "captures": { + "1": { + "name": "entity.name.tag.jsp" + } + }, + "end": "(?=/>)", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(name|required|fragment|rtexprvalue|type|description)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "\\G(include)(?=\\s)", + "captures": { + "1": { + "name": "entity.name.tag.jsp" + } + }, + "end": "(?=/>)", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(file)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "\\G(page)(?=\\s)", + "captures": { + "1": { + "name": "entity.name.tag.jsp" + } + }, + "end": "(?=/>)", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(language|extends|import|session|buffer|autoFlush|isThreadSafe|info|errorPage|isErrorPage|contentType|pageEncoding|isElIgnored)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "\\G(tag)(?=\\s)", + "captures": { + "1": { + "name": "entity.name.tag.jsp" + } + }, + "end": "(?=/>)", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(display-name|body-content|dynamic-attributes|small-icon|large-icon|description|example|language|import|pageEncoding|isELIgnored)(=)((\")[^\"]*(\"))" + } + ] + }, + { + "begin": "\\G(variable)(?=\\s)", + "captures": { + "1": { + "name": "entity.name.tag.jsp" + } + }, + "end": "(?=/>)", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.jsp" + }, + "2": { + "name": "punctuation.separator.key-value.jsp" + }, + "3": { + "name": "string.quoted.double.jsp" + }, + "4": { + "name": "punctuation.definition.string.begin.jsp" + }, + "5": { + "name": "punctuation.definition.string.end.jsp" + } + }, + "match": "(name-given|alias|variable-class|declare|scope|description)(=)((\")[^\"]*(\"))" + } + ] + } + ] + }, + "embedded": { + "begin": "(<)(jsp:(declaration|expression|scriptlet))(>)", + "beginCaptures": { + "0": { + "name": "meta.tag.template.$3.jsp" + }, + "1": { + "name": "punctuation.definition.tag.begin.jsp" + }, + "2": { + "name": "entity.name.tag.jsp" + }, + "4": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "contentName": "source.java", + "end": "((<)/)(jsp:\\3)(>)", + "endCaptures": { + "0": { + "name": "meta.tag.template.$4.jsp" + }, + "1": { + "name": "punctuation.definition.tag.begin.jsp" + }, + "2": { + "name": "source.java" + }, + "3": { + "name": "entity.name.tag.jsp" + }, + "4": { + "name": "punctuation.definition.tag.end.jsp" + } + }, + "name": "meta.embedded.block.jsp", + "patterns": [ + { + "include": "source.java" + } + ] + } + } + } + }, + "scopeName": "text.html.jsp", + "uuid": "FFF2D8D5-6282-45DF-A508-5C254E29FFC2" +} From 6273c01d7125304e4098f473050ac831c26d6317 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 10:55:54 +0800 Subject: [PATCH 377/441] fix: `git rev-list` raises errors after selected commit in `Histories` page (#1101) Signed-off-by: leo --- src/Commands/QueryCommitChildren.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Commands/QueryCommitChildren.cs b/src/Commands/QueryCommitChildren.cs index 6a6ed909..31fb34f8 100644 --- a/src/Commands/QueryCommitChildren.cs +++ b/src/Commands/QueryCommitChildren.cs @@ -9,7 +9,7 @@ namespace SourceGit.Commands WorkingDirectory = repo; Context = repo; _commit = commit; - Args = $"rev-list -{max} --parents --branches --remotes --ancestry-path={commit} ^{commit}"; + Args = $"rev-list -{max} --parents --branches --remotes --ancestry-path ^{commit}"; } public List Result() From 4b41029768fd7a808e13d57c579dd88e7e7d8dae Mon Sep 17 00:00:00 2001 From: Gadfly Date: Mon, 17 Mar 2025 11:31:50 +0800 Subject: [PATCH 378/441] fix: use better JSP grammar file and add licensing information (#1102) --- src/Resources/Grammars/haxe.json | 6 +- src/Resources/Grammars/hxml.json | 6 +- src/Resources/Grammars/jsp.json | 1226 ++-------------------------- src/Resources/Grammars/kotlin.json | 6 +- src/Resources/Grammars/toml.json | 5 +- 5 files changed, 76 insertions(+), 1173 deletions(-) diff --git a/src/Resources/Grammars/haxe.json b/src/Resources/Grammars/haxe.json index 12acc538..3f78154d 100644 --- a/src/Resources/Grammars/haxe.json +++ b/src/Resources/Grammars/haxe.json @@ -1,7 +1,9 @@ { "information_for_contributors": [ "This file has been copied from https://github.com/vshaxe/haxe-TmLanguage/blob/ddad8b4c6d0781ac20be0481174ec1be772c5da5/haxe.tmLanguage", - "and converted to JSON using https://marketplace.visualstudio.com/items?itemName=pedro-w.tmlanguage" + "and converted to JSON using https://marketplace.visualstudio.com/items?itemName=pedro-w.tmlanguage", + "The original file was licensed under the MIT License", + "https://github.com/vshaxe/haxe-TmLanguage/blob/ddad8b4c6d0781ac20be0481174ec1be772c5da5/LICENSE.md" ], "fileTypes": [ "hx", @@ -2485,4 +2487,4 @@ "name": "variable.other.hx" } } -} \ No newline at end of file +} diff --git a/src/Resources/Grammars/hxml.json b/src/Resources/Grammars/hxml.json index 829c403e..3be42577 100644 --- a/src/Resources/Grammars/hxml.json +++ b/src/Resources/Grammars/hxml.json @@ -1,7 +1,9 @@ { "information_for_contributors": [ "This file has been copied from https://github.com/vshaxe/haxe-TmLanguage/blob/ddad8b4c6d0781ac20be0481174ec1be772c5da5/hxml.tmLanguage", - "and converted to JSON using https://marketplace.visualstudio.com/items?itemName=pedro-w.tmlanguage" + "and converted to JSON using https://marketplace.visualstudio.com/items?itemName=pedro-w.tmlanguage", + "The original file was licensed under the MIT License", + "https://github.com/vshaxe/haxe-TmLanguage/blob/ddad8b4c6d0781ac20be0481174ec1be772c5da5/LICENSE.md" ], "fileTypes": [ "hxml" @@ -67,4 +69,4 @@ ], "scopeName": "source.hxml", "uuid": "CB1B853A-C4C8-42C3-BA70-1B1605BE51C1" -} \ No newline at end of file +} diff --git a/src/Resources/Grammars/jsp.json b/src/Resources/Grammars/jsp.json index f0067748..2fbfd97c 100644 --- a/src/Resources/Grammars/jsp.json +++ b/src/Resources/Grammars/jsp.json @@ -1,1206 +1,100 @@ { "information_for_contributors": [ - "This file has been copied from https://github.com/J0hnMilt0n/vscode-jsp/blob/b33b7e4d47f3b5f4b82e93dfcadd180149153d02/syntaxes/jsp.tmLanguage.json" + "This file has been copied from https://github.com/samuel-weinhardt/vscode-jsp-lang/blob/0e89ecdb13650dbbe5a1e85b47b2e1530bf2f355/syntaxes/jsp.tmLanguage.json", + "The original file was licensed under the MIT License", + "https://github.com/samuel-weinhardt/vscode-jsp-lang/blob/0e89ecdb13650dbbe5a1e85b47b2e1530bf2f355/LICENSE" ], - "fileTypes": [ - "jsp", - "jspf", - "tag" + "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", + "name": "Jakarta Server Pages", + "fileTypes": ["jsp", "jspf", "tag"], + "scopeName": "text.html.jsp", + "patterns": [ + { "include": "#comment" }, + { "include": "#directive" }, + { "include": "#expression" }, + { "include": "text.html.derivative" } ], "injections": { - "text.html.jsp - (meta.embedded.block.jsp | meta.embedded.line.jsp | meta.tag | comment), meta.tag string.quoted": { + "L:text.html.jsp -comment -meta.tag.directive.jsp -meta.tag.scriptlet.jsp": { "patterns": [ - { - "include": "#comment" - }, - { - "include": "#declaration" - }, - { - "include": "#expression" - }, - { - "include": "#el_expression" - }, - { - "include": "#tags" - }, - { - "begin": "(^\\s*)(?=<%(?=\\s))", - "beginCaptures": { - "0": { - "name": "punctuation.whitespace.embedded.leading.erb" - } - }, - "end": "(?!\\G)(\\s*$\\n)?", - "endCaptures": { - "0": { - "name": "punctuation.whitespace.embedded.trailing.erb" - } - }, - "patterns": [ - { - "include": "#scriptlet" - } - ] - }, - { - "include": "#scriptlet" - } - ] + { "include": "#scriptlet" } + ], + "comment": "allow scriptlets anywhere except comments and nested" + }, + "L:meta.attribute (string.quoted.single.html | string.quoted.double.html) -string.template.expression.jsp": { + "patterns": [ + { "include": "#expression" }, + { "include": "text.html.derivative" } + ], + "comment": "allow expressions and tags within HTML attributes (not nested)" } }, - "keyEquivalent": "^~J", - "name": "JavaServer Pages", - "patterns": [ - { - "include": "#xml_tags" - }, - { - "include": "text.html.basic" - } - ], "repository": { "comment": { + "name": "comment.block.jsp", "begin": "<%--", - "captures": { - "0": { - "name": "punctuation.definition.comment.jsp" - } - }, - "end": "--%>", - "name": "comment.block.jsp" + "end": "--%>" }, - "declaration": { - "begin": "<%!", + "directive": { + "name": "meta.tag.directive.jsp", + "begin": "(<)(%@)", + "end": "(%)(>)", "beginCaptures": { - "0": { - "name": "punctuation.section.embedded.begin.jsp" - } + "1": { "name": "punctuation.definition.tag.jsp" }, + "2": { "name": "entity.name.tag.jsp" } }, - "contentName": "source.java", - "end": "(%)>", "endCaptures": { - "0": { - "name": "punctuation.section.embedded.end.jsp" - }, - "1": { - "name": "source.java" - } + "1": { "name": "entity.name.tag.jsp" }, + "2": { "name": "punctuation.definition.tag.jsp" } }, - "name": "meta.embedded.line.declaration.jsp", "patterns": [ { - "include": "source.java" - } - ] - }, - "el_expression": { - "begin": "\\$\\{", - "beginCaptures": { - "0": { - "name": "punctuation.section.embedded.begin.jsp" - } - }, - "contentName": "source.java", - "end": "(\\})", - "endCaptures": { - "0": { - "name": "punctuation.section.embedded.end.jsp" + "match": "\\b(attribute|include|page|tag|taglib|variable)\\b(?!\\s*=)", + "name": "keyword.control.directive.jsp" }, - "1": { - "name": "source.java" - } - }, - "name": "meta.embedded.line.el_expression.jsp", - "patterns": [ - { - "include": "source.java" - } - ] - }, - "expression": { - "begin": "<%=", - "beginCaptures": { - "0": { - "name": "punctuation.section.embedded.begin.jsp" - } - }, - "contentName": "source.java", - "end": "(%)>", - "endCaptures": { - "0": { - "name": "punctuation.section.embedded.end.jsp" - }, - "1": { - "name": "source.java" - } - }, - "name": "meta.embedded.line.expression.jsp", - "patterns": [ - { - "include": "source.java" - } + { "include": "text.html.basic#attribute" } ] }, "scriptlet": { - "begin": "<%", + "name": "meta.tag.scriptlet.jsp", + "contentName": "meta.embedded.block.java", + "begin": "(<)(%[\\s!=])", + "end": "(%)(>)", "beginCaptures": { - "0": { - "name": "punctuation.section.embedded.begin.jsp" - } + "1": { "name": "punctuation.definition.tag.jsp" }, + "2": { "name": "entity.name.tag.jsp" } }, - "contentName": "source.java", - "end": "(%)>", "endCaptures": { - "0": { - "name": "punctuation.section.embedded.end.jsp" - }, - "1": { - "name": "source.java" - } + "1": { "name": "entity.name.tag.jsp" }, + "2": { "name": "punctuation.definition.tag.jsp" } }, - "name": "meta.embedded.block.scriptlet.jsp", "patterns": [ { - "match": "\\{", - "name": "punctuation.section.scope.begin.java" + "match": "\\{(?=\\s*(%>|$))", + "comment": "consume trailing curly brackets for fragmented scriptlets" }, - { - "match": "\\}", - "name": "punctuation.section.scope.end.java" - }, - { - "include": "source.java" - } + { "include": "source.java" } ] }, - "tags": { - "begin": "(<%@)\\s*(?=(attribute|include|page|tag|taglib|variable)\\s)", + "expression": { + "name": "string.template.expression.jsp", + "contentName": "meta.embedded.block.java", + "begin": "[$#]\\{", + "end": "\\}", "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.jsp" - } + "0": { "name": "punctuation.definition.template-expression.begin.jsp" } }, - "end": "%>", "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.jsp" - } + "0": { "name": "punctuation.definition.template-expression.end.jsp" } }, - "name": "meta.tag.template.include.jsp", "patterns": [ - { - "begin": "\\G(attribute)(?=\\s)", - "captures": { - "1": { - "name": "keyword.control.attribute.jsp" - } - }, - "end": "(?=%>)", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(name|required|fragment|rtexprvalue|type|description)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "\\G(include)(?=\\s)", - "captures": { - "1": { - "name": "keyword.control.include.jsp" - } - }, - "end": "(?=%>)", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(file)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "\\G(page)(?=\\s)", - "captures": { - "1": { - "name": "keyword.control.page.jsp" - } - }, - "end": "(?=%>)", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(language|extends|import|session|buffer|autoFlush|isThreadSafe|info|errorPage|isErrorPage|contentType|pageEncoding|isElIgnored)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "\\G(tag)(?=\\s)", - "captures": { - "1": { - "name": "keyword.control.tag.jsp" - } - }, - "end": "(?=%>)", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(display-name|body-content|dynamic-attributes|small-icon|large-icon|description|example|language|import|pageEncoding|isELIgnored)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "\\G(taglib)(?=\\s)", - "captures": { - "1": { - "name": "keyword.control.taglib.jsp" - } - }, - "end": "(?=%>)", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(uri|tagdir|prefix)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "\\G(variable)(?=\\s)", - "captures": { - "1": { - "name": "keyword.control.variable.jsp" - } - }, - "end": "(?=%>)", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(name-given|alias|variable-class|declare|scope|description)(=)((\")[^\"]*(\"))" - } - ] - } + { "include": "#escape" }, + { "include": "source.java" } ] }, - "xml_tags": { - "patterns": [ - { - "begin": "(^\\s*)(?=)", - "beginCaptures": { - "0": { - "name": "punctuation.whitespace.embedded.leading.erb" - } - }, - "end": "(?!\\G)(\\s*$\\n)?", - "endCaptures": { - "0": { - "name": "punctuation.whitespace.embedded.trailing.erb" - } - }, - "patterns": [ - { - "include": "#embedded" - } - ] - }, - { - "include": "#embedded" - }, - { - "include": "#directive" - }, - { - "include": "#actions" - } - ], - "repository": { - "actions": { - "patterns": [ - { - "begin": "(", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "name": "meta.tag.template.attribute.jsp", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(name|trim)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "captures": { - "1": { - "name": "punctuation.definition.tag.begin.jsp" - }, - "2": { - "name": "entity.name.tag.jsp" - }, - "3": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "match": "()", - "name": "meta.tag.template.body.jsp" - }, - { - "begin": "(", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "name": "meta.tag.template.element.jsp", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(name)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "(<)(jsp:doBody)\\b", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.jsp" - }, - "2": { - "name": "entity.name.tag.jsp" - } - }, - "end": "/>", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "name": "meta.tag.template.dobody.jsp", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(var|varReader|scope)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "(", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "name": "meta.tag.template.forward.jsp", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(page)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "(<)(jsp:param)\\b", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.jsp" - }, - "2": { - "name": "entity.name.tag.jsp" - } - }, - "end": "/>", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "name": "meta.tag.template.param.jsp", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(name|value)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "(<)(jsp:getProperty)\\b", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.jsp" - }, - "2": { - "name": "entity.name.tag.jsp" - } - }, - "end": "/>", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "name": "meta.tag.template.getproperty.jsp", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(name|property)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "(", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "name": "meta.tag.template.include.jsp", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(page|flush)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "(<)(jsp:invoke)\\b", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.jsp" - }, - "2": { - "name": "entity.name.tag.jsp" - } - }, - "end": "/>", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "name": "meta.tag.template.invoke.jsp", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(fragment|var|varReader|scope)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "(<)(jsp:output)\\b", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.jsp" - }, - "2": { - "name": "entity.name.tag.jsp" - } - }, - "end": "/>", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "name": "meta.tag.template.output.jsp", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(omit-xml-declaration|doctype-root-element|doctype-system|doctype-public)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "(", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "name": "meta.tag.template.plugin.jsp", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(type|code|codebase|name|archive|align|height|hspace|jreversion|nspluginurl|iepluginurl)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "captures": { - "1": { - "name": "punctuation.definition.tag.begin.jsp" - }, - "2": { - "name": "entity.name.tag.jsp" - }, - "3": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "end": ">", - "match": "()", - "name": "meta.tag.template.fallback.jsp" - }, - { - "begin": "(", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "name": "meta.tag.template.root.jsp", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(xmlns|version|xmlns:taglibPrefix)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "(<)(jsp:setProperty)\\b", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.jsp" - }, - "2": { - "name": "entity.name.tag.jsp" - } - }, - "end": "/>", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "name": "meta.tag.template.setproperty.jsp", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(name|property|value)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "captures": { - "1": { - "name": "punctuation.definition.tag.begin.jsp" - }, - "2": { - "name": "entity.name.tag.jsp" - }, - "3": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "end": ">", - "match": "()", - "name": "meta.tag.template.text.jsp" - }, - { - "begin": "(", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "name": "meta.tag.template.usebean.jsp", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(id|scope|class|type|beanName)(=)((\")[^\"]*(\"))" - } - ] - } - ] - }, - "directive": { - "begin": "(<)(jsp:directive\\.(?=(attribute|include|page|tag|variable)\\s))", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.jsp" - }, - "2": { - "name": "entity.name.tag.jsp" - } - }, - "end": "/>", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "name": "meta.tag.template.$3.jsp", - "patterns": [ - { - "begin": "\\G(attribute)(?=\\s)", - "captures": { - "1": { - "name": "entity.name.tag.jsp" - } - }, - "end": "(?=/>)", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(name|required|fragment|rtexprvalue|type|description)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "\\G(include)(?=\\s)", - "captures": { - "1": { - "name": "entity.name.tag.jsp" - } - }, - "end": "(?=/>)", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(file)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "\\G(page)(?=\\s)", - "captures": { - "1": { - "name": "entity.name.tag.jsp" - } - }, - "end": "(?=/>)", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(language|extends|import|session|buffer|autoFlush|isThreadSafe|info|errorPage|isErrorPage|contentType|pageEncoding|isElIgnored)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "\\G(tag)(?=\\s)", - "captures": { - "1": { - "name": "entity.name.tag.jsp" - } - }, - "end": "(?=/>)", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(display-name|body-content|dynamic-attributes|small-icon|large-icon|description|example|language|import|pageEncoding|isELIgnored)(=)((\")[^\"]*(\"))" - } - ] - }, - { - "begin": "\\G(variable)(?=\\s)", - "captures": { - "1": { - "name": "entity.name.tag.jsp" - } - }, - "end": "(?=/>)", - "patterns": [ - { - "captures": { - "1": { - "name": "entity.other.attribute-name.jsp" - }, - "2": { - "name": "punctuation.separator.key-value.jsp" - }, - "3": { - "name": "string.quoted.double.jsp" - }, - "4": { - "name": "punctuation.definition.string.begin.jsp" - }, - "5": { - "name": "punctuation.definition.string.end.jsp" - } - }, - "match": "(name-given|alias|variable-class|declare|scope|description)(=)((\")[^\"]*(\"))" - } - ] - } - ] - }, - "embedded": { - "begin": "(<)(jsp:(declaration|expression|scriptlet))(>)", - "beginCaptures": { - "0": { - "name": "meta.tag.template.$3.jsp" - }, - "1": { - "name": "punctuation.definition.tag.begin.jsp" - }, - "2": { - "name": "entity.name.tag.jsp" - }, - "4": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "contentName": "source.java", - "end": "((<)/)(jsp:\\3)(>)", - "endCaptures": { - "0": { - "name": "meta.tag.template.$4.jsp" - }, - "1": { - "name": "punctuation.definition.tag.begin.jsp" - }, - "2": { - "name": "source.java" - }, - "3": { - "name": "entity.name.tag.jsp" - }, - "4": { - "name": "punctuation.definition.tag.end.jsp" - } - }, - "name": "meta.embedded.block.jsp", - "patterns": [ - { - "include": "source.java" - } - ] - } - } + "escape": { + "match": "\\\\.", + "name": "constant.character.escape.jsp" } - }, - "scopeName": "text.html.jsp", - "uuid": "FFF2D8D5-6282-45DF-A508-5C254E29FFC2" + } } diff --git a/src/Resources/Grammars/kotlin.json b/src/Resources/Grammars/kotlin.json index e8f844d0..2857f717 100644 --- a/src/Resources/Grammars/kotlin.json +++ b/src/Resources/Grammars/kotlin.json @@ -1,6 +1,8 @@ { "information_for_contributors": [ - "This file has been copied from https://github.com/eclipse/buildship/blob/6bb773e7692f913dec27105129ebe388de34e68b/org.eclipse.buildship.kotlindsl.provider/kotlin.tmLanguage.json" + "This file has been copied from https://github.com/eclipse/buildship/blob/6bb773e7692f913dec27105129ebe388de34e68b/org.eclipse.buildship.kotlindsl.provider/kotlin.tmLanguage.json", + "The original file was licensed under the Eclipse Public License, Version 1.0", + "https://github.com/eclipse-buildship/buildship/blob/6bb773e7692f913dec27105129ebe388de34e68b/README.md" ], "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", "name": "Kotlin", @@ -698,4 +700,4 @@ "name": "variable.language.this.kotlin" } } -} \ No newline at end of file +} diff --git a/src/Resources/Grammars/toml.json b/src/Resources/Grammars/toml.json index 86c2ef87..6be4678f 100644 --- a/src/Resources/Grammars/toml.json +++ b/src/Resources/Grammars/toml.json @@ -3,7 +3,10 @@ "scopeName": "source.toml", "uuid": "8b4e5008-c50d-11ea-a91b-54ee75aeeb97", "information_for_contributors": [ - "Originally was maintained by aster (galaster@foxmail.com). This notice is only kept here for the record, please don't send e-mails about bugs and other issues." + "Originally was maintained by aster (galaster@foxmail.com). This notice is only kept here for the record, please don't send e-mails about bugs and other issues.", + "This file has been copied from https://github.com/kkiyama117/coc-toml/blob/main/toml.tmLanguage.json", + "The original file was licensed under the MIT License", + "https://github.com/kkiyama117/coc-toml/blob/main/LICENSE" ], "patterns": [ { From a480ba0139f0f5c792a722b017ca6bcfcb70d389 Mon Sep 17 00:00:00 2001 From: Gadfly Date: Mon, 17 Mar 2025 11:41:13 +0800 Subject: [PATCH 379/441] docs: Add third-party components and licenses section (cherry picked from commit 95c697248755f7b6de4d2d0bfdaa9de1e572c9f6) --- README.md | 4 ++++ THIRD-PARTY-LICENSES.md | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 THIRD-PARTY-LICENSES.md diff --git a/README.md b/README.md index c932ec8a..670456c2 100644 --- a/README.md +++ b/README.md @@ -201,3 +201,7 @@ dotnet run --project src/SourceGit.csproj Thanks to all the people who contribute. [![Contributors](https://contrib.rocks/image?repo=sourcegit-scm/sourcegit&columns=20)](https://github.com/sourcegit-scm/sourcegit/graphs/contributors) + +## Third-Party Components + +For detailed license information, see [THIRD-PARTY-LICENSES.md](THIRD-PARTY-LICENSES.md). diff --git a/THIRD-PARTY-LICENSES.md b/THIRD-PARTY-LICENSES.md new file mode 100644 index 00000000..6188ad8b --- /dev/null +++ b/THIRD-PARTY-LICENSES.md @@ -0,0 +1,38 @@ +# Third-Party Licenses + +This project incorporates components from the following third parties: + +## haxe-TmLanguage + +- **Source**: https://github.com/vshaxe/haxe-TmLanguage +- **Commit**: ddad8b4c6d0781ac20be0481174ec1be772c5da5 +- **License**: MIT License +- **License Link**: https://github.com/vshaxe/haxe-TmLanguage/blob/ddad8b4c6d0781ac20be0481174ec1be772c5da5/LICENSE.md + +## coc-toml + +- **Source**: https://github.com/kkiyama117/coc-toml +- **Commit**: aac3e0c65955c03314b2733041b19f903b7cc447 +- **License**: MIT License +- **License Link**: https://github.com/kkiyama117/coc-toml/blob/aac3e0c65955c03314b2733041b19f903b7cc447/LICENSE + +## eclipse-buildship + +- **Source**: https://github.com/eclipse/buildship +- **Commit**: 6bb773e7692f913dec27105129ebe388de34e68b +- **License**: Eclipse Public License 1.0 +- **License Link**: https://github.com/eclipse-buildship/buildship/blob/6bb773e7692f913dec27105129ebe388de34e68b/README.md + +## vscode-jsp-lang + +- **Source**: https://github.com/samuel-weinhardt/vscode-jsp-lang +- **Commit**: 0e89ecdb13650dbbe5a1e85b47b2e1530bf2f355 +- **License**: MIT License +- **License Link**: https://github.com/samuel-weinhardt/vscode-jsp-lang/blob/0e89ecdb13650dbbe5a1e85b47b2e1530bf2f355/LICENSE + +## JetBrainsMono + +- **Source**: https://github.com/JetBrains/JetBrainsMono +- **Commit**: v2.304 +- **License**: SIL Open Font License, Version 1.1 +- **License Link**: https://github.com/JetBrains/JetBrainsMono/blob/v2.304/OFL.txt From 8f8385072c7a0ef1bb527c93921d335d38edfc94 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 11:56:33 +0800 Subject: [PATCH 380/441] doc: add third-party components Signed-off-by: leo --- THIRD-PARTY-LICENSES.md | 43 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/THIRD-PARTY-LICENSES.md b/THIRD-PARTY-LICENSES.md index 6188ad8b..e4e0e07b 100644 --- a/THIRD-PARTY-LICENSES.md +++ b/THIRD-PARTY-LICENSES.md @@ -2,6 +2,48 @@ This project incorporates components from the following third parties: +## AvaloniaUI + +- **Source**: https://github.com/AvaloniaUI/Avalonia +- **Version**: 11.2.5 +- **License**: MIT License +- **License Link**: https://github.com/AvaloniaUI/Avalonia/blob/master/licence.md + +## AvaloniaEdit + +- **Source**: https://github.com/AvaloniaUI/AvaloniaEdit +- **Version**: 11.2.0 +- **License**: MIT License +- **License Link**: https://github.com/AvaloniaUI/AvaloniaEdit/blob/master/LICENSE + +## LiveChartsCore.SkiaSharpView.Avalonia + +- **Source**: https://github.com/beto-rodriguez/LiveCharts2 +- **Version**: 2.0.0-rc5.4 +- **License**: MIT License +- **License Link**: https://github.com/beto-rodriguez/LiveCharts2/blob/master/LICENSE + +## TextMateSharp + +- **Source**: https://github.com/danipen/TextMateSharp +- **Version**: 1.0.66 +- **License**: MIT License +- **License Link**: https://github.com/danipen/TextMateSharp/blob/master/LICENSE.md + +## OpenAI .NET SDK + +- **Source**: https://github.com/openai/openai-dotnet +- **Version**: 2.2.0-beta2 +- **License**: MIT License +- **License Link**: https://github.com/openai/openai-dotnet/blob/main/LICENSE + +## Azure.AI.OpenAI + +- **Source**: https://github.com/Azure/azure-sdk-for-net +- **Version**: 2.2.0-beta2 +- **License**: MIT License +- **License Link**: https://github.com/Azure/azure-sdk-for-net/blob/main/LICENSE.txt + ## haxe-TmLanguage - **Source**: https://github.com/vshaxe/haxe-TmLanguage @@ -36,3 +78,4 @@ This project incorporates components from the following third parties: - **Commit**: v2.304 - **License**: SIL Open Font License, Version 1.1 - **License Link**: https://github.com/JetBrains/JetBrainsMono/blob/v2.304/OFL.txt + From 99a45335feb91dc588baabab01676d4abe4eb880 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 12:01:29 +0800 Subject: [PATCH 381/441] doc: group third-party components by types Signed-off-by: leo --- THIRD-PARTY-LICENSES.md | 73 ++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/THIRD-PARTY-LICENSES.md b/THIRD-PARTY-LICENSES.md index e4e0e07b..722414b2 100644 --- a/THIRD-PARTY-LICENSES.md +++ b/THIRD-PARTY-LICENSES.md @@ -2,80 +2,85 @@ This project incorporates components from the following third parties: -## AvaloniaUI +## Packages + +### AvaloniaUI - **Source**: https://github.com/AvaloniaUI/Avalonia - **Version**: 11.2.5 - **License**: MIT License - **License Link**: https://github.com/AvaloniaUI/Avalonia/blob/master/licence.md -## AvaloniaEdit +### AvaloniaEdit - **Source**: https://github.com/AvaloniaUI/AvaloniaEdit - **Version**: 11.2.0 - **License**: MIT License - **License Link**: https://github.com/AvaloniaUI/AvaloniaEdit/blob/master/LICENSE -## LiveChartsCore.SkiaSharpView.Avalonia +### LiveChartsCore.SkiaSharpView.Avalonia - **Source**: https://github.com/beto-rodriguez/LiveCharts2 - **Version**: 2.0.0-rc5.4 - **License**: MIT License - **License Link**: https://github.com/beto-rodriguez/LiveCharts2/blob/master/LICENSE -## TextMateSharp +### TextMateSharp - **Source**: https://github.com/danipen/TextMateSharp - **Version**: 1.0.66 - **License**: MIT License - **License Link**: https://github.com/danipen/TextMateSharp/blob/master/LICENSE.md -## OpenAI .NET SDK +### OpenAI .NET SDK - **Source**: https://github.com/openai/openai-dotnet - **Version**: 2.2.0-beta2 - **License**: MIT License - **License Link**: https://github.com/openai/openai-dotnet/blob/main/LICENSE -## Azure.AI.OpenAI +### Azure.AI.OpenAI - **Source**: https://github.com/Azure/azure-sdk-for-net - **Version**: 2.2.0-beta2 - **License**: MIT License - **License Link**: https://github.com/Azure/azure-sdk-for-net/blob/main/LICENSE.txt -## haxe-TmLanguage +## Fonts -- **Source**: https://github.com/vshaxe/haxe-TmLanguage -- **Commit**: ddad8b4c6d0781ac20be0481174ec1be772c5da5 -- **License**: MIT License -- **License Link**: https://github.com/vshaxe/haxe-TmLanguage/blob/ddad8b4c6d0781ac20be0481174ec1be772c5da5/LICENSE.md - -## coc-toml - -- **Source**: https://github.com/kkiyama117/coc-toml -- **Commit**: aac3e0c65955c03314b2733041b19f903b7cc447 -- **License**: MIT License -- **License Link**: https://github.com/kkiyama117/coc-toml/blob/aac3e0c65955c03314b2733041b19f903b7cc447/LICENSE - -## eclipse-buildship - -- **Source**: https://github.com/eclipse/buildship -- **Commit**: 6bb773e7692f913dec27105129ebe388de34e68b -- **License**: Eclipse Public License 1.0 -- **License Link**: https://github.com/eclipse-buildship/buildship/blob/6bb773e7692f913dec27105129ebe388de34e68b/README.md - -## vscode-jsp-lang - -- **Source**: https://github.com/samuel-weinhardt/vscode-jsp-lang -- **Commit**: 0e89ecdb13650dbbe5a1e85b47b2e1530bf2f355 -- **License**: MIT License -- **License Link**: https://github.com/samuel-weinhardt/vscode-jsp-lang/blob/0e89ecdb13650dbbe5a1e85b47b2e1530bf2f355/LICENSE - -## JetBrainsMono +### JetBrainsMono - **Source**: https://github.com/JetBrains/JetBrainsMono - **Commit**: v2.304 - **License**: SIL Open Font License, Version 1.1 - **License Link**: https://github.com/JetBrains/JetBrainsMono/blob/v2.304/OFL.txt +## Gramar Files + +### haxe-TmLanguage + +- **Source**: https://github.com/vshaxe/haxe-TmLanguage +- **Commit**: ddad8b4c6d0781ac20be0481174ec1be772c5da5 +- **License**: MIT License +- **License Link**: https://github.com/vshaxe/haxe-TmLanguage/blob/ddad8b4c6d0781ac20be0481174ec1be772c5da5/LICENSE.md + +### coc-toml + +- **Source**: https://github.com/kkiyama117/coc-toml +- **Commit**: aac3e0c65955c03314b2733041b19f903b7cc447 +- **License**: MIT License +- **License Link**: https://github.com/kkiyama117/coc-toml/blob/aac3e0c65955c03314b2733041b19f903b7cc447/LICENSE + +### eclipse-buildship + +- **Source**: https://github.com/eclipse/buildship +- **Commit**: 6bb773e7692f913dec27105129ebe388de34e68b +- **License**: Eclipse Public License 1.0 +- **License Link**: https://github.com/eclipse-buildship/buildship/blob/6bb773e7692f913dec27105129ebe388de34e68b/README.md + +### vscode-jsp-lang + +- **Source**: https://github.com/samuel-weinhardt/vscode-jsp-lang +- **Commit**: 0e89ecdb13650dbbe5a1e85b47b2e1530bf2f355 +- **License**: MIT License +- **License Link**: https://github.com/samuel-weinhardt/vscode-jsp-lang/blob/0e89ecdb13650dbbe5a1e85b47b2e1530bf2f355/LICENSE From 10fd0f9d15d0d58f0f27c5128c97b9abbdaea161 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 12:02:32 +0800 Subject: [PATCH 382/441] doc: fix typo Signed-off-by: leo --- THIRD-PARTY-LICENSES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/THIRD-PARTY-LICENSES.md b/THIRD-PARTY-LICENSES.md index 722414b2..2338263c 100644 --- a/THIRD-PARTY-LICENSES.md +++ b/THIRD-PARTY-LICENSES.md @@ -55,7 +55,7 @@ This project incorporates components from the following third parties: - **License**: SIL Open Font License, Version 1.1 - **License Link**: https://github.com/JetBrains/JetBrainsMono/blob/v2.304/OFL.txt -## Gramar Files +## Grammar Files ### haxe-TmLanguage From ddfc868df3c20acd77a74d4c12ecaf07c22c6c04 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 15:08:49 +0800 Subject: [PATCH 383/441] ux: re-design merge option style Signed-off-by: leo --- src/Models/MergeMode.cs | 2 +- src/ViewModels/Merge.cs | 10 +++++----- src/Views/Merge.axaml | 27 ++++++++++++++++++++++----- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/Models/MergeMode.cs b/src/Models/MergeMode.cs index 15e3f7e9..e4389b32 100644 --- a/src/Models/MergeMode.cs +++ b/src/Models/MergeMode.cs @@ -6,7 +6,7 @@ [ new MergeMode("Default", "Fast-forward if possible", ""), new MergeMode("No Fast-forward", "Always create a merge commit", "--no-ff"), - new MergeMode("Squash", "Use '--squash'", "--squash"), + new MergeMode("Squash", "Squash merge", "--squash"), new MergeMode("Don't commit", "Merge without commit", "--no-ff --no-commit"), ]; diff --git a/src/ViewModels/Merge.cs b/src/ViewModels/Merge.cs index 174bb1e1..bde9b66d 100644 --- a/src/ViewModels/Merge.cs +++ b/src/ViewModels/Merge.cs @@ -15,7 +15,7 @@ namespace SourceGit.ViewModels get; } - public Models.MergeMode SelectedMode + public Models.MergeMode Mode { get; set; @@ -28,7 +28,7 @@ namespace SourceGit.ViewModels Source = source; Into = into; - SelectedMode = AutoSelectMergeMode(); + Mode = AutoSelectMergeMode(); View = new Views.Merge() { DataContext = this }; } @@ -39,7 +39,7 @@ namespace SourceGit.ViewModels Source = source; Into = into; - SelectedMode = AutoSelectMergeMode(); + Mode = AutoSelectMergeMode(); View = new Views.Merge() { DataContext = this }; } @@ -50,7 +50,7 @@ namespace SourceGit.ViewModels Source = source; Into = into; - SelectedMode = AutoSelectMergeMode(); + Mode = AutoSelectMergeMode(); View = new Views.Merge() { DataContext = this }; } @@ -61,7 +61,7 @@ namespace SourceGit.ViewModels return Task.Run(() => { - new Commands.Merge(_repo.FullPath, _sourceName, SelectedMode.Arg, SetProgressDescription).Exec(); + new Commands.Merge(_repo.FullPath, _sourceName, Mode.Arg, SetProgressDescription).Exec(); CallUIThread(() => _repo.SetWatcherEnabled(true)); return true; }); diff --git a/src/Views/Merge.axaml b/src/Views/Merge.axaml index 805ac6d0..b7c76b6b 100644 --- a/src/Views/Merge.axaml +++ b/src/Views/Merge.axaml @@ -60,15 +60,32 @@ Height="28" Padding="8,0" VerticalAlignment="Center" HorizontalAlignment="Stretch" ItemsSource="{Binding Source={x:Static m:MergeMode.Supported}}" - SelectedItem="{Binding SelectedMode, Mode=TwoWay}"> + SelectedItem="{Binding Mode, Mode=TwoWay}" + Grid.IsSharedSizeScope="True"> - - - - + + + + + + + + + + + + + + + + + + + + From cdd1926e2f2eb4be2c1ee381c2e567787ea79599 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 15:30:32 +0800 Subject: [PATCH 384/441] refactor: rewrite `git apply` implementation - Do not translate commandline options for `git` - Re-design combox layout for `git apply` popup Signed-off-by: leo --- src/Models/ApplyWhiteSpaceMode.cs | 12 ++++++++++-- src/Resources/Locales/de_DE.axaml | 8 -------- src/Resources/Locales/en_US.axaml | 8 -------- src/Resources/Locales/es_ES.axaml | 8 -------- src/Resources/Locales/fr_FR.axaml | 8 -------- src/Resources/Locales/it_IT.axaml | 8 -------- src/Resources/Locales/pt_BR.axaml | 8 -------- src/Resources/Locales/ru_RU.axaml | 8 -------- src/Resources/Locales/zh_CN.axaml | 8 -------- src/Resources/Locales/zh_TW.axaml | 8 -------- src/ViewModels/Apply.cs | 20 ++------------------ src/Views/Apply.axaml | 31 ++++++++++++++++++++++++------- 12 files changed, 36 insertions(+), 99 deletions(-) diff --git a/src/Models/ApplyWhiteSpaceMode.cs b/src/Models/ApplyWhiteSpaceMode.cs index 6fbce0b2..aad45f57 100644 --- a/src/Models/ApplyWhiteSpaceMode.cs +++ b/src/Models/ApplyWhiteSpaceMode.cs @@ -2,14 +2,22 @@ { public class ApplyWhiteSpaceMode { + public static readonly ApplyWhiteSpaceMode[] Supported = + [ + new ApplyWhiteSpaceMode("No Warn", "Turns off the trailing whitespace warning", "nowarn"), + new ApplyWhiteSpaceMode("Warn", "Outputs warnings for a few such errors, but applies", "warn"), + new ApplyWhiteSpaceMode("Error", "Raise errors and refuses to apply the patch", "error"), + new ApplyWhiteSpaceMode("Error All", "Similar to 'error', but shows more", "error-all"), + ]; + public string Name { get; set; } public string Desc { get; set; } public string Arg { get; set; } public ApplyWhiteSpaceMode(string n, string d, string a) { - Name = App.Text(n); - Desc = App.Text(d); + Name = n; + Desc = d; Arg = a; } } diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index aff8ffc5..31dc1d9b 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -25,18 +25,10 @@ Verwende OpenAI, um Commit-Nachrichten zu generieren Als Commit-Nachricht verwenden Patch - Fehler - Fehler werfen und anwenden des Patches verweigern - Alle Fehler - Ähnlich wie 'Fehler', zeigt aber mehr an Patch-Datei: Wähle die anzuwendende .patch-Datei Ignoriere Leerzeichenänderungen - Keine Warnungen - Keine Warnung vor Leerzeichen am Zeilenende Patch anwenden - Warnen - Gibt eine Warnung für ein paar solcher Fehler aus, aber wendet es an Leerzeichen: Stash anwenden Nach dem Anwenden löschen diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 818bd9bb..b1f83836 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -22,18 +22,10 @@ Use AI to generate commit message APPLY AS COMMIT MESSAGE Patch - Error - Raise errors and refuses to apply the patch - Error All - Similar to 'error', but shows more Patch File: Select .patch file to apply Ignore whitespace changes - No Warn - Turns off the trailing whitespace warning Apply Patch - Warn - Outputs warnings for a few such errors, but applies Whitespace: Apply Stash Delete after applying diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index e909a14e..6bf38df1 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -25,18 +25,10 @@ Usar OpenAI para generar mensaje de commit APLICAR CÓMO MENSAJE DE COMMIT Aplicar Parche - Error - Genera errores y se niega a aplicar el parche - Error Todo - Similar a 'error', pero muestra más Archivo del Parche: Seleccionar archivo .patch para aplicar Ignorar cambios de espacios en blanco - Sin Advertencia - Desactiva la advertencia de espacios en blanco al final Aplicar Parche - Advertencia - Genera advertencias para algunos de estos errores, pero aplica Espacios en Blanco: Aplicar Stash Borrar después de aplicar diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index aecea9ad..ebb3ba89 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -23,18 +23,10 @@ Assistant IA Utiliser l'IA pour générer un message de commit Appliquer - Erreur - Soulever les erreurs et refuser d'appliquer le patch - Toutes les erreurs - Similaire à 'Erreur', mais plus détaillé Fichier de patch : Selectionner le fichier .patch à appliquer Ignorer les changements d'espaces blancs - Pas d'avertissement - Désactiver l'avertissement sur les espaces blancs terminaux Appliquer le patch - Avertissement - Affiche des avertissements pour ce type d'erreurs tout en appliquant le patch Espaces blancs : Archiver... Enregistrer l'archive sous : diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml index 4dcc8771..ebfd3939 100644 --- a/src/Resources/Locales/it_IT.axaml +++ b/src/Resources/Locales/it_IT.axaml @@ -25,18 +25,10 @@ Usa AI per generare il messaggio di commit APPLICA COME MESSAGGIO DI COMMIT Applica - Errore - Genera errori e si rifiuta di applicare la patch - Tutti gli errori - Simile a 'errore', ma mostra di più File Patch: Seleziona file .patch da applicare Ignora modifiche agli spazi - Nessun avviso - Disattiva l'avviso sugli spazi finali Applica Patch - Avviso - Mostra avvisi per alcuni errori, ma applica comunque Spazi: Applica lo stash Rimuovi dopo aver applicato diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index b146bf0e..b4677840 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -48,18 +48,10 @@ Assietente IA Utilizar IA para gerar mensagem de commit Patch - Erro - Erros levantados e se recusa a aplicar o patch - Erro Total - Semelhante a 'erro', mas mostra mais Arquivo de Patch: Selecione o arquivo .patch para aplicar Ignorar mudanças de espaço em branco - Sem Aviso - Desativa o aviso de espaço em branco no final Aplicar Patch - Aviso - Emite avisos para alguns erros, mas aplica Espaço em Branco: Arquivar... Salvar Arquivo Como: diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index 07fb7c94..b2ba2158 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -25,18 +25,10 @@ Использовать OpenAI для создания сообщения о ревизии ПРИМЕНИТЬ КАК СООБЩЕНИЕ РЕВИЗИИ Исправить - Ошибка - Выдает ошибки и отказывается применять заплатку - Все ошибки - Аналогично «ошибке», но показывает больше Файл заплатки: Выберите файл .patch для применения Игнорировать изменения пробелов - Нет предупреждений - Отключить предупреждения о пробелах в конце Применить заплатку - Предупреждать - Выдавать предупреждения о нескольких таких ошибках, но применять Пробел: Отложить Удалить после применения diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 2d160ad2..768061dd 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -25,18 +25,10 @@ 使用AI助手生成提交信息 应用本次生成 应用补丁(apply) - 错误 - 输出错误,并终止应用补丁 - 更多错误 - 与【错误】级别相似,但输出内容更多 补丁文件 : 选择补丁文件 忽略空白符号 - 忽略 - 关闭所有警告 应用补丁 - 警告 - 应用补丁,输出关于空白符的警告 空白符号处理 : 应用贮藏 在成功应用后丢弃该贮藏 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index e50a600d..6d63c1ee 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -25,18 +25,10 @@ 使用 AI 產生提交訊息 套用為提交訊息 套用修補檔 (apply patch) - 錯誤 - 輸出錯誤,並中止套用修補檔 - 更多錯誤 - 與 [錯誤] 級別相似,但輸出更多內容 修補檔: 選擇修補檔 忽略空白符號 - 忽略 - 關閉所有警告 套用修補檔 - 警告 - 套用修補檔,輸出關於空白字元的警告 空白字元處理: 套用擱置變更 套用擱置變更後刪除 diff --git a/src/ViewModels/Apply.cs b/src/ViewModels/Apply.cs index 09567761..60001476 100644 --- a/src/ViewModels/Apply.cs +++ b/src/ViewModels/Apply.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.IO; using System.Threading.Tasks; @@ -21,12 +20,6 @@ namespace SourceGit.ViewModels set => SetProperty(ref _ignoreWhiteSpace, value); } - public List WhiteSpaceModes - { - get; - private set; - } - public Models.ApplyWhiteSpaceMode SelectedWhiteSpaceMode { get; @@ -37,23 +30,14 @@ namespace SourceGit.ViewModels { _repo = repo; - WhiteSpaceModes = new List { - new Models.ApplyWhiteSpaceMode("Apply.NoWarn", "Apply.NoWarn.Desc", "nowarn"), - new Models.ApplyWhiteSpaceMode("Apply.Warn", "Apply.Warn.Desc", "warn"), - new Models.ApplyWhiteSpaceMode("Apply.Error", "Apply.Error.Desc", "error"), - new Models.ApplyWhiteSpaceMode("Apply.ErrorAll", "Apply.ErrorAll.Desc", "error-all") - }; - SelectedWhiteSpaceMode = WhiteSpaceModes[0]; - + SelectedWhiteSpaceMode = Models.ApplyWhiteSpaceMode.Supported[0]; View = new Views.Apply() { DataContext = this }; } public static ValidationResult ValidatePatchFile(string file, ValidationContext _) { if (File.Exists(file)) - { return ValidationResult.Success; - } return new ValidationResult($"File '{file}' can NOT be found!!!"); } diff --git a/src/Views/Apply.axaml b/src/Views/Apply.axaml index a5100cd6..6c2478bb 100644 --- a/src/Views/Apply.axaml +++ b/src/Views/Apply.axaml @@ -39,17 +39,34 @@ + IsEnabled="{Binding !IgnoreWhiteSpace}" + Grid.IsSharedSizeScope="True"> - - - - - + + + + + + + + + + + + + + + + + + + + + Date: Mon, 17 Mar 2025 07:30:48 +0000 Subject: [PATCH 385/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 670456c2..f9216874 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.07%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-%E2%88%9A-brightgreen)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.66%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.39%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.06%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-%E2%88%9A-brightgreen)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.57%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.30%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index e3f9d2a1..ae9f4777 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,4 +1,4 @@ -### de_DE.axaml: 99.07% +### de_DE.axaml: 99.06%
@@ -24,7 +24,7 @@
-### fr_FR.axaml: 91.66% +### fr_FR.axaml: 91.57%
@@ -106,7 +106,7 @@
-### pt_BR.axaml: 91.39% +### pt_BR.axaml: 91.30%
From cea8a90680a46a9bf54e0b1649af1f4607138e4b Mon Sep 17 00:00:00 2001 From: Gadfly Date: Mon, 17 Mar 2025 15:56:13 +0800 Subject: [PATCH 386/441] refactor: use $GIT_COMMON_DIR instead of cut $GIT_DIR/worktrees (#1103) --- src/Commands/QueryGitCommonDir.cs | 26 ++++++++++++++++++++++++++ src/Models/IRepository.cs | 1 + src/Models/Watcher.cs | 6 +----- src/Resources/Locales/de_DE.axaml | 2 +- src/Resources/Locales/en_US.axaml | 2 +- src/Resources/Locales/es_ES.axaml | 2 +- src/Resources/Locales/fr_FR.axaml | 2 +- src/Resources/Locales/it_IT.axaml | 2 +- src/Resources/Locales/pt_BR.axaml | 2 +- src/Resources/Locales/ru_RU.axaml | 2 +- src/Resources/Locales/zh_CN.axaml | 2 +- src/Resources/Locales/zh_TW.axaml | 2 +- src/ViewModels/Launcher.cs | 6 +++++- src/ViewModels/Repository.cs | 10 +++++++++- 14 files changed, 51 insertions(+), 16 deletions(-) create mode 100644 src/Commands/QueryGitCommonDir.cs diff --git a/src/Commands/QueryGitCommonDir.cs b/src/Commands/QueryGitCommonDir.cs new file mode 100644 index 00000000..1076243e --- /dev/null +++ b/src/Commands/QueryGitCommonDir.cs @@ -0,0 +1,26 @@ +using System.IO; + +namespace SourceGit.Commands +{ + public class QueryGitCommonDir : Command + { + public QueryGitCommonDir(string workDir) + { + WorkingDirectory = workDir; + Args = "rev-parse --git-common-dir"; + RaiseError = false; + } + + public string Result() + { + var rs = ReadToEnd().StdOut; + if (string.IsNullOrEmpty(rs)) + return null; + + rs = rs.Trim(); + if (Path.IsPathRooted(rs)) + return rs; + return Path.GetFullPath(Path.Combine(WorkingDirectory, rs)); + } + } +} diff --git a/src/Models/IRepository.cs b/src/Models/IRepository.cs index 12b1adba..90409c2f 100644 --- a/src/Models/IRepository.cs +++ b/src/Models/IRepository.cs @@ -4,6 +4,7 @@ { string FullPath { get; set; } string GitDir { get; set; } + string GitCommonDir { get; set; } void RefreshBranches(); void RefreshWorktrees(); diff --git a/src/Models/Watcher.cs b/src/Models/Watcher.cs index d0ccdea5..320f31d6 100644 --- a/src/Models/Watcher.cs +++ b/src/Models/Watcher.cs @@ -24,11 +24,7 @@ namespace SourceGit.Models _wcWatcher.EnableRaisingEvents = true; // If this repository is a worktree repository, just watch the main repository's gitdir. - var gitDirNormalized = _repo.GitDir.Replace("\\", "/"); - var worktreeIdx = gitDirNormalized.IndexOf(".git/worktrees/", StringComparison.Ordinal); - var repoWatchDir = _repo.GitDir; - if (worktreeIdx > 0) - repoWatchDir = _repo.GitDir.Substring(0, worktreeIdx + 4); + var repoWatchDir = _repo.GitCommonDir.Replace("\\", "/"); _repoWatcher = new FileSystemWatcher(); _repoWatcher.Path = repoWatchDir; diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index 31dc1d9b..2ebc1ae7 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -501,7 +501,7 @@ Remote löschen Ziel: Worktrees löschen - Worktree Informationen in `$GIT_DIR/worktrees` löschen + Worktree Informationen in `$GIT_COMMON_DIR/worktrees` löschen Pull Remote-Branch: Alle Branches fetchen diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index b1f83836..4401e8bc 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -504,7 +504,7 @@ Prune Remote Target: Prune Worktrees - Prune worktree information in `$GIT_DIR/worktrees` + Prune worktree information in `$GIT_COMMON_DIR/worktrees` Pull Remote Branch: Fetch all branches diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index 6bf38df1..f57ee230 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -508,7 +508,7 @@ Podar Remoto Destino: Podar Worktrees - Podar información de worktree en `$GIT_DIR/worktrees` + Podar información de worktree en `$GIT_COMMON_DIR/worktrees` Pull Rama Remota: Fetch todas las ramas diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index ebb3ba89..94df8d66 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -476,7 +476,7 @@ Élaguer une branche distant Cible : Élaguer les Worktrees - Élaguer les information de worktree dans `$GIT_DIR/worktrees` + Élaguer les information de worktree dans `$GIT_COMMON_DIR/worktrees` Pull Branche distante : Fetch toutes les branches diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml index ebfd3939..8e6f73fa 100644 --- a/src/Resources/Locales/it_IT.axaml +++ b/src/Resources/Locales/it_IT.axaml @@ -507,7 +507,7 @@ Potatura Remota Destinazione: Potatura Worktrees - Potatura delle informazioni di worktree in `$GIT_DIR/worktrees` + Potatura delle informazioni di worktree in `$GIT_COMMON_DIR/worktrees` Scarica Branch Remoto: Recupera tutti i branch diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index b4677840..c03e39d2 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -490,7 +490,7 @@ Prunar Remoto Alvo: Podar Worktrees - Podar informações de worktree em `$GIT_DIR/worktrees` + Podar informações de worktree em `$GIT_COMMON_DIR/worktrees` Puxar Branch Remoto: Buscar todos os branches diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index b2ba2158..3273ac07 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -508,7 +508,7 @@ Удалить внешний репозиторий Цель: Удалить рабочий каталог - Информация об обрезке рабочего каталога в «$GIT_DIR/worktrees» + Информация об обрезке рабочего каталога в «$GIT_COMMON_DIR/worktrees» Забрать Ветка внешнего репозитория: Извлечь все ветки diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 768061dd..2a8d08b5 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -508,7 +508,7 @@ 清理远程已删除分支 目标 : 清理工作树 - 清理在`$GIT_DIR/worktrees`中的无效工作树信息 + 清理在`$GIT_COMMON_DIR/worktrees`中的无效工作树信息 拉回(pull) 拉取分支 : 拉取远程中的所有分支变更 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 6d63c1ee..5bb68782 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -507,7 +507,7 @@ 清理遠端已刪除分支 目標: 清理工作區 - 清理在 `$GIT_DIR/worktrees` 中的無效工作區資訊 + 清理在 `$GIT_COMMON_DIR/worktrees` 中的無效工作區資訊 拉取 (pull) 拉取分支: 拉取遠端中的所有分支 diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index 06479394..4307665d 100644 --- a/src/ViewModels/Launcher.cs +++ b/src/ViewModels/Launcher.cs @@ -282,6 +282,7 @@ namespace SourceGit.ViewModels var isBare = new Commands.IsBareRepository(node.Id).Result(); var gitDir = node.Id; + var gitCommonDir = gitDir; if (!isBare) { gitDir = new Commands.QueryGitDir(node.Id).Result(); @@ -291,9 +292,12 @@ namespace SourceGit.ViewModels App.RaiseException(ctx, "Given path is not a valid git repository!"); return; } + gitCommonDir = new Commands.QueryGitCommonDir(node.Id).Result(); + if (string.IsNullOrEmpty(gitCommonDir)) + gitCommonDir = gitDir; } - var repo = new Repository(isBare, node.Id, gitDir); + var repo = new Repository(isBare, node.Id, gitDir, gitCommonDir); repo.Open(); if (page == null) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 97c52d8e..5cc933e9 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -45,6 +45,12 @@ namespace SourceGit.ViewModels set => SetProperty(ref _gitDir, value); } + public string GitCommonDir + { + get => _gitCommonDir; + set => SetProperty(ref _gitCommonDir, value); + } + public Models.RepositorySettings Settings { get => _settings; @@ -429,11 +435,12 @@ namespace SourceGit.ViewModels set; } = 0; - public Repository(bool isBare, string path, string gitDir) + public Repository(bool isBare, string path, string gitDir, string gitCommonDir) { IsBare = isBare; FullPath = path; GitDir = gitDir; + GitCommonDir = gitCommonDir; } public void Open() @@ -2437,6 +2444,7 @@ namespace SourceGit.ViewModels private string _fullpath = string.Empty; private string _gitDir = string.Empty; + private string _gitCommonDir = string.Empty; private Models.RepositorySettings _settings = null; private Models.FilterMode _historiesFilterMode = Models.FilterMode.None; private bool _hasAllowedSignersFile = false; From b4ab4afd3ab8eded049ea7b4849d821f64d14273 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 16:17:20 +0800 Subject: [PATCH 387/441] code_review: PR #1103 Since we only use `$GIT_COMMON_DIR` in filesystem watcher, it is unnecessary to store this value in `Repository`, and we can query the `$GIT_COMMON_DIR` only when it looks like a worktree Signed-off-by: leo --- src/Models/IRepository.cs | 3 +-- src/Models/Watcher.cs | 5 +---- src/ViewModels/Launcher.cs | 6 +----- src/ViewModels/Repository.cs | 19 +++++++++++++------ 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/Models/IRepository.cs b/src/Models/IRepository.cs index 90409c2f..9283266e 100644 --- a/src/Models/IRepository.cs +++ b/src/Models/IRepository.cs @@ -3,8 +3,7 @@ public interface IRepository { string FullPath { get; set; } - string GitDir { get; set; } - string GitCommonDir { get; set; } + string GitDirForWatcher { get; } void RefreshBranches(); void RefreshWorktrees(); diff --git a/src/Models/Watcher.cs b/src/Models/Watcher.cs index 320f31d6..d419363a 100644 --- a/src/Models/Watcher.cs +++ b/src/Models/Watcher.cs @@ -23,11 +23,8 @@ namespace SourceGit.Models _wcWatcher.Deleted += OnWorkingCopyChanged; _wcWatcher.EnableRaisingEvents = true; - // If this repository is a worktree repository, just watch the main repository's gitdir. - var repoWatchDir = _repo.GitCommonDir.Replace("\\", "/"); - _repoWatcher = new FileSystemWatcher(); - _repoWatcher.Path = repoWatchDir; + _repoWatcher.Path = _repo.GitDirForWatcher; _repoWatcher.Filter = "*"; _repoWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName; _repoWatcher.IncludeSubdirectories = true; diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index 4307665d..06479394 100644 --- a/src/ViewModels/Launcher.cs +++ b/src/ViewModels/Launcher.cs @@ -282,7 +282,6 @@ namespace SourceGit.ViewModels var isBare = new Commands.IsBareRepository(node.Id).Result(); var gitDir = node.Id; - var gitCommonDir = gitDir; if (!isBare) { gitDir = new Commands.QueryGitDir(node.Id).Result(); @@ -292,12 +291,9 @@ namespace SourceGit.ViewModels App.RaiseException(ctx, "Given path is not a valid git repository!"); return; } - gitCommonDir = new Commands.QueryGitCommonDir(node.Id).Result(); - if (string.IsNullOrEmpty(gitCommonDir)) - gitCommonDir = gitDir; } - var repo = new Repository(isBare, node.Id, gitDir, gitCommonDir); + var repo = new Repository(isBare, node.Id, gitDir); repo.Open(); if (page == null) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 5cc933e9..85665634 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -45,10 +45,19 @@ namespace SourceGit.ViewModels set => SetProperty(ref _gitDir, value); } - public string GitCommonDir + public string GitDirForWatcher { - get => _gitCommonDir; - set => SetProperty(ref _gitCommonDir, value); + get + { + // Only try to get `$GIT_COMMON_DIR` if this repository looks like a worktree. + if (_gitDir.Replace("\\", "/").IndexOf(".git/worktrees/", StringComparison.Ordinal) > 0) + { + var commonDir = new Commands.QueryGitCommonDir(_fullpath).Result(); + return string.IsNullOrEmpty(commonDir) ? _gitDir : commonDir; + } + + return _gitDir; + } } public Models.RepositorySettings Settings @@ -435,12 +444,11 @@ namespace SourceGit.ViewModels set; } = 0; - public Repository(bool isBare, string path, string gitDir, string gitCommonDir) + public Repository(bool isBare, string path, string gitDir) { IsBare = isBare; FullPath = path; GitDir = gitDir; - GitCommonDir = gitCommonDir; } public void Open() @@ -2444,7 +2452,6 @@ namespace SourceGit.ViewModels private string _fullpath = string.Empty; private string _gitDir = string.Empty; - private string _gitCommonDir = string.Empty; private Models.RepositorySettings _settings = null; private Models.FilterMode _historiesFilterMode = Models.FilterMode.None; private bool _hasAllowedSignersFile = false; From 7031693489d6c92da2db74393f690aba6d1b3da7 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 16:29:56 +0800 Subject: [PATCH 388/441] refactor: pass dirs to watcher directly Signed-off-by: leo --- src/Models/IRepository.cs | 3 --- src/Models/Watcher.cs | 6 +++--- src/ViewModels/Repository.cs | 26 ++++++++++---------------- 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/Models/IRepository.cs b/src/Models/IRepository.cs index 9283266e..0224d81f 100644 --- a/src/Models/IRepository.cs +++ b/src/Models/IRepository.cs @@ -2,9 +2,6 @@ { public interface IRepository { - string FullPath { get; set; } - string GitDirForWatcher { get; } - void RefreshBranches(); void RefreshWorktrees(); void RefreshTags(); diff --git a/src/Models/Watcher.cs b/src/Models/Watcher.cs index d419363a..3ccecad4 100644 --- a/src/Models/Watcher.cs +++ b/src/Models/Watcher.cs @@ -8,12 +8,12 @@ namespace SourceGit.Models { public class Watcher : IDisposable { - public Watcher(IRepository repo) + public Watcher(IRepository repo, string fullpath, string gitDir) { _repo = repo; _wcWatcher = new FileSystemWatcher(); - _wcWatcher.Path = _repo.FullPath; + _wcWatcher.Path = fullpath; _wcWatcher.Filter = "*"; _wcWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.CreationTime; _wcWatcher.IncludeSubdirectories = true; @@ -24,7 +24,7 @@ namespace SourceGit.Models _wcWatcher.EnableRaisingEvents = true; _repoWatcher = new FileSystemWatcher(); - _repoWatcher.Path = _repo.GitDirForWatcher; + _repoWatcher.Path = gitDir; _repoWatcher.Filter = "*"; _repoWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName; _repoWatcher.IncludeSubdirectories = true; diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 85665634..4f2f3ca3 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -45,21 +45,6 @@ namespace SourceGit.ViewModels set => SetProperty(ref _gitDir, value); } - public string GitDirForWatcher - { - get - { - // Only try to get `$GIT_COMMON_DIR` if this repository looks like a worktree. - if (_gitDir.Replace("\\", "/").IndexOf(".git/worktrees/", StringComparison.Ordinal) > 0) - { - var commonDir = new Commands.QueryGitCommonDir(_fullpath).Result(); - return string.IsNullOrEmpty(commonDir) ? _gitDir : commonDir; - } - - return _gitDir; - } - } - public Models.RepositorySettings Settings { get => _settings; @@ -472,7 +457,16 @@ namespace SourceGit.ViewModels try { - _watcher = new Models.Watcher(this); + // For worktrees, we need to watch the $GIT_COMMON_DIR instead of the $GIT_DIR. + var gitDirForWatcher = _gitDir; + if (_gitDir.Replace("\\", "/").IndexOf(".git/worktrees/", StringComparison.Ordinal) > 0) + { + var commonDir = new Commands.QueryGitCommonDir(_fullpath).Result(); + if (!string.IsNullOrEmpty(commonDir)) + gitDirForWatcher = commonDir; + } + + _watcher = new Models.Watcher(this, _fullpath, gitDirForWatcher); } catch (Exception ex) { From 3e8bba0d0bd3e16057791a8df6fc95e2897a8a40 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 17:06:26 +0800 Subject: [PATCH 389/441] ux: re-design `About` page Signed-off-by: leo --- src/Resources/Icons.axaml | 1 + src/Resources/Locales/de_DE.axaml | 5 ---- src/Resources/Locales/en_US.axaml | 5 ---- src/Resources/Locales/es_ES.axaml | 5 ---- src/Resources/Locales/fr_FR.axaml | 5 ---- src/Resources/Locales/it_IT.axaml | 5 ---- src/Resources/Locales/pt_BR.axaml | 5 ---- src/Resources/Locales/ru_RU.axaml | 5 ---- src/Resources/Locales/zh_CN.axaml | 5 ---- src/Resources/Locales/zh_TW.axaml | 5 ---- src/Views/About.axaml | 45 +++++++++++-------------------- src/Views/About.axaml.cs | 26 +++--------------- 12 files changed, 21 insertions(+), 96 deletions(-) diff --git a/src/Resources/Icons.axaml b/src/Resources/Icons.axaml index 9426d20a..66589440 100644 --- a/src/Resources/Icons.axaml +++ b/src/Resources/Icons.axaml @@ -54,6 +54,7 @@ M939 94v710L512 998 85 805V94h-64A21 21 0 010 73v-0C0 61 10 51 21 51h981c12 0 21 10 21 21v0c0 12-10 21-21 21h-64zm-536 588L512 624l109 58c6 3 13 4 20 3a32 32 0 0026-37l-21-122 88-87c5-5 8-11 9-18a32 32 0 00-27-37l-122-18-54-111a32 32 0 00-57 0l-54 111-122 18c-7 1-13 4-18 9a33 33 0 001 46l88 87-21 122c-1 7-0 14 3 20a32 32 0 0043 14z M236 542a32 32 0 109 63l86-12a180 180 0 0022 78l-71 47a32 32 0 1035 53l75-50a176 176 0 00166 40L326 529zM512 16C238 16 16 238 16 512s222 496 496 496 496-222 496-496S786 16 512 16zm0 896c-221 0-400-179-400-400a398 398 0 0186-247l561 561A398 398 0 01512 912zm314-154L690 622a179 179 0 004-29l85 12a32 32 0 109-63l-94-13v-49l94-13a32 32 0 10-9-63l-87 12a180 180 0 00-20-62l71-47A32 32 0 10708 252l-75 50a181 181 0 00-252 10l-115-115A398 398 0 01512 112c221 0 400 179 400 400a398 398 0 01-86 247z M884 159l-18-18a43 43 0 00-38-12l-235 43a166 166 0 00-101 60L400 349a128 128 0 00-148 47l-120 171a21 21 0 005 29l17 12a128 128 0 00178-32l27-38 124 124-38 27a128 128 0 00-32 178l12 17a21 21 0 0029 5l171-120a128 128 0 0047-148l117-92A166 166 0 00853 431l43-235a43 43 0 00-12-38zm-177 249a64 64 0 110-90 64 64 0 010 90zm-373 312a21 21 0 010 30l-139 139a21 21 0 01-30 0l-30-30a21 21 0 010-30l139-139a21 21 0 0130 0z + M525 0C235 0 0 235 0 525c0 232 150 429 359 498 26 5 36-11 36-25 0-12-1-54-1-97-146 31-176-63-176-63-23-61-58-76-58-76-48-32 3-32 3-32 53 3 81 54 81 54 47 80 123 57 153 43 4-34 18-57 33-70-116-12-239-57-239-259 0-57 21-104 54-141-5-13-23-67 5-139 0 0 44-14 144 54 42-11 87-17 131-17s90 6 131 17C756 203 801 217 801 217c29 72 10 126 5 139 34 37 54 83 54 141 0 202-123 246-240 259 19 17 36 48 36 97 0 70-1 127-1 144 0 14 10 30 36 25 209-70 359-266 359-498C1050 235 814 0 525 0z M590 74 859 342V876c0 38-31 68-68 68H233c-38 0-68-31-68-68V142c0-38 31-68 68-68h357zm-12 28H233a40 40 0 00-40 38L193 142v734a40 40 0 0038 40L233 916h558a40 40 0 0040-38L831 876V354L578 102zM855 371h-215c-46 0-83-36-84-82l0-2V74h28v213c0 30 24 54 54 55l2 0h215v28zM57 489m28 0 853 0q28 0 28 28l0 284q0 28-28 28l-853 0q-28 0-28-28l0-284q0-28 28-28ZM157 717c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C184 610 172 603 156 603c-29 0-54 21-54 57 0 37 24 56 54 56zM245 711v-108h-34v108h34zm69 0v-86H341V603H262v22h28V711h24zM393 711v-108h-34v108h34zm66 6c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C485 610 474 603 458 603c-29 0-54 21-54 57 0 37 24 56 54 56zm88-6v-36c0-13-2-28-3-40h1l10 24 25 52H603v-108h-23v36c0 13 2 28 3 40h-1l-10-24L548 603H523v108h23zM677 717c30 0 51-22 51-57 0-36-21-56-51-56-30 0-51 20-51 56 0 36 21 57 51 57zm3-23c-16 0-26-12-26-32 0-19 10-31 26-31 16 0 26 11 26 31S696 694 680 694zm93 17v-38h13l21 38H836l-25-43c12-5 19-15 19-31 0-26-20-34-44-34H745v108h27zm16-51H774v-34h15c16 0 25 4 25 16s-9 18-25 18zM922 711v-22h-43v-23h35v-22h-35V625h41V603H853v108h68z M30 271l241 0 0-241-241 0 0 241zM392 271l241 0 0-241-241 0 0 241zM753 30l0 241 241 0 0-241-241 0zM30 632l241 0 0-241-241 0 0 241zM392 632l241 0 0-241-241 0 0 241zM753 632l241 0 0-241-241 0 0 241zM30 994l241 0 0-241-241 0 0 241zM392 994l241 0 0-241-241 0 0 241zM753 994l241 0 0-241-241 0 0 241z M0 512M1024 512M512 0M512 1024M955 323q0 23-16 39l-414 414-78 78q-16 16-39 16t-39-16l-78-78-207-207q-16-16-16-39t16-39l78-78q16-16 39-16t39 16l168 169 375-375q16-16 39-16t39 16l78 78q16 16 16 39z diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index 2ebc1ae7..7144ef43 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -4,11 +4,6 @@ Info Über SourceGit - • Erstellt mit - • Grafik gerendert durch - • Texteditor von - • Monospace-Schriftarten von - • Quelltext findest du auf Open Source & freier Git GUI Client Worktree hinzufügen Was auschecken: diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 4401e8bc..312d4945 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -1,11 +1,6 @@ About About SourceGit - • Build with - • Chart is rendered by - • TextEditor from - • Monospace fonts come from - • Source code can be found at Opensource & Free Git GUI Client Add Worktree What to Checkout: diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index f57ee230..e7e953e5 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -4,11 +4,6 @@ Acerca de Acerca de SourceGit - • Construido con - • El gráfico es renderizado por - • Editor de texto de - • Las fuentes monoespaciadas provienen de - • El código fuente se puede encontrar en Cliente Git GUI de código abierto y gratuito Agregar Worktree Qué Checkout: diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index 94df8d66..f3a71390 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -4,11 +4,6 @@ À propos À propos de SourceGit - • Compilé avec - • Le graphique est rendu par - • TextEditor de - • Les polices Monospace proviennent de - • Le code source est disponible sur Client Git Open Source et Gratuit Ajouter un Worktree Que récupérer : diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml index 8e6f73fa..782d6e78 100644 --- a/src/Resources/Locales/it_IT.axaml +++ b/src/Resources/Locales/it_IT.axaml @@ -4,11 +4,6 @@ Informazioni Informazioni su SourceGit - • Creato con - • Il grafico è reso da - • Editor di testo da - • I font monospaziati provengono da - • Il codice sorgente è disponibile su Client GUI Git open source e gratuito Aggiungi Worktree Di cosa fare il checkout: diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index c03e39d2..e811cf3e 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -29,11 +29,6 @@ Sobre Sobre o SourceGit - • Construído com - • Gráfico desenhado por - • Editor de Texto de - • Fontes monoespaçadas de - • Código-fonte pode ser encontrado em Cliente Git GUI Livre e de Código Aberto Adicionar Worktree O que Checar: diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index 3273ac07..99948eca 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -4,11 +4,6 @@ О программе О SourceGit - • Сборка с - • Диаграмма отображается с помощью - • Текстовый редактор от - • Моноширинные шрифты взяты из - • Исходный код можно найти по адресу Бесплатный графический клиент Git с исходным кодом Добавить рабочий каталог Переключиться на: diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 2a8d08b5..aae292f3 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -4,11 +4,6 @@ 关于软件 关于本软件 - • 项目依赖于 - • 图表绘制组件来自 - • 文本编辑器使用 - • 等宽字体来自于 - • 项目源代码地址 开源免费的Git客户端 新增工作树 检出分支方式 : diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 5bb68782..97c96c6c 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -4,11 +4,6 @@ 關於 關於 SourceGit - • 專案依賴於 - • 圖表繪製元件來自 - • 文字編輯器使用 - • 等寬字型來自於 - • 專案原始碼網址 開源免費的 Git 客戶端 新增工作區 簽出分支方式: diff --git a/src/Views/About.axaml b/src/Views/About.axaml index ecdf156e..28529b63 100644 --- a/src/Views/About.axaml +++ b/src/Views/About.axaml @@ -3,12 +3,12 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:v="using:SourceGit.Views" - mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" + mc:Ignorable="d" d:DesignWidth="520" d:DesignHeight="230" x:Class="SourceGit.Views.About" x:Name="ThisControl" Icon="/App.ico" Title="{DynamicResource Text.About}" - SizeToContent="WidthAndHeight" + Width="520" Height="230" CanResize="False" WindowStartupLocation="CenterScreen"> @@ -34,7 +34,7 @@ IsVisible="{OnPlatform True, macOS=False}"/> - + - - + + - + - + + - - - - - - - - - - - - - - - - - - - - - - + + + + diff --git a/src/Views/About.axaml.cs b/src/Views/About.axaml.cs index 631df0f9..d393f94c 100644 --- a/src/Views/About.axaml.cs +++ b/src/Views/About.axaml.cs @@ -1,5 +1,5 @@ using System.Reflection; -using Avalonia.Input; +using Avalonia.Interactivity; namespace SourceGit.Views { @@ -19,31 +19,13 @@ namespace SourceGit.Views TxtCopyright.Text = copyright.Copyright; } - private void OnVisitAvaloniaUI(object _, PointerPressedEventArgs e) + private void OnVisitWebsite(object _, RoutedEventArgs e) { - Native.OS.OpenBrowser("https://www.avaloniaui.net/"); + Native.OS.OpenBrowser("https://sourcegit-scm.github.io/"); e.Handled = true; } - private void OnVisitAvaloniaEdit(object _, PointerPressedEventArgs e) - { - Native.OS.OpenBrowser("https://github.com/AvaloniaUI/AvaloniaEdit"); - e.Handled = true; - } - - private void OnVisitJetBrainsMonoFont(object _, PointerPressedEventArgs e) - { - Native.OS.OpenBrowser("https://www.jetbrains.com/lp/mono/"); - e.Handled = true; - } - - private void OnVisitLiveCharts2(object _, PointerPressedEventArgs e) - { - Native.OS.OpenBrowser("https://livecharts.dev/"); - e.Handled = true; - } - - private void OnVisitSourceCode(object _, PointerPressedEventArgs e) + private void OnVisitSourceCode(object _, RoutedEventArgs e) { Native.OS.OpenBrowser("https://github.com/sourcegit-scm/sourcegit"); e.Handled = true; From 5845ef3eb64bb5651737685bb25403d169e033c6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 17 Mar 2025 09:06:42 +0000 Subject: [PATCH 390/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f9216874..13887a13 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.06%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-%E2%88%9A-brightgreen)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.57%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.30%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.06%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-%E2%88%9A-brightgreen)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.51%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.24%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index ae9f4777..b1e1f2c8 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -24,7 +24,7 @@
-### fr_FR.axaml: 91.57% +### fr_FR.axaml: 91.51%
@@ -106,7 +106,7 @@
-### pt_BR.axaml: 91.30% +### pt_BR.axaml: 91.24%
From 398b14695ce9900e4b712b54e1ddf987953ac23f Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 17:10:42 +0800 Subject: [PATCH 391/441] enhance: the git dir of worktree's owner repository may not named `.git` Signed-off-by: leo --- src/ViewModels/Repository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 4f2f3ca3..f1c43e7c 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -459,7 +459,7 @@ namespace SourceGit.ViewModels { // For worktrees, we need to watch the $GIT_COMMON_DIR instead of the $GIT_DIR. var gitDirForWatcher = _gitDir; - if (_gitDir.Replace("\\", "/").IndexOf(".git/worktrees/", StringComparison.Ordinal) > 0) + if (_gitDir.Replace("\\", "/").IndexOf("/worktrees/", StringComparison.Ordinal) > 0) { var commonDir = new Commands.QueryGitCommonDir(_fullpath).Result(); if (!string.IsNullOrEmpty(commonDir)) From c9fe373dda59dfc87fb927aa9bac3ebf538c22ce Mon Sep 17 00:00:00 2001 From: Leonardo Date: Mon, 17 Mar 2025 10:15:17 +0100 Subject: [PATCH 392/441] add missing key and fix untranslated one (#1104) --- src/Resources/Locales/it_IT.axaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml index 782d6e78..d002dfef 100644 --- a/src/Resources/Locales/it_IT.axaml +++ b/src/Resources/Locales/it_IT.axaml @@ -454,7 +454,8 @@ Abilita streaming ASPETTO Font Predefinito - Font Size + Larghezza della Tab Editor + Dimensione Font Dimensione Font Predefinita Dimensione Font Editor Font Monospaziato From 2b95ea2ab1cac2cda9b27add6439406f47c163e0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 17 Mar 2025 09:15:30 +0000 Subject: [PATCH 393/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 13887a13..dff78418 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.06%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-%E2%88%9A-brightgreen)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.51%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.24%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.06%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-%E2%88%9A-brightgreen)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.51%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-%E2%88%9A-brightgreen)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.24%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index b1e1f2c8..0f8ccc2b 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -96,13 +96,13 @@
-### it_IT.axaml: 99.87% +### it_IT.axaml: 100.00%
Missing Keys -- Text.Preferences.Appearance.EditorTabWidth +
From a0cddaea8020b1ca891217df3f918a1a05560e97 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 19:53:47 +0800 Subject: [PATCH 394/441] feature: support `--ff-only` option for `git merge` command Signed-off-by: leo --- src/Models/MergeMode.cs | 1 + src/ViewModels/Histories.cs | 6 +++--- src/ViewModels/Merge.cs | 12 +++++++----- src/ViewModels/Repository.cs | 6 +++--- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/Models/MergeMode.cs b/src/Models/MergeMode.cs index e4389b32..5dc70030 100644 --- a/src/Models/MergeMode.cs +++ b/src/Models/MergeMode.cs @@ -5,6 +5,7 @@ public static readonly MergeMode[] Supported = [ new MergeMode("Default", "Fast-forward if possible", ""), + new MergeMode("Fast-forward", "Refuse to merge when fast-forward is not possible", "--ff-only"), new MergeMode("No Fast-forward", "Always create a merge commit", "--no-ff"), new MergeMode("Squash", "Squash merge", "--squash"), new MergeMode("Don't commit", "Merge without commit", "--no-ff --no-commit"), diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index 0e67915c..01114dd3 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -871,7 +871,7 @@ namespace SourceGit.ViewModels return; if (_repo.CanCreatePopup()) - _repo.ShowAndStartPopup(new Merge(_repo, b, current.Name)); + _repo.ShowAndStartPopup(new Merge(_repo, b, current.Name, true)); e.Handled = true; }; @@ -972,7 +972,7 @@ namespace SourceGit.ViewModels merge.Click += (_, e) => { if (_repo.CanCreatePopup()) - _repo.ShowPopup(new Merge(_repo, branch, current.Name)); + _repo.ShowPopup(new Merge(_repo, branch, current.Name, false)); e.Handled = true; }; submenu.Items.Add(merge); @@ -1060,7 +1060,7 @@ namespace SourceGit.ViewModels merge.Click += (_, e) => { if (_repo.CanCreatePopup()) - _repo.ShowPopup(new Merge(_repo, branch, current.Name)); + _repo.ShowPopup(new Merge(_repo, branch, current.Name, false)); e.Handled = true; }; diff --git a/src/ViewModels/Merge.cs b/src/ViewModels/Merge.cs index bde9b66d..be938867 100644 --- a/src/ViewModels/Merge.cs +++ b/src/ViewModels/Merge.cs @@ -21,14 +21,14 @@ namespace SourceGit.ViewModels set; } - public Merge(Repository repo, Models.Branch source, string into) + public Merge(Repository repo, Models.Branch source, string into, bool forceFastForward) { _repo = repo; _sourceName = source.FriendlyName; Source = source; Into = into; - Mode = AutoSelectMergeMode(); + Mode = forceFastForward ? Models.MergeMode.Supported[1] : AutoSelectMergeMode(); View = new Views.Merge() { DataContext = this }; } @@ -72,12 +72,14 @@ namespace SourceGit.ViewModels var config = new Commands.Config(_repo.FullPath).Get($"branch.{Into}.mergeoptions"); if (string.IsNullOrEmpty(config)) return Models.MergeMode.Supported[0]; - if (config.Equals("--no-ff", StringComparison.Ordinal)) + if (config.Equals("--ff-only", StringComparison.Ordinal)) return Models.MergeMode.Supported[1]; - if (config.Equals("--squash", StringComparison.Ordinal)) + if (config.Equals("--no-ff", StringComparison.Ordinal)) return Models.MergeMode.Supported[2]; - if (config.Equals("--no-commit", StringComparison.Ordinal) || config.Equals("--no-ff --no-commit", StringComparison.Ordinal)) + if (config.Equals("--squash", StringComparison.Ordinal)) return Models.MergeMode.Supported[3]; + if (config.Equals("--no-commit", StringComparison.Ordinal) || config.Equals("--no-ff --no-commit", StringComparison.Ordinal)) + return Models.MergeMode.Supported[4]; return Models.MergeMode.Supported[0]; } diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index f1c43e7c..bf283532 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1516,7 +1516,7 @@ namespace SourceGit.ViewModels return; if (CanCreatePopup()) - ShowAndStartPopup(new Merge(this, b, branch.Name)); + ShowAndStartPopup(new Merge(this, b, branch.Name, true)); e.Handled = true; }; @@ -1595,7 +1595,7 @@ namespace SourceGit.ViewModels merge.Click += (_, e) => { if (CanCreatePopup()) - ShowPopup(new Merge(this, branch, _currentBranch.Name)); + ShowPopup(new Merge(this, branch, _currentBranch.Name, false)); e.Handled = true; }; @@ -1876,7 +1876,7 @@ namespace SourceGit.ViewModels merge.Click += (_, e) => { if (CanCreatePopup()) - ShowPopup(new Merge(this, branch, _currentBranch.Name)); + ShowPopup(new Merge(this, branch, _currentBranch.Name, false)); e.Handled = true; }; From b930066b5a2bc0d085a8c628f89b75c268fc6456 Mon Sep 17 00:00:00 2001 From: Gadfly Date: Mon, 17 Mar 2025 19:59:28 +0800 Subject: [PATCH 395/441] fix: improve line splitting to handle both LF and CRLF line endings (#1106) --- src/Commands/CountLocalChangesWithoutUntracked.cs | 2 +- src/Commands/QueryCommitSignInfo.cs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Commands/CountLocalChangesWithoutUntracked.cs b/src/Commands/CountLocalChangesWithoutUntracked.cs index 7ab9a54a..924f8a89 100644 --- a/src/Commands/CountLocalChangesWithoutUntracked.cs +++ b/src/Commands/CountLocalChangesWithoutUntracked.cs @@ -16,7 +16,7 @@ namespace SourceGit.Commands var rs = ReadToEnd(); if (rs.IsSuccess) { - var lines = rs.StdOut.Split('\n', StringSplitOptions.RemoveEmptyEntries); + var lines = rs.StdOut.Split(['\n', '\r'], StringSplitOptions.RemoveEmptyEntries); return lines.Length; } diff --git a/src/Commands/QueryCommitSignInfo.cs b/src/Commands/QueryCommitSignInfo.cs index 5c81cf57..7b53a1f2 100644 --- a/src/Commands/QueryCommitSignInfo.cs +++ b/src/Commands/QueryCommitSignInfo.cs @@ -1,4 +1,6 @@ -namespace SourceGit.Commands +using System; + +namespace SourceGit.Commands { public class QueryCommitSignInfo : Command { @@ -22,7 +24,7 @@ if (raw.Length <= 1) return null; - var lines = raw.Split('\n'); + var lines = raw.Split(['\n', '\r'], StringSplitOptions.RemoveEmptyEntries); return new Models.CommitSignInfo() { VerifyResult = lines[0][0], From 808302ce84813d59a6a859139dd8f84143cc5f5f Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 20:35:31 +0800 Subject: [PATCH 396/441] code_review: PR #1106 - Use new syntex `[...]` instead of `new char[] {...}` to create char arrays - Use `string.ReplaceLineEndings('\n').Split('\n')` instead of `string.Split(['\n', '\r'], StringSplitOptions.RemoveEmptyEntries)` because that the `Signer` part may be missing Signed-off-by: leo --- src/Commands/Config.cs | 2 +- src/Commands/CountLocalChangesWithoutUntracked.cs | 2 +- src/Commands/LFS.cs | 2 +- src/Commands/QueryBranches.cs | 2 +- src/Commands/QueryCommitSignInfo.cs | 4 ++-- src/Commands/QueryCommits.cs | 6 +++--- src/Commands/QueryRefsContainsCommit.cs | 2 +- src/Commands/QueryStagedChangesWithAmend.cs | 2 +- src/Commands/QuerySubmodules.cs | 4 ++-- src/Commands/QueryTrackStatus.cs | 2 +- src/Commands/Worktree.cs | 2 +- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Commands/Config.cs b/src/Commands/Config.cs index 2fb83325..49e8fcb7 100644 --- a/src/Commands/Config.cs +++ b/src/Commands/Config.cs @@ -29,7 +29,7 @@ namespace SourceGit.Commands var rs = new Dictionary(); if (output.IsSuccess) { - var lines = output.StdOut.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + var lines = output.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { var idx = line.IndexOf('=', StringComparison.Ordinal); diff --git a/src/Commands/CountLocalChangesWithoutUntracked.cs b/src/Commands/CountLocalChangesWithoutUntracked.cs index 924f8a89..0ba508f8 100644 --- a/src/Commands/CountLocalChangesWithoutUntracked.cs +++ b/src/Commands/CountLocalChangesWithoutUntracked.cs @@ -16,7 +16,7 @@ namespace SourceGit.Commands var rs = ReadToEnd(); if (rs.IsSuccess) { - var lines = rs.StdOut.Split(['\n', '\r'], StringSplitOptions.RemoveEmptyEntries); + var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); return lines.Length; } diff --git a/src/Commands/LFS.cs b/src/Commands/LFS.cs index 2b7d1de4..f7e56486 100644 --- a/src/Commands/LFS.cs +++ b/src/Commands/LFS.cs @@ -82,7 +82,7 @@ namespace SourceGit.Commands var rs = cmd.ReadToEnd(); if (rs.IsSuccess) { - var lines = rs.StdOut.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); + var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { var match = REG_LOCK().Match(line); diff --git a/src/Commands/QueryBranches.cs b/src/Commands/QueryBranches.cs index 44438cef..8dbc4055 100644 --- a/src/Commands/QueryBranches.cs +++ b/src/Commands/QueryBranches.cs @@ -24,7 +24,7 @@ namespace SourceGit.Commands if (!rs.IsSuccess) return branches; - var lines = rs.StdOut.Split('\n', StringSplitOptions.RemoveEmptyEntries); + var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); var remoteBranches = new HashSet(); foreach (var line in lines) { diff --git a/src/Commands/QueryCommitSignInfo.cs b/src/Commands/QueryCommitSignInfo.cs index 7b53a1f2..4f729a8d 100644 --- a/src/Commands/QueryCommitSignInfo.cs +++ b/src/Commands/QueryCommitSignInfo.cs @@ -20,11 +20,11 @@ namespace SourceGit.Commands if (!rs.IsSuccess) return null; - var raw = rs.StdOut.Trim(); + var raw = rs.StdOut.Trim().ReplaceLineEndings("\n"); if (raw.Length <= 1) return null; - var lines = raw.Split(['\n', '\r'], StringSplitOptions.RemoveEmptyEntries); + var lines = raw.Split('\n'); return new Models.CommitSignInfo() { VerifyResult = lines[0][0], diff --git a/src/Commands/QueryCommits.cs b/src/Commands/QueryCommits.cs index 312c068f..8d704aee 100644 --- a/src/Commands/QueryCommits.cs +++ b/src/Commands/QueryCommits.cs @@ -10,7 +10,7 @@ namespace SourceGit.Commands { WorkingDirectory = repo; Context = repo; - Args = $"log --no-show-signature --decorate=full --pretty=format:%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s {limits}"; + Args = $"log --no-show-signature --decorate=full --format=%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s {limits}"; _findFirstMerged = needFindHead; } @@ -35,7 +35,7 @@ namespace SourceGit.Commands var argsBuilder = new StringBuilder(); argsBuilder.Append(search); - var words = filter.Split(new[] { ' ', '\t', '\r' }, StringSplitOptions.RemoveEmptyEntries); + var words = filter.Split([' ', '\t', '\r'], StringSplitOptions.RemoveEmptyEntries); foreach (var word in words) { var escaped = word.Trim().Replace("\"", "\\\"", StringComparison.Ordinal); @@ -124,7 +124,7 @@ namespace SourceGit.Commands Args = $"log --since=\"{_commits[^1].CommitterTimeStr}\" --format=\"%H\""; var rs = ReadToEnd(); - var shas = rs.StdOut.Split('\n', StringSplitOptions.RemoveEmptyEntries); + var shas = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); if (shas.Length == 0) return; diff --git a/src/Commands/QueryRefsContainsCommit.cs b/src/Commands/QueryRefsContainsCommit.cs index 82e9b341..cabe1b50 100644 --- a/src/Commands/QueryRefsContainsCommit.cs +++ b/src/Commands/QueryRefsContainsCommit.cs @@ -20,7 +20,7 @@ namespace SourceGit.Commands if (!output.IsSuccess) return rs; - var lines = output.StdOut.Split('\n'); + var lines = output.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { if (line.EndsWith("/HEAD", StringComparison.Ordinal)) diff --git a/src/Commands/QueryStagedChangesWithAmend.cs b/src/Commands/QueryStagedChangesWithAmend.cs index f5c9659f..cfea5e35 100644 --- a/src/Commands/QueryStagedChangesWithAmend.cs +++ b/src/Commands/QueryStagedChangesWithAmend.cs @@ -24,7 +24,7 @@ namespace SourceGit.Commands if (rs.IsSuccess) { var changes = new List(); - var lines = rs.StdOut.Split('\n', StringSplitOptions.RemoveEmptyEntries); + var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { var match = REG_FORMAT2().Match(line); diff --git a/src/Commands/QuerySubmodules.cs b/src/Commands/QuerySubmodules.cs index 1ceccf78..e2debd06 100644 --- a/src/Commands/QuerySubmodules.cs +++ b/src/Commands/QuerySubmodules.cs @@ -26,7 +26,7 @@ namespace SourceGit.Commands var rs = ReadToEnd(); var builder = new StringBuilder(); - var lines = rs.StdOut.Split('\n', System.StringSplitOptions.RemoveEmptyEntries); + var lines = rs.StdOut.Split(['r', '\n'], System.StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { var match = REG_FORMAT1().Match(line); @@ -55,7 +55,7 @@ namespace SourceGit.Commands return submodules; var dirty = new HashSet(); - lines = rs.StdOut.Split('\n', System.StringSplitOptions.RemoveEmptyEntries); + lines = rs.StdOut.Split(['\r', '\n'], System.StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { var match = REG_FORMAT_STATUS().Match(line); diff --git a/src/Commands/QueryTrackStatus.cs b/src/Commands/QueryTrackStatus.cs index 0bf9746f..e7e1f1c9 100644 --- a/src/Commands/QueryTrackStatus.cs +++ b/src/Commands/QueryTrackStatus.cs @@ -19,7 +19,7 @@ namespace SourceGit.Commands if (!rs.IsSuccess) return status; - var lines = rs.StdOut.Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); + var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { if (line[0] == '>') diff --git a/src/Commands/Worktree.cs b/src/Commands/Worktree.cs index b73b8573..960d5501 100644 --- a/src/Commands/Worktree.cs +++ b/src/Commands/Worktree.cs @@ -21,7 +21,7 @@ namespace SourceGit.Commands var last = null as Models.Worktree; if (rs.IsSuccess) { - var lines = rs.StdOut.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { if (line.StartsWith("worktree ", StringComparison.Ordinal)) From 8d47bd5cd9451360acda528f9dff25fdec431686 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 20:46:01 +0800 Subject: [PATCH 397/441] refactor: use `--format=` instead of `--pretty=format:` Signed-off-by: leo --- src/Commands/QueryCommitFullMessage.cs | 2 +- src/Commands/QueryCommitSignInfo.cs | 6 ++---- src/Commands/QueryCommits.cs | 2 +- src/Commands/QueryCommitsForInteractiveRebase.cs | 2 +- src/Commands/QuerySingleCommit.cs | 2 +- src/Commands/QueryStashes.cs | 2 +- src/Commands/Statistics.cs | 2 +- 7 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/Commands/QueryCommitFullMessage.cs b/src/Commands/QueryCommitFullMessage.cs index c8f1867d..36b6d1c7 100644 --- a/src/Commands/QueryCommitFullMessage.cs +++ b/src/Commands/QueryCommitFullMessage.cs @@ -6,7 +6,7 @@ namespace SourceGit.Commands { WorkingDirectory = repo; Context = repo; - Args = $"show --no-show-signature --pretty=format:%B -s {sha}"; + Args = $"show --no-show-signature --format=%B -s {sha}"; } public string Result() diff --git a/src/Commands/QueryCommitSignInfo.cs b/src/Commands/QueryCommitSignInfo.cs index 4f729a8d..799e142d 100644 --- a/src/Commands/QueryCommitSignInfo.cs +++ b/src/Commands/QueryCommitSignInfo.cs @@ -1,6 +1,4 @@ -using System; - -namespace SourceGit.Commands +namespace SourceGit.Commands { public class QueryCommitSignInfo : Command { @@ -9,7 +7,7 @@ namespace SourceGit.Commands WorkingDirectory = repo; Context = repo; - const string baseArgs = "show --no-show-signature --pretty=format:\"%G?%n%GS%n%GK\" -s"; + const string baseArgs = "show --no-show-signature --format=%G?%n%GS%n%GK -s"; const string fakeSignersFileArg = "-c gpg.ssh.allowedSignersFile=/dev/null"; Args = $"{(useFakeSignersFile ? fakeSignersFileArg : string.Empty)} {baseArgs} {sha}"; } diff --git a/src/Commands/QueryCommits.cs b/src/Commands/QueryCommits.cs index 8d704aee..dd3c39b4 100644 --- a/src/Commands/QueryCommits.cs +++ b/src/Commands/QueryCommits.cs @@ -48,7 +48,7 @@ namespace SourceGit.Commands WorkingDirectory = repo; Context = repo; - Args = $"log -1000 --date-order --no-show-signature --decorate=full --pretty=format:%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s " + search; + Args = $"log -1000 --date-order --no-show-signature --decorate=full --format=%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s " + search; _findFirstMerged = false; } diff --git a/src/Commands/QueryCommitsForInteractiveRebase.cs b/src/Commands/QueryCommitsForInteractiveRebase.cs index 232d86e5..615060a5 100644 --- a/src/Commands/QueryCommitsForInteractiveRebase.cs +++ b/src/Commands/QueryCommitsForInteractiveRebase.cs @@ -11,7 +11,7 @@ namespace SourceGit.Commands WorkingDirectory = repo; Context = repo; - Args = $"log --date-order --no-show-signature --decorate=full --pretty=format:\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {on}..HEAD"; + Args = $"log --date-order --no-show-signature --decorate=full --format=\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {on}..HEAD"; } public List Result() diff --git a/src/Commands/QuerySingleCommit.cs b/src/Commands/QuerySingleCommit.cs index 1e1c9ea4..35289ec5 100644 --- a/src/Commands/QuerySingleCommit.cs +++ b/src/Commands/QuerySingleCommit.cs @@ -8,7 +8,7 @@ namespace SourceGit.Commands { WorkingDirectory = repo; Context = repo; - Args = $"show --no-show-signature --decorate=full --pretty=format:%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s -s {sha}"; + Args = $"show --no-show-signature --decorate=full --format=%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s -s {sha}"; } public Models.Commit Result() diff --git a/src/Commands/QueryStashes.cs b/src/Commands/QueryStashes.cs index ccf601c5..dd5d10cc 100644 --- a/src/Commands/QueryStashes.cs +++ b/src/Commands/QueryStashes.cs @@ -9,7 +9,7 @@ namespace SourceGit.Commands { WorkingDirectory = repo; Context = repo; - Args = "stash list --pretty=format:%H%n%P%n%ct%n%gd%n%s"; + Args = "stash list --format=%H%n%P%n%ct%n%gd%n%s"; } public List Result() diff --git a/src/Commands/Statistics.cs b/src/Commands/Statistics.cs index 511c43e8..1439cedd 100644 --- a/src/Commands/Statistics.cs +++ b/src/Commands/Statistics.cs @@ -8,7 +8,7 @@ namespace SourceGit.Commands { WorkingDirectory = repo; Context = repo; - Args = $"log --date-order --branches --remotes -{max} --pretty=format:\"%ct$%aN\""; + Args = $"log --date-order --branches --remotes -{max} --format=%ct$%aN"; } public Models.Statistics Result() From 695db2a319918d6ec96ec317432b0b656a154ab3 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 17 Mar 2025 20:57:18 +0800 Subject: [PATCH 398/441] code_style: run `dotnet format` Signed-off-by: leo --- src/Commands/QueryCommitSignInfo.cs | 1 - src/Native/MacOS.cs | 2 +- src/Views/About.axaml | 2 +- src/Views/AddWorktree.axaml | 10 +- src/Views/Askpass.axaml | 4 +- src/Views/AssumeUnchangedManager.axaml | 10 +- src/Views/Blame.axaml | 2 +- src/Views/BranchCompare.axaml | 4 +- src/Views/ChangeCollectionView.axaml | 4 +- src/Views/ChangeViewModeSwitcher.axaml | 2 +- src/Views/CherryPick.axaml | 8 +- src/Views/Clone.axaml | 36 ++-- src/Views/CommitBaseInfo.axaml | 14 +- src/Views/CommitChanges.axaml | 2 +- src/Views/CommitDetail.axaml | 20 +-- src/Views/CommitMessageTextBox.axaml | 4 +- src/Views/CommitRelationTracking.axaml | 2 +- src/Views/ConfigureWorkspace.axaml | 10 +- src/Views/ConfirmCommitWithoutFiles.axaml | 2 +- src/Views/DeleteBranch.axaml | 2 +- src/Views/DeleteRepositoryNode.axaml | 2 +- src/Views/DeleteTag.axaml | 2 +- src/Views/DiffView.axaml | 26 +-- src/Views/Discard.axaml | 16 +- src/Views/EditRepositoryNode.axaml | 2 +- src/Views/FileHistories.axaml | 6 +- src/Views/FilterModeSwitchButton.axaml | 2 +- src/Views/Histories.axaml | 12 +- src/Views/Hotkeys.axaml | 12 +- src/Views/ImageDiffView.axaml | 12 +- src/Views/Init.axaml | 2 +- src/Views/InteractiveRebase.axaml | 22 +-- src/Views/LFSFetch.axaml | 4 +- src/Views/LFSLocks.axaml | 4 +- src/Views/LFSTrackCustomPattern.axaml | 2 +- src/Views/Launcher.axaml | 6 +- src/Views/LauncherPage.axaml | 8 +- src/Views/LauncherTabBar.axaml | 2 +- src/Views/Merge.axaml | 2 +- src/Views/MergeMultiple.axaml | 6 +- src/Views/PopupRunningStatus.axaml | 6 +- src/Views/Preferences.axaml | 12 +- src/Views/Push.axaml | 4 +- src/Views/RepositoryConfigure.axaml | 14 +- src/Views/RepositoryToolbar.axaml | 210 +++++++++++----------- src/Views/RevisionCompare.axaml | 4 +- src/Views/RevisionFileContentViewer.axaml | 4 +- src/Views/RevisionFiles.axaml | 2 +- src/Views/Reword.axaml | 4 +- src/Views/SelfUpdate.axaml | 2 +- src/Views/StashChanges.axaml | 12 +- src/Views/TagsView.axaml | 20 +-- src/Views/TextDiffView.axaml | 10 +- src/Views/WelcomeToolbar.axaml | 4 +- src/Views/WorkingCopy.axaml | 16 +- 55 files changed, 307 insertions(+), 308 deletions(-) diff --git a/src/Commands/QueryCommitSignInfo.cs b/src/Commands/QueryCommitSignInfo.cs index 799e142d..133949af 100644 --- a/src/Commands/QueryCommitSignInfo.cs +++ b/src/Commands/QueryCommitSignInfo.cs @@ -29,7 +29,6 @@ Signer = lines[1], Key = lines[2] }; - } } } diff --git a/src/Native/MacOS.cs b/src/Native/MacOS.cs index 123b160b..d7ef4701 100644 --- a/src/Native/MacOS.cs +++ b/src/Native/MacOS.cs @@ -31,7 +31,7 @@ namespace SourceGit.Native var env = File.ReadAllText(customPathFile).Trim(); if (!string.IsNullOrEmpty(env)) path = env; - } + } Environment.SetEnvironmentVariable("PATH", path); } diff --git a/src/Views/About.axaml b/src/Views/About.axaml index 28529b63..d0dd7b82 100644 --- a/src/Views/About.axaml +++ b/src/Views/About.axaml @@ -28,7 +28,7 @@ Text="{DynamicResource Text.About}" HorizontalAlignment="Center" VerticalAlignment="Center" IsHitTestVisible="False"/> - + diff --git a/src/Views/AddWorktree.axaml b/src/Views/AddWorktree.axaml index d6853aab..1811008c 100644 --- a/src/Views/AddWorktree.axaml +++ b/src/Views/AddWorktree.axaml @@ -27,7 +27,7 @@ - +
- + - - + Text="{DynamicResource Text.AddWorktree.Tracking}"/> + - + - + - + - + @@ -62,7 +62,7 @@ - + @@ -73,7 +73,7 @@ ToolTip.Tip="{DynamicResource Text.Diff.Next}"> - + - - + - + diff --git a/src/Views/Discard.axaml b/src/Views/Discard.axaml index 23162060..1699b051 100644 --- a/src/Views/Discard.axaml +++ b/src/Views/Discard.axaml @@ -11,16 +11,16 @@ - + - - + @@ -31,13 +31,13 @@ Text="{DynamicResource Text.Discard.Changes}"/> - +
- + - + - diff --git a/src/Views/EditRepositoryNode.axaml b/src/Views/EditRepositoryNode.axaml index ac8f50f3..615e3f11 100644 --- a/src/Views/EditRepositoryNode.axaml +++ b/src/Views/EditRepositoryNode.axaml @@ -43,7 +43,7 @@ Fill="{Binding Converter={x:Static c:IntConverters.ToBookmarkBrush}}" HorizontalAlignment="Center" VerticalAlignment="Center" Data="{StaticResource Icons.Bookmark}"/> - + diff --git a/src/Views/FileHistories.axaml b/src/Views/FileHistories.axaml index 124b2e00..e33156fb 100644 --- a/src/Views/FileHistories.axaml +++ b/src/Views/FileHistories.axaml @@ -37,7 +37,7 @@ Text="{DynamicResource Text.FileHistory}" HorizontalAlignment="Center" VerticalAlignment="Center" IsHitTestVisible="False"/> - +
@@ -184,7 +184,7 @@ - + @@ -234,7 +234,7 @@ HorizontalAlignment="Center" VerticalAlignment="Center" IsVisible="{Binding IsLoading}"/> - + diff --git a/src/Views/FilterModeSwitchButton.axaml b/src/Views/FilterModeSwitchButton.axaml index 0fbbbf8e..b202c434 100644 --- a/src/Views/FilterModeSwitchButton.axaml +++ b/src/Views/FilterModeSwitchButton.axaml @@ -5,7 +5,7 @@ xmlns:m="using:SourceGit.Models" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="SourceGit.Views.FilterModeSwitchButton" - x:Name="ThisControl"> + x:Name="ThisControl"> @@ -104,7 +104,7 @@ - + diff --git a/src/Views/LFSTrackCustomPattern.axaml b/src/Views/LFSTrackCustomPattern.axaml index 36eaef65..f60304d5 100644 --- a/src/Views/LFSTrackCustomPattern.axaml +++ b/src/Views/LFSTrackCustomPattern.axaml @@ -11,7 +11,7 @@ - + + WindowStartupLocation="CenterScreen"> @@ -80,7 +80,7 @@ - @@ -93,7 +93,7 @@ - + diff --git a/src/Views/LauncherPage.axaml b/src/Views/LauncherPage.axaml index 81f504c1..7ce450de 100644 --- a/src/Views/LauncherPage.axaml +++ b/src/Views/LauncherPage.axaml @@ -17,14 +17,14 @@ - + - + @@ -32,7 +32,7 @@ - + @@ -138,7 +138,7 @@ + diff --git a/src/Views/LauncherTabBar.axaml b/src/Views/LauncherTabBar.axaml index 9b748e91..73b48f58 100644 --- a/src/Views/LauncherTabBar.axaml +++ b/src/Views/LauncherTabBar.axaml @@ -54,7 +54,7 @@ - + - + diff --git a/src/Views/MergeMultiple.axaml b/src/Views/MergeMultiple.axaml index bb543e16..332d9fef 100644 --- a/src/Views/MergeMultiple.axaml +++ b/src/Views/MergeMultiple.axaml @@ -12,7 +12,7 @@ - + - + @@ -84,7 +84,7 @@ - + diff --git a/src/Views/PopupRunningStatus.axaml b/src/Views/PopupRunningStatus.axaml index c2d86f51..a8467415 100644 --- a/src/Views/PopupRunningStatus.axaml +++ b/src/Views/PopupRunningStatus.axaml @@ -9,19 +9,19 @@ x:Name="ThisControl"> - + - + - + - + - + @@ -635,7 +635,7 @@ - + @@ -646,7 +646,7 @@ - + @@ -725,8 +725,8 @@ - - + + diff --git a/src/Views/RepositoryConfigure.axaml b/src/Views/RepositoryConfigure.axaml index f6a02c49..de777800 100644 --- a/src/Views/RepositoryConfigure.axaml +++ b/src/Views/RepositoryConfigure.axaml @@ -65,7 +65,7 @@ CornerRadius="3" Watermark="{DynamicResource Text.Configure.Email.Placeholder}" Text="{Binding UserEmail, Mode=TwoWay}"/> - + - @@ -256,7 +256,7 @@ - + @@ -315,7 +315,7 @@ - + @@ -442,7 +442,7 @@ - + diff --git a/src/Views/RepositoryToolbar.axaml b/src/Views/RepositoryToolbar.axaml index a409d8d0..9f7f1801 100644 --- a/src/Views/RepositoryToolbar.axaml +++ b/src/Views/RepositoryToolbar.axaml @@ -8,128 +8,128 @@ x:Class="SourceGit.Views.RepositoryToolbar" x:DataType="vm:Repository"> - - + + - - - + - + - - + - - + + - + + + + - + + + - + + + - + + + - + - - + - - + - - - - - - - - + - - - - - - - - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Views/RevisionCompare.axaml b/src/Views/RevisionCompare.axaml index 73703ff1..f0498fbf 100644 --- a/src/Views/RevisionCompare.axaml +++ b/src/Views/RevisionCompare.axaml @@ -15,7 +15,7 @@ - + @@ -32,7 +32,7 @@ - + diff --git a/src/Views/RevisionFileContentViewer.axaml b/src/Views/RevisionFileContentViewer.axaml index a3a168cf..86393316 100644 --- a/src/Views/RevisionFileContentViewer.axaml +++ b/src/Views/RevisionFileContentViewer.axaml @@ -35,12 +35,12 @@ - + - + diff --git a/src/Views/RevisionFiles.axaml b/src/Views/RevisionFiles.axaml index e0c6577d..6575dc66 100644 --- a/src/Views/RevisionFiles.axaml +++ b/src/Views/RevisionFiles.axaml @@ -50,7 +50,7 @@ - + - + - + - + - + - + + - + diff --git a/src/Views/WorkingCopy.axaml b/src/Views/WorkingCopy.axaml index c9b94d59..4d79135d 100644 --- a/src/Views/WorkingCopy.axaml +++ b/src/Views/WorkingCopy.axaml @@ -23,7 +23,7 @@ - + @@ -106,7 +106,7 @@ - + - + - + @@ -186,7 +186,7 @@ - + @@ -277,7 +277,7 @@ Width="18" Height="18" HorizontalAlignment="Right" IsVisible="{Binding IsCommitting}"/> - + - + From 760e44877ba02104638f0f5fd31c0ee556d6ff7d Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 18 Mar 2025 12:15:00 +0800 Subject: [PATCH 399/441] fix: wrong split char Signed-off-by: leo --- src/Commands/QuerySubmodules.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Commands/QuerySubmodules.cs b/src/Commands/QuerySubmodules.cs index e2debd06..6016b0be 100644 --- a/src/Commands/QuerySubmodules.cs +++ b/src/Commands/QuerySubmodules.cs @@ -26,7 +26,7 @@ namespace SourceGit.Commands var rs = ReadToEnd(); var builder = new StringBuilder(); - var lines = rs.StdOut.Split(['r', '\n'], System.StringSplitOptions.RemoveEmptyEntries); + var lines = rs.StdOut.Split(['\r', '\n'], System.StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { var match = REG_FORMAT1().Match(line); From 822452a20c36054837612cbf43e21795bead6ecc Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 18 Mar 2025 15:55:32 +0800 Subject: [PATCH 400/441] enhance: show inner exception message if possible when check update failed Signed-off-by: leo --- src/App.axaml.cs | 2 +- src/Models/{Version.cs => SelfUpdate.cs} | 24 ++++++++++++-- src/Views/SelfUpdate.axaml | 41 ++++++++++++------------ 3 files changed, 43 insertions(+), 24 deletions(-) rename src/Models/{Version.cs => SelfUpdate.cs} (65%) diff --git a/src/App.axaml.cs b/src/App.axaml.cs index f59d35db..af5e6177 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -532,7 +532,7 @@ namespace SourceGit catch (Exception e) { if (manually) - ShowSelfUpdateResult(e); + ShowSelfUpdateResult(new Models.SelfUpdateFailed(e)); } }); } diff --git a/src/Models/Version.cs b/src/Models/SelfUpdate.cs similarity index 65% rename from src/Models/Version.cs rename to src/Models/SelfUpdate.cs index 35c21778..e02f80d8 100644 --- a/src/Models/Version.cs +++ b/src/Models/SelfUpdate.cs @@ -1,4 +1,5 @@ -using System.Reflection; +using System; +using System.Reflection; using System.Text.Json.Serialization; namespace SourceGit.Models @@ -32,5 +33,24 @@ namespace SourceGit.Models } } - public class AlreadyUpToDate { } + public class AlreadyUpToDate + { + } + + public class SelfUpdateFailed + { + public string Reason + { + get; + private set; + } + + public SelfUpdateFailed(Exception e) + { + if (e.InnerException is { } inner) + Reason = inner.Message; + else + Reason = e.Message; + } + } } diff --git a/src/Views/SelfUpdate.axaml b/src/Views/SelfUpdate.axaml index 0a6fef34..2d5990e7 100644 --- a/src/Views/SelfUpdate.axaml +++ b/src/Views/SelfUpdate.axaml @@ -5,7 +5,6 @@ xmlns:m="using:SourceGit.Models" xmlns:vm="using:SourceGit.ViewModels" xmlns:v="using:SourceGit.Views" - xmlns:sys="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="SourceGit.Views.SelfUpdate" x:DataType="vm:SelfUpdate" @@ -87,26 +86,6 @@ - - - - - - - - - -
-### ru_RU.axaml: 99.73% +### ru_RU.axaml: 100.00%
Missing Keys -- Text.Repository.HistoriesOptions -- Text.Repository.HistoriesOptions.ShowTagsInGraph +
From a5bdcab3415ac76caee4493e7444dd2bb3c2d2d6 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 20 Mar 2025 09:38:02 +0800 Subject: [PATCH 406/441] code_style: move dynamic context menu creation to view models Signed-off-by: leo --- src/ViewModels/Repository.cs | 168 ++++++++++++++++++++++++++++------ src/Views/Repository.axaml.cs | 116 +---------------------- 2 files changed, 144 insertions(+), 140 deletions(-) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index bf283532..4f35d215 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -118,20 +118,6 @@ namespace SourceGit.ViewModels } } - public bool EnableTopoOrderInHistories - { - get => _settings.EnableTopoOrderInHistories; - set - { - if (value != _settings.EnableTopoOrderInHistories) - { - _settings.EnableTopoOrderInHistories = value; - OnPropertyChanged(); - Task.Run(RefreshCommits); - } - } - } - public bool OnlyHighlightCurrentBranchInHistories { get => _settings.OnlyHighlighCurrentBranchInHistories; @@ -145,20 +131,6 @@ namespace SourceGit.ViewModels } } - public Models.TagSortMode TagSortMode - { - get => _settings.TagSortMode; - set - { - if (value != _settings.TagSortMode) - { - _settings.TagSortMode = value; - OnPropertyChanged(); - VisibleTags = BuildVisibleTags(); - } - } - } - public string Filter { get => _filter; @@ -1470,6 +1442,97 @@ namespace SourceGit.ViewModels return menu; } + public ContextMenu CreateContextMenuForHistoriesPage() + { + var layout = new MenuItem(); + layout.Header = App.Text("Repository.HistoriesLayout"); + layout.IsEnabled = false; + + var isHorizontal = Preferences.Instance.UseTwoColumnsLayoutInHistories; + var horizontal = new MenuItem(); + horizontal.Header = App.Text("Repository.HistoriesLayout.Horizontal"); + if (isHorizontal) + horizontal.Icon = App.CreateMenuIcon("Icons.Check"); + horizontal.Click += (_, ev) => + { + Preferences.Instance.UseTwoColumnsLayoutInHistories = true; + ev.Handled = true; + }; + + var vertical = new MenuItem(); + vertical.Header = App.Text("Repository.HistoriesLayout.Vertical"); + if (!isHorizontal) + vertical.Icon = App.CreateMenuIcon("Icons.Check"); + vertical.Click += (_, ev) => + { + Preferences.Instance.UseTwoColumnsLayoutInHistories = false; + ev.Handled = true; + }; + + var order = new MenuItem(); + order.Header = App.Text("Repository.HistoriesOrder"); + order.IsEnabled = false; + + var dateOrder = new MenuItem(); + dateOrder.Header = App.Text("Repository.HistoriesOrder.ByDate"); + dateOrder.SetValue(Views.MenuItemExtension.CommandProperty, "--date-order"); + if (!_settings.EnableTopoOrderInHistories) + dateOrder.Icon = App.CreateMenuIcon("Icons.Check"); + dateOrder.Click += (_, ev) => + { + if (_settings.EnableTopoOrderInHistories) + { + _settings.EnableTopoOrderInHistories = false; + Task.Run(RefreshCommits); + } + + ev.Handled = true; + }; + + var topoOrder = new MenuItem(); + topoOrder.Header = App.Text("Repository.HistoriesOrder.Topo"); + topoOrder.SetValue(Views.MenuItemExtension.CommandProperty, "--top-order"); + if (_settings.EnableTopoOrderInHistories) + topoOrder.Icon = App.CreateMenuIcon("Icons.Check"); + topoOrder.Click += (_, ev) => + { + if (!_settings.EnableTopoOrderInHistories) + { + _settings.EnableTopoOrderInHistories = true; + Task.Run(RefreshCommits); + } + + ev.Handled = true; + }; + + var others = new MenuItem(); + others.Header = App.Text("Repository.HistoriesOptions"); + others.IsEnabled = false; + + var showTagsInGraph = new MenuItem(); + showTagsInGraph.Header = App.Text("Repository.HistoriesOptions.ShowTagsInGraph"); + if (Preferences.Instance.ShowTagsInGraph) + showTagsInGraph.Icon = App.CreateMenuIcon("Icons.Check"); + showTagsInGraph.Click += (_, ev) => + { + Preferences.Instance.ShowTagsInGraph = !Preferences.Instance.ShowTagsInGraph; + ev.Handled = true; + }; + + var menu = new ContextMenu(); + menu.Items.Add(layout); + menu.Items.Add(horizontal); + menu.Items.Add(vertical); + menu.Items.Add(new MenuItem() { Header = "-" }); + menu.Items.Add(order); + menu.Items.Add(dateOrder); + menu.Items.Add(topoOrder); + menu.Items.Add(new MenuItem() { Header = "-" }); + menu.Items.Add(others); + menu.Items.Add(showTagsInGraph); + return menu; + } + public ContextMenu CreateContextMenuForLocalBranch(Models.Branch branch) { var menu = new ContextMenu(); @@ -2065,6 +2128,55 @@ namespace SourceGit.ViewModels return menu; } + public ContextMenu CreateContextMenuForTagSortMode() + { + var mode = _settings.TagSortMode; + var changeMode = new Action((m) => + { + if (_settings.TagSortMode != m) + { + _settings.TagSortMode = m; + VisibleTags = BuildVisibleTags(); + } + }); + + var byCreatorDate = new MenuItem(); + byCreatorDate.Header = App.Text("Repository.Tags.OrderByCreatorDate"); + if (mode == Models.TagSortMode.CreatorDate) + byCreatorDate.Icon = App.CreateMenuIcon("Icons.Check"); + byCreatorDate.Click += (_, ev) => + { + changeMode(Models.TagSortMode.CreatorDate); + ev.Handled = true; + }; + + var byNameAsc = new MenuItem(); + byNameAsc.Header = App.Text("Repository.Tags.OrderByNameAsc"); + if (mode == Models.TagSortMode.NameInAscending) + byNameAsc.Icon = App.CreateMenuIcon("Icons.Check"); + byNameAsc.Click += (_, ev) => + { + changeMode(Models.TagSortMode.NameInAscending); + ev.Handled = true; + }; + + var byNameDes = new MenuItem(); + byNameDes.Header = App.Text("Repository.Tags.OrderByNameDes"); + if (mode == Models.TagSortMode.NameInDescending) + byNameDes.Icon = App.CreateMenuIcon("Icons.Check"); + byNameDes.Click += (_, ev) => + { + changeMode(Models.TagSortMode.NameInDescending); + ev.Handled = true; + }; + + var menu = new ContextMenu(); + menu.Items.Add(byCreatorDate); + menu.Items.Add(byNameAsc); + menu.Items.Add(byNameDes); + return menu; + } + public ContextMenu CreateContextMenuForSubmodule(string submodule) { var open = new MenuItem(); diff --git a/src/Views/Repository.axaml.cs b/src/Views/Repository.axaml.cs index e98adf70..d848c000 100644 --- a/src/Views/Repository.axaml.cs +++ b/src/Views/Repository.axaml.cs @@ -396,83 +396,8 @@ namespace SourceGit.Views { if (sender is Button button && DataContext is ViewModels.Repository repo) { - var layout = new MenuItem(); - layout.Header = App.Text("Repository.HistoriesLayout"); - layout.IsEnabled = false; - - var isHorizontal = ViewModels.Preferences.Instance.UseTwoColumnsLayoutInHistories; - var horizontal = new MenuItem(); - horizontal.Header = App.Text("Repository.HistoriesLayout.Horizontal"); - if (isHorizontal) - horizontal.Icon = App.CreateMenuIcon("Icons.Check"); - horizontal.Click += (_, ev) => - { - ViewModels.Preferences.Instance.UseTwoColumnsLayoutInHistories = true; - ev.Handled = true; - }; - - var vertical = new MenuItem(); - vertical.Header = App.Text("Repository.HistoriesLayout.Vertical"); - if (!isHorizontal) - vertical.Icon = App.CreateMenuIcon("Icons.Check"); - vertical.Click += (_, ev) => - { - ViewModels.Preferences.Instance.UseTwoColumnsLayoutInHistories = false; - ev.Handled = true; - }; - - var order = new MenuItem(); - order.Header = App.Text("Repository.HistoriesOrder"); - order.IsEnabled = false; - - var dateOrder = new MenuItem(); - dateOrder.Header = App.Text("Repository.HistoriesOrder.ByDate"); - dateOrder.SetValue(MenuItemExtension.CommandProperty, "--date-order"); - if (!repo.EnableTopoOrderInHistories) - dateOrder.Icon = App.CreateMenuIcon("Icons.Check"); - dateOrder.Click += (_, ev) => - { - repo.EnableTopoOrderInHistories = false; - ev.Handled = true; - }; - - var topoOrder = new MenuItem(); - topoOrder.Header = App.Text("Repository.HistoriesOrder.Topo"); - topoOrder.SetValue(MenuItemExtension.CommandProperty, "--top-order"); - if (repo.EnableTopoOrderInHistories) - topoOrder.Icon = App.CreateMenuIcon("Icons.Check"); - topoOrder.Click += (_, ev) => - { - repo.EnableTopoOrderInHistories = true; - ev.Handled = true; - }; - - var others = new MenuItem(); - others.Header = App.Text("Repository.HistoriesOptions"); - others.IsEnabled = false; - - var showTagsInGraph = new MenuItem(); - showTagsInGraph.Header = App.Text("Repository.HistoriesOptions.ShowTagsInGraph"); - if (ViewModels.Preferences.Instance.ShowTagsInGraph) - showTagsInGraph.Icon = App.CreateMenuIcon("Icons.Check"); - showTagsInGraph.Click += (_, ev) => - { - ViewModels.Preferences.Instance.ShowTagsInGraph = !ViewModels.Preferences.Instance.ShowTagsInGraph; - ev.Handled = true; - }; - - var menu = new ContextMenu(); - menu.Items.Add(layout); - menu.Items.Add(horizontal); - menu.Items.Add(vertical); - menu.Items.Add(new MenuItem() { Header = "-" }); - menu.Items.Add(order); - menu.Items.Add(dateOrder); - menu.Items.Add(topoOrder); - menu.Items.Add(new MenuItem() { Header = "-" }); - menu.Items.Add(others); - menu.Items.Add(showTagsInGraph); - menu.Open(button); + var menu = repo.CreateContextMenuForHistoriesPage(); + menu?.Open(button); } e.Handled = true; @@ -482,41 +407,8 @@ namespace SourceGit.Views { if (sender is Button button && DataContext is ViewModels.Repository repo) { - var byCreatorDate = new MenuItem(); - byCreatorDate.Header = App.Text("Repository.Tags.OrderByCreatorDate"); - if (repo.TagSortMode == Models.TagSortMode.CreatorDate) - byCreatorDate.Icon = App.CreateMenuIcon("Icons.Check"); - byCreatorDate.Click += (_, ev) => - { - repo.TagSortMode = Models.TagSortMode.CreatorDate; - ev.Handled = true; - }; - - var byNameAsc = new MenuItem(); - byNameAsc.Header = App.Text("Repository.Tags.OrderByNameAsc"); - if (repo.TagSortMode == Models.TagSortMode.NameInAscending) - byNameAsc.Icon = App.CreateMenuIcon("Icons.Check"); - byNameAsc.Click += (_, ev) => - { - repo.TagSortMode = Models.TagSortMode.NameInAscending; - ev.Handled = true; - }; - - var byNameDes = new MenuItem(); - byNameDes.Header = App.Text("Repository.Tags.OrderByNameDes"); - if (repo.TagSortMode == Models.TagSortMode.NameInDescending) - byNameDes.Icon = App.CreateMenuIcon("Icons.Check"); - byNameDes.Click += (_, ev) => - { - repo.TagSortMode = Models.TagSortMode.NameInDescending; - ev.Handled = true; - }; - - var menu = new ContextMenu(); - menu.Items.Add(byCreatorDate); - menu.Items.Add(byNameAsc); - menu.Items.Add(byNameDes); - menu.Open(button); + var menu = repo.CreateContextMenuForTagSortMode(); + menu?.Open(button); } e.Handled = true; From 145273b4a71e2c9d91a7c0cca461d5fa6b900e86 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 20 Mar 2025 11:10:48 +0800 Subject: [PATCH 407/441] refactor: move `Show tags in commit graph` to `Preferences` (#1109) Signed-off-by: leo --- src/Resources/Locales/en_US.axaml | 3 +-- src/Resources/Locales/ru_RU.axaml | 3 +-- src/Resources/Locales/zh_CN.axaml | 3 +-- src/Resources/Locales/zh_TW.axaml | 3 +-- src/ViewModels/Repository.cs | 17 ----------------- src/Views/Preferences.axaml | 9 +++++++-- 6 files changed, 11 insertions(+), 27 deletions(-) diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 293dd77b..f24d6c65 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -471,6 +471,7 @@ History Commits Show author time instead of commit time in graph Show children in the commit details + Show tags in commit graph Subject Guide Length GIT Enable Auto CRLF @@ -569,8 +570,6 @@ LAYOUT Horizontal Vertical - OPTIONS - Show Tags in Graph COMMITS ORDER Commit Date Topologically diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index 24d296e3..707c9ed9 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -475,6 +475,7 @@ Максимальная длина истории Показывать время автора вместо времени ревизии на графике Показать наследника в деталях комментария + Показывать метки на графике Длина темы ревизии GIT Включить автозавершение CRLF @@ -574,8 +575,6 @@ РАСПОЛОЖЕНИЕ Горизонтально Вертикально - ОПЦИИ - Показывать метки на графике ЗАПРОС РЕВИЗИЙ Дата ревизии Топологически diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index b8dcf417..93d08bd0 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -475,6 +475,7 @@ 最大历史提交数 在提交路线图中显示修改时间而非提交时间 在提交详情页中显示子提交列表 + 在提交路线图中显示标签 SUBJECT字数检测 GIT配置 自动换行转换 @@ -573,8 +574,6 @@ 布局方式 水平排布 竖直排布 - 其它设置 - 在提交路线图中显示标签 提交列表排序规则 按提交时间 按拓扑排序 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 1d2cee7c..d5a7a77c 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -474,6 +474,7 @@ 最大歷史提交數 在提交路線圖中顯示修改時間而非提交時間 在提交詳細資訊中顯示後續提交 + 在路線圖中顯示標籤 提交標題字數偵測 Git 設定 自動換行轉換 @@ -572,8 +573,6 @@ 版面配置 橫向顯示 縱向顯示 - 其它設定 - 在路線圖中顯示標籤 提交顯示順序 依時間排序 依拓撲排序 diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 4f35d215..6ea41e04 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1505,20 +1505,6 @@ namespace SourceGit.ViewModels ev.Handled = true; }; - var others = new MenuItem(); - others.Header = App.Text("Repository.HistoriesOptions"); - others.IsEnabled = false; - - var showTagsInGraph = new MenuItem(); - showTagsInGraph.Header = App.Text("Repository.HistoriesOptions.ShowTagsInGraph"); - if (Preferences.Instance.ShowTagsInGraph) - showTagsInGraph.Icon = App.CreateMenuIcon("Icons.Check"); - showTagsInGraph.Click += (_, ev) => - { - Preferences.Instance.ShowTagsInGraph = !Preferences.Instance.ShowTagsInGraph; - ev.Handled = true; - }; - var menu = new ContextMenu(); menu.Items.Add(layout); menu.Items.Add(horizontal); @@ -1527,9 +1513,6 @@ namespace SourceGit.ViewModels menu.Items.Add(order); menu.Items.Add(dateOrder); menu.Items.Add(topoOrder); - menu.Items.Add(new MenuItem() { Header = "-" }); - menu.Items.Add(others); - menu.Items.Add(showTagsInGraph); return menu; } diff --git a/src/Views/Preferences.axaml b/src/Views/Preferences.axaml index d2b08467..702ec20f 100644 --- a/src/Views/Preferences.axaml +++ b/src/Views/Preferences.axaml @@ -46,7 +46,7 @@ - + + + - Date: Thu, 20 Mar 2025 03:11:14 +0000 Subject: [PATCH 408/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 25 ++++++++++--------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 1655d03a..5b3dbc20 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-98.79%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-99.73%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.26%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.73%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-90.99%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-98.92%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-99.87%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.39%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.12%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index 55262e90..b7f87cdf 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,4 +1,4 @@ -### de_DE.axaml: 98.79% +### de_DE.axaml: 98.92%
@@ -10,24 +10,22 @@ - Text.Diff.Last - Text.Preferences.AI.Streaming - Text.Preferences.Appearance.EditorTabWidth -- Text.Repository.HistoriesOptions -- Text.Repository.HistoriesOptions.ShowTagsInGraph +- Text.Preferences.General.ShowTagsInGraph - Text.StashCM.SaveAsPatch
-### es_ES.axaml: 99.73% +### es_ES.axaml: 99.87%
Missing Keys -- Text.Repository.HistoriesOptions -- Text.Repository.HistoriesOptions.ShowTagsInGraph +- Text.Preferences.General.ShowTagsInGraph
-### fr_FR.axaml: 91.26% +### fr_FR.axaml: 91.39%
@@ -66,6 +64,7 @@ - Text.Preferences.Appearance.FontSize.Editor - Text.Preferences.General.DateFormat - Text.Preferences.General.ShowChildren +- Text.Preferences.General.ShowTagsInGraph - Text.Preferences.Git.SSLVerify - Text.Repository.CustomActions - Text.Repository.FilterCommits @@ -75,8 +74,6 @@ - Text.Repository.HistoriesLayout - Text.Repository.HistoriesLayout.Horizontal - Text.Repository.HistoriesLayout.Vertical -- Text.Repository.HistoriesOptions -- Text.Repository.HistoriesOptions.ShowTagsInGraph - Text.Repository.HistoriesOrder - Text.Repository.HistoriesOrder.ByDate - Text.Repository.HistoriesOrder.Topo @@ -101,18 +98,17 @@
-### it_IT.axaml: 99.73% +### it_IT.axaml: 99.87%
Missing Keys -- Text.Repository.HistoriesOptions -- Text.Repository.HistoriesOptions.ShowTagsInGraph +- Text.Preferences.General.ShowTagsInGraph
-### pt_BR.axaml: 90.99% +### pt_BR.axaml: 91.12%
@@ -159,13 +155,12 @@ - Text.Preferences.Appearance.EditorTabWidth - Text.Preferences.General.DateFormat - Text.Preferences.General.ShowChildren +- Text.Preferences.General.ShowTagsInGraph - Text.Preferences.Git.SSLVerify - Text.Repository.FilterCommits - Text.Repository.HistoriesLayout - Text.Repository.HistoriesLayout.Horizontal - Text.Repository.HistoriesLayout.Vertical -- Text.Repository.HistoriesOptions -- Text.Repository.HistoriesOptions.ShowTagsInGraph - Text.Repository.HistoriesOrder - Text.Repository.Notifications.Clear - Text.Repository.OnlyHighlightCurrentBranchInHistories From 891e1b2ec8fc6a00882186e390c06a365ea05d46 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 20 Mar 2025 19:55:50 +0800 Subject: [PATCH 409/441] ux: show name of stash instead of SHA which is useless to user Signed-off-by: leo --- src/Views/StashesPage.axaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/StashesPage.axaml b/src/Views/StashesPage.axaml index 028764ca..6b087eb8 100644 --- a/src/Views/StashesPage.axaml +++ b/src/Views/StashesPage.axaml @@ -92,7 +92,7 @@ - + From 65dbfd336d4fe33e05ce6864fdf589e95c96b3c7 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 20 Mar 2025 20:53:30 +0800 Subject: [PATCH 410/441] refactor: it's not necessary to store untracked file list for selected stash Signed-off-by: leo --- src/Models/Stash.cs | 1 - src/ViewModels/StashesPage.cs | 25 ++++++++----------------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/Models/Stash.cs b/src/Models/Stash.cs index 8dca3bdb..257b6d33 100644 --- a/src/Models/Stash.cs +++ b/src/Models/Stash.cs @@ -10,7 +10,6 @@ namespace SourceGit.Models public List Parents { get; set; } = []; public ulong Time { get; set; } = 0; public string Message { get; set; } = ""; - public bool HasUntracked => Parents.Count == 3; public string TimeStr => DateTime.UnixEpoch.AddSeconds(Time).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime); } diff --git a/src/ViewModels/StashesPage.cs b/src/ViewModels/StashesPage.cs index ec7cc84a..d8443c91 100644 --- a/src/ViewModels/StashesPage.cs +++ b/src/ViewModels/StashesPage.cs @@ -59,24 +59,16 @@ namespace SourceGit.ViewModels Task.Run(() => { var changes = new Commands.CompareRevisions(_repo.FullPath, $"{value.SHA}^", value.SHA).Result(); - var untracked = new HashSet(); - if (value.HasUntracked) + if (value.Parents.Count == 3) { - var untrackedChanges = new Commands.CompareRevisions(_repo.FullPath, "4b825dc642cb6eb9a060e54bf8d69288fbee4904", value.Parents[2]).Result(); - foreach (var c in untrackedChanges) - { - untracked.Add(c.Path); + var untracked = new Commands.CompareRevisions(_repo.FullPath, "4b825dc642cb6eb9a060e54bf8d69288fbee4904", value.Parents[2]).Result(); + foreach (var c in untracked) changes.Add(c); - } + + changes.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal)); } - changes.Sort((l, r) => Models.NumericSort.Compare(l.Path, r.Path)); - - Dispatcher.UIThread.Invoke(() => - { - Changes = changes; - _untrackedChanges = untracked; - }); + Dispatcher.UIThread.Invoke(() => Changes = changes); }); } } @@ -102,7 +94,7 @@ namespace SourceGit.ViewModels { if (value == null) DiffContext = null; - else if (_untrackedChanges.Contains(value.Path)) + else if (value.Index == Models.ChangeState.Added && _selectedStash.Parents.Count == 3) DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption("4b825dc642cb6eb9a060e54bf8d69288fbee4904", _selectedStash.Parents[2], value), _diffContext); else DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(_selectedStash.Parents[0], _selectedStash.SHA, value), _diffContext); @@ -178,7 +170,7 @@ namespace SourceGit.ViewModels var opts = new List(); foreach (var c in _changes) { - if (_untrackedChanges.Contains(c.Path)) + if (c.Index == Models.ChangeState.Added && _selectedStash.Parents.Count == 3) opts.Add(new Models.DiffOption("4b825dc642cb6eb9a060e54bf8d69288fbee4904", _selectedStash.Parents[2], c)); else opts.Add(new Models.DiffOption(_selectedStash.Parents[0], _selectedStash.SHA, c)); @@ -303,7 +295,6 @@ namespace SourceGit.ViewModels private List _visibleStashes = new List(); private string _searchFilter = string.Empty; private Models.Stash _selectedStash = null; - private HashSet _untrackedChanges = new HashSet(); private List _changes = null; private Models.Change _selectedChange = null; private DiffContext _diffContext = null; From 38d87fa1a1b443ede1cab537af489fd46431be21 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 20 Mar 2025 21:12:08 +0800 Subject: [PATCH 411/441] feature: use `git stash show -u --name-status ` command to query changes in selected stash if git >= 2.32.0 Signed-off-by: leo --- src/Commands/QueryStashChanges.cs | 68 +++++++++++++++++++++++++++++++ src/Models/GitVersions.cs | 13 ++++-- src/ViewModels/StashChanges.cs | 4 +- src/ViewModels/StashesPage.cs | 26 ++++++++---- 4 files changed, 98 insertions(+), 13 deletions(-) create mode 100644 src/Commands/QueryStashChanges.cs diff --git a/src/Commands/QueryStashChanges.cs b/src/Commands/QueryStashChanges.cs new file mode 100644 index 00000000..7fc27ea3 --- /dev/null +++ b/src/Commands/QueryStashChanges.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace SourceGit.Commands +{ + /// + /// Query stash changes. Requires git >= 2.32.0 + /// + public partial class QueryStashChanges : Command + { + [GeneratedRegex(@"^([MADRC])\s+(.+)$")] + private static partial Regex REG_FORMAT(); + + public QueryStashChanges(string repo, string stash) + { + WorkingDirectory = repo; + Context = repo; + Args = $"stash show -u --name-status \"{stash}\""; + } + + public List Result() + { + var rs = ReadToEnd(); + if (!rs.IsSuccess) + return []; + + var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); + var outs = new List(); + foreach (var line in lines) + { + var match = REG_FORMAT().Match(line); + if (!match.Success) + continue; + + var change = new Models.Change() { Path = match.Groups[2].Value }; + var status = match.Groups[1].Value; + + switch (status[0]) + { + case 'M': + change.Set(Models.ChangeState.Modified); + outs.Add(change); + break; + case 'A': + change.Set(Models.ChangeState.Added); + outs.Add(change); + break; + case 'D': + change.Set(Models.ChangeState.Deleted); + outs.Add(change); + break; + case 'R': + change.Set(Models.ChangeState.Renamed); + outs.Add(change); + break; + case 'C': + change.Set(Models.ChangeState.Copied); + outs.Add(change); + break; + } + } + + outs.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal)); + return outs; + } + } +} diff --git a/src/Models/GitVersions.cs b/src/Models/GitVersions.cs index 394a9518..92fd8c59 100644 --- a/src/Models/GitVersions.cs +++ b/src/Models/GitVersions.cs @@ -13,13 +13,18 @@ public static readonly System.Version ADD_WITH_PATHSPECFILE = new System.Version(2, 25, 0); /// - /// The minimal version of Git that supports the `stash` command with the `--pathspec-from-file` option. + /// The minimal version of Git that supports the `stash push` command with the `--pathspec-from-file` option. /// - public static readonly System.Version STASH_WITH_PATHSPECFILE = new System.Version(2, 26, 0); + public static readonly System.Version STASH_PUSH_WITH_PATHSPECFILE = new System.Version(2, 26, 0); /// - /// The minimal version of Git that supports the `stash` command with the `--staged` option. + /// The minimal version of Git that supports the `stash push` command with the `--staged` option. /// - public static readonly System.Version STASH_ONLY_STAGED = new System.Version(2, 35, 0); + public static readonly System.Version STASH_PUSH_ONLY_STAGED = new System.Version(2, 35, 0); + + /// + /// The minimal version of Git that supports the `stash show` command with the `-u` option. + /// + public static readonly System.Version STASH_SHOW_WITH_UNTRACKED = new System.Version(2, 32, 0); } } diff --git a/src/ViewModels/StashChanges.cs b/src/ViewModels/StashChanges.cs index 33ebb1f3..e35aaad0 100644 --- a/src/ViewModels/StashChanges.cs +++ b/src/ViewModels/StashChanges.cs @@ -64,7 +64,7 @@ namespace SourceGit.ViewModels { if (OnlyStaged) { - if (Native.OS.GitVersion >= Models.GitVersions.STASH_ONLY_STAGED) + if (Native.OS.GitVersion >= Models.GitVersions.STASH_PUSH_ONLY_STAGED) { succ = new Commands.Stash(_repo.FullPath).PushOnlyStaged(Message, KeepIndex); } @@ -109,7 +109,7 @@ namespace SourceGit.ViewModels return true; var succ = false; - if (Native.OS.GitVersion >= Models.GitVersions.STASH_WITH_PATHSPECFILE) + if (Native.OS.GitVersion >= Models.GitVersions.STASH_PUSH_WITH_PATHSPECFILE) { var paths = new List(); foreach (var c in changes) diff --git a/src/ViewModels/StashesPage.cs b/src/ViewModels/StashesPage.cs index d8443c91..77ed5551 100644 --- a/src/ViewModels/StashesPage.cs +++ b/src/ViewModels/StashesPage.cs @@ -58,14 +58,26 @@ namespace SourceGit.ViewModels { Task.Run(() => { - var changes = new Commands.CompareRevisions(_repo.FullPath, $"{value.SHA}^", value.SHA).Result(); - if (value.Parents.Count == 3) - { - var untracked = new Commands.CompareRevisions(_repo.FullPath, "4b825dc642cb6eb9a060e54bf8d69288fbee4904", value.Parents[2]).Result(); - foreach (var c in untracked) - changes.Add(c); + var changes = null as List; - changes.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal)); + if (Native.OS.GitVersion >= Models.GitVersions.STASH_SHOW_WITH_UNTRACKED) + { + changes = new Commands.QueryStashChanges(_repo.FullPath, value.Name).Result(); + } + else + { + changes = new Commands.CompareRevisions(_repo.FullPath, $"{value.SHA}^", value.SHA).Result(); + if (value.Parents.Count == 3) + { + var untracked = new Commands.CompareRevisions(_repo.FullPath, "4b825dc642cb6eb9a060e54bf8d69288fbee4904", value.Parents[2]).Result(); + var needSort = changes.Count > 0; + + foreach (var c in untracked) + changes.Add(c); + + if (needSort) + changes.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal)); + } } Dispatcher.UIThread.Invoke(() => Changes = changes); From 7cd5814410b152a1363b9cf173e9e67928dd6fe1 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 20 Mar 2025 21:18:51 +0800 Subject: [PATCH 412/441] enhance: better regex for output of `Commands.CompareRevisions` Signed-off-by: leo --- src/Commands/CompareRevisions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Commands/CompareRevisions.cs b/src/Commands/CompareRevisions.cs index 8a6f2832..e311a88e 100644 --- a/src/Commands/CompareRevisions.cs +++ b/src/Commands/CompareRevisions.cs @@ -6,7 +6,7 @@ namespace SourceGit.Commands { public partial class CompareRevisions : Command { - [GeneratedRegex(@"^(\s?[\w\?]{1,4})\s+(.+)$")] + [GeneratedRegex(@"^([MADRC])\s+(.+)$")] private static partial Regex REG_FORMAT(); public CompareRevisions(string repo, string start, string end) From 5467703a6e085853fbb10762d0d93abc223b004c Mon Sep 17 00:00:00 2001 From: Ilian Delagrange <62717259+ilianoKokoro@users.noreply.github.com> Date: Thu, 20 Mar 2025 21:30:57 -0400 Subject: [PATCH 413/441] localization: add missing french translations (#1113) Co-authored-by: Ilian Delagrange --- src/Resources/Locales/fr_FR.axaml | 64 +++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index f3a71390..19c0859c 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -684,4 +684,68 @@ Verrouiller Supprimer Déverrouiller + RE-GÉNÉRER + APPLIQUER COMME MESSAGE DE COMMIT + Appliquer le Stash + Supprimer après l'application + Rétablir les modifications de l'index + Stash: + Action personnalisée + Branche en amont invalide! + Initialiser et mettre à jour les sous-modules + Branche + Attendre la fin de l'action + Les espaces seront remplacés par des tirets. + Chemin: + Tous les enfants seront retirés de la liste. + Cela le supprimera uniquement de la liste, pas du disque ! + Première différence + Dernière différence + Traitement du commit + Fusionnement + Arrêté à + Annulation du commit + Source: + Fusionner (Plusieurs) + Commit tous les changement + Stratégie: + Cibles: + Activer le streaming + Largeur de tab dans l'éditeur + Taille de police + Défaut + Éditeur + Format de date + Afficher les enfants dans les détails du commit + Afficher les tags dans le graphique des commits + Activer la vérification HTTP SSL + Actions personnalisées + Visibilité dans le graphique + Réinitialiser + Cacher dans le graphique des commits + Filtrer dans le graphique des commits + DISPOSITION + Horizontal + Vertical + ORDRE DES COMMITS + Date du commit + Topologiquement + EFFACER LES NOTIFICATIONS + PASSER + Par date de créateur + Par nom (Croissant) + Par nom (Décroissant) + Trier + Utiliser le temps relatif dans les historiques + Analyser les repositories + Définir la branche suivie + Branche: + Retirer la branche amont + En amont: + Aller sur + Restauration automatique après le stashing + Vos fichiers de travail restent inchangés, mais une sauvegarde est enregistrée. + Sauvegarder en tant que patch... + Commit (Modifier) + SignOff From 56253e95c337210215d85546b1378e9f7b119ce3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 21 Mar 2025 01:31:07 +0000 Subject: [PATCH 414/441] doc: Update translation status and missing keys --- README.md | 2 +- TRANSLATION.md | 67 ++------------------------------------------------ 2 files changed, 3 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index 5b3dbc20..2f13fce6 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-98.92%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-99.87%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.39%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.12%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) +[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-98.92%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-99.87%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-%E2%88%9A-brightgreen)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.12%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) > [!NOTE] > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) diff --git a/TRANSLATION.md b/TRANSLATION.md index b7f87cdf..aa8da630 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -25,76 +25,13 @@
-### fr_FR.axaml: 91.39% +### fr_FR.axaml: 100.00%
Missing Keys -- Text.AIAssistant.Regen -- Text.AIAssistant.Use -- Text.ApplyStash -- Text.ApplyStash.DropAfterApply -- Text.ApplyStash.RestoreIndex -- Text.ApplyStash.Stash -- Text.BranchCM.CustomAction -- Text.BranchUpstreamInvalid -- Text.Clone.RecurseSubmodules -- Text.Configure.CustomAction.Scope.Branch -- Text.Configure.CustomAction.WaitForExit -- Text.CreateBranch.Name.WarnSpace -- Text.DeleteRepositoryNode.Path -- Text.DeleteRepositoryNode.TipForGroup -- Text.DeleteRepositoryNode.TipForRepository -- Text.Diff.First -- Text.Diff.Last -- Text.InProgress.CherryPick.Head -- Text.InProgress.Merge.Operating -- Text.InProgress.Rebase.StoppedAt -- Text.InProgress.Revert.Head -- Text.Merge.Source -- Text.MergeMultiple -- Text.MergeMultiple.CommitChanges -- Text.MergeMultiple.Strategy -- Text.MergeMultiple.Targets -- Text.Preferences.AI.Streaming -- Text.Preferences.Appearance.EditorTabWidth -- Text.Preferences.Appearance.FontSize -- Text.Preferences.Appearance.FontSize.Default -- Text.Preferences.Appearance.FontSize.Editor -- Text.Preferences.General.DateFormat -- Text.Preferences.General.ShowChildren -- Text.Preferences.General.ShowTagsInGraph -- Text.Preferences.Git.SSLVerify -- Text.Repository.CustomActions -- Text.Repository.FilterCommits -- Text.Repository.FilterCommits.Default -- Text.Repository.FilterCommits.Exclude -- Text.Repository.FilterCommits.Include -- Text.Repository.HistoriesLayout -- Text.Repository.HistoriesLayout.Horizontal -- Text.Repository.HistoriesLayout.Vertical -- Text.Repository.HistoriesOrder -- Text.Repository.HistoriesOrder.ByDate -- Text.Repository.HistoriesOrder.Topo -- Text.Repository.Notifications.Clear -- Text.Repository.Skip -- Text.Repository.Tags.OrderByCreatorDate -- Text.Repository.Tags.OrderByNameAsc -- Text.Repository.Tags.OrderByNameDes -- Text.Repository.Tags.Sort -- Text.Repository.UseRelativeTimeInHistories -- Text.ScanRepositories -- Text.SetUpstream -- Text.SetUpstream.Local -- Text.SetUpstream.Unset -- Text.SetUpstream.Upstream -- Text.SHALinkCM.NavigateTo -- Text.Stash.AutoRestore -- Text.Stash.AutoRestore.Tip -- Text.StashCM.SaveAsPatch -- Text.WorkingCopy.CommitToEdit -- Text.WorkingCopy.SignOff +
From 8c1e1a3e6a0cb4ea41ed8a6361bc2a894a492617 Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 21 Mar 2025 09:45:42 +0800 Subject: [PATCH 415/441] fix: text diff view scrolling issue introduced by AvaloniaEdit `11.2.0` (commit 7caa03a09b) - `SyncScrollOffset` does not update in `side-by-side` mode while scrolling - Highlighted chunk is not cleared when scroll by drag scrollbar Signed-off-by: leo --- src/Views/TextDiffView.axaml.cs | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 925c7622..0d20a990 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -565,7 +565,6 @@ namespace SourceGit.Views ScrollToLine(prev.Start); } } - // NOTE: Not implemented (button hidden) for non-block navigation. } public void GotoPrevChange() @@ -678,7 +677,6 @@ namespace SourceGit.Views ScrollToLine(next.Start); } } - // NOTE: Not implemented (button hidden) for non-block navigation. } public override void Render(DrawingContext context) @@ -1229,7 +1227,7 @@ namespace SourceGit.Views if (scroller != null) { scroller.Bind(ScrollViewer.OffsetProperty, new Binding("ScrollOffset", BindingMode.TwoWay)); - scroller.GotFocus += OnTextViewScrollGotFocus; + scroller.ScrollChanged += OnTextViewScrollChanged; } } @@ -1237,7 +1235,7 @@ namespace SourceGit.Views { var scroller = this.FindDescendantOfType(); if (scroller != null) - scroller.GotFocus -= OnTextViewScrollGotFocus; + scroller.ScrollChanged -= OnTextViewScrollChanged; base.OnUnloaded(e); } @@ -1274,9 +1272,9 @@ namespace SourceGit.Views GC.Collect(); } - private void OnTextViewScrollGotFocus(object sender, GotFocusEventArgs e) + private void OnTextViewScrollChanged(object sender, ScrollChangedEventArgs e) { - if (EnableChunkSelection && !TextArea.IsPointerOver) + if (sender is ScrollViewer { IsExpanded: true, IsPointerOver: true } scroller) TrySetChunk(null); } } @@ -1446,12 +1444,9 @@ namespace SourceGit.Views _scrollViewer = this.FindDescendantOfType(); if (_scrollViewer != null) { - _scrollViewer.GotFocus += OnTextViewScrollGotFocus; _scrollViewer.ScrollChanged += OnTextViewScrollChanged; _scrollViewer.Bind(ScrollViewer.OffsetProperty, new Binding("SyncScrollOffset", BindingMode.OneWay)); } - - TextArea.PointerWheelChanged += OnTextAreaPointerWheelChanged; } protected override void OnUnloaded(RoutedEventArgs e) @@ -1459,12 +1454,9 @@ namespace SourceGit.Views if (_scrollViewer != null) { _scrollViewer.ScrollChanged -= OnTextViewScrollChanged; - _scrollViewer.GotFocus -= OnTextViewScrollGotFocus; _scrollViewer = null; } - TextArea.PointerWheelChanged -= OnTextAreaPointerWheelChanged; - base.OnUnloaded(e); GC.Collect(); } @@ -1499,22 +1491,15 @@ namespace SourceGit.Views } } - private void OnTextViewScrollGotFocus(object sender, GotFocusEventArgs e) - { - if (EnableChunkSelection && !TextArea.IsPointerOver) - TrySetChunk(null); - } - private void OnTextViewScrollChanged(object sender, ScrollChangedEventArgs e) { - if (TextArea.IsFocused && DataContext is ViewModels.TwoSideTextDiff diff) + if (IsPointerOver && DataContext is ViewModels.TwoSideTextDiff diff) + { diff.SyncScrollOffset = _scrollViewer?.Offset ?? Vector.Zero; - } - private void OnTextAreaPointerWheelChanged(object sender, PointerWheelEventArgs e) - { - if (!TextArea.IsFocused) - Focus(); + if (sender is ScrollViewer { IsExpanded: true, IsPointerOver: true } scroller ) + TrySetChunk(null); + } } private ScrollViewer _scrollViewer = null; From cdc0fbb753e9e2326765ef193eea0ca4e1812227 Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 21 Mar 2025 10:23:52 +0800 Subject: [PATCH 416/441] doc: update README.md Signed-off-by: leo --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2f13fce6..00779cc7 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ * GIT commands with GUI * Clone/Fetch/Pull/Push... * Merge/Rebase/Reset/Revert/Amend/Cherry-pick... - * Amend/Reword + * Amend/Reword/Squash * Interactive rebase * Branches * Remotes @@ -40,6 +40,7 @@ * Git LFS * Issue Link * Workspace +* Custom Action * Using AI to generate commit message (C# port of [anjerodev/commitollama](https://github.com/anjerodev/commitollama)) > [!WARNING] From 39f4cd173287a3d531e6e3225009b5527f77e193 Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 21 Mar 2025 10:54:47 +0800 Subject: [PATCH 417/441] ci: move all translation status to `TRANSLATION.md` and do not modify `README.md ` while checking localization Signed-off-by: leo --- README.md | 7 +-- TRANSLATION.md | 66 +++++++++-------------------- build/scripts/localization-check.js | 45 ++++++++------------ 3 files changed, 38 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index 00779cc7..d63886ed 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ * Supports SSH access with each remote * GIT commands with GUI * Clone/Fetch/Pull/Push... - * Merge/Rebase/Reset/Revert/Amend/Cherry-pick... + * Merge/Rebase/Reset/Revert/Cherry-pick... * Amend/Reword/Squash * Interactive rebase * Branches @@ -48,10 +48,7 @@ ## Translation Status -[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-98.92%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-99.87%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-%E2%88%9A-brightgreen)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.12%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) - -> [!NOTE] -> You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) +You can find the current translation status in [TRANSLATION.md](TRANSLATION.md) ## How to Use diff --git a/TRANSLATION.md b/TRANSLATION.md index aa8da630..a96f0fc6 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,8 +1,15 @@ -### de_DE.axaml: 98.92% +# Translation Status +This document shows the translation status of each locale file in the repository. + +## Details + +### ![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen) + +### ![de__DE](https://img.shields.io/badge/de__DE-98.92%25-yellow)
-Missing Keys +Missing keys in de_DE.axaml - Text.BranchUpstreamInvalid - Text.Configure.CustomAction.WaitForExit @@ -15,41 +22,30 @@
-### es_ES.axaml: 99.87% - +### ![es__ES](https://img.shields.io/badge/es__ES-99.87%25-yellow)
-Missing Keys +Missing keys in es_ES.axaml - Text.Preferences.General.ShowTagsInGraph
-### fr_FR.axaml: 100.00% +### ![fr__FR](https://img.shields.io/badge/fr__FR-%E2%88%9A-brightgreen) +### ![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)
-Missing Keys - - - -
- -### it_IT.axaml: 99.87% - - -
-Missing Keys +Missing keys in it_IT.axaml - Text.Preferences.General.ShowTagsInGraph
-### pt_BR.axaml: 91.12% - +### ![pt__BR](https://img.shields.io/badge/pt__BR-91.12%25-yellow)
-Missing Keys +Missing keys in pt_BR.axaml - Text.AIAssistant.Regen - Text.AIAssistant.Use @@ -120,32 +116,8 @@
-### ru_RU.axaml: 100.00% +### ![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen) +### ![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen) -
-Missing Keys - - - -
- -### zh_CN.axaml: 100.00% - - -
-Missing Keys - - - -
- -### zh_TW.axaml: 100.00% - - -
-Missing Keys - - - -
+### ![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen) \ No newline at end of file diff --git a/build/scripts/localization-check.js b/build/scripts/localization-check.js index ed89a5e8..1e8f1f0d 100644 --- a/build/scripts/localization-check.js +++ b/build/scripts/localization-check.js @@ -6,7 +6,6 @@ const repoRoot = path.join(__dirname, '../../'); const localesDir = path.join(repoRoot, 'src/Resources/Locales'); const enUSFile = path.join(localesDir, 'en_US.axaml'); const outputFile = path.join(repoRoot, 'TRANSLATION.md'); -const readmeFile = path.join(repoRoot, 'README.md'); const parser = new xml2js.Parser(); @@ -18,46 +17,36 @@ async function parseXml(filePath) { async function calculateTranslationRate() { const enUSData = await parseXml(enUSFile); const enUSKeys = new Set(enUSData.ResourceDictionary['x:String'].map(item => item.$['x:Key'])); - - const translationRates = []; - const badges = []; - const files = (await fs.readdir(localesDir)).filter(file => file !== 'en_US.axaml' && file.endsWith('.axaml')); - // Add en_US badge first - badges.push(`[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md)`); + const lines = []; + + lines.push('# Translation Status'); + lines.push('This document shows the translation status of each locale file in the repository.'); + lines.push(`## Details`); + lines.push(`### ![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)`); for (const file of files) { + const locale = file.replace('.axaml', '').replace('_', '__'); const filePath = path.join(localesDir, file); const localeData = await parseXml(filePath); const localeKeys = new Set(localeData.ResourceDictionary['x:String'].map(item => item.$['x:Key'])); - const missingKeys = [...enUSKeys].filter(key => !localeKeys.has(key)); - const translationRate = ((enUSKeys.size - missingKeys.length) / enUSKeys.size) * 100; - translationRates.push(`### ${file}: ${translationRate.toFixed(2)}%\n`); - translationRates.push(`
\nMissing Keys\n\n${missingKeys.map(key => `- ${key}`).join('\n')}\n\n
`); + if (missingKeys.length > 0) { + const progress = ((enUSKeys.size - missingKeys.length) / enUSKeys.size) * 100; + const badgeColor = progress >= 75 ? 'yellow' : 'red'; - // Add badges - const locale = file.replace('.axaml', '').replace('_', '__'); - if (translationRate === 100) { - badges.push(`[![${locale}](https://img.shields.io/badge/${locale}-%E2%88%9A-brightgreen)](TRANSLATION.md)`); + lines.push(`### ![${locale}](https://img.shields.io/badge/${locale}-${progress.toFixed(2)}%25-${badgeColor})`); + lines.push(`
\nMissing keys in ${file}\n\n${missingKeys.map(key => `- ${key}`).join('\n')}\n\n
`) } else { - const badgeColor = translationRate >= 75 ? 'yellow' : 'red'; - badges.push(`[![${locale}](https://img.shields.io/badge/${locale}-${translationRate.toFixed(2)}%25-${badgeColor})](TRANSLATION.md)`); - } + lines.push(`### ![${locale}](https://img.shields.io/badge/${locale}-%E2%88%9A-brightgreen)`); + } } - console.log(translationRates.join('\n\n')); - - await fs.writeFile(outputFile, translationRates.join('\n\n') + '\n', 'utf8'); - - // Update README.md - let readmeContent = await fs.readFile(readmeFile, 'utf8'); - const badgeSection = `## Translation Status\n\n${badges.join(' ')}`; - console.log(badgeSection); - readmeContent = readmeContent.replace(/## Translation Status\n\n.*\n\n/, badgeSection + '\n\n'); - await fs.writeFile(readmeFile, readmeContent, 'utf8'); + const content = lines.join('\n\n'); + console.log(content); + await fs.writeFile(outputFile, content, 'utf8'); } calculateTranslationRate().catch(err => console.error(err)); From 03f49ccff01a2c3d4aad95a0bebb49b67faf1cb3 Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 21 Mar 2025 17:35:59 +0800 Subject: [PATCH 418/441] refactor: text diff view block navigation Signed-off-by: leo --- src/Views/DiffView.axaml | 7 +- src/Views/DiffView.axaml.cs | 18 +++-- src/Views/TextDiffView.axaml.cs | 138 +++++++++++++++----------------- 3 files changed, 77 insertions(+), 86 deletions(-) diff --git a/src/Views/DiffView.axaml b/src/Views/DiffView.axaml index 12cfa451..c4da158d 100644 --- a/src/Views/DiffView.axaml +++ b/src/Views/DiffView.axaml @@ -285,10 +285,9 @@ - + diff --git a/src/Views/DiffView.axaml.cs b/src/Views/DiffView.axaml.cs index 889f0df7..f0824307 100644 --- a/src/Views/DiffView.axaml.cs +++ b/src/Views/DiffView.axaml.cs @@ -13,30 +13,32 @@ namespace SourceGit.Views private void OnGotoFirstChange(object _, RoutedEventArgs e) { - var textDiff = this.FindDescendantOfType(); - textDiff?.GotoFirstChange(); + this.FindDescendantOfType()?.GotoFirstChange(); e.Handled = true; } private void OnGotoPrevChange(object _, RoutedEventArgs e) { - var textDiff = this.FindDescendantOfType(); - textDiff?.GotoPrevChange(); + this.FindDescendantOfType()?.GotoPrevChange(); e.Handled = true; } private void OnGotoNextChange(object _, RoutedEventArgs e) { - var textDiff = this.FindDescendantOfType(); - textDiff?.GotoNextChange(); + this.FindDescendantOfType()?.GotoNextChange(); e.Handled = true; } private void OnGotoLastChange(object _, RoutedEventArgs e) { - var textDiff = this.FindDescendantOfType(); - textDiff?.GotoLastChange(); + this.FindDescendantOfType()?.GotoLastChange(); e.Handled = true; } + + private void OnBlockNavigationChanged(object sender, RoutedEventArgs e) + { + if (sender is TextDiffView { UseBlockNavigation: true } textDiff) + BlockNavigationIndicator.Text = textDiff.BlockNavigation?.Indicator ?? string.Empty; + } } } diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 0d20a990..7b461e57 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -553,7 +553,7 @@ namespace SourceGit.Views { } - public void GotoFirstChange() + public virtual void GotoFirstChange() { var blockNavigation = BlockNavigation; if (blockNavigation != null) @@ -567,7 +567,7 @@ namespace SourceGit.Views } } - public void GotoPrevChange() + public virtual void GotoPrevChange() { var blockNavigation = BlockNavigation; if (blockNavigation != null) @@ -623,7 +623,7 @@ namespace SourceGit.Views } } - public void GotoNextChange() + public virtual void GotoNextChange() { var blockNavigation = BlockNavigation; if (blockNavigation != null) @@ -665,7 +665,7 @@ namespace SourceGit.Views } } - public void GotoLastChange() + public virtual void GotoLastChange() { var blockNavigation = BlockNavigation; if (blockNavigation != null) @@ -766,15 +766,13 @@ namespace SourceGit.Views { var oldValue = change.OldValue as ViewModels.BlockNavigation; if (oldValue != null) - { oldValue.PropertyChanged -= OnBlockNavigationPropertyChanged; - if (oldValue.Current != -1) - TextArea?.TextView?.Redraw(); - } var newValue = change.NewValue as ViewModels.BlockNavigation; if (newValue != null) newValue.PropertyChanged += OnBlockNavigationPropertyChanged; + + TextArea?.TextView?.Redraw(); } } @@ -793,9 +791,10 @@ namespace SourceGit.Views base.OnKeyDown(e); } - private void OnBlockNavigationPropertyChanged(object _1, PropertyChangedEventArgs _2) + private void OnBlockNavigationPropertyChanged(object _1, PropertyChangedEventArgs e) { - TextArea?.TextView?.Redraw(); + if (e.PropertyName == "Current") + TextArea?.TextView?.Redraw(); } private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e) @@ -1223,19 +1222,18 @@ namespace SourceGit.Views { base.OnLoaded(e); - var scroller = this.FindDescendantOfType(); - if (scroller != null) + _scrollViewer = this.FindDescendantOfType(); + if (_scrollViewer != null) { - scroller.Bind(ScrollViewer.OffsetProperty, new Binding("ScrollOffset", BindingMode.TwoWay)); - scroller.ScrollChanged += OnTextViewScrollChanged; + _scrollViewer.Bind(ScrollViewer.OffsetProperty, new Binding("ScrollOffset", BindingMode.TwoWay)); + _scrollViewer.ScrollChanged += OnTextViewScrollChanged; } } protected override void OnUnloaded(RoutedEventArgs e) { - var scroller = this.FindDescendantOfType(); - if (scroller != null) - scroller.ScrollChanged -= OnTextViewScrollChanged; + if (_scrollViewer != null) + _scrollViewer.ScrollChanged -= OnTextViewScrollChanged; base.OnUnloaded(e); } @@ -1274,9 +1272,11 @@ namespace SourceGit.Views private void OnTextViewScrollChanged(object sender, ScrollChangedEventArgs e) { - if (sender is ScrollViewer { IsExpanded: true, IsPointerOver: true } scroller) + if (_scrollViewer is { IsExpanded: true, IsPointerOver: true }) TrySetChunk(null); } + + private ScrollViewer _scrollViewer = null; } public class SingleSideTextDiffPresenter : ThemedTextDiffPresenter @@ -1288,14 +1288,6 @@ namespace SourceGit.Views TextArea.LeftMargins.Add(new LineModifyTypeMargin()); } - public void ForceSyncScrollOffset() - { - if (_scrollViewer == null) - return; - if (DataContext is ViewModels.TwoSideTextDiff diff) - diff.SyncScrollOffset = _scrollViewer?.Offset ?? Vector.Zero; - } - public override List GetLines() { if (DataContext is ViewModels.TwoSideTextDiff diff) @@ -1310,6 +1302,30 @@ namespace SourceGit.Views return 0; } + public override void GotoFirstChange() + { + base.GotoFirstChange(); + DirectSyncScrollOffset(); + } + + public override void GotoPrevChange() + { + base.GotoPrevChange(); + DirectSyncScrollOffset(); + } + + public override void GotoNextChange() + { + base.GotoNextChange(); + DirectSyncScrollOffset(); + } + + public override void GotoLastChange() + { + base.GotoLastChange(); + DirectSyncScrollOffset(); + } + public override void UpdateSelectedChunk(double y) { var diff = DataContext as ViewModels.TwoSideTextDiff; @@ -1497,11 +1513,17 @@ namespace SourceGit.Views { diff.SyncScrollOffset = _scrollViewer?.Offset ?? Vector.Zero; - if (sender is ScrollViewer { IsExpanded: true, IsPointerOver: true } scroller ) + if (_scrollViewer is { IsExpanded: true, IsPointerOver: true } ) TrySetChunk(null); } } + private void DirectSyncScrollOffset() + { + if (_scrollViewer is { } && DataContext is ViewModels.TwoSideTextDiff diff) + diff.SyncScrollOffset = _scrollViewer?.Offset ?? Vector.Zero; + } + private ScrollViewer _scrollViewer = null; } @@ -1679,13 +1701,13 @@ namespace SourceGit.Views set => SetValue(BlockNavigationProperty, value); } - public static readonly StyledProperty BlockNavigationIndicatorProperty = - AvaloniaProperty.Register(nameof(BlockNavigationIndicator)); + public static readonly RoutedEvent BlockNavigationChangedEvent = + RoutedEvent.Register(nameof(BlockNavigationChanged), RoutingStrategies.Tunnel | RoutingStrategies.Bubble); - public string BlockNavigationIndicator + public event EventHandler BlockNavigationChanged { - get => GetValue(BlockNavigationIndicatorProperty); - set => SetValue(BlockNavigationIndicatorProperty, value); + add { AddHandler(BlockNavigationChangedEvent, value); } + remove { RemoveHandler(BlockNavigationChangedEvent, value); } } static TextDiffView() @@ -1723,54 +1745,26 @@ namespace SourceGit.Views public void GotoFirstChange() { - var presenter = this.FindDescendantOfType(); - if (presenter == null) - return; - - presenter.GotoFirstChange(); - if (presenter is SingleSideTextDiffPresenter singleSide) - singleSide.ForceSyncScrollOffset(); - - BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty; + this.FindDescendantOfType()?.GotoFirstChange(); + RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent)); } public void GotoPrevChange() { - var presenter = this.FindDescendantOfType(); - if (presenter == null) - return; - - presenter.GotoPrevChange(); - if (presenter is SingleSideTextDiffPresenter singleSide) - singleSide.ForceSyncScrollOffset(); - - BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty; + this.FindDescendantOfType()?.GotoPrevChange(); + RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent)); } public void GotoNextChange() { - var presenter = this.FindDescendantOfType(); - if (presenter == null) - return; - - presenter.GotoNextChange(); - if (presenter is SingleSideTextDiffPresenter singleSide) - singleSide.ForceSyncScrollOffset(); - - BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty; + this.FindDescendantOfType()?.GotoNextChange(); + RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent)); } public void GotoLastChange() { - var presenter = this.FindDescendantOfType(); - if (presenter == null) - return; - - presenter.GotoLastChange(); - if (presenter is SingleSideTextDiffPresenter singleSide) - singleSide.ForceSyncScrollOffset(); - - BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty; + this.FindDescendantOfType()?.GotoLastChange(); + RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent)); } protected override void OnDataContextChanged(EventArgs e) @@ -1820,15 +1814,11 @@ namespace SourceGit.Views private void RefreshBlockNavigation() { if (UseBlockNavigation) - { BlockNavigation = new ViewModels.BlockNavigation(Editor.Content); - BlockNavigationIndicator = BlockNavigation.Indicator; - } else - { BlockNavigation = null; - BlockNavigationIndicator = "-/-"; - } + + RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent)); } private void OnStageChunk(object _1, RoutedEventArgs _2) From 9590f96a449124187b1a6ad4e06cbe42f58e26ca Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 21 Mar 2025 17:46:11 +0800 Subject: [PATCH 419/441] enhance: clear highlight chunk while scrolling out of `TextArea.TextView` Signed-off-by: leo --- src/Views/TextDiffView.axaml.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 7b461e57..c55719de 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -1272,7 +1272,7 @@ namespace SourceGit.Views private void OnTextViewScrollChanged(object sender, ScrollChangedEventArgs e) { - if (_scrollViewer is { IsExpanded: true, IsPointerOver: true }) + if (!TextArea.TextView.IsPointerOver) TrySetChunk(null); } @@ -1513,7 +1513,7 @@ namespace SourceGit.Views { diff.SyncScrollOffset = _scrollViewer?.Offset ?? Vector.Zero; - if (_scrollViewer is { IsExpanded: true, IsPointerOver: true } ) + if (!TextArea.TextView.IsPointerOver) TrySetChunk(null); } } From d335cac167e817c2581921259ca40569f605d855 Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 21 Mar 2025 18:00:46 +0800 Subject: [PATCH 420/441] enhance: only raise `BlockNavigationChangedEvent` when `UseBlockNavigation` enabled Signed-off-by: leo --- src/Views/DiffView.axaml.cs | 2 +- src/Views/TextDiffView.axaml.cs | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Views/DiffView.axaml.cs b/src/Views/DiffView.axaml.cs index f0824307..9dd27f24 100644 --- a/src/Views/DiffView.axaml.cs +++ b/src/Views/DiffView.axaml.cs @@ -37,7 +37,7 @@ namespace SourceGit.Views private void OnBlockNavigationChanged(object sender, RoutedEventArgs e) { - if (sender is TextDiffView { UseBlockNavigation: true } textDiff) + if (sender is TextDiffView textDiff) BlockNavigationIndicator.Text = textDiff.BlockNavigation?.Indicator ?? string.Empty; } } diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index c55719de..7ce9f288 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -1746,25 +1746,25 @@ namespace SourceGit.Views public void GotoFirstChange() { this.FindDescendantOfType()?.GotoFirstChange(); - RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent)); + TryRaiseBlockNavigationChanged(); } public void GotoPrevChange() { this.FindDescendantOfType()?.GotoPrevChange(); - RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent)); + TryRaiseBlockNavigationChanged(); } public void GotoNextChange() { this.FindDescendantOfType()?.GotoNextChange(); - RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent)); + TryRaiseBlockNavigationChanged(); } public void GotoLastChange() { this.FindDescendantOfType()?.GotoLastChange(); - RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent)); + TryRaiseBlockNavigationChanged(); } protected override void OnDataContextChanged(EventArgs e) @@ -1818,7 +1818,7 @@ namespace SourceGit.Views else BlockNavigation = null; - RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent)); + TryRaiseBlockNavigationChanged(); } private void OnStageChunk(object _1, RoutedEventArgs _2) @@ -1990,5 +1990,11 @@ namespace SourceGit.Views repo.MarkWorkingCopyDirtyManually(); repo.SetWatcherEnabled(true); } + + private void TryRaiseBlockNavigationChanged() + { + if (UseBlockNavigation) + RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent)); + } } } From 88bb603dc9686ff54a738219678590091db0b929 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 24 Mar 2025 09:44:41 +0800 Subject: [PATCH 421/441] version: Release 2025.10 Signed-off-by: leo --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 23993bfb..e78345d1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2025.09 \ No newline at end of file +2025.10 \ No newline at end of file From 0a877c6730ecc44ca16e32b670dd4bcf348c42d3 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 24 Mar 2025 10:03:27 +0800 Subject: [PATCH 422/441] project: upgrade `OpenAI` and `Azure.AI.OpenAI` to `2.2.0-beta.4` Signed-off-by: leo --- src/SourceGit.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj index 3578d59f..2a4b3c91 100644 --- a/src/SourceGit.csproj +++ b/src/SourceGit.csproj @@ -48,10 +48,10 @@ - + - +
From fc85dd3269bb3c122b36d8b43f7612dd8e242d03 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 24 Mar 2025 19:28:16 +0800 Subject: [PATCH 423/441] enhance: improve `Repository.Open()` performance (#1121) Signed-off-by: leo --- src/ViewModels/Launcher.cs | 47 +++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index 06479394..9ae99b33 100644 --- a/src/ViewModels/Launcher.cs +++ b/src/ViewModels/Launcher.cs @@ -275,22 +275,16 @@ namespace SourceGit.ViewModels if (!Path.Exists(node.Id)) { - var ctx = page == null ? ActivePage.Node.Id : page.Node.Id; - App.RaiseException(ctx, "Repository does NOT exists any more. Please remove it."); + App.RaiseException(node.Id, "Repository does NOT exists any more. Please remove it."); return; } var isBare = new Commands.IsBareRepository(node.Id).Result(); - var gitDir = node.Id; - if (!isBare) + var gitDir = isBare ? node.Id : GetRepositoryGitDir(node.Id); + if (string.IsNullOrEmpty(gitDir)) { - gitDir = new Commands.QueryGitDir(node.Id).Result(); - if (string.IsNullOrEmpty(gitDir)) - { - var ctx = page == null ? ActivePage.Node.Id : page.Node.Id; - App.RaiseException(ctx, "Given path is not a valid git repository!"); - return; - } + App.RaiseException(node.Id, "Given path is not a valid git repository!"); + return; } var repo = new Repository(isBare, node.Id, gitDir); @@ -469,6 +463,37 @@ namespace SourceGit.ViewModels return menu; } + private string GetRepositoryGitDir(string repo) + { + var fullpath = Path.Combine(repo, ".git"); + if (Directory.Exists(fullpath)) + { + if (Directory.Exists(Path.Combine(fullpath, "refs")) && + Directory.Exists(Path.Combine(fullpath, "objects")) && + File.Exists(Path.Combine(fullpath, "HEAD"))) + return fullpath; + + return null; + } + + if (File.Exists(fullpath)) + { + var redirect = File.ReadAllText(fullpath).Trim(); + if (redirect.StartsWith("gitdir: ", StringComparison.Ordinal)) + redirect = redirect.Substring(8); + + if (!Path.IsPathRooted(redirect)) + redirect = Path.GetFullPath(Path.Combine(repo, redirect)); + + if (Directory.Exists(redirect)) + return redirect; + + return null; + } + + return new Commands.QueryGitDir(repo).Result(); + } + private void SwitchWorkspace(Workspace to) { foreach (var one in Pages) From 380e6713b5418ee9f27a7b9bb5dd7e6c4556de82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20J=2E=20Mart=C3=ADnez=20M=2E?= <56406225+jjesus-dev@users.noreply.github.com> Date: Mon, 24 Mar 2025 19:51:22 -0600 Subject: [PATCH 424/441] localization: update spanish translations (#1124) --- src/Resources/Locales/es_ES.axaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index e7e953e5..2f4a7230 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -475,6 +475,7 @@ Commits en el historial Mostrar hora del autor en lugar de la hora del commit en el gráfico Mostrar hijos en los detalles de commit + Mostrar etiquetas en el gráfico de commit Longitud de la guía del asunto GIT Habilitar Auto CRLF @@ -604,7 +605,7 @@ Por Fecha de Creación Por Nombre (Ascendiente) Por Nombre (Descendiente) - Sort + Ordenar Abrir en Terminal Usar tiempo relativo en las historias WORKTREES From 467089aec55005918bd42ba1294234bb06ee8bd0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 25 Mar 2025 01:51:33 +0000 Subject: [PATCH 425/441] doc: Update translation status and missing keys --- TRANSLATION.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/TRANSLATION.md b/TRANSLATION.md index a96f0fc6..30a2a679 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -22,14 +22,7 @@ This document shows the translation status of each locale file in the repository -### ![es__ES](https://img.shields.io/badge/es__ES-99.87%25-yellow) - -
-Missing keys in es_ES.axaml - -- Text.Preferences.General.ShowTagsInGraph - -
+### ![es__ES](https://img.shields.io/badge/es__ES-%E2%88%9A-brightgreen) ### ![fr__FR](https://img.shields.io/badge/fr__FR-%E2%88%9A-brightgreen) From f37ac904b9b2babddbba5b970f45de583e30fc33 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 25 Mar 2025 10:33:39 +0800 Subject: [PATCH 426/441] =?UTF-8?q?enhance:=20do=20not=20create=20crash=20?= =?UTF-8?q?log=20for=20unobserved=20task=20exceptions=20(#1121=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: leo --- src/App.axaml.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/App.axaml.cs b/src/App.axaml.cs index af5e6177..86c5200c 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -37,7 +37,6 @@ namespace SourceGit TaskScheduler.UnobservedTaskException += (_, e) => { - LogException(e.Exception); e.SetObserved(); }; From ca0fb7ae1090068de4a7a42de113d0c9c4e203ff Mon Sep 17 00:00:00 2001 From: Iacopo Sbalchiero Date: Wed, 26 Mar 2025 02:27:10 +0100 Subject: [PATCH 427/441] Adding template for Azure DevOps workitems (#1128) * feat: add Azure DevOps issue tracker integration * localization: add Azure DevOps sample rule to issue tracker in multiple languages --- src/Resources/Locales/en_US.axaml | 1 + src/Resources/Locales/es_ES.axaml | 1 + src/Resources/Locales/fr_FR.axaml | 1 + src/Resources/Locales/it_IT.axaml | 1 + src/Resources/Locales/pt_BR.axaml | 1 + src/Resources/Locales/ru_RU.axaml | 1 + src/ViewModels/RepositoryConfigure.cs | 5 +++++ src/Views/RepositoryConfigure.axaml | 1 + 8 files changed, 12 insertions(+) diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index f24d6c65..75d312ea 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -160,6 +160,7 @@ Add Sample GitLab Issue Rule Add Sample GitLab Merge Request Rule Add Sample Jira Rule + Add Sample Azure DevOps Rule New Rule Issue Regex Expression: Rule Name: diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index 2f4a7230..e1eccaa7 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -161,6 +161,7 @@ Añadir Regla de Ejemplo para Pull Requests de Gitee Añadir Regla de Ejemplo para Github Añadir Regla de Ejemplo para Jira + Añadir Regla de Ejemplo para Azure DevOps Añadir Regla de Ejemplo para Incidencias de GitLab Añadir Regla de Ejemplo para Merge Requests de GitLab Nueva Regla diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index 19c0859c..1c3d7d34 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -151,6 +151,7 @@ Ajouter une règle d'exemple pour Pull Request Gitee Ajouter une règle d'exemple Github Ajouter une règle d'exemple Jira + Ajouter une règle d'exemple Azure DevOps Ajouter une règle d'exemple pour Incidents GitLab Ajouter une règle d'exemple pour Merge Request GitLab Nouvelle règle diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml index d002dfef..da7d18d1 100644 --- a/src/Resources/Locales/it_IT.axaml +++ b/src/Resources/Locales/it_IT.axaml @@ -161,6 +161,7 @@ Aggiungi una regola di esempio per un Pull Request Gitee Aggiungi una regola di esempio per GitHub Aggiungi una regola di esempio per Jira + Aggiungi una regola di esempio per Azure DevOps Aggiungi una regola di esempio per Issue GitLab Aggiungi una regola di esempio per una Merge Request GitLab Nuova Regola diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index e811cf3e..e799741c 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -168,6 +168,7 @@ RASTREADOR DE PROBLEMAS Adicionar Regra de Exemplo do Github Adicionar Regra de Exemplo do Jira + Adicionar Regra de Exemplo do Azure DevOps Adicionar Regra de Exemplo do GitLab Adicionar regra de exemplo de Merge Request do GitLab Nova Regra diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index 707c9ed9..53f04a5b 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -161,6 +161,7 @@ Добавить пример правила запроса скачивания из Gitea Добавить пример правила для Git Добавить пример правила Jira + Добавить пример правила Azure DevOps Добавить пример правила выдачи GitLab Добавить пример правила запроса на слияние в GitLab Новое правило diff --git a/src/ViewModels/RepositoryConfigure.cs b/src/ViewModels/RepositoryConfigure.cs index cf23b6d8..3f590758 100644 --- a/src/ViewModels/RepositoryConfigure.cs +++ b/src/ViewModels/RepositoryConfigure.cs @@ -203,6 +203,11 @@ namespace SourceGit.ViewModels SelectedIssueTrackerRule = _repo.Settings.AddIssueTracker("Jira Tracker", "PROJ-(\\d+)", "https://jira.yourcompany.com/browse/PROJ-$1"); } + public void AddSampleAzureWorkItemTracker() + { + SelectedIssueTrackerRule = _repo.Settings.AddIssueTracker("Azure DevOps Tracker", "#(\\d+)", "https://dev.azure.com/yourcompany/workspace/_workitems/edit/$1"); + } + public void AddSampleGitLabIssueTracker() { var link = "https://gitlab.com/username/repository/-/issues/$1"; diff --git a/src/Views/RepositoryConfigure.axaml b/src/Views/RepositoryConfigure.axaml index de777800..e41375b9 100644 --- a/src/Views/RepositoryConfigure.axaml +++ b/src/Views/RepositoryConfigure.axaml @@ -283,6 +283,7 @@ + From dccf53e51823a8da0eceaa3059d408d6f35c15d3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 26 Mar 2025 01:27:21 +0000 Subject: [PATCH 428/441] doc: Update translation status and missing keys --- TRANSLATION.md | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/TRANSLATION.md b/TRANSLATION.md index 30a2a679..b6ba3ed3 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -6,13 +6,14 @@ This document shows the translation status of each locale file in the repository ### ![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen) -### ![de__DE](https://img.shields.io/badge/de__DE-98.92%25-yellow) +### ![de__DE](https://img.shields.io/badge/de__DE-98.79%25-yellow)
Missing keys in de_DE.axaml - Text.BranchUpstreamInvalid - Text.Configure.CustomAction.WaitForExit +- Text.Configure.IssueTracker.AddSampleAzure - Text.Diff.First - Text.Diff.Last - Text.Preferences.AI.Streaming @@ -35,7 +36,7 @@ This document shows the translation status of each locale file in the repository
-### ![pt__BR](https://img.shields.io/badge/pt__BR-91.12%25-yellow) +### ![pt__BR](https://img.shields.io/badge/pt__BR-91.13%25-yellow)
Missing keys in pt_BR.axaml @@ -111,6 +112,20 @@ This document shows the translation status of each locale file in the repository ### ![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen) -### ![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen) +### ![zh__CN](https://img.shields.io/badge/zh__CN-99.87%25-yellow) -### ![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen) \ No newline at end of file +
+Missing keys in zh_CN.axaml + +- Text.Configure.IssueTracker.AddSampleAzure + +
+ +### ![zh__TW](https://img.shields.io/badge/zh__TW-99.87%25-yellow) + +
+Missing keys in zh_TW.axaml + +- Text.Configure.IssueTracker.AddSampleAzure + +
\ No newline at end of file From 4fb853d1fd91d13e852f64556808705cd345be45 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 26 Mar 2025 09:30:41 +0800 Subject: [PATCH 429/441] localization: add translation `Text.Configure.IssueTracker.AddSampleAzure` for Chinese (#1128) Signed-off-by: leo --- src/Resources/Locales/zh_CN.axaml | 1 + src/Resources/Locales/zh_TW.axaml | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 93d08bd0..ad9b4179 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -157,6 +157,7 @@ 分钟 默认远程 ISSUE追踪 + 新增匹配Azure DevOps规则 新增匹配Gitee议题规则 新增匹配Gitee合并请求规则 新增匹配Github Issue规则 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index d5a7a77c..173ad099 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -157,6 +157,7 @@ 分鐘 預設遠端存放庫 Issue 追蹤 + 新增符合 Azure DevOps 規則 新增符合 Gitee 議題規則 新增符合 Gitee 合併請求規則 新增符合 GitHub Issue 規則 From fc3767754621a0f50b833f7e2259e41b7cd8caad Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 26 Mar 2025 01:30:58 +0000 Subject: [PATCH 430/441] doc: Update translation status and missing keys --- TRANSLATION.md | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/TRANSLATION.md b/TRANSLATION.md index b6ba3ed3..183e77e6 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -112,20 +112,6 @@ This document shows the translation status of each locale file in the repository ### ![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen) -### ![zh__CN](https://img.shields.io/badge/zh__CN-99.87%25-yellow) +### ![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen) -
-Missing keys in zh_CN.axaml - -- Text.Configure.IssueTracker.AddSampleAzure - -
- -### ![zh__TW](https://img.shields.io/badge/zh__TW-99.87%25-yellow) - -
-Missing keys in zh_TW.axaml - -- Text.Configure.IssueTracker.AddSampleAzure - -
\ No newline at end of file +### ![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen) \ No newline at end of file From 4153eec1a8594e67f7b70f81812042886af50dec Mon Sep 17 00:00:00 2001 From: Gadfly Date: Wed, 26 Mar 2025 12:15:15 +0800 Subject: [PATCH 431/441] chore: Update DEB package configuration with installed size (#1130) --- build/resources/deb/DEBIAN/control | 3 ++- build/scripts/package.linux.sh | 11 +++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/build/resources/deb/DEBIAN/control b/build/resources/deb/DEBIAN/control index f553db8b..71786b43 100755 --- a/build/resources/deb/DEBIAN/control +++ b/build/resources/deb/DEBIAN/control @@ -1,7 +1,8 @@ Package: sourcegit -Version: 8.23 +Version: 2025.10 Priority: optional Depends: libx11-6, libice6, libsm6, libicu | libicu76 | libicu74 | libicu72 | libicu71 | libicu70 | libicu69 | libicu68 | libicu67 | libicu66 | libicu65 | libicu63 | libicu60 | libicu57 | libicu55 | libicu52, xdg-utils Architecture: amd64 +Installed-Size: 60440 Maintainer: longshuang@msn.cn Description: Open-source & Free Git GUI Client diff --git a/build/scripts/package.linux.sh b/build/scripts/package.linux.sh index 5abb058b..1b4adbdc 100755 --- a/build/scripts/package.linux.sh +++ b/build/scripts/package.linux.sh @@ -56,8 +56,15 @@ cp -f SourceGit/* resources/deb/opt/sourcegit ln -rsf resources/deb/opt/sourcegit/sourcegit resources/deb/usr/bin cp -r resources/_common/applications resources/deb/usr/share cp -r resources/_common/icons resources/deb/usr/share -sed -i -e "s/^Version:.*/Version: $VERSION/" -e "s/^Architecture:.*/Architecture: $arch/" resources/deb/DEBIAN/control -dpkg-deb --root-owner-group --build resources/deb "sourcegit_$VERSION-1_$arch.deb" +# Calculate installed size in KB +installed_size=$(du -sk resources/deb | cut -f1) +# Update the control file +sed -i -e "s/^Version:.*/Version: $VERSION/" \ + -e "s/^Architecture:.*/Architecture: $arch/" \ + -e "s/^Installed-Size:.*/Installed-Size: $installed_size/" \ + resources/deb/DEBIAN/control +# Build deb package with gzip compression +dpkg-deb -Zgzip --root-owner-group --build resources/deb "sourcegit_$VERSION-1_$arch.deb" rpmbuild -bb --target="$target" resources/rpm/SPECS/build.spec --define "_topdir $(pwd)/resources/rpm" --define "_version $VERSION" mv "resources/rpm/RPMS/$target/sourcegit-$VERSION-1.$target.rpm" ./ From 1575ae977eb1ba1923e2d02e0521a90064aa7b95 Mon Sep 17 00:00:00 2001 From: Gadfly Date: Thu, 27 Mar 2025 20:22:46 +0800 Subject: [PATCH 432/441] fix: improve font family name handling by collapsing multiple spaces (#1131) --- src/App.axaml.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/App.axaml.cs b/src/App.axaml.cs index 86c5200c..0448a247 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -559,8 +559,22 @@ namespace SourceGit foreach (var part in parts) { var t = part.Trim(); - if (!string.IsNullOrEmpty(t)) - trimmed.Add(t); + if (string.IsNullOrEmpty(t)) + continue; + + // Collapse multiple spaces into single space + var prevChar = '\0'; + var sb = new StringBuilder(); + + foreach (var c in t) + { + if (c == ' ' && prevChar == ' ') + continue; + sb.Append(c); + prevChar = c; + } + + trimmed.Add(sb.ToString()); } return trimmed.Count > 0 ? string.Join(',', trimmed) : string.Empty; From 56ebc182f2fa244276c2c1014c978ef7cb72c32f Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 28 Mar 2025 12:20:36 +0800 Subject: [PATCH 433/441] enhance: try to reinstate not onl the working tree's change, but also the index's ones (#1135) Signed-off-by: leo --- src/Commands/Stash.cs | 2 +- src/Resources/Locales/de_DE.axaml | 1 - src/Resources/Locales/en_US.axaml | 1 - src/Resources/Locales/es_ES.axaml | 1 - src/Resources/Locales/fr_FR.axaml | 1 - src/Resources/Locales/it_IT.axaml | 1 - src/Resources/Locales/pt_BR.axaml | 1 - src/Resources/Locales/ru_RU.axaml | 1 - src/Resources/Locales/zh_CN.axaml | 1 - src/Resources/Locales/zh_TW.axaml | 1 - 10 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/Commands/Stash.cs b/src/Commands/Stash.cs index 7acfdf38..7d1a269b 100644 --- a/src/Commands/Stash.cs +++ b/src/Commands/Stash.cs @@ -82,7 +82,7 @@ namespace SourceGit.Commands public bool Pop(string name) { - Args = $"stash pop -q \"{name}\""; + Args = $"stash pop -q --index \"{name}\""; return Exec(); } diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index 7144ef43..ba6592e9 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -650,7 +650,6 @@ Lokale Änderungen stashen Anwenden Entfernen - Anwenden und entfernen Stash entfernen Entfernen: Stashes diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 75d312ea..5c400979 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -655,7 +655,6 @@ Stash Local Changes Apply Drop - Pop Save as Patch... Drop Stash Drop: diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index e1eccaa7..54cb588d 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -659,7 +659,6 @@ Stash Cambios Locales Aplicar Eliminar - Pop Guardar como Parche... Eliminar Stash Eliminar: diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index 1c3d7d34..2dcd52ab 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -600,7 +600,6 @@ Stash les changements locaux Appliquer Effacer - Extraire Effacer le Stash Effacer : Stashes diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml index da7d18d1..e973a99c 100644 --- a/src/Resources/Locales/it_IT.axaml +++ b/src/Resources/Locales/it_IT.axaml @@ -659,7 +659,6 @@ Stasha Modifiche Locali Applica Elimina - Estrai Salva come Patch... Elimina Stash Elimina: diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index e799741c..8ff00158 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -620,7 +620,6 @@ Guardar Alterações Locais Aplicar Descartar - Pop Descartar Stash Descartar: Stashes diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index 53f04a5b..ede88a10 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -660,7 +660,6 @@ Отложить локальные изменения Принять Отбросить - Применить Сохранить как заплатку... Отбросить тайник Отбросить: diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index ad9b4179..783e5696 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -659,7 +659,6 @@ 贮藏本地变更 应用(apply) 删除(drop) - 应用并删除(pop) 另存为补丁... 丢弃贮藏确认 丢弃贮藏 : diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 173ad099..c10d195f 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -658,7 +658,6 @@ 擱置本機變更 套用 (apply) 刪除 (drop) - 套用並刪除 (pop) 另存為修補檔 (patch)... 捨棄擱置變更確認 捨棄擱置變更: From b26c8a64ad7ebf62e450ca6b121bd0ab3fc14860 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 28 Mar 2025 04:20:55 +0000 Subject: [PATCH 434/441] doc: Update translation status and missing keys --- TRANSLATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TRANSLATION.md b/TRANSLATION.md index 183e77e6..b51fa09b 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -36,7 +36,7 @@ This document shows the translation status of each locale file in the repository
-### ![pt__BR](https://img.shields.io/badge/pt__BR-91.13%25-yellow) +### ![pt__BR](https://img.shields.io/badge/pt__BR-91.12%25-yellow)
Missing keys in pt_BR.axaml From 276d000bcf66c8e5f686cc3eba0f98d486ee0cf9 Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 28 Mar 2025 18:01:15 +0800 Subject: [PATCH 435/441] refactor: change `Copy File Name` to `Copy Full Path` for selected file or change (#1132) Signed-off-by: leo --- src/Native/OS.cs | 9 +++++++++ src/Resources/Locales/de_DE.axaml | 1 - src/Resources/Locales/en_US.axaml | 2 +- src/Resources/Locales/es_ES.axaml | 1 - src/Resources/Locales/fr_FR.axaml | 1 - src/Resources/Locales/it_IT.axaml | 1 - src/Resources/Locales/pt_BR.axaml | 1 - src/Resources/Locales/ru_RU.axaml | 1 - src/Resources/Locales/zh_CN.axaml | 2 +- src/Resources/Locales/zh_TW.axaml | 2 +- src/ViewModels/BranchCompare.cs | 12 ++++++------ src/ViewModels/CommitDetail.cs | 24 ++++++++++++------------ src/ViewModels/RevisionCompare.cs | 12 ++++++------ src/ViewModels/StashesPage.cs | 12 ++++++------ src/ViewModels/WorkingCopy.cs | 24 ++++++++++++------------ 15 files changed, 54 insertions(+), 51 deletions(-) diff --git a/src/Native/OS.cs b/src/Native/OS.cs index f11d1e7f..320b5208 100644 --- a/src/Native/OS.cs +++ b/src/Native/OS.cs @@ -162,6 +162,15 @@ namespace SourceGit.Native _backend.OpenWithDefaultEditor(file); } + public static string GetAbsPath(string root, string sub) + { + var fullpath = Path.Combine(root, sub); + if (OperatingSystem.IsWindows()) + return fullpath.Replace('/', '\\'); + + return fullpath; + } + private static void UpdateGitVersion() { if (string.IsNullOrEmpty(_gitExecutable) || !File.Exists(_gitExecutable)) diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index ba6592e9..bbfe4545 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -186,7 +186,6 @@ Kopieren Kopiere gesamten Text Pfad kopieren - Dateinamen kopieren Branch erstellen... Basierend auf: Erstellten Branch auschecken diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 5c400979..5ff1e3a4 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -186,7 +186,7 @@ Copy Copy All Text Copy Path - Copy File Name + Copy Full Path Create Branch... Based On: Check out the created branch diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index 54cb588d..d8018097 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -189,7 +189,6 @@ Copiar Copiar Todo el Texto Copiar Ruta - Copiar Nombre del Archivo Crear Rama... Basado En: Checkout de la rama creada diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index 2dcd52ab..70d0af22 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -178,7 +178,6 @@ Type de Changement : Copier Copier tout le texte - Copier le nom de fichier Copier le chemin Créer une branche... Basé sur : diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml index e973a99c..85038d9e 100644 --- a/src/Resources/Locales/it_IT.axaml +++ b/src/Resources/Locales/it_IT.axaml @@ -189,7 +189,6 @@ Copia Copia Tutto il Testo Copia Percorso - Copia Nome File Crea Branch... Basato Su: Checkout del Branch Creato diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index 8ff00158..4ee6cdbc 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -196,7 +196,6 @@ Copiar Copiar todo o texto Copiar Caminho - Copiar Nome do Arquivo Criar Branch... Baseado Em: Checar o branch criado diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index ede88a10..2d48d127 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -190,7 +190,6 @@ Копировать Копировать весь текст Копировать путь - Копировать имя файла Создать ветку... Основан на: Проверить созданную ветку diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 783e5696..8d2b4f1e 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -189,7 +189,7 @@ 复制 复制全部文本 复制路径 - 复制文件名 + 复制完整路径 新建分支 ... 新分支基于 : 完成后切换到新分支 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index c10d195f..8e823f68 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -189,7 +189,7 @@ 複製 複製全部內容 複製路徑 - 複製檔案名稱 + 複製完整路徑 新增分支... 新分支基於: 完成後切換到新分支 diff --git a/src/ViewModels/BranchCompare.cs b/src/ViewModels/BranchCompare.cs index b3c0009c..4edb978c 100644 --- a/src/ViewModels/BranchCompare.cs +++ b/src/ViewModels/BranchCompare.cs @@ -163,15 +163,15 @@ namespace SourceGit.ViewModels }; menu.Items.Add(copyPath); - var copyFileName = new MenuItem(); - copyFileName.Header = App.Text("CopyFileName"); - copyFileName.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFileName.Click += (_, e) => + var copyFullPath = new MenuItem(); + copyFullPath.Header = App.Text("CopyFullPath"); + copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); + copyFullPath.Click += (_, e) => { - App.CopyText(Path.GetFileName(change.Path)); + App.CopyText(Native.OS.GetAbsPath(_repo, change.Path)); e.Handled = true; }; - menu.Items.Add(copyFileName); + menu.Items.Add(copyFullPath); return menu; } diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index 34ac8308..d04e674b 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -425,17 +425,17 @@ namespace SourceGit.ViewModels ev.Handled = true; }; - var copyFileName = new MenuItem(); - copyFileName.Header = App.Text("CopyFileName"); - copyFileName.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFileName.Click += (_, e) => + var copyFullPath = new MenuItem(); + copyFullPath.Header = App.Text("CopyFullPath"); + copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); + copyFullPath.Click += (_, e) => { - App.CopyText(Path.GetFileName(change.Path)); + App.CopyText(Native.OS.GetAbsPath(_repo.FullPath, change.Path)); e.Handled = true; }; menu.Items.Add(copyPath); - menu.Items.Add(copyFileName); + menu.Items.Add(copyFullPath); return menu; } @@ -562,17 +562,17 @@ namespace SourceGit.ViewModels ev.Handled = true; }; - var copyFileName = new MenuItem(); - copyFileName.Header = App.Text("CopyFileName"); - copyFileName.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFileName.Click += (_, e) => + var copyFullPath = new MenuItem(); + copyFullPath.Header = App.Text("CopyFullPath"); + copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); + copyFullPath.Click += (_, e) => { - App.CopyText(Path.GetFileName(file.Path)); + App.CopyText(Native.OS.GetAbsPath(_repo.FullPath, file.Path)); e.Handled = true; }; menu.Items.Add(copyPath); - menu.Items.Add(copyFileName); + menu.Items.Add(copyFullPath); return menu; } diff --git a/src/ViewModels/RevisionCompare.cs b/src/ViewModels/RevisionCompare.cs index 77a408e0..3b5717a6 100644 --- a/src/ViewModels/RevisionCompare.cs +++ b/src/ViewModels/RevisionCompare.cs @@ -183,15 +183,15 @@ namespace SourceGit.ViewModels }; menu.Items.Add(copyPath); - var copyFileName = new MenuItem(); - copyFileName.Header = App.Text("CopyFileName"); - copyFileName.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFileName.Click += (_, e) => + var copyFullPath = new MenuItem(); + copyFullPath.Header = App.Text("CopyFullPath"); + copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); + copyFullPath.Click += (_, e) => { - App.CopyText(Path.GetFileName(change.Path)); + App.CopyText(Native.OS.GetAbsPath(_repo, change.Path)); e.Handled = true; }; - menu.Items.Add(copyFileName); + menu.Items.Add(copyFullPath); return menu; } diff --git a/src/ViewModels/StashesPage.cs b/src/ViewModels/StashesPage.cs index 77ed5551..e69d9bb5 100644 --- a/src/ViewModels/StashesPage.cs +++ b/src/ViewModels/StashesPage.cs @@ -251,12 +251,12 @@ namespace SourceGit.ViewModels ev.Handled = true; }; - var copyFileName = new MenuItem(); - copyFileName.Header = App.Text("CopyFileName"); - copyFileName.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFileName.Click += (_, e) => + var copyFullPath = new MenuItem(); + copyFullPath.Header = App.Text("CopyFullPath"); + copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); + copyFullPath.Click += (_, e) => { - App.CopyText(Path.GetFileName(change.Path)); + App.CopyText(Native.OS.GetAbsPath(_repo.FullPath, change.Path)); e.Handled = true; }; @@ -267,7 +267,7 @@ namespace SourceGit.ViewModels menu.Items.Add(resetToThisRevision); menu.Items.Add(new MenuItem { Header = "-" }); menu.Items.Add(copyPath); - menu.Items.Add(copyFileName); + menu.Items.Add(copyFullPath); return menu; } diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index f9ddb288..40b4c50c 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -903,15 +903,15 @@ namespace SourceGit.ViewModels }; menu.Items.Add(copy); - var copyFileName = new MenuItem(); - copyFileName.Header = App.Text("CopyFileName"); - copyFileName.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFileName.Click += (_, e) => + var copyFullPath = new MenuItem(); + copyFullPath.Header = App.Text("CopyFullPath"); + copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); + copyFullPath.Click += (_, e) => { - App.CopyText(Path.GetFileName(change.Path)); + App.CopyText(Native.OS.GetAbsPath(_repo.FullPath, change.Path)); e.Handled = true; }; - menu.Items.Add(copyFileName); + menu.Items.Add(copyFullPath); } else { @@ -1270,17 +1270,17 @@ namespace SourceGit.ViewModels e.Handled = true; }; - var copyFileName = new MenuItem(); - copyFileName.Header = App.Text("CopyFileName"); - copyFileName.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFileName.Click += (_, e) => + var copyFullPath = new MenuItem(); + copyFullPath.Header = App.Text("CopyFullPath"); + copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); + copyFullPath.Click += (_, e) => { - App.CopyText(Path.GetFileName(change.Path)); + App.CopyText(Native.OS.GetAbsPath(_repo.FullPath, change.Path)); e.Handled = true; }; menu.Items.Add(copyPath); - menu.Items.Add(copyFileName); + menu.Items.Add(copyFullPath); } else { From ce7196490a5d7143f7502ea8b4aad89a3c719ab8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 28 Mar 2025 10:02:16 +0000 Subject: [PATCH 436/441] doc: Update translation status and missing keys --- TRANSLATION.md | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/TRANSLATION.md b/TRANSLATION.md index b51fa09b..c79847be 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -6,7 +6,7 @@ This document shows the translation status of each locale file in the repository ### ![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen) -### ![de__DE](https://img.shields.io/badge/de__DE-98.79%25-yellow) +### ![de__DE](https://img.shields.io/badge/de__DE-98.65%25-yellow)
Missing keys in de_DE.axaml @@ -14,6 +14,7 @@ This document shows the translation status of each locale file in the repository - Text.BranchUpstreamInvalid - Text.Configure.CustomAction.WaitForExit - Text.Configure.IssueTracker.AddSampleAzure +- Text.CopyFullPath - Text.Diff.First - Text.Diff.Last - Text.Preferences.AI.Streaming @@ -23,20 +24,35 @@ This document shows the translation status of each locale file in the repository
-### ![es__ES](https://img.shields.io/badge/es__ES-%E2%88%9A-brightgreen) +### ![es__ES](https://img.shields.io/badge/es__ES-99.87%25-yellow) -### ![fr__FR](https://img.shields.io/badge/fr__FR-%E2%88%9A-brightgreen) +
+Missing keys in es_ES.axaml -### ![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow) +- Text.CopyFullPath + +
+ +### ![fr__FR](https://img.shields.io/badge/fr__FR-99.87%25-yellow) + +
+Missing keys in fr_FR.axaml + +- Text.CopyFullPath + +
+ +### ![it__IT](https://img.shields.io/badge/it__IT-99.73%25-yellow)
Missing keys in it_IT.axaml +- Text.CopyFullPath - Text.Preferences.General.ShowTagsInGraph
-### ![pt__BR](https://img.shields.io/badge/pt__BR-91.12%25-yellow) +### ![pt__BR](https://img.shields.io/badge/pt__BR-90.98%25-yellow)
Missing keys in pt_BR.axaml @@ -59,6 +75,7 @@ This document shows the translation status of each locale file in the repository - Text.Configure.CustomAction.WaitForExit - Text.Configure.IssueTracker.AddSampleGiteeIssue - Text.Configure.IssueTracker.AddSampleGiteePullRequest +- Text.CopyFullPath - Text.CreateBranch.Name.WarnSpace - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup @@ -110,7 +127,14 @@ This document shows the translation status of each locale file in the repository
-### ![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen) +### ![ru__RU](https://img.shields.io/badge/ru__RU-99.87%25-yellow) + +
+Missing keys in ru_RU.axaml + +- Text.CopyFullPath + +
### ![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen) From 1482a005bb616d5f16926ec77d469e324ce1095a Mon Sep 17 00:00:00 2001 From: AquariusStar <48148723+AquariusStar@users.noreply.github.com> Date: Mon, 31 Mar 2025 04:20:54 +0300 Subject: [PATCH 437/441] localization: update and fix translation russian (#1136) --- src/Resources/Locales/ru_RU.axaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index 2d48d127..2ea274d1 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -190,6 +190,7 @@ Копировать Копировать весь текст Копировать путь + Копировать полный путь Создать ветку... Основан на: Проверить созданную ветку @@ -212,7 +213,7 @@ Вид: С примечаниями Простой - Удерживайте Ctrl, чтобы начать сразу + Удерживайте Ctrl, чтобы сразу начать Вырезать Удалить ветку Ветка: @@ -330,7 +331,7 @@ Добавить шаблон отслеживания в LFS Git Извлечь Извлечь объекты LFS - Запустить «git lfs fetch», чтобы загрузить объекты LFS Git. При этом рабочая копия не обновляется. + Запустить (git lfs fetch), чтобы загрузить объекты LFS Git. При этом рабочая копия не обновляется. Установить перехват LFS Git Показывать блокировки Нет заблокированных файлов @@ -340,10 +341,10 @@ Разблокировать Принудительно разблокировать Обрезать - Запустить «git lfs prune», чтобы удалить старые файлы LFS из локального хранилища + Запустить (git lfs prune), чтобы удалить старые файлы LFS из локального хранилища Забрать Забрать объекты LFS - Запустить «git lfs pull», чтобы загрузить все файлы LFS Git для текущей ссылки и проверить + Запустить (git lfs pull), чтобы загрузить все файлы LFS Git для текущей ссылки и проверить Выложить Выложить объекты LFS Отправляйте большие файлы, помещенные в очередь, в конечную точку LFS Git @@ -557,7 +558,7 @@ Отказ Автоматическое извлечение изменений с внешних репозиторий... Очистить (Сбор мусора и удаление) - Запустить команду «git gc» для данного репозитория. + Запустить команду (git gc) для данного репозитория. Очистить всё Настройка репозитория ПРОДОЛЖИТЬ From 9ee3a00fbae017de54c33f56ff0d0d3d1b53e29c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 31 Mar 2025 01:21:15 +0000 Subject: [PATCH 438/441] doc: Update translation status and missing keys --- TRANSLATION.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/TRANSLATION.md b/TRANSLATION.md index c79847be..341fdce0 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -127,14 +127,7 @@ This document shows the translation status of each locale file in the repository
-### ![ru__RU](https://img.shields.io/badge/ru__RU-99.87%25-yellow) - -
-Missing keys in ru_RU.axaml - -- Text.CopyFullPath - -
+### ![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen) ### ![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen) From 07d99f5fd28cae320cf20b229438ead47ca68e79 Mon Sep 17 00:00:00 2001 From: qiufengshe Date: Mon, 31 Mar 2025 09:21:38 +0800 Subject: [PATCH 439/441] enhance: get email hash code opimization (#1137) (cherry picked from commit 839b92a284d6b103894f6a8a39e5ce1f99bb12fa) --- src/Models/AvatarManager.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Models/AvatarManager.cs b/src/Models/AvatarManager.cs index 9f0bceaf..a506d886 100644 --- a/src/Models/AvatarManager.cs +++ b/src/Models/AvatarManager.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -196,8 +196,8 @@ namespace SourceGit.Models private string GetEmailHash(string email) { var lowered = email.ToLower(CultureInfo.CurrentCulture).Trim(); - var hash = MD5.Create().ComputeHash(Encoding.Default.GetBytes(lowered)); - var builder = new StringBuilder(); + var hash = MD5.HashData(Encoding.Default.GetBytes(lowered).AsSpan()); + var builder = new StringBuilder(hash.Length * 2); foreach (var c in hash) builder.Append(c.ToString("x2")); return builder.ToString(); From 0045e06d7888ea1463e6f2291bfe8b76d927b563 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 31 Mar 2025 09:29:07 +0800 Subject: [PATCH 440/441] project: upgrade `AvaloniaUI` to `11.2.6` Signed-off-by: leo --- src/SourceGit.csproj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj index 2a4b3c91..852c9e34 100644 --- a/src/SourceGit.csproj +++ b/src/SourceGit.csproj @@ -41,11 +41,11 @@ - - - - - + + + + + From ae5fa6a793801fa6171257ef3aa9f94a6f7ba3be Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 31 Mar 2025 09:29:56 +0800 Subject: [PATCH 441/441] version: Release 2025.11 Signed-off-by: leo --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index e78345d1..75c26f38 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2025.10 \ No newline at end of file +2025.11 \ No newline at end of file