mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-11-01 13:13:21 -07:00
refactor: rewrite & redesign the ux for AddWorktree
popup (#205)
This commit is contained in:
parent
a260c89c0d
commit
db8e534a0a
5 changed files with 100 additions and 54 deletions
|
@ -8,6 +8,9 @@
|
||||||
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• Source code can be found at </x:String>
|
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• Source code can be found at </x:String>
|
||||||
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">Opensource & Free Git GUI Client</x:String>
|
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">Opensource & Free Git GUI Client</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree" xml:space="preserve">Add Worktree</x:String>
|
<x:String x:Key="Text.AddWorktree" xml:space="preserve">Add Worktree</x:String>
|
||||||
|
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">What to Checkout:</x:String>
|
||||||
|
<x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">Existing Branch</x:String>
|
||||||
|
<x:String x:Key="Text.AddWorktree.WhatToCheckout.CreateNew" xml:space="preserve">Create New Branch</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">Location:</x:String>
|
<x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">Location:</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Location.Placeholder" xml:space="preserve">Path for this worktree. Relative path is supported.</x:String>
|
<x:String x:Key="Text.AddWorktree.Location.Placeholder" xml:space="preserve">Path for this worktree. Relative path is supported.</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">Branch Name:</x:String>
|
<x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">Branch Name:</x:String>
|
||||||
|
|
|
@ -11,9 +11,12 @@
|
||||||
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• 项目源代码地址 </x:String>
|
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• 项目源代码地址 </x:String>
|
||||||
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">开源免费的Git客户端</x:String>
|
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">开源免费的Git客户端</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree" xml:space="preserve">新增工作树</x:String>
|
<x:String x:Key="Text.AddWorktree" xml:space="preserve">新增工作树</x:String>
|
||||||
|
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">检出分支方式 :</x:String>
|
||||||
|
<x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">已有分支</x:String>
|
||||||
|
<x:String x:Key="Text.AddWorktree.WhatToCheckout.CreateNew" xml:space="preserve">创建新分支</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">工作树路径 :</x:String>
|
<x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">工作树路径 :</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Location.Placeholder" xml:space="preserve">填写该工作树的路径。支持相对路径。</x:String>
|
<x:String x:Key="Text.AddWorktree.Location.Placeholder" xml:space="preserve">填写该工作树的路径。支持相对路径。</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">自定义分支名 :</x:String>
|
<x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">分支名 :</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">选填。默认使用目标文件夹名称。</x:String>
|
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">选填。默认使用目标文件夹名称。</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">跟踪分支</x:String>
|
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">跟踪分支</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">设置上游跟踪分支</x:String>
|
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">设置上游跟踪分支</x:String>
|
||||||
|
|
|
@ -11,9 +11,12 @@
|
||||||
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• 專案原始碼地址 </x:String>
|
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• 專案原始碼地址 </x:String>
|
||||||
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">開源免費的Git客戶端</x:String>
|
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">開源免費的Git客戶端</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree" xml:space="preserve">新增工作樹</x:String>
|
<x:String x:Key="Text.AddWorktree" xml:space="preserve">新增工作樹</x:String>
|
||||||
|
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">檢出分支方式 :</x:String>
|
||||||
|
<x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">已有分支</x:String>
|
||||||
|
<x:String x:Key="Text.AddWorktree.WhatToCheckout.CreateNew" xml:space="preserve">創建新分支</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">工作樹路徑 :</x:String>
|
<x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">工作樹路徑 :</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Location.Placeholder" xml:space="preserve">填寫該工作樹的路徑。支援相對路徑。</x:String>
|
<x:String x:Key="Text.AddWorktree.Location.Placeholder" xml:space="preserve">填寫該工作樹的路徑。支援相對路徑。</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">自定义分支名 :</x:String>
|
<x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">分支名 :</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">選填。 預設使用目標資料夾名稱。</x:String>
|
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">選填。 預設使用目標資料夾名稱。</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">跟蹤分支</x:String>
|
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">跟蹤分支</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">設置上游跟蹤分支</x:String>
|
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">設置上游跟蹤分支</x:String>
|
||||||
|
|
|
@ -1,29 +1,51 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace SourceGit.ViewModels
|
namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
public partial class AddWorktree : Popup
|
public class AddWorktree : Popup
|
||||||
{
|
{
|
||||||
[GeneratedRegex(@"^[\w\-/\.]+$")]
|
|
||||||
private static partial Regex REG_NAME();
|
|
||||||
|
|
||||||
[Required(ErrorMessage = "Worktree path is required!")]
|
[Required(ErrorMessage = "Worktree path is required!")]
|
||||||
[CustomValidation(typeof(AddWorktree), nameof(ValidateWorktreePath))]
|
[CustomValidation(typeof(AddWorktree), nameof(ValidateWorktreePath))]
|
||||||
public string Path
|
public string Path
|
||||||
{
|
{
|
||||||
get => _path;
|
get => _path;
|
||||||
set => SetProperty(ref _path, value, true);
|
set => SetProperty(ref _path, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[CustomValidation(typeof(AddWorktree), nameof(ValidateBranchName))]
|
public bool UseExistingBranch
|
||||||
public string CustomName
|
|
||||||
{
|
{
|
||||||
get => _customName;
|
get => _useExistingBranch;
|
||||||
set => SetProperty(ref _customName, value, true);
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref _useExistingBranch, value, true))
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
SelectedBranch = LocalBranches.Count > 0 ? LocalBranches[0] : string.Empty;
|
||||||
|
else
|
||||||
|
SelectedBranch = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> LocalBranches
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> RemoteBranches
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SelectedBranch
|
||||||
|
{
|
||||||
|
get => _selectedBranch;
|
||||||
|
set => SetProperty(ref _selectedBranch, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SetTrackingBranch
|
public bool SetTrackingBranch
|
||||||
|
@ -32,12 +54,6 @@ namespace SourceGit.ViewModels
|
||||||
set => SetProperty(ref _setTrackingBranch, value);
|
set => SetProperty(ref _setTrackingBranch, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> TrackingBranches
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
private set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string SelectedTrackingBranch
|
public string SelectedTrackingBranch
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
|
@ -48,15 +64,23 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
_repo = repo;
|
_repo = repo;
|
||||||
|
|
||||||
TrackingBranches = new List<string>();
|
LocalBranches = new List<string>();
|
||||||
|
RemoteBranches = new List<string>();
|
||||||
foreach (var branch in repo.Branches)
|
foreach (var branch in repo.Branches)
|
||||||
{
|
{
|
||||||
if (!branch.IsLocal)
|
if (branch.IsLocal)
|
||||||
TrackingBranches.Add($"{branch.Remote}/{branch.Name}");
|
LocalBranches.Add(branch.Name);
|
||||||
|
else
|
||||||
|
RemoteBranches.Add($"{branch.Remote}/{branch.Name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TrackingBranches.Count > 0)
|
if (LocalBranches.Count > 0)
|
||||||
SelectedTrackingBranch = TrackingBranches[0];
|
SelectedBranch = LocalBranches[0];
|
||||||
|
else
|
||||||
|
SelectedBranch = string.Empty;
|
||||||
|
|
||||||
|
if (RemoteBranches.Count > 0)
|
||||||
|
SelectedTrackingBranch = RemoteBranches[0];
|
||||||
else
|
else
|
||||||
SelectedTrackingBranch = string.Empty;
|
SelectedTrackingBranch = string.Empty;
|
||||||
|
|
||||||
|
@ -81,25 +105,6 @@ namespace SourceGit.ViewModels
|
||||||
if (folders.Length > 0)
|
if (folders.Length > 0)
|
||||||
return new ValidationResult("Given path is not empty!!!");
|
return new ValidationResult("Given path is not empty!!!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ValidationResult.Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ValidationResult ValidateBranchName(string name, ValidationContext ctx)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(name))
|
|
||||||
return ValidationResult.Success;
|
|
||||||
|
|
||||||
var creator = ctx.ObjectInstance as AddWorktree;
|
|
||||||
if (creator == null)
|
|
||||||
return new ValidationResult("Missing runtime context to create branch!");
|
|
||||||
|
|
||||||
foreach (var b in creator._repo.Branches)
|
|
||||||
{
|
|
||||||
var test = b.IsLocal ? b.Name : $"{b.Remote}/{b.Name}";
|
|
||||||
if (test == name)
|
|
||||||
return new ValidationResult("A branch with same name already exists!");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ValidationResult.Success;
|
return ValidationResult.Success;
|
||||||
}
|
}
|
||||||
|
@ -113,7 +118,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
return Task.Run(() =>
|
return Task.Run(() =>
|
||||||
{
|
{
|
||||||
var succ = new Commands.Worktree(_repo.FullPath).Add(_path, _customName, tracking, SetProgressDescription);
|
var succ = new Commands.Worktree(_repo.FullPath).Add(_path, _selectedBranch, tracking, SetProgressDescription);
|
||||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||||
return succ;
|
return succ;
|
||||||
});
|
});
|
||||||
|
@ -121,7 +126,8 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
private Repository _repo = null;
|
private Repository _repo = null;
|
||||||
private string _path = string.Empty;
|
private string _path = string.Empty;
|
||||||
private string _customName = string.Empty;
|
private bool _useExistingBranch = true;
|
||||||
|
private string _selectedBranch = string.Empty;
|
||||||
private bool _setTrackingBranch = false;
|
private bool _setTrackingBranch = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<TextBlock FontSize="18"
|
<TextBlock FontSize="18"
|
||||||
Classes="bold"
|
Classes="bold"
|
||||||
Text="{DynamicResource Text.AddWorktree}"/>
|
Text="{DynamicResource Text.AddWorktree}"/>
|
||||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,Auto" ColumnDefinitions="120,*">
|
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,Auto,32" ColumnDefinitions="150,*">
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
|
@ -30,20 +30,47 @@
|
||||||
</Button>
|
</Button>
|
||||||
</TextBox.InnerRightContent>
|
</TextBox.InnerRightContent>
|
||||||
</TextBox>
|
</TextBox>
|
||||||
|
|
||||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||||
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
|
Margin="0,0,8,0"
|
||||||
|
Text="{DynamicResource Text.AddWorktree.WhatToCheckout}"/>
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="1" Height="32" Orientation="Horizontal">
|
||||||
|
<RadioButton Content="{DynamicResource Text.AddWorktree.WhatToCheckout.Existing}"
|
||||||
|
GroupName="LocalChanges"
|
||||||
|
IsChecked="{Binding UseExistingBranch, Mode=TwoWay}" />
|
||||||
|
<RadioButton Content="{DynamicResource Text.AddWorktree.WhatToCheckout.CreateNew}"
|
||||||
|
GroupName="LocalChanges"
|
||||||
|
Margin="8,0,0,0" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
Text="{DynamicResource Text.AddWorktree.Name}"/>
|
Text="{DynamicResource Text.AddWorktree.Name}"/>
|
||||||
<TextBox Grid.Row="1" Grid.Column="1"
|
<ComboBox Grid.Row="2" Grid.Column="1"
|
||||||
|
Height="28" Padding="8,0"
|
||||||
|
VerticalAlignment="Center" HorizontalAlignment="Stretch"
|
||||||
|
ItemsSource="{Binding LocalBranches}"
|
||||||
|
SelectedItem="{Binding SelectedBranch, Mode=TwoWay}"
|
||||||
|
IsEnabled="{Binding UseExistingBranch, Mode=OneWay}"
|
||||||
|
IsVisible="{Binding UseExistingBranch, Mode=OneWay}">
|
||||||
|
<ComboBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<StackPanel Orientation="Horizontal" Height="20" VerticalAlignment="Center">
|
||||||
|
<Path Margin="0,0,8,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG1}" Data="{StaticResource Icons.Branch}"/>
|
||||||
|
<TextBlock Text="{Binding}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ComboBox.ItemTemplate>
|
||||||
|
</ComboBox>
|
||||||
|
<TextBox Grid.Row="2" Grid.Column="1"
|
||||||
Height="28"
|
Height="28"
|
||||||
CornerRadius="3"
|
CornerRadius="3"
|
||||||
Text="{Binding CustomName, Mode=TwoWay}"
|
Text="{Binding SelectedBranch, Mode=TwoWay}"
|
||||||
Watermark="{DynamicResource Text.AddWorktree.Name.Placeholder}"/>
|
Watermark="{DynamicResource Text.AddWorktree.Name.Placeholder}"
|
||||||
|
IsEnabled="{Binding !UseExistingBranch, Mode=OneWay}"
|
||||||
<CheckBox Grid.Row="2" Grid.Column="1"
|
IsVisible="{Binding !UseExistingBranch, Mode=OneWay}"/>
|
||||||
Content="{DynamicResource Text.AddWorktree.Tracking.Toggle}"
|
|
||||||
IsChecked="{Binding SetTrackingBranch, Mode=TwoWay}"/>
|
|
||||||
|
|
||||||
<Border Grid.Row="3" Grid.Column="0"
|
<Border Grid.Row="3" Grid.Column="0"
|
||||||
Height="32"
|
Height="32"
|
||||||
|
@ -55,7 +82,7 @@
|
||||||
<ComboBox Grid.Row="3" Grid.Column="1"
|
<ComboBox Grid.Row="3" Grid.Column="1"
|
||||||
Height="28" Padding="8,0"
|
Height="28" Padding="8,0"
|
||||||
VerticalAlignment="Center" HorizontalAlignment="Stretch"
|
VerticalAlignment="Center" HorizontalAlignment="Stretch"
|
||||||
ItemsSource="{Binding TrackingBranches}"
|
ItemsSource="{Binding RemoteBranches}"
|
||||||
SelectedItem="{Binding SelectedTrackingBranch, Mode=TwoWay}"
|
SelectedItem="{Binding SelectedTrackingBranch, Mode=TwoWay}"
|
||||||
IsVisible="{Binding SetTrackingBranch, Mode=OneWay}">
|
IsVisible="{Binding SetTrackingBranch, Mode=OneWay}">
|
||||||
<ComboBox.ItemTemplate>
|
<ComboBox.ItemTemplate>
|
||||||
|
@ -67,6 +94,10 @@
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ComboBox.ItemTemplate>
|
</ComboBox.ItemTemplate>
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
|
|
||||||
|
<CheckBox Grid.Row="4" Grid.Column="1"
|
||||||
|
Content="{DynamicResource Text.AddWorktree.Tracking.Toggle}"
|
||||||
|
IsChecked="{Binding SetTrackingBranch, Mode=TwoWay}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|
Loading…
Reference in a new issue