diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 469ac96b..cea5479a 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -594,6 +594,10 @@ Open Data Storage Directory Open File Open in External Merge Tool + Open Local Repository + Bookmark: + Group: + Folder: Optional. Create New Tab Close Tab diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 9ab93f57..05ac46fb 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -598,6 +598,10 @@ 浏览应用数据目录 打开文件 使用外部对比工具查看 + 打开本地仓库 + 书签 : + 分组 : + 仓库位置 : 选填。 新建空白页 关闭标签页 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index dd35a996..890a7560 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -598,6 +598,10 @@ 瀏覽程式資料目錄 開啟檔案 使用外部比對工具檢視 + 開啟本機存放庫 + 書籤: + 群組: + 存放庫位置: 選填。 新增分頁 關閉分頁 diff --git a/src/ViewModels/OpenLocalRepository.cs b/src/ViewModels/OpenLocalRepository.cs new file mode 100644 index 00000000..18fd9d6a --- /dev/null +++ b/src/ViewModels/OpenLocalRepository.cs @@ -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 Groups + { + get; + } + + public RepositoryNode Group + { + get => _group; + set => SetProperty(ref _group, value); + } + + public List 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(); + CollectGroups(Groups, Preferences.Instance.RepositoryNodes); + if (Groups.Count > 0 && _group == null) + Group = Groups[0]; + + Bookmarks = new List(); + 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 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 outs, List 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; + } +} diff --git a/src/ViewModels/Welcome.cs b/src/ViewModels/Welcome.cs index 66bde74b..49539292 100644 --- a/src/ViewModels/Welcome.cs +++ b/src/ViewModels/Welcome.cs @@ -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()) diff --git a/src/Views/OpenLocalRepository.axaml b/src/Views/OpenLocalRepository.axaml new file mode 100644 index 00000000..45dbfdf4 --- /dev/null +++ b/src/Views/OpenLocalRepository.axaml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Views/OpenLocalRepository.axaml.cs b/src/Views/OpenLocalRepository.axaml.cs new file mode 100644 index 00000000..151662c2 --- /dev/null +++ b/src/Views/OpenLocalRepository.axaml.cs @@ -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; + } + } +} diff --git a/src/Views/WelcomeToolbar.axaml b/src/Views/WelcomeToolbar.axaml index c218058c..0114c3d3 100644 --- a/src/Views/WelcomeToolbar.axaml +++ b/src/Views/WelcomeToolbar.axaml @@ -19,7 +19,7 @@ - diff --git a/src/Views/WelcomeToolbar.axaml.cs b/src/Views/WelcomeToolbar.axaml.cs index d949c095..19894c4a 100644 --- a/src/Views/WelcomeToolbar.axaml.cs +++ b/src/Views/WelcomeToolbar.axaml.cs @@ -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; - } } }