diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml
index 8015d1e8d..c30a3ea2a 100644
--- a/src/Resources/Locales/en_US.axaml
+++ b/src/Resources/Locales/en_US.axaml
@@ -708,12 +708,14 @@
Run `git gc` command for this repository.
Clear all
Clear
+ Collapse All
Configure this repository
CONTINUE
Custom Actions
No Custom Actions
Dashboard
Discard all changes
+ Expand All
Open in File Browser
Search Branches/Tags/Submodules
Visibility in Graph
diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml
index 8f9817472..354772b3c 100644
--- a/src/Resources/Locales/es_ES.axaml
+++ b/src/Resources/Locales/es_ES.axaml
@@ -703,12 +703,14 @@
Ejecutar comando `git gc` para este repositorio.
Limpiar todo
Limpiar
+ Contraer Todo
Configurar este repositorio
CONTINUAR
Acciones Personalizadas
No hay ninguna Acción Personalizada
Dashboard
Descartar todos los cambios
+ Expandir Todo
Abrir en el Explorador
Buscar Ramas/Etiquetas/Submódulos
Visibilidad en el Gráfico
diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml
index 66e448d6e..d36518148 100644
--- a/src/Resources/Locales/fr_FR.axaml
+++ b/src/Resources/Locales/fr_FR.axaml
@@ -688,12 +688,14 @@
Lancer `git gc` pour ce repository.
Tout effacer
Nettoyer
+ Tout Réduire
Configurer ce repository
CONTINUER
Actions personnalisées
Pas d'actions personnalisées
Tableau de bord
Rejeter tous les changements
+ Tout Développer
Ouvrir dans l'explorateur de fichiers
Rechercher Branches/Tags/Submodules
Visibilité dans le graphique
diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml
index b5c919220..ed408ce15 100644
--- a/src/Resources/Locales/it_IT.axaml
+++ b/src/Resources/Locales/it_IT.axaml
@@ -642,12 +642,14 @@
Esegui il comando `git gc` per questo repository.
Cancella tutto
Cancella
+ Comprimi Tutto
Configura questo repository
CONTINUA
Azioni Personalizzate
Nessuna Azione Personalizzata
Dashboard
Scarta tutte le modifiche
+ Espandi Tutto
Apri nell'Esplora File
Cerca Branch/Tag/Sottomodulo
Visibilità nel grafico
diff --git a/src/Views/BranchTree.axaml.cs b/src/Views/BranchTree.axaml.cs
index 834e0fc6b..8c150ccea 100644
--- a/src/Views/BranchTree.axaml.cs
+++ b/src/Views/BranchTree.axaml.cs
@@ -387,6 +387,84 @@ public void ToggleNodeIsExpanded(ViewModels.BranchTreeNode node)
_disableSelectionChangingEvent = false;
}
+ public void ExpandAll()
+ {
+ if (Nodes == null || Nodes.Count == 0)
+ return;
+
+ _disableSelectionChangingEvent = true;
+
+ // Set IsExpanded = true on all folder nodes recursively
+ SetExpandedRecursive(Nodes, true);
+
+ // Rebuild rows
+ var rows = Rows;
+ rows.Clear();
+ var newRows = new List();
+ MakeRows(newRows, Nodes, 0);
+ rows.AddRange(newRows);
+
+ // Persist state for all nodes
+ var repo = DataContext as ViewModels.Repository;
+ if (repo != null)
+ PersistExpandedState(Nodes, repo);
+
+ RaiseEvent(new RoutedEventArgs(RowsChangedEvent));
+ _disableSelectionChangingEvent = false;
+ }
+
+ public void CollapseAll()
+ {
+ if (Nodes == null || Nodes.Count == 0)
+ return;
+
+ _disableSelectionChangingEvent = true;
+
+ // Set IsExpanded = false on all folder nodes recursively
+ SetExpandedRecursive(Nodes, false);
+
+ // Rebuild rows (only root nodes visible)
+ var rows = Rows;
+ rows.Clear();
+ var newRows = new List();
+ MakeRows(newRows, Nodes, 0);
+ rows.AddRange(newRows);
+
+ // Persist state for all nodes
+ var repo = DataContext as ViewModels.Repository;
+ if (repo != null)
+ PersistExpandedState(Nodes, repo);
+
+ RaiseEvent(new RoutedEventArgs(RowsChangedEvent));
+ _disableSelectionChangingEvent = false;
+ }
+
+ private void SetExpandedRecursive(List nodes, bool expanded)
+ {
+ foreach (var node in nodes)
+ {
+ // Only set IsExpanded for folder nodes (not branch leaves)
+ if (node.Backend is not Models.Branch)
+ node.IsExpanded = expanded;
+
+ // Recurse into children
+ if (node.Children != null && node.Children.Count > 0)
+ SetExpandedRecursive(node.Children, expanded);
+ }
+ }
+
+ private void PersistExpandedState(List nodes, ViewModels.Repository repo)
+ {
+ foreach (var node in nodes)
+ {
+ if (node.Backend is not Models.Branch)
+ repo.UpdateBranchNodeIsExpanded(node);
+
+ if (node.Children != null && node.Children.Count > 0)
+ PersistExpandedState(node.Children, repo);
+ }
+ }
+
protected override void OnSizeChanged(SizeChangedEventArgs e)
{
base.OnSizeChanged(e);
diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml
index 145a1e654..140a64929 100644
--- a/src/Views/Repository.axaml
+++ b/src/Views/Repository.axaml
@@ -192,36 +192,60 @@
-
-
-
-
-
-
-
-
-
+ Margin="6,0,0,0"
+ Fill="{DynamicResource Brush.FG2}"
+ Data="{StaticResource Icons.Search}"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Views/Repository.axaml.cs b/src/Views/Repository.axaml.cs
index f99184f5e..1792d5429 100644
--- a/src/Views/Repository.axaml.cs
+++ b/src/Views/Repository.axaml.cs
@@ -598,5 +598,41 @@ private async void OnBisectCommand(object sender, RoutedEventArgs e)
e.Handled = true;
}
+
+ private void OnExpandAllNodes(object sender, RoutedEventArgs e)
+ {
+ if (DataContext is ViewModels.Repository repo)
+ {
+ repo.IsLocalBranchGroupExpanded = true;
+ repo.IsRemoteGroupExpanded = true;
+ repo.IsTagGroupExpanded = true;
+ repo.IsSubmoduleGroupExpanded = true;
+ repo.IsWorktreeGroupExpanded = true;
+ }
+
+ LocalBranchTree?.ExpandAll();
+ RemoteBranchTree?.ExpandAll();
+ TagsList?.ExpandAll();
+ SubmoduleList?.ExpandAll();
+ e.Handled = true;
+ }
+
+ private void OnCollapseAllNodes(object sender, RoutedEventArgs e)
+ {
+ if (DataContext is ViewModels.Repository repo)
+ {
+ repo.IsLocalBranchGroupExpanded = false;
+ repo.IsRemoteGroupExpanded = false;
+ repo.IsTagGroupExpanded = false;
+ repo.IsSubmoduleGroupExpanded = false;
+ repo.IsWorktreeGroupExpanded = false;
+ }
+
+ LocalBranchTree?.CollapseAll();
+ RemoteBranchTree?.CollapseAll();
+ TagsList?.CollapseAll();
+ SubmoduleList?.CollapseAll();
+ e.Handled = true;
+ }
}
}
diff --git a/src/Views/SubmodulesView.axaml.cs b/src/Views/SubmodulesView.axaml.cs
index 6e4b7b7f9..457c90dd3 100644
--- a/src/Views/SubmodulesView.axaml.cs
+++ b/src/Views/SubmodulesView.axaml.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using Avalonia;
using Avalonia.Controls;
@@ -118,6 +119,61 @@ public void ToggleNodeIsExpanded(ViewModels.SubmoduleTreeNode node)
}
}
+ public void ExpandAll()
+ {
+ if (Content is ViewModels.SubmoduleCollectionAsTree tree)
+ {
+ SetExpandedRecursive(tree.Tree, true);
+
+ // Rebuild rows manually
+ tree.Rows.Clear();
+ MakeTreeRows(tree.Rows, tree.Tree);
+
+ Rows = tree.Rows.Count;
+ RaiseEvent(new RoutedEventArgs(RowsChangedEvent));
+ }
+ }
+
+ public void CollapseAll()
+ {
+ if (Content is ViewModels.SubmoduleCollectionAsTree tree)
+ {
+ SetExpandedRecursive(tree.Tree, false);
+
+ // Rebuild rows manually
+ tree.Rows.Clear();
+ MakeTreeRows(tree.Rows, tree.Tree);
+
+ Rows = tree.Rows.Count;
+ RaiseEvent(new RoutedEventArgs(RowsChangedEvent));
+ }
+ }
+
+ private void MakeTreeRows(Avalonia.Collections.AvaloniaList rows, List nodes)
+ {
+ foreach (var node in nodes)
+ {
+ rows.Add(node);
+
+ if (!node.IsExpanded || !node.IsFolder)
+ continue;
+
+ MakeTreeRows(rows, node.Children);
+ }
+ }
+
+ private void SetExpandedRecursive(List nodes, bool expanded)
+ {
+ foreach (var node in nodes)
+ {
+ if (node.IsFolder)
+ node.IsExpanded = expanded;
+
+ if (node.Children != null && node.Children.Count > 0)
+ SetExpandedRecursive(node.Children, expanded);
+ }
+ }
+
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
diff --git a/src/Views/TagsView.axaml.cs b/src/Views/TagsView.axaml.cs
index 8ff788a08..8557b24eb 100644
--- a/src/Views/TagsView.axaml.cs
+++ b/src/Views/TagsView.axaml.cs
@@ -144,6 +144,61 @@ public void ToggleNodeIsExpanded(ViewModels.TagTreeNode node)
}
}
+ public void ExpandAll()
+ {
+ if (Content is ViewModels.TagCollectionAsTree tree)
+ {
+ SetExpandedRecursive(tree.Tree, true);
+
+ // Rebuild rows manually
+ tree.Rows.Clear();
+ MakeTreeRows(tree.Rows, tree.Tree);
+
+ Rows = tree.Rows.Count;
+ RaiseEvent(new RoutedEventArgs(RowsChangedEvent));
+ }
+ }
+
+ public void CollapseAll()
+ {
+ if (Content is ViewModels.TagCollectionAsTree tree)
+ {
+ SetExpandedRecursive(tree.Tree, false);
+
+ // Rebuild rows manually
+ tree.Rows.Clear();
+ MakeTreeRows(tree.Rows, tree.Tree);
+
+ Rows = tree.Rows.Count;
+ RaiseEvent(new RoutedEventArgs(RowsChangedEvent));
+ }
+ }
+
+ private void MakeTreeRows(Avalonia.Collections.AvaloniaList rows, List nodes)
+ {
+ foreach (var node in nodes)
+ {
+ rows.Add(node);
+
+ if (!node.IsExpanded || !node.IsFolder)
+ continue;
+
+ MakeTreeRows(rows, node.Children);
+ }
+ }
+
+ private void SetExpandedRecursive(List nodes, bool expanded)
+ {
+ foreach (var node in nodes)
+ {
+ if (node.IsFolder)
+ node.IsExpanded = expanded;
+
+ if (node.Children != null && node.Children.Count > 0)
+ SetExpandedRecursive(node.Children, expanded);
+ }
+ }
+
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);