diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml
index 011f26c7..fdb1acb8 100644
--- a/src/Resources/Locales/en_US.axaml
+++ b/src/Resources/Locales/en_US.axaml
@@ -512,6 +512,7 @@
Open in Browser
ERROR
NOTICE
+ Open Repositories
Tabs
Workspaces
Merge Branch
diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml
index 88f020e4..76a334b1 100644
--- a/src/Resources/Locales/zh_CN.axaml
+++ b/src/Resources/Locales/zh_CN.axaml
@@ -516,6 +516,7 @@
在浏览器中访问
出错了
系统提示
+ 打开其他仓库
页面列表
工作区列表
合并分支
diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml
index e329f352..185ac79b 100644
--- a/src/Resources/Locales/zh_TW.axaml
+++ b/src/Resources/Locales/zh_TW.axaml
@@ -516,6 +516,7 @@
在瀏覽器中開啟連結
發生錯誤
系統提示
+ 開啟存放庫
頁面列表
工作區列表
合併分支
diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs
index c1155e40..964fa112 100644
--- a/src/ViewModels/Launcher.cs
+++ b/src/ViewModels/Launcher.cs
@@ -43,10 +43,10 @@ namespace SourceGit.ViewModels
}
}
- public IDisposable Switcher
+ public QuickLauncher QuickLauncher
{
- get => _switcher;
- private set => SetProperty(ref _switcher, value);
+ get => _quickLauncher;
+ set => SetProperty(ref _quickLauncher, value);
}
public Launcher(string startupRepo)
@@ -127,17 +127,6 @@ namespace SourceGit.ViewModels
_ignoreIndexChange = false;
}
- public void OpenTabSwitcher()
- {
- Switcher = new LauncherPageSwitcher(this);
- }
-
- public void CancelSwitcher()
- {
- Switcher?.Dispose();
- Switcher = null;
- }
-
public void SwitchWorkspace(Workspace to)
{
if (to == null || to.IsActive)
@@ -492,6 +481,6 @@ namespace SourceGit.ViewModels
private LauncherPage _activePage = null;
private bool _ignoreIndexChange = false;
private string _title = string.Empty;
- private IDisposable _switcher = null;
+ private QuickLauncher _quickLauncher = null;
}
}
diff --git a/src/ViewModels/LauncherPageSwitcher.cs b/src/ViewModels/LauncherPageSwitcher.cs
deleted file mode 100644
index b732ca0e..00000000
--- a/src/ViewModels/LauncherPageSwitcher.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-using System;
-using System.Collections.Generic;
-using CommunityToolkit.Mvvm.ComponentModel;
-
-namespace SourceGit.ViewModels
-{
- public class LauncherPageSwitcher : ObservableObject, IDisposable
- {
- public List VisiblePages
- {
- get => _visiblePages;
- private set => SetProperty(ref _visiblePages, value);
- }
-
- public string SearchFilter
- {
- get => _searchFilter;
- set
- {
- if (SetProperty(ref _searchFilter, value))
- UpdateVisiblePages();
- }
- }
-
- public LauncherPage SelectedPage
- {
- get => _selectedPage;
- set => SetProperty(ref _selectedPage, value);
- }
-
- public LauncherPageSwitcher(Launcher launcher)
- {
- _launcher = launcher;
- UpdateVisiblePages();
- SelectedPage = launcher.ActivePage;
- }
-
- public void ClearFilter()
- {
- SearchFilter = string.Empty;
- }
-
- public void Switch()
- {
- _launcher.ActivePage = _selectedPage ?? _launcher.ActivePage;
- _launcher.CancelSwitcher();
- }
-
- public void Dispose()
- {
- _visiblePages.Clear();
- _selectedPage = null;
- _searchFilter = string.Empty;
- }
-
- private void UpdateVisiblePages()
- {
- var visible = new List();
- if (string.IsNullOrEmpty(_searchFilter))
- {
- visible.AddRange(_launcher.Pages);
- }
- else
- {
- foreach (var page in _launcher.Pages)
- {
- if (page.Node.Name.Contains(_searchFilter, StringComparison.OrdinalIgnoreCase) ||
- (page.Node.IsRepository && page.Node.Id.Contains(_searchFilter, StringComparison.OrdinalIgnoreCase)))
- {
- visible.Add(page);
- }
- }
- }
-
- VisiblePages = visible;
- SelectedPage = visible.Count > 0 ? visible[0] : null;
- }
-
- private Launcher _launcher = null;
- private List _visiblePages = [];
- private string _searchFilter = string.Empty;
- private LauncherPage _selectedPage = null;
- }
-}
diff --git a/src/ViewModels/QuickLauncher.cs b/src/ViewModels/QuickLauncher.cs
new file mode 100644
index 00000000..a665a755
--- /dev/null
+++ b/src/ViewModels/QuickLauncher.cs
@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+using CommunityToolkit.Mvvm.ComponentModel;
+
+namespace SourceGit.ViewModels
+{
+ public class QuickLauncher : ObservableObject
+ {
+ public List VisiblePages
+ {
+ get => _visiblePages;
+ private set => SetProperty(ref _visiblePages, value);
+ }
+
+ public List VisibleRepos
+ {
+ get => _visibleRepos;
+ private set => SetProperty(ref _visibleRepos, value);
+ }
+
+ public string SearchFilter
+ {
+ get => _searchFilter;
+ set
+ {
+ if (SetProperty(ref _searchFilter, value))
+ UpdateVisible();
+ }
+ }
+
+ public LauncherPage SelectedPage
+ {
+ get => _selectedPage;
+ set
+ {
+ if (SetProperty(ref _selectedPage, value) && value != null)
+ SelectedRepo = null;
+ }
+ }
+
+ public RepositoryNode SelectedRepo
+ {
+ get => _selectedRepo;
+ set
+ {
+ if (SetProperty(ref _selectedRepo, value) && value != null)
+ SelectedPage = null;
+ }
+ }
+
+ public QuickLauncher(Launcher launcher)
+ {
+ _launcher = launcher;
+
+ foreach (var page in _launcher.Pages)
+ {
+ if (page.Node.IsRepository)
+ _opened.Add(page.Node.Id);
+ }
+
+ UpdateVisible();
+ }
+
+ public void ClearFilter()
+ {
+ SearchFilter = string.Empty;
+ }
+
+ public void OpenOrSwitchTo()
+ {
+ if (_selectedPage != null)
+ _launcher.ActivePage = _selectedPage;
+ else if (_selectedRepo != null)
+ _launcher.OpenRepositoryInTab(_selectedRepo, null);
+
+ _launcher.QuickLauncher = null;
+ }
+
+ private void UpdateVisible()
+ {
+ var pages = new List();
+ foreach (var page in _launcher.Pages)
+ {
+ if (string.IsNullOrEmpty(_searchFilter) ||
+ page.Node.Name.Contains(_searchFilter, StringComparison.OrdinalIgnoreCase) ||
+ (page.Node.IsRepository && page.Node.Id.Contains(_searchFilter, StringComparison.OrdinalIgnoreCase)))
+ pages.Add(page);
+ }
+
+ var repos = new List();
+ CollectVisibleRepository(repos, Preferences.Instance.RepositoryNodes);
+
+ VisiblePages = pages;
+ VisibleRepos = repos;
+ }
+
+ private void CollectVisibleRepository(List outs, List nodes)
+ {
+ foreach (var node in nodes)
+ {
+ if (!node.IsRepository)
+ {
+ CollectVisibleRepository(outs, node.SubNodes);
+ continue;
+ }
+
+ if (_opened.Contains(node.Id))
+ continue;
+
+ if (string.IsNullOrEmpty(_searchFilter) ||
+ node.Id.Contains(_searchFilter, StringComparison.OrdinalIgnoreCase) ||
+ node.Name.Contains(_searchFilter, StringComparison.OrdinalIgnoreCase))
+ outs.Add(node);
+ }
+ }
+
+ private Launcher _launcher = null;
+ private HashSet _opened = new HashSet();
+ private List _visiblePages = [];
+ private List _visibleRepos = [];
+ private string _searchFilter = string.Empty;
+ private LauncherPage _selectedPage = null;
+ private RepositoryNode _selectedRepo = null;
+ }
+}
diff --git a/src/Views/Launcher.axaml b/src/Views/Launcher.axaml
index c45947b8..85c1b781 100644
--- a/src/Views/Launcher.axaml
+++ b/src/Views/Launcher.axaml
@@ -90,7 +90,7 @@
-