Skip to content

Commit db8e534

Browse files
committed
refactor: rewrite & redesign the ux for AddWorktree popup (#205)
1 parent a260c89 commit db8e534

File tree

5 files changed

+98
-52
lines changed

5 files changed

+98
-52
lines changed

src/Resources/Locales/en_US.axaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• Source code can be found at </x:String>
99
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">Opensource &amp; Free Git GUI Client</x:String>
1010
<x:String x:Key="Text.AddWorktree" xml:space="preserve">Add Worktree</x:String>
11+
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">What to Checkout:</x:String>
12+
<x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">Existing Branch</x:String>
13+
<x:String x:Key="Text.AddWorktree.WhatToCheckout.CreateNew" xml:space="preserve">Create New Branch</x:String>
1114
<x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">Location:</x:String>
1215
<x:String x:Key="Text.AddWorktree.Location.Placeholder" xml:space="preserve">Path for this worktree. Relative path is supported.</x:String>
1316
<x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">Branch Name:</x:String>

src/Resources/Locales/zh_CN.axaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@
1111
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• 项目源代码地址 </x:String>
1212
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">开源免费的Git客户端</x:String>
1313
<x:String x:Key="Text.AddWorktree" xml:space="preserve">新增工作树</x:String>
14+
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">检出分支方式 :</x:String>
15+
<x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">已有分支</x:String>
16+
<x:String x:Key="Text.AddWorktree.WhatToCheckout.CreateNew" xml:space="preserve">创建新分支</x:String>
1417
<x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">工作树路径 :</x:String>
1518
<x:String x:Key="Text.AddWorktree.Location.Placeholder" xml:space="preserve">填写该工作树的路径。支持相对路径。</x:String>
16-
<x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">自定义分支名 :</x:String>
19+
<x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">分支名 :</x:String>
1720
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">选填。默认使用目标文件夹名称。</x:String>
1821
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">跟踪分支</x:String>
1922
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">设置上游跟踪分支</x:String>

src/Resources/Locales/zh_TW.axaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@
1111
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• 專案原始碼地址 </x:String>
1212
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">開源免費的Git客戶端</x:String>
1313
<x:String x:Key="Text.AddWorktree" xml:space="preserve">新增工作樹</x:String>
14+
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">檢出分支方式 :</x:String>
15+
<x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">已有分支</x:String>
16+
<x:String x:Key="Text.AddWorktree.WhatToCheckout.CreateNew" xml:space="preserve">創建新分支</x:String>
1417
<x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">工作樹路徑 :</x:String>
1518
<x:String x:Key="Text.AddWorktree.Location.Placeholder" xml:space="preserve">填寫該工作樹的路徑。支援相對路徑。</x:String>
16-
<x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">自定义分支名 :</x:String>
19+
<x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">分支名 :</x:String>
1720
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">選填。 預設使用目標資料夾名稱。</x:String>
1821
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">跟蹤分支</x:String>
1922
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">設置上游跟蹤分支</x:String>

src/ViewModels/AddWorktree.cs

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,59 @@
11
using System.Collections.Generic;
22
using System.ComponentModel.DataAnnotations;
33
using System.IO;
4-
using System.Text.RegularExpressions;
54
using System.Threading.Tasks;
65

76
namespace SourceGit.ViewModels
87
{
9-
public partial class AddWorktree : Popup
8+
public class AddWorktree : Popup
109
{
11-
[GeneratedRegex(@"^[\w\-/\.]+$")]
12-
private static partial Regex REG_NAME();
13-
1410
[Required(ErrorMessage = "Worktree path is required!")]
1511
[CustomValidation(typeof(AddWorktree), nameof(ValidateWorktreePath))]
1612
public string Path
1713
{
1814
get => _path;
19-
set => SetProperty(ref _path, value, true);
15+
set => SetProperty(ref _path, value);
2016
}
2117

22-
[CustomValidation(typeof(AddWorktree), nameof(ValidateBranchName))]
23-
public string CustomName
18+
public bool UseExistingBranch
2419
{
25-
get => _customName;
26-
set => SetProperty(ref _customName, value, true);
20+
get => _useExistingBranch;
21+
set
22+
{
23+
if (SetProperty(ref _useExistingBranch, value, true))
24+
{
25+
if (value)
26+
SelectedBranch = LocalBranches.Count > 0 ? LocalBranches[0] : string.Empty;
27+
else
28+
SelectedBranch = string.Empty;
29+
}
30+
}
2731
}
2832

29-
public bool SetTrackingBranch
33+
public List<string> LocalBranches
3034
{
31-
get => _setTrackingBranch;
32-
set => SetProperty(ref _setTrackingBranch, value);
35+
get;
36+
private set;
3337
}
3438

35-
public List<string> TrackingBranches
39+
public List<string> RemoteBranches
3640
{
3741
get;
3842
private set;
3943
}
4044

45+
public string SelectedBranch
46+
{
47+
get => _selectedBranch;
48+
set => SetProperty(ref _selectedBranch, value);
49+
}
50+
51+
public bool SetTrackingBranch
52+
{
53+
get => _setTrackingBranch;
54+
set => SetProperty(ref _setTrackingBranch, value);
55+
}
56+
4157
public string SelectedTrackingBranch
4258
{
4359
get;
@@ -48,15 +64,23 @@ public AddWorktree(Repository repo)
4864
{
4965
_repo = repo;
5066

51-
TrackingBranches = new List<string>();
67+
LocalBranches = new List<string>();
68+
RemoteBranches = new List<string>();
5269
foreach (var branch in repo.Branches)
5370
{
54-
if (!branch.IsLocal)
55-
TrackingBranches.Add($"{branch.Remote}/{branch.Name}");
71+
if (branch.IsLocal)
72+
LocalBranches.Add(branch.Name);
73+
else
74+
RemoteBranches.Add($"{branch.Remote}/{branch.Name}");
5675
}
5776

58-
if (TrackingBranches.Count > 0)
59-
SelectedTrackingBranch = TrackingBranches[0];
77+
if (LocalBranches.Count > 0)
78+
SelectedBranch = LocalBranches[0];
79+
else
80+
SelectedBranch = string.Empty;
81+
82+
if (RemoteBranches.Count > 0)
83+
SelectedTrackingBranch = RemoteBranches[0];
6084
else
6185
SelectedTrackingBranch = string.Empty;
6286

@@ -81,25 +105,6 @@ public static ValidationResult ValidateWorktreePath(string path, ValidationConte
81105
if (folders.Length > 0)
82106
return new ValidationResult("Given path is not empty!!!");
83107
}
84-
85-
return ValidationResult.Success;
86-
}
87-
88-
public static ValidationResult ValidateBranchName(string name, ValidationContext ctx)
89-
{
90-
if (string.IsNullOrEmpty(name))
91-
return ValidationResult.Success;
92-
93-
var creator = ctx.ObjectInstance as AddWorktree;
94-
if (creator == null)
95-
return new ValidationResult("Missing runtime context to create branch!");
96-
97-
foreach (var b in creator._repo.Branches)
98-
{
99-
var test = b.IsLocal ? b.Name : $"{b.Remote}/{b.Name}";
100-
if (test == name)
101-
return new ValidationResult("A branch with same name already exists!");
102-
}
103108

104109
return ValidationResult.Success;
105110
}
@@ -113,15 +118,16 @@ public override Task<bool> Sure()
113118

114119
return Task.Run(() =>
115120
{
116-
var succ = new Commands.Worktree(_repo.FullPath).Add(_path, _customName, tracking, SetProgressDescription);
121+
var succ = new Commands.Worktree(_repo.FullPath).Add(_path, _selectedBranch, tracking, SetProgressDescription);
117122
CallUIThread(() => _repo.SetWatcherEnabled(true));
118123
return succ;
119124
});
120125
}
121126

122127
private Repository _repo = null;
123128
private string _path = string.Empty;
124-
private string _customName = string.Empty;
129+
private bool _useExistingBranch = true;
130+
private string _selectedBranch = string.Empty;
125131
private bool _setTrackingBranch = false;
126132
}
127133
}

src/Views/AddWorktree.axaml

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<TextBlock FontSize="18"
1414
Classes="bold"
1515
Text="{DynamicResource Text.AddWorktree}"/>
16-
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,Auto" ColumnDefinitions="120,*">
16+
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,Auto,32" ColumnDefinitions="150,*">
1717
<TextBlock Grid.Row="0" Grid.Column="0"
1818
HorizontalAlignment="Right" VerticalAlignment="Center"
1919
Margin="0,0,8,0"
@@ -30,20 +30,47 @@
3030
</Button>
3131
</TextBox.InnerRightContent>
3232
</TextBox>
33-
33+
3434
<TextBlock Grid.Row="1" Grid.Column="0"
35+
HorizontalAlignment="Right" VerticalAlignment="Center"
36+
Margin="0,0,8,0"
37+
Text="{DynamicResource Text.AddWorktree.WhatToCheckout}"/>
38+
<StackPanel Grid.Row="1" Grid.Column="1" Height="32" Orientation="Horizontal">
39+
<RadioButton Content="{DynamicResource Text.AddWorktree.WhatToCheckout.Existing}"
40+
GroupName="LocalChanges"
41+
IsChecked="{Binding UseExistingBranch, Mode=TwoWay}" />
42+
<RadioButton Content="{DynamicResource Text.AddWorktree.WhatToCheckout.CreateNew}"
43+
GroupName="LocalChanges"
44+
Margin="8,0,0,0" />
45+
</StackPanel>
46+
47+
<TextBlock Grid.Row="2" Grid.Column="0"
3548
HorizontalAlignment="Right" VerticalAlignment="Center"
3649
Margin="0,0,8,0"
3750
Text="{DynamicResource Text.AddWorktree.Name}"/>
38-
<TextBox Grid.Row="1" Grid.Column="1"
51+
<ComboBox Grid.Row="2" Grid.Column="1"
52+
Height="28" Padding="8,0"
53+
VerticalAlignment="Center" HorizontalAlignment="Stretch"
54+
ItemsSource="{Binding LocalBranches}"
55+
SelectedItem="{Binding SelectedBranch, Mode=TwoWay}"
56+
IsEnabled="{Binding UseExistingBranch, Mode=OneWay}"
57+
IsVisible="{Binding UseExistingBranch, Mode=OneWay}">
58+
<ComboBox.ItemTemplate>
59+
<DataTemplate>
60+
<StackPanel Orientation="Horizontal" Height="20" VerticalAlignment="Center">
61+
<Path Margin="0,0,8,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG1}" Data="{StaticResource Icons.Branch}"/>
62+
<TextBlock Text="{Binding}"/>
63+
</StackPanel>
64+
</DataTemplate>
65+
</ComboBox.ItemTemplate>
66+
</ComboBox>
67+
<TextBox Grid.Row="2" Grid.Column="1"
3968
Height="28"
4069
CornerRadius="3"
41-
Text="{Binding CustomName, Mode=TwoWay}"
42-
Watermark="{DynamicResource Text.AddWorktree.Name.Placeholder}"/>
43-
44-
<CheckBox Grid.Row="2" Grid.Column="1"
45-
Content="{DynamicResource Text.AddWorktree.Tracking.Toggle}"
46-
IsChecked="{Binding SetTrackingBranch, Mode=TwoWay}"/>
70+
Text="{Binding SelectedBranch, Mode=TwoWay}"
71+
Watermark="{DynamicResource Text.AddWorktree.Name.Placeholder}"
72+
IsEnabled="{Binding !UseExistingBranch, Mode=OneWay}"
73+
IsVisible="{Binding !UseExistingBranch, Mode=OneWay}"/>
4774

4875
<Border Grid.Row="3" Grid.Column="0"
4976
Height="32"
@@ -55,7 +82,7 @@
5582
<ComboBox Grid.Row="3" Grid.Column="1"
5683
Height="28" Padding="8,0"
5784
VerticalAlignment="Center" HorizontalAlignment="Stretch"
58-
ItemsSource="{Binding TrackingBranches}"
85+
ItemsSource="{Binding RemoteBranches}"
5986
SelectedItem="{Binding SelectedTrackingBranch, Mode=TwoWay}"
6087
IsVisible="{Binding SetTrackingBranch, Mode=OneWay}">
6188
<ComboBox.ItemTemplate>
@@ -67,6 +94,10 @@
6794
</DataTemplate>
6895
</ComboBox.ItemTemplate>
6996
</ComboBox>
97+
98+
<CheckBox Grid.Row="4" Grid.Column="1"
99+
Content="{DynamicResource Text.AddWorktree.Tracking.Toggle}"
100+
IsChecked="{Binding SetTrackingBranch, Mode=TwoWay}"/>
70101
</Grid>
71102
</StackPanel>
72103
</UserControl>

0 commit comments

Comments
 (0)