mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-22 20:37:19 -08: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.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.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.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>
|
||||
|
|
|
@ -11,9 +11,12 @@
|
|||
<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.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.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.Tracking" 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.SubTitle" xml:space="preserve">開源免費的Git客戶端</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.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.Tracking" 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.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
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!")]
|
||||
[CustomValidation(typeof(AddWorktree), nameof(ValidateWorktreePath))]
|
||||
public string Path
|
||||
{
|
||||
get => _path;
|
||||
set => SetProperty(ref _path, value, true);
|
||||
set => SetProperty(ref _path, value);
|
||||
}
|
||||
|
||||
[CustomValidation(typeof(AddWorktree), nameof(ValidateBranchName))]
|
||||
public string CustomName
|
||||
public bool UseExistingBranch
|
||||
{
|
||||
get => _customName;
|
||||
set => SetProperty(ref _customName, value, true);
|
||||
get => _useExistingBranch;
|
||||
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
|
||||
|
@ -32,12 +54,6 @@ namespace SourceGit.ViewModels
|
|||
set => SetProperty(ref _setTrackingBranch, value);
|
||||
}
|
||||
|
||||
public List<string> TrackingBranches
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string SelectedTrackingBranch
|
||||
{
|
||||
get;
|
||||
|
@ -48,15 +64,23 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
_repo = repo;
|
||||
|
||||
TrackingBranches = new List<string>();
|
||||
LocalBranches = new List<string>();
|
||||
RemoteBranches = new List<string>();
|
||||
foreach (var branch in repo.Branches)
|
||||
{
|
||||
if (!branch.IsLocal)
|
||||
TrackingBranches.Add($"{branch.Remote}/{branch.Name}");
|
||||
if (branch.IsLocal)
|
||||
LocalBranches.Add(branch.Name);
|
||||
else
|
||||
RemoteBranches.Add($"{branch.Remote}/{branch.Name}");
|
||||
}
|
||||
|
||||
if (TrackingBranches.Count > 0)
|
||||
SelectedTrackingBranch = TrackingBranches[0];
|
||||
if (LocalBranches.Count > 0)
|
||||
SelectedBranch = LocalBranches[0];
|
||||
else
|
||||
SelectedBranch = string.Empty;
|
||||
|
||||
if (RemoteBranches.Count > 0)
|
||||
SelectedTrackingBranch = RemoteBranches[0];
|
||||
else
|
||||
SelectedTrackingBranch = string.Empty;
|
||||
|
||||
|
@ -81,25 +105,6 @@ namespace SourceGit.ViewModels
|
|||
if (folders.Length > 0)
|
||||
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;
|
||||
}
|
||||
|
@ -113,7 +118,7 @@ namespace SourceGit.ViewModels
|
|||
|
||||
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));
|
||||
return succ;
|
||||
});
|
||||
|
@ -121,7 +126,8 @@ namespace SourceGit.ViewModels
|
|||
|
||||
private Repository _repo = null;
|
||||
private string _path = string.Empty;
|
||||
private string _customName = string.Empty;
|
||||
private bool _useExistingBranch = true;
|
||||
private string _selectedBranch = string.Empty;
|
||||
private bool _setTrackingBranch = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<TextBlock FontSize="18"
|
||||
Classes="bold"
|
||||
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"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
|
@ -30,20 +30,47 @@
|
|||
</Button>
|
||||
</TextBox.InnerRightContent>
|
||||
</TextBox>
|
||||
|
||||
|
||||
<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"
|
||||
Margin="0,0,8,0"
|
||||
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"
|
||||
CornerRadius="3"
|
||||
Text="{Binding CustomName, Mode=TwoWay}"
|
||||
Watermark="{DynamicResource Text.AddWorktree.Name.Placeholder}"/>
|
||||
|
||||
<CheckBox Grid.Row="2" Grid.Column="1"
|
||||
Content="{DynamicResource Text.AddWorktree.Tracking.Toggle}"
|
||||
IsChecked="{Binding SetTrackingBranch, Mode=TwoWay}"/>
|
||||
Text="{Binding SelectedBranch, Mode=TwoWay}"
|
||||
Watermark="{DynamicResource Text.AddWorktree.Name.Placeholder}"
|
||||
IsEnabled="{Binding !UseExistingBranch, Mode=OneWay}"
|
||||
IsVisible="{Binding !UseExistingBranch, Mode=OneWay}"/>
|
||||
|
||||
<Border Grid.Row="3" Grid.Column="0"
|
||||
Height="32"
|
||||
|
@ -55,7 +82,7 @@
|
|||
<ComboBox Grid.Row="3" Grid.Column="1"
|
||||
Height="28" Padding="8,0"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding TrackingBranches}"
|
||||
ItemsSource="{Binding RemoteBranches}"
|
||||
SelectedItem="{Binding SelectedTrackingBranch, Mode=TwoWay}"
|
||||
IsVisible="{Binding SetTrackingBranch, Mode=OneWay}">
|
||||
<ComboBox.ItemTemplate>
|
||||
|
@ -67,6 +94,10 @@
|
|||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<CheckBox Grid.Row="4" Grid.Column="1"
|
||||
Content="{DynamicResource Text.AddWorktree.Tracking.Toggle}"
|
||||
IsChecked="{Binding SetTrackingBranch, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
Loading…
Reference in a new issue