diff --git a/TRANSLATION.md b/TRANSLATION.md
index c7b37e8c..aee0e2a0 100644
--- a/TRANSLATION.md
+++ b/TRANSLATION.md
@@ -13,10 +13,10 @@ This document shows the translation status of each locale file in the repository
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
-- Text.Hotkeys.Global.OpenWorkspaces
-- Text.Hotkeys.Global.OpenWorkspaceAtIndex
+- Text.Hotkeys.Global.SwitchWorkspace
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.Repository.ShowSubmodulesAsTree
+- Text.Repository.WorkspaceSwitcher
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
@@ -31,8 +31,8 @@ This document shows the translation status of each locale file in the repository
Missing keys in es_ES.axaml
-- Text.Hotkeys.Global.OpenWorkspaces
-- Text.Hotkeys.Global.OpenWorkspaceAtIndex
+- Text.Hotkeys.Global.SwitchWorkspace
+- Text.Repository.WorkspaceSwitcher
@@ -60,8 +60,7 @@ This document shows the translation status of each locale file in the repository
- Text.ConfirmEmptyCommit.WithLocalChanges
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
-- Text.Hotkeys.Global.OpenWorkspaces
-- Text.Hotkeys.Global.OpenWorkspaceAtIndex
+- Text.Hotkeys.Global.SwitchWorkspace
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.BranchSort
@@ -71,6 +70,7 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.ShowSubmodulesAsTree
- Text.Repository.ViewLogs
- Text.Repository.Visit
+- Text.Repository.WorkspaceSwitcher
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
@@ -94,8 +94,8 @@ This document shows the translation status of each locale file in the repository
Missing keys in it_IT.axaml
-- Text.Hotkeys.Global.OpenWorkspaces
-- Text.Hotkeys.Global.OpenWorkspaceAtIndex
+- Text.Hotkeys.Global.SwitchWorkspace
+- Text.Repository.WorkspaceSwitcher
@@ -123,8 +123,7 @@ This document shows the translation status of each locale file in the repository
- Text.ConfirmEmptyCommit.WithLocalChanges
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
-- Text.Hotkeys.Global.OpenWorkspaces
-- Text.Hotkeys.Global.OpenWorkspaceAtIndex
+- Text.Hotkeys.Global.SwitchWorkspace
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.BranchSort
@@ -136,6 +135,7 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.Tags.OrderByNameDes
- Text.Repository.ViewLogs
- Text.Repository.Visit
+- Text.Repository.WorkspaceSwitcher
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
@@ -207,8 +207,7 @@ This document shows the translation status of each locale file in the repository
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Hotkeys.Global.Clone
-- Text.Hotkeys.Global.OpenWorkspaces
-- Text.Hotkeys.Global.OpenWorkspaceAtIndex
+- Text.Hotkeys.Global.SwitchWorkspace
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.InProgress.CherryPick.Head
- Text.InProgress.Merge.Operating
@@ -246,6 +245,7 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.UseRelativeTimeInHistories
- Text.Repository.ViewLogs
- Text.Repository.Visit
+- Text.Repository.WorkspaceSwitcher
- Text.SetUpstream
- Text.SetUpstream.Local
- Text.SetUpstream.Unset
@@ -279,9 +279,9 @@ This document shows the translation status of each locale file in the repository
Missing keys in ru_RU.axaml
-- Text.Hotkeys.Global.OpenWorkspaces
-- Text.Hotkeys.Global.OpenWorkspaceAtIndex
+- Text.Hotkeys.Global.SwitchWorkspace
- Text.Repository.ShowSubmodulesAsTree
+- Text.Repository.WorkspaceSwitcher
@@ -309,8 +309,7 @@ This document shows the translation status of each locale file in the repository
- Text.ConfirmEmptyCommit.WithLocalChanges
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
-- Text.Hotkeys.Global.OpenWorkspaces
-- Text.Hotkeys.Global.OpenWorkspaceAtIndex
+- Text.Hotkeys.Global.SwitchWorkspace
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.BranchSort
@@ -320,6 +319,7 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.ShowSubmodulesAsTree
- Text.Repository.ViewLogs
- Text.Repository.Visit
+- Text.Repository.WorkspaceSwitcher
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
@@ -358,8 +358,7 @@ This document shows the translation status of each locale file in the repository
- Text.ConfigureWorkspace.Name
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
-- Text.Hotkeys.Global.OpenWorkspaces
-- Text.Hotkeys.Global.OpenWorkspaceAtIndex
+- Text.Hotkeys.Global.SwitchWorkspace
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.BranchSort
@@ -369,6 +368,7 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.ShowSubmodulesAsTree
- Text.Repository.ViewLogs
- Text.Repository.Visit
+- Text.Repository.WorkspaceSwitcher
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
@@ -382,22 +382,6 @@ This document shows the translation status of each locale file in the repository
-### 
+### 
-
-Missing keys in zh_CN.axaml
-
-- Text.Hotkeys.Global.OpenWorkspaces
-- Text.Hotkeys.Global.OpenWorkspaceAtIndex
-
-
-
-### 
-
-
-Missing keys in zh_TW.axaml
-
-- Text.Hotkeys.Global.OpenWorkspaces
-- Text.Hotkeys.Global.OpenWorkspaceAtIndex
-
-
\ No newline at end of file
+### 
\ No newline at end of file
diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml
index 63c9815d..4ce0a1ad 100644
--- a/src/Resources/Locales/en_US.axaml
+++ b/src/Resources/Locales/en_US.axaml
@@ -386,8 +386,7 @@
Go to previous page
Create new page
Open Preferences dialog
- Open Workspaces dialog
- Switch to corresponding workspace
+ Switch active workspace
REPOSITORY
Commit staged changes
Commit and push staged changes
@@ -636,6 +635,7 @@
Use relative time in histories
View Logs
Visit '{0}' in Browser
+ Switch Workspace
WORKTREES
Add Worktree
Prune
diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml
index 56227607..1fd1a610 100644
--- a/src/Resources/Locales/zh_CN.axaml
+++ b/src/Resources/Locales/zh_CN.axaml
@@ -390,6 +390,7 @@
切换到上一个页面
新建页面
打开偏好设置面板
+ 切换工作区
仓库页面快捷键
提交暂存区更改
提交暂存区更改并推送
@@ -638,6 +639,7 @@
在提交列表中使用相对时间
查看命令日志
访问远程仓库 '{0}'
+ 切换工作区
工作树列表
新增工作树
清理
diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml
index 204e1cf7..eca8214c 100644
--- a/src/Resources/Locales/zh_TW.axaml
+++ b/src/Resources/Locales/zh_TW.axaml
@@ -390,6 +390,7 @@
切換到上一個頁面
新增頁面
開啟偏好設定面板
+ 切換工作區
存放庫頁面快速鍵
提交暫存區變更
提交暫存區變更並推送
@@ -638,6 +639,7 @@
在提交列表中使用相對時間
檢視 Git 指令記錄
檢視遠端存放庫 '{0}'
+ 切換工作區
工作區列表
新增工作區
清理
diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs
index 5eaca763..9a54bb32 100644
--- a/src/ViewModels/Launcher.cs
+++ b/src/ViewModels/Launcher.cs
@@ -23,6 +23,12 @@ namespace SourceGit.ViewModels
private set;
}
+ public WorkspaceSwitcher WorkspaceSwitcher
+ {
+ get => _workspaceSwitcher;
+ set => SetProperty(ref _workspaceSwitcher, value);
+ }
+
public Workspace ActiveWorkspace
{
get => _activeWorkspace;
@@ -130,6 +136,79 @@ namespace SourceGit.ViewModels
_ignoreIndexChange = false;
}
+ public void OpenWorkspaceSwitcher()
+ {
+ WorkspaceSwitcher = new WorkspaceSwitcher(this);
+ }
+
+ public void CancelWorkspaceSwitcher()
+ {
+ WorkspaceSwitcher = null;
+ }
+
+ public void SwitchWorkspace(Workspace to)
+ {
+ if (to.IsActive)
+ return;
+
+ foreach (var one in Pages)
+ {
+ if (!one.CanCreatePopup() || one.Data is Repository { IsAutoFetching: true })
+ {
+ App.RaiseException(null, "You have unfinished task(s) in opened pages. Please wait!!!");
+ return;
+ }
+ }
+
+ _ignoreIndexChange = true;
+
+ var pref = Preferences.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();
+ 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);
+ }
+
+ var activeIdx = to.ActiveIdx;
+ if (activeIdx >= 0 && activeIdx < Pages.Count)
+ {
+ ActivePage = Pages[activeIdx];
+ }
+ else
+ {
+ ActivePage = Pages[0];
+ to.ActiveIdx = 0;
+ }
+
+ _ignoreIndexChange = false;
+ Preferences.Instance.Save();
+ GC.Collect();
+ }
+
public void AddNewTab()
{
var page = new LauncherPage();
@@ -463,14 +542,6 @@ namespace SourceGit.ViewModels
return menu;
}
- public void SwitchWorkspace(int idx)
- {
- var pref = Preferences.Instance;
- if (idx >= pref.Workspaces.Count || pref.Workspaces[idx].IsActive) return;
-
- SwitchWorkspace(pref.Workspaces[idx]);
- }
-
private string GetRepositoryGitDir(string repo)
{
var fullpath = Path.Combine(repo, ".git");
@@ -501,66 +572,6 @@ namespace SourceGit.ViewModels
return new Commands.QueryGitDir(repo).Result();
}
-
- private void SwitchWorkspace(Workspace to)
- {
- foreach (var one in Pages)
- {
- if (!one.CanCreatePopup() || one.Data is Repository { IsAutoFetching: true })
- {
- App.RaiseException(null, "You have unfinished task(s) in opened pages. Please wait!!!");
- return;
- }
- }
-
- _ignoreIndexChange = true;
-
- var pref = Preferences.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();
- 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);
- }
-
- var activeIdx = to.ActiveIdx;
- if (activeIdx >= 0 && activeIdx < Pages.Count)
- {
- ActivePage = Pages[activeIdx];
- }
- else
- {
- ActivePage = Pages[0];
- to.ActiveIdx = 0;
- }
-
- _ignoreIndexChange = false;
- Preferences.Instance.Save();
- GC.Collect();
- }
private void CloseRepositoryInTab(LauncherPage page, bool removeFromWorkspace = true)
{
@@ -581,7 +592,7 @@ namespace SourceGit.ViewModels
return;
var workspace = _activeWorkspace.Name;
- if (_activePage is { Data: Repository repo })
+ if (_activePage is { Data: Repository })
{
var node = _activePage.Node;
var name = node.Name;
@@ -607,5 +618,6 @@ namespace SourceGit.ViewModels
private LauncherPage _activePage = null;
private bool _ignoreIndexChange = false;
private string _title = string.Empty;
+ private WorkspaceSwitcher _workspaceSwitcher = null;
}
}
diff --git a/src/ViewModels/WorkspaceSwitcher.cs b/src/ViewModels/WorkspaceSwitcher.cs
new file mode 100644
index 00000000..01d62744
--- /dev/null
+++ b/src/ViewModels/WorkspaceSwitcher.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using CommunityToolkit.Mvvm.ComponentModel;
+
+namespace SourceGit.ViewModels
+{
+ public class WorkspaceSwitcher : ObservableObject
+ {
+ public List VisibleWorkspaces
+ {
+ get => _visibleWorkspaces;
+ private set => SetProperty(ref _visibleWorkspaces, value);
+ }
+
+ public string SearchFilter
+ {
+ get => _searchFilter;
+ set
+ {
+ if (SetProperty(ref _searchFilter, value))
+ UpdateVisibleWorkspaces();
+ }
+ }
+
+ public Workspace SelectedWorkspace
+ {
+ get => _selectedWorkspace;
+ set => SetProperty(ref _selectedWorkspace, value);
+ }
+
+ public WorkspaceSwitcher(Launcher launcher)
+ {
+ _launcher = launcher;
+ UpdateVisibleWorkspaces();
+ }
+
+ public void ClearFilter()
+ {
+ SearchFilter = string.Empty;
+ }
+
+ public void Switch()
+ {
+ if (_selectedWorkspace is { })
+ _launcher.SwitchWorkspace(_selectedWorkspace);
+
+ _launcher.CancelWorkspaceSwitcher();
+ }
+
+ private void UpdateVisibleWorkspaces()
+ {
+ var visible = new List();
+ if (string.IsNullOrEmpty(_searchFilter))
+ {
+ visible.AddRange(Preferences.Instance.Workspaces);
+ }
+ else
+ {
+ foreach (var workspace in Preferences.Instance.Workspaces)
+ {
+ if (workspace.Name.Contains(_searchFilter, StringComparison.OrdinalIgnoreCase))
+ visible.Add(workspace);
+ }
+ }
+
+ VisibleWorkspaces = visible;
+ SelectedWorkspace = visible.Count == 0 ? null : visible[0];
+ }
+
+ private Launcher _launcher = null;
+ private List _visibleWorkspaces = null;
+ private string _searchFilter = string.Empty;
+ private Workspace _selectedWorkspace = null;
+ }
+}
diff --git a/src/Views/Avatar.cs b/src/Views/Avatar.cs
index 87bc7ce3..5dacac69 100644
--- a/src/Views/Avatar.cs
+++ b/src/Views/Avatar.cs
@@ -78,10 +78,10 @@ namespace SourceGit.Views
if (switches[idx])
context.FillRectangle(brush, new Rect(x, y, stepX, stepY));
- if (switches[idx+1])
+ if (switches[idx + 1])
context.FillRectangle(brush, new Rect(x + stepX, y, stepX, stepY));
- if (switches[idx+2])
+ if (switches[idx + 2])
context.FillRectangle(brush, new Rect(x + stepX * 2, y, stepX, stepY));
}
@@ -94,7 +94,7 @@ namespace SourceGit.Views
if (switches[idx])
context.FillRectangle(brush, new Rect(x, y, stepX, stepY));
- if (switches[idx-1])
+ if (switches[idx - 1])
context.FillRectangle(brush, new Rect(x + stepX, y, stepX, stepY));
}
}
diff --git a/src/Views/Hotkeys.axaml b/src/Views/Hotkeys.axaml
index b1d436a4..5d9a6f9f 100644
--- a/src/Views/Hotkeys.axaml
+++ b/src/Views/Hotkeys.axaml
@@ -45,7 +45,7 @@
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Increase}}"
Margin="0,0,0,8"/>
-
+
@@ -70,11 +70,8 @@
-
-
-
-
-
+
+
-
-
diff --git a/src/Views/Launcher.axaml.cs b/src/Views/Launcher.axaml.cs
index f558ff99..02cc4f08 100644
--- a/src/Views/Launcher.axaml.cs
+++ b/src/Views/Launcher.axaml.cs
@@ -100,7 +100,7 @@ namespace SourceGit.Views
if (change.Property == WindowStateProperty)
{
- _lastWindowState = (WindowState)change.OldValue;
+ _lastWindowState = (WindowState)change.OldValue!;
var state = (WindowState)change.NewValue!;
if (!OperatingSystem.IsMacOS() && !UseSystemWindowFrame)
@@ -157,6 +157,12 @@ namespace SourceGit.Views
if (e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control))
{
+ if (e.Key == Key.P)
+ {
+ vm.OpenWorkspaceSwitcher();
+ e.Handled = true;
+ }
+
if (e.Key == Key.W)
{
vm.CloseTab(null);
@@ -248,30 +254,10 @@ namespace SourceGit.Views
}
}
}
- else if (e.KeyModifiers.HasFlag(KeyModifiers.Alt))
- {
- if (e.Key == Key.Space && DataContext is ViewModels.Launcher launcher)
- {
- var menu = launcher.CreateContextForWorkspace();
- var workspacesButton = this.FindControl("WorkspacesButton");
- if (menu != null)
- {
- menu.PlacementTarget = workspacesButton;
- menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
- menu.Open(workspacesButton);
- }
- }
- else
- {
- SwitchToWorkspaceIndex(e.Key);
- }
-
- e.Handled = true;
- return;
- }
else if (e.Key == Key.Escape)
{
vm.ActivePage.CancelPopup();
+ vm.CancelWorkspaceSwitcher();
e.Handled = true;
return;
}
@@ -303,29 +289,6 @@ namespace SourceGit.Views
}
}
- private void SwitchToWorkspaceIndex(Key eKey)
- {
- int newIndex;
- switch (eKey)
- {
- case Key.D1 or Key.NumPad1: newIndex = 0; break;
- case Key.D2 or Key.NumPad2: newIndex = 1; break;
- case Key.D3 or Key.NumPad3: newIndex = 2; break;
- case Key.D4 or Key.NumPad4: newIndex = 3; break;
- case Key.D5 or Key.NumPad5: newIndex = 4; break;
- case Key.D6 or Key.NumPad6: newIndex = 5; break;
- case Key.D7 or Key.NumPad7: newIndex = 6; break;
- case Key.D8 or Key.NumPad8: newIndex = 7; break;
- case Key.D9 or Key.NumPad9: newIndex = 8; break;
- default: return;
- }
-
- if (DataContext is ViewModels.Launcher launcher)
- {
- launcher.SwitchWorkspace(newIndex);
- }
- }
-
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyUp(e);
diff --git a/src/Views/WorkspaceSwitcher.axaml b/src/Views/WorkspaceSwitcher.axaml
new file mode 100644
index 00000000..49fed451
--- /dev/null
+++ b/src/Views/WorkspaceSwitcher.axaml
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Views/WorkspaceSwitcher.axaml.cs b/src/Views/WorkspaceSwitcher.axaml.cs
new file mode 100644
index 00000000..04bdae1a
--- /dev/null
+++ b/src/Views/WorkspaceSwitcher.axaml.cs
@@ -0,0 +1,49 @@
+using Avalonia.Controls;
+using Avalonia.Input;
+
+namespace SourceGit.Views
+{
+ public partial class WorkspaceSwitcher : UserControl
+ {
+ public WorkspaceSwitcher()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnKeyDown(KeyEventArgs e)
+ {
+ base.OnKeyDown(e);
+
+ if (e.Key == Key.Enter && DataContext is ViewModels.WorkspaceSwitcher switcher)
+ {
+ switcher.Switch();
+ e.Handled = true;
+ }
+ }
+
+ private void OnItemDoubleTapped(object sender, TappedEventArgs e)
+ {
+ if (DataContext is ViewModels.WorkspaceSwitcher switcher)
+ {
+ switcher.Switch();
+ e.Handled = true;
+ }
+ }
+
+ private void OnSearchBoxKeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.Key == Key.Down && WorkspaceListBox.ItemCount > 0)
+ {
+ WorkspaceListBox.Focus(NavigationMethod.Directional);
+
+ if (WorkspaceListBox.SelectedIndex < 0)
+ WorkspaceListBox.SelectedIndex = 0;
+ else if (WorkspaceListBox.SelectedIndex < WorkspaceListBox.ItemCount)
+ WorkspaceListBox.SelectedIndex++;
+
+ e.Handled = true;
+ }
+ }
+ }
+}
+