mirror of
https://fastgit.cc/github.com/sourcegit-scm/sourcegit
synced 2026-04-21 05:10:25 +08:00
refactor: rewrite Open Local Repository feature
Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
@@ -594,6 +594,10 @@
|
||||
<x:String x:Key="Text.OpenAppDataDir" xml:space="preserve">Open Data Storage Directory</x:String>
|
||||
<x:String x:Key="Text.OpenFile" xml:space="preserve">Open File</x:String>
|
||||
<x:String x:Key="Text.OpenInExternalMergeTool" xml:space="preserve">Open in External Merge Tool</x:String>
|
||||
<x:String x:Key="Text.OpenLocalRepository" xml:space="preserve">Open Local Repository</x:String>
|
||||
<x:String x:Key="Text.OpenLocalRepository.Bookmark" xml:space="preserve">Bookmark:</x:String>
|
||||
<x:String x:Key="Text.OpenLocalRepository.Group" xml:space="preserve">Group:</x:String>
|
||||
<x:String x:Key="Text.OpenLocalRepository.Path" xml:space="preserve">Folder:</x:String>
|
||||
<x:String x:Key="Text.Optional" xml:space="preserve">Optional.</x:String>
|
||||
<x:String x:Key="Text.PageTabBar.New" xml:space="preserve">Create New Tab</x:String>
|
||||
<x:String x:Key="Text.PageTabBar.Tab.Close" xml:space="preserve">Close Tab</x:String>
|
||||
|
||||
@@ -598,6 +598,10 @@
|
||||
<x:String x:Key="Text.OpenAppDataDir" xml:space="preserve">浏览应用数据目录</x:String>
|
||||
<x:String x:Key="Text.OpenFile" xml:space="preserve">打开文件</x:String>
|
||||
<x:String x:Key="Text.OpenInExternalMergeTool" xml:space="preserve">使用外部对比工具查看</x:String>
|
||||
<x:String x:Key="Text.OpenLocalRepository" xml:space="preserve">打开本地仓库</x:String>
|
||||
<x:String x:Key="Text.OpenLocalRepository.Bookmark" xml:space="preserve">书签 :</x:String>
|
||||
<x:String x:Key="Text.OpenLocalRepository.Group" xml:space="preserve">分组 :</x:String>
|
||||
<x:String x:Key="Text.OpenLocalRepository.Path" xml:space="preserve">仓库位置 :</x:String>
|
||||
<x:String x:Key="Text.Optional" xml:space="preserve">选填。</x:String>
|
||||
<x:String x:Key="Text.PageTabBar.New" xml:space="preserve">新建空白页</x:String>
|
||||
<x:String x:Key="Text.PageTabBar.Tab.Close" xml:space="preserve">关闭标签页</x:String>
|
||||
|
||||
@@ -598,6 +598,10 @@
|
||||
<x:String x:Key="Text.OpenAppDataDir" xml:space="preserve">瀏覽程式資料目錄</x:String>
|
||||
<x:String x:Key="Text.OpenFile" xml:space="preserve">開啟檔案</x:String>
|
||||
<x:String x:Key="Text.OpenInExternalMergeTool" xml:space="preserve">使用外部比對工具檢視</x:String>
|
||||
<x:String x:Key="Text.OpenLocalRepository" xml:space="preserve">開啟本機存放庫</x:String>
|
||||
<x:String x:Key="Text.OpenLocalRepository.Bookmark" xml:space="preserve">書籤:</x:String>
|
||||
<x:String x:Key="Text.OpenLocalRepository.Group" xml:space="preserve">群組:</x:String>
|
||||
<x:String x:Key="Text.OpenLocalRepository.Path" xml:space="preserve">存放庫位置:</x:String>
|
||||
<x:String x:Key="Text.Optional" xml:space="preserve">選填。</x:String>
|
||||
<x:String x:Key="Text.PageTabBar.New" xml:space="preserve">新增分頁</x:String>
|
||||
<x:String x:Key="Text.PageTabBar.Tab.Close" xml:space="preserve">關閉分頁</x:String>
|
||||
|
||||
115
src/ViewModels/OpenLocalRepository.cs
Normal file
115
src/ViewModels/OpenLocalRepository.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class OpenLocalRepository : Popup
|
||||
{
|
||||
[Required(ErrorMessage = "Repository folder is required")]
|
||||
[CustomValidation(typeof(OpenLocalRepository), nameof(ValidateRepoPath))]
|
||||
public string RepoPath
|
||||
{
|
||||
get => _repoPath;
|
||||
set => SetProperty(ref _repoPath, value, true);
|
||||
}
|
||||
|
||||
public List<RepositoryNode> Groups
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public RepositoryNode Group
|
||||
{
|
||||
get => _group;
|
||||
set => SetProperty(ref _group, value);
|
||||
}
|
||||
|
||||
public List<int> Bookmarks
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public int Bookmark
|
||||
{
|
||||
get => _bookmark;
|
||||
set => SetProperty(ref _bookmark, value);
|
||||
}
|
||||
|
||||
public OpenLocalRepository(string pageId, RepositoryNode group)
|
||||
{
|
||||
_pageId = pageId;
|
||||
_group = group;
|
||||
|
||||
Groups = new List<RepositoryNode>();
|
||||
CollectGroups(Groups, Preferences.Instance.RepositoryNodes);
|
||||
if (Groups.Count > 0 && _group == null)
|
||||
Group = Groups[0];
|
||||
|
||||
Bookmarks = new List<int>();
|
||||
for (var i = 0; i < Models.Bookmarks.Brushes.Length; i++)
|
||||
Bookmarks.Add(i);
|
||||
}
|
||||
|
||||
public static ValidationResult ValidateRepoPath(string folder, ValidationContext _)
|
||||
{
|
||||
if (!Directory.Exists(folder))
|
||||
return new ValidationResult("Given path can NOT be found");
|
||||
return ValidationResult.Success;
|
||||
}
|
||||
|
||||
public override async Task<bool> Sure()
|
||||
{
|
||||
var isBare = await new Commands.IsBareRepository(_repoPath).GetResultAsync();
|
||||
var repoRoot = _repoPath;
|
||||
if (!isBare)
|
||||
{
|
||||
var test = await new Commands.QueryRepositoryRootPath(_repoPath).GetResultAsync();
|
||||
if (test.IsSuccess && !string.IsNullOrWhiteSpace(test.StdOut))
|
||||
{
|
||||
repoRoot = test.StdOut.Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
var launcher = App.GetLauncher();
|
||||
foreach (var page in launcher.Pages)
|
||||
{
|
||||
if (page.Node.Id.Equals(_pageId, StringComparison.Ordinal))
|
||||
{
|
||||
page.Popup = new Init(page.Node.Id, _repoPath, _group, test.StdErr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(repoRoot, _group, true);
|
||||
node.Bookmark = _bookmark;
|
||||
await node.UpdateStatusAsync(false, null);
|
||||
Welcome.Instance.Refresh();
|
||||
node.Open();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CollectGroups(List<RepositoryNode> outs, List<RepositoryNode> collections)
|
||||
{
|
||||
foreach (var node in collections)
|
||||
{
|
||||
if (!node.IsRepository)
|
||||
{
|
||||
outs.Add(node);
|
||||
CollectGroups(outs, node.SubNodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string _pageId = string.Empty;
|
||||
private string _repoPath = string.Empty;
|
||||
private RepositoryNode _group = null;
|
||||
private int _bookmark = 0;
|
||||
}
|
||||
}
|
||||
@@ -128,19 +128,6 @@ namespace SourceGit.ViewModels
|
||||
return rs.StdOut.Trim();
|
||||
}
|
||||
|
||||
public void InitRepository(string path, RepositoryNode parent, string reason)
|
||||
{
|
||||
if (!Preferences.Instance.IsGitConfigured())
|
||||
{
|
||||
Models.Notification.Send(null, App.Text("NotConfigured"), true);
|
||||
return;
|
||||
}
|
||||
|
||||
var activePage = App.GetLauncher().ActivePage;
|
||||
if (activePage != null && activePage.CanCreatePopup())
|
||||
activePage.Popup = new Init(activePage.Node.Id, path, parent, reason);
|
||||
}
|
||||
|
||||
public async Task AddRepositoryAsync(string path, RepositoryNode parent, bool moveNode, bool open)
|
||||
{
|
||||
var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(path, parent, moveNode);
|
||||
@@ -163,6 +150,19 @@ namespace SourceGit.ViewModels
|
||||
activePage.Popup = new Clone(activePage.Node.Id);
|
||||
}
|
||||
|
||||
public void OpenLocalRepository()
|
||||
{
|
||||
if (!Preferences.Instance.IsGitConfigured())
|
||||
{
|
||||
Models.Notification.Send(null, App.Text("NotConfigured"), true);
|
||||
return;
|
||||
}
|
||||
|
||||
var activePage = App.GetLauncher().ActivePage;
|
||||
if (activePage != null && activePage.CanCreatePopup())
|
||||
activePage.Popup = new OpenLocalRepository(activePage.Node.Id, null);
|
||||
}
|
||||
|
||||
public void OpenTerminal()
|
||||
{
|
||||
if (!Preferences.Instance.IsGitConfigured())
|
||||
|
||||
77
src/Views/OpenLocalRepository.axaml
Normal file
77
src/Views/OpenLocalRepository.axaml
Normal file
@@ -0,0 +1,77 @@
|
||||
<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: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.OpenLocalRepository"
|
||||
x:DataType="vm:OpenLocalRepository">
|
||||
<StackPanel Orientation="Vertical" Margin="8,0,0,0">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path Width="16" Height="16"
|
||||
Margin="0,2,0,0"
|
||||
Data="{StaticResource Icons.Folder.Open}"/>
|
||||
|
||||
<TextBlock FontSize="18"
|
||||
Margin="8,0,0,0"
|
||||
Classes="bold"
|
||||
Text="{DynamicResource Text.OpenLocalRepository}"/>
|
||||
</StackPanel>
|
||||
|
||||
<Grid Margin="8,16,0,0" RowDefinitions="32,32,32" ColumnDefinitions="Auto,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.OpenLocalRepository.Path}"/>
|
||||
<TextBox Grid.Row="0" Grid.Column="1"
|
||||
Height="28"
|
||||
CornerRadius="3"
|
||||
Text="{Binding RepoPath, Mode=TwoWay}">
|
||||
<TextBox.InnerRightContent>
|
||||
<Button Classes="icon_button" Width="28" Height="28" Margin="4,0,0,0" Click="OnSelectRepositoryFolder">
|
||||
<Path Data="{StaticResource Icons.Folder.Open}" Fill="{DynamicResource Brush.FG1}"/>
|
||||
</Button>
|
||||
</TextBox.InnerRightContent>
|
||||
</TextBox>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.OpenLocalRepository.Group}"/>
|
||||
<ComboBox Grid.Row="1" Grid.Column="1"
|
||||
Height="28" Padding="8,0"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding Groups}"
|
||||
SelectedItem="{Binding Group, Mode=TwoWay}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate DataType="vm:RepositoryNode">
|
||||
<TextBlock Text="{Binding Name, Mode=OneWay}"/>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.OpenLocalRepository.Bookmark}"/>
|
||||
<ComboBox Grid.Row="2" Grid.Column="1"
|
||||
Height="28" Padding="8,0"
|
||||
VerticalAlignment="Center"
|
||||
ItemsSource="{Binding Bookmarks}"
|
||||
SelectedItem="{Binding Bookmark, Mode=TwoWay}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Height="20">
|
||||
<Path Width="12" Height="12"
|
||||
Fill="{Binding Converter={x:Static c:IntConverters.ToBookmarkBrush}}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Data="{StaticResource Icons.Bookmark}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
56
src/Views/OpenLocalRepository.axaml.cs
Normal file
56
src/Views/OpenLocalRepository.axaml.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class OpenLocalRepository : UserControl
|
||||
{
|
||||
public OpenLocalRepository()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void OnSelectRepositoryFolder(object _1, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is not ViewModels.OpenLocalRepository vm)
|
||||
return;
|
||||
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel == null)
|
||||
return;
|
||||
|
||||
var preference = ViewModels.Preferences.Instance;
|
||||
var workspace = preference.GetActiveWorkspace();
|
||||
var initDir = workspace.DefaultCloneDir;
|
||||
if (string.IsNullOrEmpty(initDir) || !Directory.Exists(initDir))
|
||||
initDir = preference.GitDefaultCloneDir;
|
||||
|
||||
var options = new FolderPickerOpenOptions() { AllowMultiple = false };
|
||||
if (Directory.Exists(initDir))
|
||||
{
|
||||
var folder = await topLevel.StorageProvider.TryGetFolderFromPathAsync(initDir);
|
||||
options.SuggestedStartLocation = folder;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var selected = await topLevel.StorageProvider.OpenFolderPickerAsync(options);
|
||||
if (selected.Count == 1)
|
||||
{
|
||||
var folder = selected[0];
|
||||
vm.RepoPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString();
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Models.Notification.Send(null, $"Failed to open repository: {exception.Message}", true);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
<Path Width="16" Height="16" Data="{StaticResource Icons.Clone}" Margin="0,4,0,0"/>
|
||||
</Button>
|
||||
|
||||
<Button Classes="icon_button" Width="32" Click="OpenLocalRepository" ToolTip.Tip="{DynamicResource Text.Welcome.OpenOrInit}">
|
||||
<Button Classes="icon_button" Width="32" Command="{Binding OpenLocalRepository}" ToolTip.Tip="{DynamicResource Text.Welcome.OpenOrInit}">
|
||||
<Path Width="14" Height="14" Data="{StaticResource Icons.Folder.Open}" Margin="0,2,0,0"/>
|
||||
</Button>
|
||||
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
@@ -13,56 +8,5 @@ namespace SourceGit.Views
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void OpenLocalRepository(object _1, RoutedEventArgs e)
|
||||
{
|
||||
var activePage = App.GetLauncher().ActivePage;
|
||||
if (activePage == null || !activePage.CanCreatePopup())
|
||||
return;
|
||||
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel == null)
|
||||
return;
|
||||
|
||||
var preference = ViewModels.Preferences.Instance;
|
||||
var workspace = preference.GetActiveWorkspace();
|
||||
var initDir = workspace.DefaultCloneDir;
|
||||
if (string.IsNullOrEmpty(initDir) || !Directory.Exists(initDir))
|
||||
initDir = preference.GitDefaultCloneDir;
|
||||
|
||||
var options = new FolderPickerOpenOptions() { AllowMultiple = false };
|
||||
if (Directory.Exists(initDir))
|
||||
{
|
||||
var folder = await topLevel.StorageProvider.TryGetFolderFromPathAsync(initDir);
|
||||
options.SuggestedStartLocation = folder;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var selected = await topLevel.StorageProvider.OpenFolderPickerAsync(options);
|
||||
if (selected.Count == 1)
|
||||
{
|
||||
var folder = selected[0];
|
||||
var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString();
|
||||
var repoPath = await ViewModels.Welcome.Instance.GetRepositoryRootAsync(folderPath);
|
||||
if (!string.IsNullOrEmpty(repoPath))
|
||||
{
|
||||
await ViewModels.Welcome.Instance.AddRepositoryAsync(repoPath, null, false, true);
|
||||
ViewModels.Welcome.Instance.Refresh();
|
||||
}
|
||||
else if (Directory.Exists(folderPath))
|
||||
{
|
||||
var test = await new Commands.QueryRepositoryRootPath(folderPath).GetResultAsync();
|
||||
ViewModels.Welcome.Instance.InitRepository(folderPath, null, test.StdErr);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Models.Notification.Send(null, $"Failed to open repository: {exception.Message}", true);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user