mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-05-30 16:44:59 +00:00
feature: add worktree support (#205)
This commit is contained in:
parent
43af8c49a1
commit
8a8aabede3
23 changed files with 959 additions and 21 deletions
71
src/Views/AddWorktree.axaml
Normal file
71
src/Views/AddWorktree.axaml
Normal file
|
@ -0,0 +1,71 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:m="using:SourceGit.Models"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
xmlns:c="using:SourceGit.Converters"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.AddWorktree"
|
||||
x:DataType="vm:AddWorktree">
|
||||
<StackPanel Orientation="Vertical" Margin="8,0">
|
||||
<TextBlock FontSize="18"
|
||||
Classes="bold"
|
||||
Text="{DynamicResource Text.AddWorktree}"/>
|
||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,Auto" ColumnDefinitions="150,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.AddWorktree.Location}"/>
|
||||
<TextBox Grid.Row="0" Grid.Column="1"
|
||||
x:Name="TxtLocation"
|
||||
Height="28"
|
||||
CornerRadius="3"
|
||||
Text="{Binding FullPath, Mode=TwoWay}">
|
||||
<TextBox.InnerRightContent>
|
||||
<Button Classes="icon_button" Width="28" Height="28" Margin="4,0,0,0" Click="SelectLocation">
|
||||
<Path Data="{StaticResource Icons.Folder.Open}" Fill="{DynamicResource Brush.FG1}"/>
|
||||
</Button>
|
||||
</TextBox.InnerRightContent>
|
||||
</TextBox>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.AddWorktree.Name}"/>
|
||||
<TextBox Grid.Row="1" 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}"/>
|
||||
|
||||
<Border Grid.Row="3" Grid.Column="0"
|
||||
Height="32"
|
||||
IsVisible="{Binding SetTrackingBranch, Mode=OneWay}">
|
||||
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.AddWorktree.Tracking}"/>
|
||||
</Border>
|
||||
<ComboBox Grid.Row="3" Grid.Column="1"
|
||||
Height="28" Padding="8,0"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding TrackingBranches}"
|
||||
SelectedItem="{Binding SelectedTrackingBranch, Mode=TwoWay}"
|
||||
IsVisible="{Binding SetTrackingBranch, 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>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
28
src/Views/AddWorktree.axaml.cs
Normal file
28
src/Views/AddWorktree.axaml.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class AddWorktree : UserControl
|
||||
{
|
||||
public AddWorktree()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void SelectLocation(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var options = new FolderPickerOpenOptions() { AllowMultiple = false };
|
||||
var toplevel = TopLevel.GetTopLevel(this);
|
||||
if (toplevel == null)
|
||||
return;
|
||||
|
||||
var selected = await toplevel.StorageProvider.OpenFolderPickerAsync(options);
|
||||
if (selected.Count == 1)
|
||||
TxtLocation.Text = selected[0].Path.LocalPath;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
41
src/Views/LockWorktree.axaml
Normal file
41
src/Views/LockWorktree.axaml
Normal file
|
@ -0,0 +1,41 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:m="using:SourceGit.Models"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
xmlns:c="using:SourceGit.Converters"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.LockWorktree"
|
||||
x:DataType="vm:LockWorktree">
|
||||
<StackPanel Orientation="Vertical" Margin="8,0,0,0">
|
||||
<TextBlock FontSize="18"
|
||||
Classes="bold"
|
||||
Text="{DynamicResource Text.LockWorktree}"/>
|
||||
<Grid Margin="8,16,0,0" RowDefinitions="32,32" ColumnDefinitions="120,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="8,0"
|
||||
Text="{DynamicResource Text.LockWorktree.Target}"/>
|
||||
<Grid Grid.Row="0" Grid.Column="1" ColumnDefinitions="Auto,*">
|
||||
<Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.Worktree}"/>
|
||||
<TextBlock Grid.Column="1" Classes="monospace" Margin="8,0,0,0" TextTrimming="CharacterEllipsis">
|
||||
<Run Text="{Binding Target.FullPath}"/>
|
||||
<Run Text="{Binding Target.Name}" Foreground="{DynamicResource Brush.FG2}"/>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="8,0"
|
||||
Text="{DynamicResource Text.LockWorktree.Reason}"/>
|
||||
<TextBox Grid.Row="1" Grid.Column="1"
|
||||
Height="26"
|
||||
CornerRadius="3"
|
||||
Text="{Binding Reason, Mode=TwoWay}"
|
||||
Watermark="{DynamicResource Text.LockWorktree.Reason.Placeholder}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
12
src/Views/LockWorktree.axaml.cs
Normal file
12
src/Views/LockWorktree.axaml.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class LockWorktree : UserControl
|
||||
{
|
||||
public LockWorktree()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
15
src/Views/PruneWorktrees.axaml
Normal file
15
src/Views/PruneWorktrees.axaml
Normal file
|
@ -0,0 +1,15 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.PruneWorktrees">
|
||||
<StackPanel Orientation="Vertical" Margin="8,0">
|
||||
<TextBlock FontSize="18"
|
||||
Classes="bold"
|
||||
Text="{DynamicResource Text.PruneWorktrees}"/>
|
||||
<TextBlock Text="{DynamicResource Text.PruneWorktrees.Tip}"
|
||||
Margin="0,16,0,0"
|
||||
HorizontalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</UserControl>
|
12
src/Views/PruneWorktrees.axaml.cs
Normal file
12
src/Views/PruneWorktrees.axaml.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class PruneWorktrees : UserControl
|
||||
{
|
||||
public PruneWorktrees()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
34
src/Views/RemoveWorktree.axaml
Normal file
34
src/Views/RemoveWorktree.axaml
Normal file
|
@ -0,0 +1,34 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:m="using:SourceGit.Models"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
xmlns:c="using:SourceGit.Converters"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.RemoveWorktree"
|
||||
x:DataType="vm:RemoveWorktree">
|
||||
<StackPanel Orientation="Vertical" Margin="8,0,0,0">
|
||||
<TextBlock FontSize="18"
|
||||
Classes="bold"
|
||||
Text="{DynamicResource Text.RemoveWorktree}"/>
|
||||
<Grid Margin="8,16,0,0" RowDefinitions="32,32" ColumnDefinitions="120,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="8,0"
|
||||
Text="{DynamicResource Text.RemoveWorktree.Target}"/>
|
||||
<Grid Grid.Row="0" Grid.Column="1" ColumnDefinitions="Auto,*">
|
||||
<Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.Worktree}"/>
|
||||
<TextBlock Grid.Column="1" Classes="monospace" Margin="8,0,0,0" TextTrimming="CharacterEllipsis">
|
||||
<Run Text="{Binding Target.FullPath}"/>
|
||||
<Run Text="{Binding Target.Name}" Foreground="{DynamicResource Brush.FG2}"/>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
|
||||
<CheckBox Grid.Row="1" Grid.Column="1"
|
||||
Content="{DynamicResource Text.RemoveWorktree.Force}"
|
||||
IsChecked="{Binding Force, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
12
src/Views/RemoveWorktree.axaml.cs
Normal file
12
src/Views/RemoveWorktree.axaml.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class RemoveWorktree : UserControl
|
||||
{
|
||||
public RemoveWorktree()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -119,7 +119,7 @@
|
|||
</Grid>
|
||||
|
||||
<!-- Dashboard -->
|
||||
<Grid Grid.Row="1" Margin="0,0,0,8" RowDefinitions="Auto,Auto,28,Auto,28,*,28,Auto,28,Auto" IsVisible="{Binding !IsSearching}">
|
||||
<Grid Grid.Row="1" Margin="0,0,0,8" RowDefinitions="Auto,Auto,28,Auto,28,*,28,Auto,28,Auto,28,Auto" IsVisible="{Binding !IsSearching}">
|
||||
<!-- Page Switcher for Right Panel -->
|
||||
<Border Grid.Row="0" Margin="8,0,4,0" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}" CornerRadius="6">
|
||||
<Border CornerRadius="6" ClipToBounds="True">
|
||||
|
@ -463,7 +463,7 @@
|
|||
Command="{Binding UpdateSubmodules}"
|
||||
IsVisible="{Binding Submodules, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}"
|
||||
ToolTip.Tip="{DynamicResource Text.Repository.Submodules.Update}">
|
||||
<Path x:Name="iconSubmoduleUpdate" Width="12" Height="12" Data="{StaticResource Icons.Loading}"/>
|
||||
<Path Width="12" Height="12" Data="{StaticResource Icons.Loading}"/>
|
||||
</Button>
|
||||
<Button Grid.Column="3"
|
||||
Classes="icon_button"
|
||||
|
@ -531,6 +531,96 @@
|
|||
</DataGridTemplateColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
<!-- Worktrees -->
|
||||
<ToggleButton Grid.Row="10" Classes="group_expander" IsChecked="{Binding IsWorktreeGroupExpanded, Mode=TwoWay}">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto,Auto">
|
||||
<TextBlock Grid.Column="0" Classes="group_header_label" Margin="0" Text="{DynamicResource Text.Repository.Worktrees}"/>
|
||||
<TextBlock Grid.Column="1" Text="{Binding Worktrees, Converter={x:Static c:ListConverters.ToCount}}" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold"/>
|
||||
<Button Grid.Column="2"
|
||||
Classes="icon_button"
|
||||
Width="14"
|
||||
Margin="8,0"
|
||||
Command="{Binding PruneWorktrees}"
|
||||
IsVisible="{Binding Worktrees, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}"
|
||||
ToolTip.Tip="{DynamicResource Text.Repository.Worktrees.Prune}">
|
||||
<Path x:Name="icon" Width="12" Height="12" Data="{StaticResource Icons.Loading}"/>
|
||||
</Button>
|
||||
<Button Grid.Column="3"
|
||||
Classes="icon_button"
|
||||
Width="14"
|
||||
Margin="0,0,8,0"
|
||||
Command="{Binding AddWorktree}"
|
||||
ToolTip.Tip="{DynamicResource Text.Repository.Worktrees.Add}">
|
||||
<Path Width="12" Height="12" Data="{StaticResource Icons.Worktree.Add}"/>
|
||||
</Button>
|
||||
</Grid>
|
||||
</ToggleButton>
|
||||
<DataGrid Grid.Row="11"
|
||||
MaxHeight="200"
|
||||
Margin="8,0,4,0"
|
||||
Background="Transparent"
|
||||
ItemsSource="{Binding Worktrees}"
|
||||
SelectionMode="Single"
|
||||
CanUserReorderColumns="False"
|
||||
CanUserResizeColumns="False"
|
||||
CanUserSortColumns="False"
|
||||
IsReadOnly="True"
|
||||
HeadersVisibility="None"
|
||||
Focusable="False"
|
||||
RowHeight="26"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
ContextRequested="OnWorktreeContextRequested"
|
||||
DoubleTapped="OnDoubleTappedWorktree"
|
||||
IsVisible="{Binding IsWorktreeGroupExpanded, Mode=OneWay}">
|
||||
<DataGrid.Styles>
|
||||
<Style Selector="DataGridRow">
|
||||
<Setter Property="CornerRadius" Value="4" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="DataGridRow /template/ Border#RowBorder">
|
||||
<Setter Property="ClipToBounds" Value="True" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="DataGridRow:pointerover /template/ Rectangle#BackgroundRectangle">
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.AccentHovered}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="DataGridRow:selected /template/ Rectangle#BackgroundRectangle">
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}" />
|
||||
</Style>
|
||||
</DataGrid.Styles>
|
||||
|
||||
<DataGrid.Columns>
|
||||
<DataGridTemplateColumn Header="ICON">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Path Width="10" Height="10" Margin="8,0,0,0" Data="{StaticResource Icons.Worktree}"/>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
<DataGridTemplateColumn Width="*" Header="FullPath">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Classes="monospace" Margin="8,0,0,0" TextTrimming="CharacterEllipsis">
|
||||
<Run Text="{Binding FullPath}"/>
|
||||
<Run Text="{Binding Name}" Foreground="{DynamicResource Brush.FG2}"/>
|
||||
</TextBlock>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
<DataGridTemplateColumn Header="FullPath">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Path Width="10" Height="10" Margin="4,0,8,0" Data="{StaticResource Icons.Lock}" Fill="{DynamicResource Brush.FG2}" IsVisible="{Binding IsLocked}"/>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</Grid>
|
||||
|
||||
<!-- Commit Search Panel -->
|
||||
|
|
|
@ -315,6 +315,40 @@ namespace SourceGit.Views
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnDoubleTappedSubmodule(object sender, TappedEventArgs e)
|
||||
{
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
var submodule = datagrid.SelectedItem as string;
|
||||
(DataContext as ViewModels.Repository).OpenSubmodule(submodule);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnWorktreeContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
var worktree = datagrid.SelectedItem as Models.Worktree;
|
||||
var menu = repo.CreateContextMenuForWorktree(worktree);
|
||||
datagrid.OpenContextMenu(menu);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnDoubleTappedWorktree(object sender, TappedEventArgs e)
|
||||
{
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
var worktree = datagrid.SelectedItem as Models.Worktree;
|
||||
(DataContext as ViewModels.Repository).OpenWorktree(worktree);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void CollectBranchesFromNode(List<Models.Branch> outs, ViewModels.BranchTreeNode node)
|
||||
{
|
||||
if (node == null || node.IsRemote)
|
||||
|
@ -332,16 +366,5 @@ namespace SourceGit.Views
|
|||
outs.Add(b);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDoubleTappedSubmodule(object sender, TappedEventArgs e)
|
||||
{
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
var submodule = datagrid.SelectedItem as string;
|
||||
(DataContext as ViewModels.Repository).OpenSubmodule(submodule);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue