mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-05-23 21:24:59 +00:00
feature: workspace support (#445)
This commit is contained in:
parent
acd6171350
commit
ebc112a627
27 changed files with 473 additions and 109 deletions
60
src/ViewModels/ConfigureWorkspace.cs
Normal file
60
src/ViewModels/ConfigureWorkspace.cs
Normal file
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using Avalonia.Collections;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class ConfigureWorkspace : ObservableObject
|
||||
{
|
||||
public AvaloniaList<Workspace> Workspaces
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Workspace Selected
|
||||
{
|
||||
get => _selected;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selected, value))
|
||||
CanDeleteSelected = value != null && !value.IsActive;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanDeleteSelected
|
||||
{
|
||||
get => _canDeleteSelected;
|
||||
private set => SetProperty(ref _canDeleteSelected, value);
|
||||
}
|
||||
|
||||
public ConfigureWorkspace()
|
||||
{
|
||||
Workspaces = new AvaloniaList<Workspace>();
|
||||
Workspaces.AddRange(Preference.Instance.Workspaces);
|
||||
}
|
||||
|
||||
public void Add()
|
||||
{
|
||||
var workspace = new Workspace();
|
||||
workspace.Name = $"Unnamed {DateTime.Now:yyyy-MM-dd HH:mm:ss}";
|
||||
workspace.Color = 4278221015;
|
||||
|
||||
Preference.Instance.Workspaces.Add(workspace);
|
||||
Workspaces.Add(workspace);
|
||||
Selected = workspace;
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
if (_selected == null || _selected.IsActive)
|
||||
return;
|
||||
|
||||
Preference.Instance.Workspaces.Remove(_selected);
|
||||
Workspaces.Remove(_selected);
|
||||
}
|
||||
|
||||
private Workspace _selected = null;
|
||||
private bool _canDeleteSelected = false;
|
||||
}
|
||||
}
|
|
@ -17,6 +17,12 @@ namespace SourceGit.ViewModels
|
|||
private set;
|
||||
}
|
||||
|
||||
public Workspace ActiveWorkspace
|
||||
{
|
||||
get => _activeWorkspace;
|
||||
private set => SetProperty(ref _activeWorkspace, value);
|
||||
}
|
||||
|
||||
public LauncherPage ActivePage
|
||||
{
|
||||
get => _activePage;
|
||||
|
@ -29,11 +35,35 @@ namespace SourceGit.ViewModels
|
|||
|
||||
public Launcher(string startupRepo)
|
||||
{
|
||||
var pref = Preference.Instance;
|
||||
|
||||
Pages = new AvaloniaList<LauncherPage>();
|
||||
ActiveWorkspace = pref.GetActiveWorkspace();
|
||||
AddNewTab();
|
||||
|
||||
var pref = Preference.Instance;
|
||||
if (!string.IsNullOrEmpty(startupRepo))
|
||||
var repos = _activeWorkspace.Repositories.ToArray();
|
||||
foreach (var repo in repos)
|
||||
{
|
||||
var node = pref.FindNode(repo);
|
||||
if (node == null)
|
||||
{
|
||||
node = new RepositoryNode()
|
||||
{
|
||||
Id = repo,
|
||||
Name = Path.GetFileName(repo),
|
||||
Bookmark = 0,
|
||||
IsRepository = true,
|
||||
};
|
||||
}
|
||||
|
||||
OpenRepositoryInTab(node, null);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(startupRepo))
|
||||
{
|
||||
ActivePage = Pages[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
var test = new Commands.QueryRepositoryRootPath(startupRepo).ReadToEnd();
|
||||
if (!test.IsSuccess || string.IsNullOrEmpty(test.StdOut))
|
||||
|
@ -51,53 +81,6 @@ namespace SourceGit.ViewModels
|
|||
Welcome.Instance.Refresh();
|
||||
OpenRepositoryInTab(node, null);
|
||||
}
|
||||
else if (pref.RestoreTabs)
|
||||
{
|
||||
foreach (var id in pref.OpenedTabs)
|
||||
{
|
||||
var node = pref.FindNode(id);
|
||||
if (node == null)
|
||||
{
|
||||
node = new RepositoryNode()
|
||||
{
|
||||
Id = id,
|
||||
Name = Path.GetFileName(id),
|
||||
Bookmark = 0,
|
||||
IsRepository = true,
|
||||
};
|
||||
}
|
||||
|
||||
OpenRepositoryInTab(node, null);
|
||||
}
|
||||
|
||||
var lastActiveIdx = pref.LastActiveTabIdx;
|
||||
if (lastActiveIdx >= 0 && lastActiveIdx < Pages.Count)
|
||||
ActivePage = Pages[lastActiveIdx];
|
||||
}
|
||||
}
|
||||
|
||||
public void Quit()
|
||||
{
|
||||
var pref = Preference.Instance;
|
||||
pref.OpenedTabs.Clear();
|
||||
|
||||
if (pref.RestoreTabs)
|
||||
{
|
||||
foreach (var page in Pages)
|
||||
{
|
||||
if (page.Node.IsRepository)
|
||||
pref.OpenedTabs.Add(page.Node.Id);
|
||||
}
|
||||
}
|
||||
|
||||
pref.LastActiveTabIdx = Pages.IndexOf(ActivePage);
|
||||
pref.Save();
|
||||
|
||||
foreach (var page in Pages)
|
||||
{
|
||||
if (page.Data is Repository repo)
|
||||
repo.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public void AddNewTab()
|
||||
|
@ -247,6 +230,7 @@ namespace SourceGit.ViewModels
|
|||
};
|
||||
|
||||
repo.Open();
|
||||
ActiveWorkspace.AddRepository(repo.FullPath);
|
||||
Models.AutoFetchManager.Instance.AddRepository(repo.FullPath);
|
||||
|
||||
if (page == null)
|
||||
|
@ -294,6 +278,46 @@ namespace SourceGit.ViewModels
|
|||
_activePage.Notifications.Add(notification);
|
||||
}
|
||||
|
||||
public ContextMenu CreateContextForWorkspace()
|
||||
{
|
||||
var pref = Preference.Instance;
|
||||
var menu = new ContextMenu();
|
||||
|
||||
for (var i = 0; i < pref.Workspaces.Count; i++)
|
||||
{
|
||||
var workspace = pref.Workspaces[i];
|
||||
|
||||
var icon = App.CreateMenuIcon(workspace.IsActive ? "Icons.Check" : "Icons.Workspace");
|
||||
icon.Fill = workspace.Brush;
|
||||
|
||||
var item = new MenuItem();
|
||||
item.Header = workspace.Name;
|
||||
item.Icon = icon;
|
||||
item.Click += (_, e) =>
|
||||
{
|
||||
if (!workspace.IsActive)
|
||||
SwitchWorkspace(workspace);
|
||||
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
menu.Items.Add(item);
|
||||
}
|
||||
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
|
||||
var configure = new MenuItem();
|
||||
configure.Header = App.Text("Workspace.Configure");
|
||||
configure.Click += (_, e) =>
|
||||
{
|
||||
App.OpenDialog(new Views.ConfigureWorkspace() { DataContext = new ConfigureWorkspace() });
|
||||
e.Handled = true;
|
||||
};
|
||||
menu.Items.Add(configure);
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
public ContextMenu CreateContextForPageTab(LauncherPage page)
|
||||
{
|
||||
if (page == null)
|
||||
|
@ -369,10 +393,50 @@ namespace SourceGit.ViewModels
|
|||
return menu;
|
||||
}
|
||||
|
||||
private void CloseRepositoryInTab(LauncherPage page)
|
||||
private void SwitchWorkspace(Workspace to)
|
||||
{
|
||||
var pref = Preference.Instance;
|
||||
foreach (var w in pref.Workspaces)
|
||||
w.IsActive = false;
|
||||
|
||||
ActiveWorkspace = to;
|
||||
to.IsActive = true;
|
||||
|
||||
foreach (var one in Pages)
|
||||
CloseRepositoryInTab(one, false);
|
||||
|
||||
Pages.Clear();
|
||||
ActivePage = null;
|
||||
AddNewTab();
|
||||
|
||||
var repos = to.Repositories.ToArray();
|
||||
foreach (var repo in repos)
|
||||
{
|
||||
var node = pref.FindNode(repo);
|
||||
if (node == null)
|
||||
{
|
||||
node = new RepositoryNode()
|
||||
{
|
||||
Id = repo,
|
||||
Name = Path.GetFileName(repo),
|
||||
Bookmark = 0,
|
||||
IsRepository = true,
|
||||
};
|
||||
}
|
||||
|
||||
OpenRepositoryInTab(node, null);
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
private void CloseRepositoryInTab(LauncherPage page, bool removeFromWorkspace = true)
|
||||
{
|
||||
if (page.Data is Repository repo)
|
||||
{
|
||||
if (removeFromWorkspace)
|
||||
ActiveWorkspace.Repositories.Remove(repo.FullPath);
|
||||
|
||||
Models.AutoFetchManager.Instance.RemoveRepository(repo.FullPath);
|
||||
repo.Close();
|
||||
}
|
||||
|
@ -380,6 +444,7 @@ namespace SourceGit.ViewModels
|
|||
page.Data = null;
|
||||
}
|
||||
|
||||
private Workspace _activeWorkspace = null;
|
||||
private LauncherPage _activePage = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,9 @@ namespace SourceGit.ViewModels
|
|||
if (!_instance.IsGitConfigured())
|
||||
_instance.GitInstallPath = Native.OS.FindGitExecutable();
|
||||
|
||||
if (_instance.Workspaces.Count == 0)
|
||||
_instance.Workspaces.Add(new Workspace() { Name = "Default", Color = 4278221015 });
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
@ -133,12 +136,6 @@ namespace SourceGit.ViewModels
|
|||
set => SetProperty(ref _subjectGuideLength, value);
|
||||
}
|
||||
|
||||
public bool RestoreTabs
|
||||
{
|
||||
get => _restoreTabs;
|
||||
set => SetProperty(ref _restoreTabs, value);
|
||||
}
|
||||
|
||||
public bool UseFixedTabWidth
|
||||
{
|
||||
get => _useFixedTabWidth;
|
||||
|
@ -304,18 +301,12 @@ namespace SourceGit.ViewModels
|
|||
set;
|
||||
} = [];
|
||||
|
||||
public List<string> OpenedTabs
|
||||
public List<Workspace> Workspaces
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = [];
|
||||
|
||||
public int LastActiveTabIdx
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = 0;
|
||||
|
||||
public double LastCheckUpdateTime
|
||||
{
|
||||
get => _lastCheckUpdateTime;
|
||||
|
@ -343,6 +334,19 @@ namespace SourceGit.ViewModels
|
|||
return true;
|
||||
}
|
||||
|
||||
public Workspace GetActiveWorkspace()
|
||||
{
|
||||
foreach (var w in Workspaces)
|
||||
{
|
||||
if (w.IsActive)
|
||||
return w;
|
||||
}
|
||||
|
||||
var first = Workspaces[0];
|
||||
first.IsActive = true;
|
||||
return first;
|
||||
}
|
||||
|
||||
public void AddNode(RepositoryNode node, RepositoryNode to, bool save)
|
||||
{
|
||||
var collection = to == null ? RepositoryNodes : to.SubNodes;
|
||||
|
@ -492,7 +496,6 @@ namespace SourceGit.ViewModels
|
|||
|
||||
private int _maxHistoryCommits = 20000;
|
||||
private int _subjectGuideLength = 50;
|
||||
private bool _restoreTabs = false;
|
||||
private bool _useFixedTabWidth = true;
|
||||
|
||||
private bool _check4UpdatesOnStartup = true;
|
||||
|
|
58
src/ViewModels/Workspace.cs
Normal file
58
src/ViewModels/Workspace.cs
Normal file
|
@ -0,0 +1,58 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
using Avalonia.Media;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class Workspace : ObservableObject
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set => SetProperty(ref _name, value);
|
||||
}
|
||||
|
||||
public uint Color
|
||||
{
|
||||
get => _color;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _color, value))
|
||||
Brush = new SolidColorBrush(value);
|
||||
}
|
||||
}
|
||||
|
||||
public List<string> Repositories
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = new List<string>();
|
||||
|
||||
public bool IsActive
|
||||
{
|
||||
get => _isActive;
|
||||
set => SetProperty(ref _isActive, value);
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public IBrush Brush
|
||||
{
|
||||
get => _brush;
|
||||
private set => SetProperty(ref _brush, value);
|
||||
}
|
||||
|
||||
public void AddRepository(string repo)
|
||||
{
|
||||
if (!Repositories.Contains(repo))
|
||||
Repositories.Add(repo);
|
||||
}
|
||||
|
||||
private string _name = string.Empty;
|
||||
private uint _color = 0;
|
||||
private IBrush _brush = null;
|
||||
private bool _isActive = false;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue