refactor: drag & drop folders on repository tree (#1611)

- Allows to drag-drop multiple folders to repository tree
- Drag & drop folder to repository tree will not open repository directly

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo
2025-07-23 21:15:26 +08:00
parent 9629a339dd
commit 731e5a722a
4 changed files with 66 additions and 34 deletions

View File

@@ -68,7 +68,7 @@ namespace SourceGit.ViewModels
set;
} = [];
public void OpenOrInit()
public void Open()
{
if (IsRepository)
{
@@ -77,7 +77,7 @@ namespace SourceGit.ViewModels
}
foreach (var subNode in SubNodes)
subNode.OpenOrInit();
subNode.Open();
}
public void Edit()

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Avalonia.Collections;
using CommunityToolkit.Mvvm.ComponentModel;
@@ -81,35 +82,32 @@ namespace SourceGit.ViewModels
}
}
public void OpenOrInitRepository(string path, RepositoryNode parent, bool bMoveExistedNode)
public async Task<string> GetRepositoryRootAsync(string path)
{
if (!Directory.Exists(path))
if (!Preferences.Instance.IsGitConfigured())
{
if (File.Exists(path))
path = Path.GetDirectoryName(path);
App.RaiseException(string.Empty, App.Text("NotConfigured"));
return null;
}
var root = path;
if (!Directory.Exists(root))
{
if (File.Exists(root))
root = Path.GetDirectoryName(root);
else
return;
return null;
}
var isBare = new Commands.IsBareRepository(path).GetResultAsync().Result;
var repoRoot = path;
if (!isBare)
{
var test = new Commands.QueryRepositoryRootPath(path).GetResultAsync().Result;
if (!test.IsSuccess || string.IsNullOrEmpty(test.StdOut))
{
InitRepository(path, parent, test.StdErr);
return;
}
var isBare = await new Commands.IsBareRepository(root).GetResultAsync();
if (isBare)
return root;
repoRoot = test.StdOut.Trim();
}
var rs = await new Commands.QueryRepositoryRootPath(root).GetResultAsync();
if (!rs.IsSuccess || string.IsNullOrWhiteSpace(rs.StdOut))
return null;
var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(repoRoot, parent, bMoveExistedNode);
Refresh();
var launcher = App.GetLauncher();
launcher?.OpenRepositoryInTab(node, launcher.ActivePage);
return rs.StdOut.Trim();
}
public void InitRepository(string path, RepositoryNode parent, string reason)
@@ -125,6 +123,13 @@ namespace SourceGit.ViewModels
activePage.Popup = new Init(activePage.Node.Id, path, parent, reason);
}
public void AddRepository(string path, RepositoryNode parent, bool moveNode, bool open)
{
var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(path, parent, moveNode);
if (open)
node.Open();
}
public void Clone()
{
if (!Preferences.Instance.IsGitConfigured())

View File

@@ -1,5 +1,4 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
@@ -121,7 +120,7 @@ namespace SourceGit.Views
openAll.Icon = App.CreateMenuIcon("Icons.Folder.Open");
openAll.Click += (_, e) =>
{
node.OpenOrInit();
node.Open();
e.Handled = true;
};
@@ -136,7 +135,7 @@ namespace SourceGit.Views
open.Icon = App.CreateMenuIcon("Icons.Folder.Open");
open.Click += (_, e) =>
{
node.OpenOrInit();
node.Open();
e.Handled = true;
};
@@ -273,7 +272,7 @@ namespace SourceGit.Views
}
}
private void DropOnTreeView(object sender, DragEventArgs e)
private async void DropOnTreeView(object sender, DragEventArgs e)
{
if (e.Data.Contains("MovedRepositoryTreeNode") && e.Data.Get("MovedRepositoryTreeNode") is ViewModels.RepositoryNode moved)
{
@@ -287,11 +286,20 @@ namespace SourceGit.Views
var items = e.Data.GetFiles();
if (items != null)
{
var refresh = false;
foreach (var item in items)
{
ViewModels.Welcome.Instance.OpenOrInitRepository(item.Path.LocalPath, null, true);
break;
var path = await ViewModels.Welcome.Instance.GetRepositoryRootAsync(item.Path.LocalPath);
if (!string.IsNullOrEmpty(path))
{
ViewModels.Welcome.Instance.AddRepository(path, null, true, false);
refresh = true;
}
}
if (refresh)
ViewModels.Welcome.Instance.Refresh();
}
}
@@ -313,7 +321,7 @@ namespace SourceGit.Views
}
}
private void DropOnTreeNode(object sender, DragEventArgs e)
private async void DropOnTreeNode(object sender, DragEventArgs e)
{
if (sender is not Grid grid)
return;
@@ -342,11 +350,20 @@ namespace SourceGit.Views
var items = e.Data.GetFiles();
if (items != null)
{
var refresh = false;
foreach (var item in items)
{
ViewModels.Welcome.Instance.OpenOrInitRepository(item.Path.LocalPath, to, true);
break;
var path = await ViewModels.Welcome.Instance.GetRepositoryRootAsync(item.Path.LocalPath);
if (!string.IsNullOrEmpty(path))
{
ViewModels.Welcome.Instance.AddRepository(path, to, true, false);
refresh = true;
}
}
if (refresh)
ViewModels.Welcome.Instance.Refresh();
}
}

View File

@@ -44,7 +44,17 @@ namespace SourceGit.Views
{
var folder = selected[0];
var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString();
ViewModels.Welcome.Instance.OpenOrInitRepository(folderPath, null, false);
var repoPath = await ViewModels.Welcome.Instance.GetRepositoryRootAsync(folderPath);
if (!string.IsNullOrEmpty(repoPath))
{
ViewModels.Welcome.Instance.AddRepository(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)