Skip to content

Commit a44ff22

Browse files
committed
feature: support to open submodule of current active repo in tabs command palette (#2219)
Signed-off-by: leo <longshuang@msn.cn>
1 parent ccddd4b commit a44ff22

File tree

7 files changed

+210
-52
lines changed

7 files changed

+210
-52
lines changed

src/Resources/Locales/en_US.axaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,8 @@
545545
<x:String x:Key="Text.Launcher.Commands" xml:space="preserve">Commands</x:String>
546546
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">ERROR</x:String>
547547
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">NOTICE</x:String>
548-
<x:String x:Key="Text.Launcher.OpenRepository" xml:space="preserve">Open Repositories</x:String>
548+
<x:String x:Key="Text.Launcher.OpenRepository" xml:space="preserve">Open Repository</x:String>
549+
<x:String x:Key="Text.Launcher.OpenSubmodule" xml:space="preserve">Open Submodule</x:String>
549550
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">Tabs</x:String>
550551
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Workspaces</x:String>
551552
<x:String x:Key="Text.Merge" xml:space="preserve">Merge Branch</x:String>

src/Resources/Locales/zh_CN.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@
550550
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">出错了</x:String>
551551
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">系统提示</x:String>
552552
<x:String x:Key="Text.Launcher.OpenRepository" xml:space="preserve">打开其他仓库</x:String>
553+
<x:String x:Key="Text.Launcher.OpenSubmodule" xml:space="preserve">打开子模块</x:String>
553554
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">页面列表</x:String>
554555
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">工作区列表</x:String>
555556
<x:String x:Key="Text.Merge" xml:space="preserve">合并分支</x:String>

src/Resources/Locales/zh_TW.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@
550550
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">發生錯誤</x:String>
551551
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">系統提示</x:String>
552552
<x:String x:Key="Text.Launcher.OpenRepository" xml:space="preserve">開啟存放庫</x:String>
553+
<x:String x:Key="Text.Launcher.OpenSubmodule" xml:space="preserve">開啟子模組</x:String>
553554
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">頁面列表</x:String>
554555
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">工作區列表</x:String>
555556
<x:String x:Key="Text.Merge" xml:space="preserve">合併分支</x:String>

src/ViewModels/LauncherPagesCommandPalette.cs

Lines changed: 91 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ public List<LauncherPage> VisiblePages
1111
private set => SetProperty(ref _visiblePages, value);
1212
}
1313

14+
public List<Models.Submodule> VisibleSubmodules
15+
{
16+
get => _visibleSubmodules;
17+
private set => SetProperty(ref _visibleSubmodules, value);
18+
}
19+
1420
public List<RepositoryNode> VisibleRepos
1521
{
1622
get => _visibleRepos;
@@ -33,7 +39,23 @@ public LauncherPage SelectedPage
3339
set
3440
{
3541
if (SetProperty(ref _selectedPage, value) && value != null)
42+
{
43+
SelectedSubmodule = null;
3644
SelectedRepo = null;
45+
}
46+
}
47+
}
48+
49+
public Models.Submodule SelectedSubmodule
50+
{
51+
get => _selectedSubmodule;
52+
set
53+
{
54+
if (SetProperty(ref _selectedSubmodule, value) && value != null)
55+
{
56+
SelectedPage = null;
57+
SelectedRepo = null;
58+
}
3759
}
3860
}
3961

@@ -43,7 +65,10 @@ public RepositoryNode SelectedRepo
4365
set
4466
{
4567
if (SetProperty(ref _selectedRepo, value) && value != null)
68+
{
4669
SelectedPage = null;
70+
SelectedSubmodule = null;
71+
}
4772
}
4873
}
4974

@@ -70,10 +95,13 @@ public void OpenOrSwitchTo()
7095
_opened.Clear();
7196
_visiblePages.Clear();
7297
_visibleRepos.Clear();
98+
_visibleSubmodules.Clear();
7399
Close();
74100

75101
if (_selectedPage != null)
76102
_launcher.ActivePage = _selectedPage;
103+
else if (_selectedSubmodule != null && _launcher.ActivePage is { Data: Repository repo })
104+
repo.OpenSubmodule(_selectedSubmodule.Path);
77105
else if (_selectedRepo != null)
78106
_launcher.OpenRepositoryInTab(_selectedRepo, null);
79107
}
@@ -83,72 +111,80 @@ private void UpdateVisible()
83111
var pages = new List<LauncherPage>();
84112
CollectVisiblePages(pages);
85113

114+
var submodules = new List<Models.Submodule>();
115+
CollectVisibleSubmodules(submodules);
116+
86117
var repos = new List<RepositoryNode>();
87118
CollectVisibleRepository(repos, Preferences.Instance.RepositoryNodes);
88119

89-
var autoSelectPage = _selectedPage;
90-
var autoSelectRepo = _selectedRepo;
91-
120+
object autoSelected = null;
92121
if (_selectedPage != null)
93122
{
94123
if (pages.Contains(_selectedPage))
95-
{
96-
// Keep selection
97-
}
124+
autoSelected = _selectedPage;
98125
else if (pages.Count > 0)
99-
{
100-
autoSelectPage = pages[0];
101-
}
126+
autoSelected = pages[0];
127+
else if (submodules.Count > 0)
128+
autoSelected = submodules[0];
102129
else if (repos.Count > 0)
103-
{
104-
autoSelectPage = null;
105-
autoSelectRepo = repos[0];
106-
}
107-
else
108-
{
109-
autoSelectPage = null;
110-
}
130+
autoSelected = repos[0];
131+
}
132+
else if (_selectedSubmodule != null)
133+
{
134+
if (submodules.Contains(_selectedSubmodule))
135+
autoSelected = _selectedSubmodule;
136+
else if (submodules.Count > 0)
137+
autoSelected = submodules[0];
138+
else if (pages.Count > 0)
139+
autoSelected = pages[0];
140+
else if (repos.Count > 0)
141+
autoSelected = repos[0];
111142
}
112143
else if (_selectedRepo != null)
113144
{
114145
if (repos.Contains(_selectedRepo))
115-
{
116-
// Keep selection
117-
}
146+
autoSelected = _selectedRepo;
118147
else if (repos.Count > 0)
119-
{
120-
autoSelectRepo = repos[0];
121-
}
148+
autoSelected = repos[0];
122149
else if (pages.Count > 0)
123-
{
124-
autoSelectPage = pages[0];
125-
autoSelectRepo = null;
126-
}
127-
else
128-
{
129-
autoSelectRepo = null;
130-
}
150+
autoSelected = pages[0];
151+
else if (submodules.Count > 0)
152+
autoSelected = submodules[0];
131153
}
132154
else if (pages.Count > 0)
133155
{
134-
autoSelectPage = pages[0];
135-
autoSelectRepo = null;
156+
autoSelected = pages[0];
136157
}
137-
else if (repos.Count > 0)
158+
else if (submodules.Count > 0)
138159
{
139-
autoSelectPage = null;
140-
autoSelectRepo = repos[0];
160+
autoSelected = submodules[0];
141161
}
142-
else
162+
else if (repos.Count > 0)
143163
{
144-
autoSelectPage = null;
145-
autoSelectRepo = null;
164+
autoSelected = repos[0];
146165
}
147166

148167
VisiblePages = pages;
168+
VisibleSubmodules = submodules;
149169
VisibleRepos = repos;
150-
SelectedPage = autoSelectPage;
151-
SelectedRepo = autoSelectRepo;
170+
171+
switch (autoSelected)
172+
{
173+
case LauncherPage page:
174+
SelectedPage = page;
175+
break;
176+
case Models.Submodule submodule:
177+
SelectedSubmodule = submodule;
178+
break;
179+
case RepositoryNode repo:
180+
SelectedRepo = repo;
181+
break;
182+
default:
183+
SelectedPage = null;
184+
SelectedSubmodule = null;
185+
SelectedRepo = null;
186+
break;
187+
}
152188
}
153189

154190
private void CollectVisiblePages(List<LauncherPage> pages)
@@ -185,12 +221,26 @@ private void CollectVisibleRepository(List<RepositoryNode> outs, List<Repository
185221
}
186222
}
187223

224+
private void CollectVisibleSubmodules(List<Models.Submodule> outs)
225+
{
226+
if (_launcher.ActivePage is { Data: Repository repo } && repo.Submodules.Count > 0)
227+
{
228+
foreach (var submodule in repo.Submodules)
229+
{
230+
if (string.IsNullOrEmpty(_searchFilter) || submodule.Path.Contains(_searchFilter, StringComparison.OrdinalIgnoreCase))
231+
outs.Add(submodule);
232+
}
233+
}
234+
}
235+
188236
private Launcher _launcher = null;
189237
private HashSet<string> _opened = new HashSet<string>();
190238
private List<LauncherPage> _visiblePages = [];
239+
private List<Models.Submodule> _visibleSubmodules = [];
191240
private List<RepositoryNode> _visibleRepos = [];
192241
private string _searchFilter = string.Empty;
193242
private LauncherPage _selectedPage = null;
243+
private Models.Submodule _selectedSubmodule = null;
194244
private RepositoryNode _selectedRepo = null;
195245
}
196246
}

src/ViewModels/Repository.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1536,8 +1536,10 @@ public void OpenSubmodule(string submodule)
15361536
return;
15371537

15381538
var root = Path.GetFullPath(Path.Combine(FullPath, submodule));
1539-
var normalizedPath = root.Replace('\\', '/').TrimEnd('/');
1539+
if (!Directory.Exists(root))
1540+
return;
15401541

1542+
var normalizedPath = root.Replace('\\', '/').TrimEnd('/');
15411543
var node = Preferences.Instance.FindNode(normalizedPath) ??
15421544
new RepositoryNode
15431545
{

src/Views/LauncherPagesCommandPalette.axaml

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
33
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
44
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:m="using:SourceGit.Models"
56
xmlns:vm="using:SourceGit.ViewModels"
67
xmlns:c="using:SourceGit.Converters"
78
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
89
x:Class="SourceGit.Views.LauncherPagesCommandPalette"
910
x:DataType="vm:LauncherPagesCommandPalette">
10-
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto">
11+
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto">
1112
<TextBox Grid.Row="0"
1213
x:Name="FilterTextBox"
1314
Height="24"
@@ -88,13 +89,6 @@
8889
Width="12" Height="12"
8990
Fill="{Binding Node.Bookmark, Converter={x:Static c:IntConverters.ToBookmarkBrush}}"
9091
Data="{StaticResource Icons.Bookmark}"
91-
IsVisible="{Binding Node.IsRepository}"
92-
IsHitTestVisible="False"/>
93-
<Path Grid.Column="0"
94-
Width="12" Height="12"
95-
Fill="{DynamicResource Brush.FG1}"
96-
Data="{StaticResource Icons.Repositories}"
97-
IsVisible="{Binding !Node.IsRepository}"
9892
IsHitTestVisible="False"/>
9993
<TextBlock Grid.Column="2"
10094
VerticalAlignment="Center"
@@ -112,13 +106,71 @@
112106
</ListBox>
113107

114108
<TextBlock Grid.Row="3"
109+
Margin="6,8,0,4"
110+
Text="{DynamicResource Text.Launcher.OpenSubmodule}"
111+
FontWeight="Bold"
112+
Foreground="{DynamicResource Brush.FG2}"
113+
IsVisible="{Binding VisibleSubmodules, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}"/>
114+
115+
<ListBox Grid.Row="4"
116+
x:Name="SubmoduleListBox"
117+
MaxHeight="250"
118+
Margin="4,0"
119+
BorderThickness="0"
120+
SelectionMode="Single"
121+
Background="Transparent"
122+
Focusable="True"
123+
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
124+
ScrollViewer.VerticalScrollBarVisibility="Auto"
125+
ItemsSource="{Binding VisibleSubmodules, Mode=OneWay}"
126+
SelectedItem="{Binding SelectedSubmodule, Mode=TwoWay}"
127+
IsVisible="{Binding VisibleSubmodules, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}">
128+
<ListBox.Styles>
129+
<Style Selector="ListBoxItem">
130+
<Setter Property="Padding" Value="8,0"/>
131+
<Setter Property="MinHeight" Value="26"/>
132+
<Setter Property="CornerRadius" Value="4"/>
133+
</Style>
134+
135+
<Style Selector="ListBox">
136+
<Setter Property="FocusAdorner">
137+
<FocusAdornerTemplate>
138+
<Grid/>
139+
</FocusAdornerTemplate>
140+
</Setter>
141+
</Style>
142+
</ListBox.Styles>
143+
144+
<ListBox.ItemsPanel>
145+
<ItemsPanelTemplate>
146+
<VirtualizingStackPanel Orientation="Vertical"/>
147+
</ItemsPanelTemplate>
148+
</ListBox.ItemsPanel>
149+
150+
<ListBox.ItemTemplate>
151+
<DataTemplate DataType="m:Submodule">
152+
<Grid ColumnDefinitions="Auto,6,*" Background="Transparent" Tapped="OnItemTapped">
153+
<Path Grid.Column="0"
154+
Width="12" Height="12"
155+
Data="{StaticResource Icons.Submodule}"
156+
IsHitTestVisible="False"/>
157+
<TextBlock Grid.Column="2"
158+
VerticalAlignment="Center"
159+
Text="{Binding Path}"
160+
IsHitTestVisible="False"/>
161+
</Grid>
162+
</DataTemplate>
163+
</ListBox.ItemTemplate>
164+
</ListBox>
165+
166+
<TextBlock Grid.Row="5"
115167
Margin="6,8,0,4"
116168
Text="{DynamicResource Text.Launcher.OpenRepository}"
117169
FontWeight="Bold"
118170
Foreground="{DynamicResource Brush.FG2}"
119171
IsVisible="{Binding VisibleRepos, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}"/>
120172

121-
<ListBox Grid.Row="4"
173+
<ListBox Grid.Row="6"
122174
x:Name="RepoListBox"
123175
MaxHeight="300"
124176
Margin="4,0"

0 commit comments

Comments
 (0)