diff --git a/README.md b/README.md
index 67ee5258..3829cf54 100644
--- a/README.md
+++ b/README.md
@@ -47,7 +47,7 @@
## Translation Status
-[](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md)
+[](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md)
> [!NOTE]
> You can find the missing keys in [TRANSLATION.md](TRANSLATION.md)
diff --git a/TRANSLATION.md b/TRANSLATION.md
index 9f7a1c80..84411404 100644
--- a/TRANSLATION.md
+++ b/TRANSLATION.md
@@ -1,4 +1,17 @@
-### de_DE.axaml: 98.13%
+### 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.61%
@@ -10,41 +23,22 @@
- 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
- Text.DeleteRepositoryNode.TipForGroup
- Text.DeleteRepositoryNode.TipForRepository
+- Text.Repository.Notifications.Clear
- Text.Stash.AutoRestore
- Text.Stash.AutoRestore.Tip
- Text.WorkingCopy.SignOff
-### es_ES.axaml: 98.13%
-
-
-
-Missing Keys
-
-- Text.AIAssistant.Regen
-- Text.AIAssistant.Use
-- Text.ApplyStash
-- Text.ApplyStash.DropAfterApply
-- Text.ApplyStash.RestoreIndex
-- Text.ApplyStash.Stash
-- Text.Clone.RecurseSubmodules
-- Text.CreateBranch.Name.WarnSpace
-- Text.DeleteRepositoryNode.Path
-- Text.DeleteRepositoryNode.TipForGroup
-- Text.DeleteRepositoryNode.TipForRepository
-- Text.Stash.AutoRestore
-- Text.Stash.AutoRestore.Tip
-- Text.WorkingCopy.SignOff
-
-
-
-### fr_FR.axaml: 92.91%
+### fr_FR.axaml: 92.42%
@@ -56,7 +50,10 @@
- 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
- Text.DeleteRepositoryNode.TipForGroup
@@ -87,6 +84,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
@@ -106,7 +104,7 @@
-### it_IT.axaml: 98.40%
+### it_IT.axaml: 97.87%
@@ -118,16 +116,20 @@
- 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
- Text.DeleteRepositoryNode.TipForRepository
+- Text.Repository.Notifications.Clear
- Text.Stash.AutoRestore
- Text.Stash.AutoRestore.Tip
-### pt_BR.axaml: 92.65%
+### pt_BR.axaml: 92.15%
@@ -139,12 +141,15 @@
- 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
- Text.CreateBranch.Name.WarnSpace
@@ -172,6 +177,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
@@ -191,26 +197,14 @@
-### ru_RU.axaml: 98.13%
+### ru_RU.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.CreateBranch.Name.WarnSpace
-- Text.DeleteRepositoryNode.Path
-- Text.DeleteRepositoryNode.TipForGroup
-- Text.DeleteRepositoryNode.TipForRepository
-- Text.Stash.AutoRestore
-- Text.Stash.AutoRestore.Tip
-- Text.WorkingCopy.SignOff
+- Text.BranchCM.CustomAction
+- Text.Configure.CustomAction.Scope.Branch
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
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/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/CustomAction.cs b/src/Models/CustomAction.cs
index 8452a42d..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
@@ -34,9 +35,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/Models/Watcher.cs b/src/Models/Watcher.cs
index 7a6c5163..d0ccdea5 100644
--- a/src/Models/Watcher.cs
+++ b/src/Models/Watcher.cs
@@ -114,6 +114,7 @@ namespace SourceGit.Models
{
_updateBranch = 0;
_updateWC = 0;
+ _updateSubmodules = 0;
if (_updateTags > 0)
{
@@ -124,6 +125,7 @@ namespace SourceGit.Models
Task.Run(_repo.RefreshBranches);
Task.Run(_repo.RefreshCommits);
Task.Run(_repo.RefreshWorkingCopyChanges);
+ Task.Run(_repo.RefreshSubmodules);
Task.Run(_repo.RefreshWorktrees);
}
@@ -136,20 +138,20 @@ namespace SourceGit.Models
if (_updateSubmodules > 0 && now > _updateSubmodules)
{
_updateSubmodules = 0;
- _repo.RefreshSubmodules();
+ Task.Run(_repo.RefreshSubmodules);
}
if (_updateStashes > 0 && now > _updateStashes)
{
_updateStashes = 0;
- _repo.RefreshStashes();
+ Task.Run(_repo.RefreshStashes);
}
if (_updateTags > 0 && now > _updateTags)
{
_updateTags = 0;
- _repo.RefreshTags();
- _repo.RefreshCommits();
+ Task.Run(_repo.RefreshTags);
+ Task.Run(_repo.RefreshCommits);
}
}
@@ -178,12 +180,6 @@ namespace SourceGit.Models
(name.StartsWith("worktrees/", StringComparison.Ordinal) && name.EndsWith("/HEAD", StringComparison.Ordinal)))
{
_updateBranch = DateTime.Now.AddSeconds(.5).ToFileTime();
-
- lock (_lockSubmodule)
- {
- if (_submodules.Count > 0)
- _updateSubmodules = DateTime.Now.AddSeconds(1).ToFileTime();
- }
}
else if (name.StartsWith("objects/", StringComparison.Ordinal) || name.Equals("index", 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/Resources/Icons.axaml b/src/Resources/Icons.axaml
index c7e02431..8e865660 100644
--- a/src/Resources/Icons.axaml
+++ b/src/Resources/Icons.axaml
@@ -10,7 +10,9 @@
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
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
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/de_DE.axaml b/src/Resources/Locales/de_DE.axaml
index fe961d14..b6458822 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:
@@ -565,6 +576,7 @@
Aufheben
Im Graph ausblenden
Im Graph filtern
+ Aktiviere '--first-parent' Option
LAYOUT
Horizontal
Vertikal
@@ -573,7 +585,6 @@
Topologie
LOKALE BRANCHES
Zum HEAD wechseln
- Aktiviere '--first-parent' Option
Erstelle Branch
Nur aktuellen Branch im Graphen hervorheben
Öffne in {0}
@@ -641,6 +652,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 +733,7 @@
NICHT-VERFOLGTE DATEIEN INKLUDIEREN
KEINE BISHERIGEN COMMIT-NACHRICHTEN
KEINE COMMIT TEMPLATES
+ SignOff
GESTAGED
UNSTAGEN
ALLES UNSTAGEN
diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml
index 018b54d7..cd266666 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,12 +153,14 @@
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
Email Address
Email address
GIT
@@ -462,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
@@ -573,6 +576,7 @@
Unset
Hide in commit graph
Filter in commit graph
+ Enable '--first-parent' Option
LAYOUT
Horizontal
Vertical
@@ -581,8 +585,8 @@
Topologically
LOCAL BRANCHES
Navigate to HEAD
- Enable '--first-parent' Option
Create Branch
+ CLEAR NOTIFICATIONS
Only highlight current branch in graph
Open in {0}
Open in External Tools
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..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:
Цель:
+ Все дочерние элементы будут удалены из списка.
Подтвердите удаление группы
+ Будет удалён из списка. На диске останется.
Подтвердите удаление репозитория
Удалить подмодуль
Путь подмодуля:
@@ -567,6 +579,7 @@
Скрыть в графе ревизии
Фильтр в графе ревизии
ОТФИЛЬТРОВАНО:
+ Включить опцию --first-parent
РАСПОЛОЖЕНИЕ
Горизонтально
Вертикально
@@ -575,8 +588,8 @@
Топологически
ЛОКАЛЬНЫЕ ВЕТКИ
Навигация по ГОЛОВЕ (HEAD)
- Включить опцию --first-parent
Создать ветку
+ ОЧИСТКА УВЕДОМЛЕНИЙ
Выделять только текущую ветку на графике
Открыть в {0}
Открыть в расширенном инструменте
@@ -585,7 +598,7 @@
ДОБАВИТЬ ВНЕШНИЙ РЕПОЗИТОРИЙ
Поиск ревизии
Автор
- исполнитель
+ Ревизор
Файл
Сообщение
SHA
@@ -645,6 +658,8 @@
Подготовленные так и неподготовленные изменения выбранных файлов будут сохранены!!!
ЗАПУСК
Отложить
+ Автоматически восстанавливать после откладывания
+ Ваши рабочие файлы остаются неизменными, но отложенные сохранятся.
Включить неотслеживаемые файлы
Хранить отложенные файлы
Сообщение:
@@ -660,7 +675,7 @@
ОТЛОЖЕННЫЕ
Статистика
РЕВИЗИИ
- ИСПОЛНИТЕЛИ
+ РЕВИЗОРЫ(ИСПОЛНИТЕЛИ)
МЕСЯЦ
НЕДЕЛЯ
РЕВИЗИИ:
@@ -722,6 +737,7 @@
ВКЛЮЧИТЬ НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ
НЕТ ПОСЛЕДНИХ ВХОДНЫХ СООБЩЕНИЙ
НЕТ ШАБЛОНОВ РЕВИЗИИ
+ Завершение работы
ПОДГОТОВЛЕННЫЕ
СНЯТЬ ПОДГОТОВЛЕННЫЙ
СНЯТЬ ВСЕ ПОДГОТОВЛЕННЫЕ
diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml
index 66d1f37e..4db909c9 100644
--- a/src/Resources/Locales/zh_CN.axaml
+++ b/src/Resources/Locales/zh_CN.axaml
@@ -59,6 +59,7 @@
与当前HEAD比较
与本地工作树比较
复制分支名
+ 自定义操作
删除 ${0}$...
删除选中的 {0} 个分支
放弃所有更改
@@ -155,12 +156,14 @@
模板内容 :
自定义操作
命令行参数 :
- 请使用${REPO}代替仓库路径,${SHA}代替提交哈希
+ 请使用${REPO}代替仓库路径,${BRANCH}代替选中的分支,${SHA}代替提交哈希
可执行文件路径 :
名称 :
作用目标 :
+ 选中的分支
选中的提交
仓库
+ 等待操作执行完成
电子邮箱
邮箱地址
GIT配置
@@ -577,6 +580,7 @@
不指定
在提交列表中隐藏
使用其对提交列表过滤
+ 启用 --first-parent 过滤选项
布局方式
水平排布
竖直排布
@@ -585,8 +589,8 @@
按拓扑排序
本地分支
定位HEAD
- 启用 --first-parent 过滤选项
新建分支
+ 清空通知列表
提交路线图中仅高亮显示当前分支
在 {0} 中打开
使用外部工具打开
diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml
index f8255947..a3fe5c19 100644
--- a/src/Resources/Locales/zh_TW.axaml
+++ b/src/Resources/Locales/zh_TW.axaml
@@ -39,10 +39,10 @@
警告
套用修補檔,輸出關於空白字元的警告
空白字元處理:
- 套用擱置
- 在成功套用后捨棄擱置
- 恢復索引中已暫存的變更
- 已選擇擱置 :
+ 套用擱置變更
+ 套用擱置變更後刪除
+ 還原索引中已暫存的變更 (--index)
+ 已選擇擱置變更:
封存 (archive)...
封存檔案路徑:
選擇封存檔案的儲存路徑
@@ -59,6 +59,7 @@
與目前 HEAD 比較
與本機工作區比較
複製分支名稱
+ 自訂動作
刪除 ${0}$...
刪除所選的 {0} 個分支
捨棄所有變更
@@ -106,7 +107,7 @@
本機存放庫名稱:
本機存放庫目錄的名稱,選填。
父級目錄:
- 初始化並複製子模組
+ 初始化並更新子模組
遠端存放庫:
關閉
提交訊息編輯器
@@ -155,12 +156,14 @@
範本內容:
自訂動作
指令參數:
- 使用 ${REPO} 表示存放庫路徑、${SHA} 表示所選的提交編號
+ 使用 ${REPO} 表示存放庫路徑、${BRANCH} 表示所選的分支、${SHA} 表示所選的提交編號
可執行檔案路徑:
名稱:
執行範圍:
+ 選取的分支
選取的提交
存放庫
+ 等待自訂動作執行結束
電子郵件
電子郵件地址
Git 設定
@@ -237,7 +240,7 @@
目標:
所有子節點都會從清單中移除。
刪除群組確認
- 只會從清單中移除,而不會刪除磁碟中的檔案!
+ 只會從清單中移除,而不會刪除磁碟中的檔案!
刪除存放庫確認
刪除子模組確認
子模組路徑:
@@ -262,7 +265,7 @@
交換比對雙方
語法上色
自動換行
- 啟用基於變更區塊的導航
+ 區塊切換上/下一個差異
使用外部合併工具檢視
顯示檔案的全部內容
減少可見的行數
@@ -409,7 +412,7 @@
合併操作進行中。
正在處理
重定基底 (rebase) 操作進行中。
- 当前停止于
+ 目前停止於
復原提交操作進行中。
正在復原提交
互動式重定基底
@@ -422,8 +425,8 @@
合併分支
目標分支:
合併方式:
- 合併目標:
- 合併(多目標)
+ 合併來源:
+ 合併 (多個來源)
提交變更
合併策略:
目標列表:
@@ -576,17 +579,18 @@
取消指定
在提交列表中隱藏
以其篩選提交列表
- 佈局方式
+ 啟用 [--first-parent] 選項
+ 版面配置
橫向顯示
縱向顯示
提交顯示順序
- 依提交時間排序
+ 依時間排序
依拓撲排序
本機分支
回到 HEAD
- 啟用 [--first-parent] 選項
新增分支
- 提交圖表中僅高亮顯示目前分支
+ 清除所有通知
+ 在提交路線圖中僅對目前分支上色
在 {0} 中開啟
使用外部工具開啟
重新載入
@@ -612,7 +616,7 @@
依名稱降序
排序
在終端機中開啟
- 在提交清單中使用相對時間
+ 在提交列表中使用相對時間
工作區列表
新增工作區
清理
@@ -652,8 +656,8 @@
SSH 金鑰檔案
開 始
擱置變更 (stash)
- 暫存後自動復原工作區
- 工作區檔案保持未修改,但暫存內容已儲存。
+ 擱置變更後自動復原工作區
+ 工作區檔案保持未修改,但擱置內容已儲存。
包含未追蹤的檔案
保留已暫存的變更
擱置變更訊息:
@@ -725,7 +729,7 @@
提交並推送
歷史輸入/範本
觸發點擊事件
- 提交(修改現有提交)
+ 提交 (修改原始提交)
自動暫存全部變更並提交
未包含任何檔案變更! 您是否仍要提交 (--allow-empty)?
檢測到衝突
diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj
index af8fa5b1..7cceee7e 100644
--- a/src/SourceGit.csproj
+++ b/src/SourceGit.csproj
@@ -41,19 +41,19 @@
-
-
-
-
-
+
+
+
+
+
-
-
+
+
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/ViewModels/ExecuteCustomAction.cs b/src/ViewModels/ExecuteCustomAction.cs
index 920b9f43..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 };
}
@@ -28,7 +41,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/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/ViewModels/Repository.cs b/src/ViewModels/Repository.cs
index 44de8c35..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))
@@ -1439,7 +1448,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 +1707,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 +1978,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 +2331,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/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()
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}"/>
-
+
+
+
+
+
+
+
+
-
+
-
+
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))
{
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}}"/>
-
+
+
+
+
-
+
diff --git a/src/Views/LauncherTabBar.axaml b/src/Views/LauncherTabBar.axaml
index c957d134..9b748e91 100644
--- a/src/Views/LauncherTabBar.axaml
+++ b/src/Views/LauncherTabBar.axaml
@@ -4,11 +4,17 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:c="using:SourceGit.Converters"
+ xmlns:v="using:SourceGit.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.LauncherTabBar"
- x:DataType="vm:Launcher">
-
-
+ x:DataType="vm:Launcher"
+ x:Name="ThisControl">
+
+
@@ -96,11 +102,11 @@
-
-
-
-
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Views/LauncherTabBar.axaml.cs b/src/Views/LauncherTabBar.axaml.cs
index 129ce892..12bca91f 100644
--- a/src/Views/LauncherTabBar.axaml.cs
+++ b/src/Views/LauncherTabBar.axaml.cs
@@ -10,6 +10,15 @@ namespace SourceGit.Views
{
public partial class LauncherTabBar : UserControl
{
+ public static readonly StyledProperty IsScrollerVisibleProperty =
+ AvaloniaProperty.Register(nameof(IsScrollerVisible));
+
+ public bool IsScrollerVisible
+ {
+ get => GetValue(IsScrollerVisibleProperty);
+ set => SetValue(IsScrollerVisibleProperty, value);
+ }
+
public LauncherTabBar()
{
InitializeComponent();
@@ -43,7 +52,7 @@ namespace SourceGit.Views
if (containerEndX < startX || containerEndX > endX)
continue;
- if (OuterNewTabBtn.IsVisible && i == count - 1)
+ if (IsScrollerVisible && i == count - 1)
break;
var separatorX = containerEndX - startX + LauncherTabsScroller.Bounds.X;
@@ -143,23 +152,7 @@ namespace SourceGit.Views
private void OnTabsLayoutUpdated(object _1, EventArgs _2)
{
- if (LauncherTabsScroller.Extent.Width > LauncherTabsScroller.Viewport.Width)
- {
- LeftScrollIndicator.IsVisible = true;
- LeftScrollIndicator.IsEnabled = LauncherTabsScroller.Offset.X > 0;
- RightScrollIndicator.IsVisible = true;
- RightScrollIndicator.IsEnabled = LauncherTabsScroller.Offset.X < LauncherTabsScroller.Extent.Width - LauncherTabsScroller.Viewport.Width;
- InnerNewTabBtn.IsVisible = false;
- OuterNewTabBtn.IsVisible = true;
- }
- else
- {
- LeftScrollIndicator.IsVisible = false;
- RightScrollIndicator.IsVisible = false;
- InnerNewTabBtn.IsVisible = true;
- OuterNewTabBtn.IsVisible = false;
- }
-
+ SetCurrentValue(IsScrollerVisibleProperty, LauncherTabsScroller.Extent.Width > LauncherTabsScroller.Viewport.Width);
InvalidateVisual();
}
@@ -255,6 +248,15 @@ namespace SourceGit.Views
e.Handled = true;
}
+ private void OnGotoSelectedPage(object sender, LauncherTabSelectedEventArgs e)
+ {
+ if (DataContext is ViewModels.Launcher vm)
+ vm.ActivePage = e.Page;
+
+ PageSelector.Flyout?.Hide();
+ e.Handled = true;
+ }
+
private bool _pressedTab = false;
private Point _pressedTabPosition = new Point();
private bool _startDragTab = false;
diff --git a/src/Views/LauncherTabsSelector.axaml b/src/Views/LauncherTabsSelector.axaml
new file mode 100644
index 00000000..109a2ce7
--- /dev/null
+++ b/src/Views/LauncherTabsSelector.axaml
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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;
+ }
+}
+
diff --git a/src/Views/RemoveWorktree.axaml b/src/Views/RemoveWorktree.axaml
index 6d7ea914..736e6e40 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..30180f7d 100644
--- a/src/Views/Repository.axaml
+++ b/src/Views/Repository.axaml
@@ -372,8 +372,8 @@
-
-
+
+
@@ -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;
+ }
}
}
diff --git a/src/Views/RepositoryConfigure.axaml b/src/Views/RepositoryConfigure.axaml
index 5e9374f9..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"
@@ -341,7 +340,7 @@
-
+
@@ -412,20 +411,12 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
@@ -439,6 +430,8 @@
+
+
diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs
index 15a2a212..28fe81a8 100644
--- a/src/Views/TextDiffView.axaml.cs
+++ b/src/Views/TextDiffView.axaml.cs
@@ -970,8 +970,15 @@ 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.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);
if (startIdx == endIdx)
{
@@ -995,15 +1002,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;
}