diff --git a/TRANSLATION.md b/TRANSLATION.md index 1a9d00d1..d810b5b2 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -6,7 +6,7 @@ This document shows the translation status of each locale file in the repository ### ![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen) -### ![de__DE](https://img.shields.io/badge/de__DE-98.23%25-yellow) +### ![de__DE](https://img.shields.io/badge/de__DE-98.48%25-yellow)
Missing keys in de_DE.axaml @@ -14,11 +14,9 @@ This document shows the translation status of each locale file in the repository - Text.GitFlow.FinishWithPush - Text.GitFlow.FinishWithSquash - Text.Hotkeys.Global.SwitchWorkspace -- Text.Hotkeys.Global.SwitchTab - Text.Hotkeys.TextEditor.OpenExternalMergeTool -- Text.Launcher.Workspaces -- Text.Launcher.Pages - Text.Repository.ShowSubmodulesAsTree +- Text.Repository.WorkspaceSwitcher - Text.Submodule.Status - Text.Submodule.Status.Modified - Text.Submodule.Status.NotInited @@ -28,19 +26,17 @@ This document shows the translation status of each locale file in the repository
-### ![es__ES](https://img.shields.io/badge/es__ES-99.49%25-yellow) +### ![es__ES](https://img.shields.io/badge/es__ES-99.75%25-yellow)
Missing keys in es_ES.axaml - Text.Hotkeys.Global.SwitchWorkspace -- Text.Hotkeys.Global.SwitchTab -- Text.Launcher.Workspaces -- Text.Launcher.Pages +- Text.Repository.WorkspaceSwitcher
-### ![fr__FR](https://img.shields.io/badge/fr__FR-94.05%25-yellow) +### ![fr__FR](https://img.shields.io/badge/fr__FR-94.29%25-yellow)
Missing keys in fr_FR.axaml @@ -65,10 +61,7 @@ This document shows the translation status of each locale file in the repository - Text.GitFlow.FinishWithPush - Text.GitFlow.FinishWithSquash - Text.Hotkeys.Global.SwitchWorkspace -- Text.Hotkeys.Global.SwitchTab - Text.Hotkeys.TextEditor.OpenExternalMergeTool -- Text.Launcher.Workspaces -- Text.Launcher.Pages - Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Repository.BranchSort - Text.Repository.BranchSort.ByCommitterDate @@ -77,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 @@ -95,19 +89,17 @@ This document shows the translation status of each locale file in the repository
-### ![it__IT](https://img.shields.io/badge/it__IT-99.49%25-yellow) +### ![it__IT](https://img.shields.io/badge/it__IT-99.75%25-yellow)
Missing keys in it_IT.axaml - Text.Hotkeys.Global.SwitchWorkspace -- Text.Hotkeys.Global.SwitchTab -- Text.Launcher.Workspaces -- Text.Launcher.Pages +- Text.Repository.WorkspaceSwitcher
-### ![ja__JP](https://img.shields.io/badge/ja__JP-93.80%25-yellow) +### ![ja__JP](https://img.shields.io/badge/ja__JP-94.04%25-yellow)
Missing keys in ja_JP.axaml @@ -132,10 +124,7 @@ This document shows the translation status of each locale file in the repository - Text.GitFlow.FinishWithPush - Text.GitFlow.FinishWithSquash - Text.Hotkeys.Global.SwitchWorkspace -- Text.Hotkeys.Global.SwitchTab - Text.Hotkeys.TextEditor.OpenExternalMergeTool -- Text.Launcher.Workspaces -- Text.Launcher.Pages - Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Repository.BranchSort - Text.Repository.BranchSort.ByCommitterDate @@ -146,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 @@ -164,7 +154,7 @@ This document shows the translation status of each locale file in the repository
-### ![pt__BR](https://img.shields.io/badge/pt__BR-85.57%25-yellow) +### ![pt__BR](https://img.shields.io/badge/pt__BR-85.79%25-yellow)
Missing keys in pt_BR.axaml @@ -218,14 +208,11 @@ This document shows the translation status of each locale file in the repository - Text.GitFlow.FinishWithSquash - Text.Hotkeys.Global.Clone - Text.Hotkeys.Global.SwitchWorkspace -- Text.Hotkeys.Global.SwitchTab - Text.Hotkeys.TextEditor.OpenExternalMergeTool - Text.InProgress.CherryPick.Head - Text.InProgress.Merge.Operating - Text.InProgress.Rebase.StoppedAt - Text.InProgress.Revert.Head -- Text.Launcher.Workspaces -- Text.Launcher.Pages - Text.Merge.Source - Text.MergeMultiple - Text.MergeMultiple.CommitChanges @@ -258,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 @@ -286,17 +274,9 @@ This document shows the translation status of each locale file in the repository
-### ![ru__RU](https://img.shields.io/badge/ru__RU-99.75%25-yellow) +### ![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen) -
-Missing keys in ru_RU.axaml - -- Text.Hotkeys.Global.SwitchTab -- Text.Launcher.Pages - -
- -### ![ta__IN](https://img.shields.io/badge/ta__IN-94.05%25-yellow) +### ![ta__IN](https://img.shields.io/badge/ta__IN-94.29%25-yellow)
Missing keys in ta_IN.axaml @@ -321,10 +301,7 @@ This document shows the translation status of each locale file in the repository - Text.GitFlow.FinishWithPush - Text.GitFlow.FinishWithSquash - Text.Hotkeys.Global.SwitchWorkspace -- Text.Hotkeys.Global.SwitchTab - Text.Hotkeys.TextEditor.OpenExternalMergeTool -- Text.Launcher.Workspaces -- Text.Launcher.Pages - Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Repository.BranchSort - Text.Repository.BranchSort.ByCommitterDate @@ -333,6 +310,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 @@ -351,7 +329,7 @@ This document shows the translation status of each locale file in the repository
-### ![uk__UA](https://img.shields.io/badge/uk__UA-95.19%25-yellow) +### ![uk__UA](https://img.shields.io/badge/uk__UA-95.43%25-yellow)
Missing keys in uk_UA.axaml @@ -372,10 +350,7 @@ This document shows the translation status of each locale file in the repository - Text.GitFlow.FinishWithPush - Text.GitFlow.FinishWithSquash - Text.Hotkeys.Global.SwitchWorkspace -- Text.Hotkeys.Global.SwitchTab - Text.Hotkeys.TextEditor.OpenExternalMergeTool -- Text.Launcher.Workspaces -- Text.Launcher.Pages - Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Repository.BranchSort - Text.Repository.BranchSort.ByCommitterDate @@ -384,6 +359,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 diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index bb259272..4ce0a1ad 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -387,7 +387,6 @@ Create new page Open Preferences dialog Switch active workspace - Switch active page REPOSITORY Commit staged changes Commit and push staged changes @@ -430,8 +429,6 @@ Open in Browser ERROR NOTICE - Workspaces - Pages Merge Branch Into: Merge Option: @@ -638,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/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index 77a7ba4f..1fabffda 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -433,7 +433,6 @@ Открыть в браузере ОШИБКА УВЕДОМЛЕНИЕ - Рабочие места Влить ветку В: Опции слияния: @@ -640,6 +639,7 @@ Использовать относительное время в историях Просмотр журналов Посетить '{0}' в браузере + Переключить рабочее место РАБОЧИЕ КАТАЛОГИ ДОБАВИТЬ РАБОЧИЙ КАТАЛОГ ОБРЕЗАТЬ diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 18569a14..1fd1a610 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -391,7 +391,6 @@ 新建页面 打开偏好设置面板 切换工作区 - 切换显示页面 仓库页面快捷键 提交暂存区更改 提交暂存区更改并推送 @@ -434,8 +433,6 @@ 在浏览器中访问 出错了 系统提示 - 工作区列表 - 页面列表 合并分支 目标分支 : 合并方式 : @@ -642,6 +639,7 @@ 在提交列表中使用相对时间 查看命令日志 访问远程仓库 '{0}' + 切换工作区 工作树列表 新增工作树 清理 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index ded99a14..eca8214c 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -391,7 +391,6 @@ 新增頁面 開啟偏好設定面板 切換工作區 - 切換目前頁面 存放庫頁面快速鍵 提交暫存區變更 提交暫存區變更並推送 @@ -434,8 +433,6 @@ 在瀏覽器中開啟連結 發生錯誤 系統提示 - 工作區列表 - 頁面列表 合併分支 目標分支: 合併方式: @@ -642,6 +639,7 @@ 在提交列表中使用相對時間 檢視 Git 指令記錄 檢視遠端存放庫 '{0}' + 切換工作區 工作區列表 新增工作區 清理 diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index f21d2636..555954d9 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.IO; @@ -387,7 +387,7 @@ namespace SourceGit.ViewModels { var builder = new StringBuilder(); foreach (var c in selected) - builder.AppendLine($"{c.SHA.AsSpan(0, 10)} - {c.Subject}"); + builder.AppendLine($"{c.SHA.Substring(0, 10)} - {c.Subject}"); App.CopyText(builder.ToString()); e.Handled = true; @@ -780,7 +780,7 @@ namespace SourceGit.ViewModels copyInfo.Icon = App.CreateMenuIcon("Icons.Info"); copyInfo.Click += (_, e) => { - App.CopyText($"{commit.SHA.AsSpan(0, 10)} - {commit.Subject}"); + App.CopyText($"{commit.SHA.Substring(0, 10)} - {commit.Subject}"); e.Handled = true; }; diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index 4c0714df..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; @@ -44,12 +50,6 @@ namespace SourceGit.ViewModels } } - public IDisposable Switcher - { - get => _switcher; - private set => SetProperty(ref _switcher, value); - } - public Launcher(string startupRepo) { _ignoreIndexChange = true; @@ -138,23 +138,17 @@ namespace SourceGit.ViewModels public void OpenWorkspaceSwitcher() { - Switcher = new WorkspaceSwitcher(this); + WorkspaceSwitcher = new WorkspaceSwitcher(this); } - public void OpenTabSwitcher() + public void CancelWorkspaceSwitcher() { - Switcher = new LauncherPageSwitcher(this); - } - - public void CancelSwitcher() - { - Switcher?.Dispose(); - Switcher = null; + WorkspaceSwitcher = null; } public void SwitchWorkspace(Workspace to) { - if (to == null || to.IsActive) + if (to.IsActive) return; foreach (var one in Pages) @@ -624,6 +618,6 @@ namespace SourceGit.ViewModels private LauncherPage _activePage = null; private bool _ignoreIndexChange = false; private string _title = string.Empty; - private IDisposable _switcher = null; + private WorkspaceSwitcher _workspaceSwitcher = null; } } diff --git a/src/ViewModels/LauncherPageSwitcher.cs b/src/ViewModels/LauncherPageSwitcher.cs deleted file mode 100644 index 5f53021d..00000000 --- a/src/ViewModels/LauncherPageSwitcher.cs +++ /dev/null @@ -1,83 +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(); - } - - 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/Repository.cs b/src/ViewModels/Repository.cs index a3f63251..d24f6fbf 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -2632,7 +2632,7 @@ namespace SourceGit.ViewModels if (node.Path.Equals(path, StringComparison.Ordinal)) return node; - if (path.StartsWith(node.Path, StringComparison.Ordinal)) + if (path!.StartsWith(node.Path, StringComparison.Ordinal)) { var founded = FindBranchNode(node.Children, path); if (founded != null) diff --git a/src/ViewModels/WorkspaceSwitcher.cs b/src/ViewModels/WorkspaceSwitcher.cs index 7a2da9be..01d62744 100644 --- a/src/ViewModels/WorkspaceSwitcher.cs +++ b/src/ViewModels/WorkspaceSwitcher.cs @@ -4,7 +4,7 @@ using CommunityToolkit.Mvvm.ComponentModel; namespace SourceGit.ViewModels { - public class WorkspaceSwitcher : ObservableObject, IDisposable + public class WorkspaceSwitcher : ObservableObject { public List VisibleWorkspaces { @@ -41,15 +41,10 @@ namespace SourceGit.ViewModels public void Switch() { - _launcher.SwitchWorkspace(_selectedWorkspace); - _launcher.CancelSwitcher(); - } + if (_selectedWorkspace is { }) + _launcher.SwitchWorkspace(_selectedWorkspace); - public void Dispose() - { - _visibleWorkspaces.Clear(); - _selectedWorkspace = null; - _searchFilter = string.Empty; + _launcher.CancelWorkspaceSwitcher(); } private void UpdateVisibleWorkspaces() diff --git a/src/Views/Hotkeys.axaml b/src/Views/Hotkeys.axaml index 5275f264..5d9a6f9f 100644 --- a/src/Views/Hotkeys.axaml +++ b/src/Views/Hotkeys.axaml @@ -45,8 +45,8 @@ FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Increase}}" Margin="0,0,0,8"/> - - + + @@ -55,7 +55,7 @@ - + @@ -70,11 +70,8 @@ - + - - - - - + + IsVisible="{Binding WorkspaceSwitcher, Converter={x:Static ObjectConverters.IsNotNull}}"> - + - - - - diff --git a/src/Views/Launcher.axaml.cs b/src/Views/Launcher.axaml.cs index be4cdf5b..02cc4f08 100644 --- a/src/Views/Launcher.axaml.cs +++ b/src/Views/Launcher.axaml.cs @@ -133,8 +133,8 @@ namespace SourceGit.Views return; } - // Ctrl+, opens preference dialog (macOS use hotkeys in system menu bar) - if (!OperatingSystem.IsMacOS() && e is { KeyModifiers: KeyModifiers.Control, Key: Key.OemComma }) + // Ctrl+Shift+P opens preference dialog (macOS use hotkeys in system menu bar) + if (!OperatingSystem.IsMacOS() && e is { KeyModifiers: (KeyModifiers.Control | KeyModifiers.Shift), Key: Key.P }) { App.ShowWindow(new Preferences(), true); e.Handled = true; @@ -149,7 +149,7 @@ namespace SourceGit.Views } // Ctrl+Q quits the application (macOS use hotkeys in system menu bar) - if (!OperatingSystem.IsMacOS() && e is { KeyModifiers: KeyModifiers.Control, Key: Key.Q }) + if (!OperatingSystem.IsMacOS() && e.KeyModifiers == KeyModifiers.Control && e.Key == Key.Q) { App.Quit(0); return; @@ -157,18 +157,10 @@ namespace SourceGit.Views if (e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control)) { - if (e.KeyModifiers.HasFlag(KeyModifiers.Shift) && e.Key == Key.P) + if (e.Key == Key.P) { vm.OpenWorkspaceSwitcher(); e.Handled = true; - return; - } - - if (e.Key == Key.P) - { - vm.OpenTabSwitcher(); - e.Handled = true; - return; } if (e.Key == Key.W) @@ -265,7 +257,7 @@ namespace SourceGit.Views else if (e.Key == Key.Escape) { vm.ActivePage.CancelPopup(); - vm.CancelSwitcher(); + vm.CancelWorkspaceSwitcher(); e.Handled = true; return; } @@ -322,13 +314,6 @@ namespace SourceGit.Views e.Handled = true; } - private void OnCancelSwitcher(object sender, PointerPressedEventArgs e) - { - if (e.Source == sender) - (DataContext as ViewModels.Launcher)?.CancelSwitcher(); - e.Handled = true; - } - private KeyModifiers _unhandledModifiers = KeyModifiers.None; private WindowState _lastWindowState = WindowState.Normal; } diff --git a/src/Views/LauncherPageSwitcher.axaml.cs b/src/Views/LauncherPageSwitcher.axaml.cs deleted file mode 100644 index 1effb93c..00000000 --- a/src/Views/LauncherPageSwitcher.axaml.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Avalonia.Controls; -using Avalonia.Input; - -namespace SourceGit.Views -{ - public partial class LauncherPageSwitcher : UserControl - { - public LauncherPageSwitcher() - { - InitializeComponent(); - } - - protected override void OnKeyDown(KeyEventArgs e) - { - base.OnKeyDown(e); - - if (e.Key == Key.Enter && DataContext is ViewModels.LauncherPageSwitcher switcher) - { - switcher.Switch(); - e.Handled = true; - } - } - - private void OnItemDoubleTapped(object sender, TappedEventArgs e) - { - if (DataContext is ViewModels.LauncherPageSwitcher switcher) - { - switcher.Switch(); - e.Handled = true; - } - } - - private void OnSearchBoxKeyDown(object sender, KeyEventArgs e) - { - if (e.Key == Key.Down && PagesListBox.ItemCount > 0) - { - PagesListBox.Focus(NavigationMethod.Directional); - - if (PagesListBox.SelectedIndex < 0) - PagesListBox.SelectedIndex = 0; - else if (PagesListBox.SelectedIndex < PagesListBox.ItemCount) - PagesListBox.SelectedIndex++; - - e.Handled = true; - } - } - } -} - diff --git a/src/Views/LauncherTabBar.axaml b/src/Views/LauncherTabBar.axaml index a56da2b0..0376e259 100644 --- a/src/Views/LauncherTabBar.axaml +++ b/src/Views/LauncherTabBar.axaml @@ -40,7 +40,7 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/src/Views/LauncherTabBar.axaml.cs b/src/Views/LauncherTabBar.axaml.cs index 270902bc..12bca91f 100644 --- a/src/Views/LauncherTabBar.axaml.cs +++ b/src/Views/LauncherTabBar.axaml.cs @@ -1,7 +1,6 @@ using System; using Avalonia; -using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; @@ -20,20 +19,6 @@ namespace SourceGit.Views set => SetValue(IsScrollerVisibleProperty, value); } - public static readonly StyledProperty SearchFilterProperty = - AvaloniaProperty.Register(nameof(SearchFilter)); - - public string SearchFilter - { - get => GetValue(SearchFilterProperty); - set => SetValue(SearchFilterProperty, value); - } - - public AvaloniaList SelectablePages - { - get; - } = []; - public LauncherTabBar() { InitializeComponent(); @@ -141,14 +126,6 @@ namespace SourceGit.Views context.DrawGeometry(fill, stroke, geo); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) - { - base.OnPropertyChanged(change); - - if (change.Property == SearchFilterProperty) - UpdateSelectablePages(); - } - private void ScrollTabs(object _, PointerWheelEventArgs e) { if (!e.KeyModifiers.HasFlag(KeyModifiers.Shift)) @@ -271,95 +248,13 @@ namespace SourceGit.Views e.Handled = true; } - private void OnTabsDropdownOpened(object sender, EventArgs e) + private void OnGotoSelectedPage(object sender, LauncherTabSelectedEventArgs e) { - UpdateSelectablePages(); - } + if (DataContext is ViewModels.Launcher vm) + vm.ActivePage = e.Page; - private void OnTabsDropdownClosed(object sender, EventArgs e) - { - SelectablePages.Clear(); - SearchFilter = string.Empty; - } - - private void OnTabsDropdownKeyDown(object sender, KeyEventArgs e) - { - if (e.Key == Key.Escape) - { - PageSelector.Flyout?.Hide(); - e.Handled = true; - } - else if (e.Key == Key.Enter) - { - if (TabsDropdownList.SelectedItem is ViewModels.LauncherPage page && - DataContext is ViewModels.Launcher vm) - { - vm.ActivePage = page; - PageSelector.Flyout?.Hide(); - e.Handled = true; - } - } - } - - private void OnTabsDropdownSearchBoxKeyDown(object sender, KeyEventArgs e) - { - if (e.Key == Key.Down && TabsDropdownList.ItemCount > 0) - { - TabsDropdownList.Focus(NavigationMethod.Directional); - - if (TabsDropdownList.SelectedIndex < 0) - TabsDropdownList.SelectedIndex = 0; - else if (TabsDropdownList.SelectedIndex < TabsDropdownList.ItemCount) - TabsDropdownList.SelectedIndex++; - - e.Handled = true; - } - } - - private void OnTabsDropdownLostFocus(object sender, RoutedEventArgs e) - { - if (sender is Control { IsFocused: false, IsKeyboardFocusWithin: false }) - PageSelector.Flyout?.Hide(); - } - - private void OnClearSearchFilter(object sender, RoutedEventArgs e) - { - SearchFilter = string.Empty; - } - - private void OnTabsDropdownItemDoubleTapped(object sender, TappedEventArgs e) - { - if (sender is Control { DataContext: ViewModels.LauncherPage page } && - DataContext is ViewModels.Launcher vm) - { - vm.ActivePage = page; - PageSelector.Flyout?.Hide(); - e.Handled = true; - } - } - - private void UpdateSelectablePages() - { - if (DataContext is not ViewModels.Launcher vm) - return; - - SelectablePages.Clear(); - - var pages = vm.Pages; - var filter = SearchFilter?.Trim() ?? ""; - if (string.IsNullOrEmpty(filter)) - { - SelectablePages.AddRange(pages); - return; - } - - foreach (var page in pages) - { - var node = page.Node; - if (node.Name.Contains(filter, StringComparison.OrdinalIgnoreCase) || - (node.IsRepository && node.Id.Contains(filter, StringComparison.OrdinalIgnoreCase))) - SelectablePages.Add(page); - } + PageSelector.Flyout?.Hide(); + e.Handled = true; } private bool _pressedTab = false; diff --git a/src/Views/LauncherPageSwitcher.axaml b/src/Views/LauncherTabsSelector.axaml similarity index 70% rename from src/Views/LauncherPageSwitcher.axaml rename to src/Views/LauncherTabsSelector.axaml index 4d785b55..109a2ce7 100644 --- a/src/Views/LauncherPageSwitcher.axaml +++ b/src/Views/LauncherTabsSelector.axaml @@ -3,27 +3,19 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="using:SourceGit.ViewModels" - xmlns:v="using:SourceGit.Views" xmlns:c="using:SourceGit.Converters" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" - x:Class="SourceGit.Views.LauncherPageSwitcher" - x:DataType="vm:LauncherPageSwitcher"> - - - - + + + VerticalContentAlignment="Center"> - + ItemsSource="{Binding #ThisControl.VisiblePages}" + SelectionChanged="OnPageSelectionChanged"> @@ -83,28 +72,30 @@ - + - - diff --git a/src/Views/LauncherTabsSelector.axaml.cs b/src/Views/LauncherTabsSelector.axaml.cs new file mode 100644 index 00000000..61d7a966 --- /dev/null +++ b/src/Views/LauncherTabsSelector.axaml.cs @@ -0,0 +1,120 @@ +using System; + +using Avalonia; +using Avalonia.Collections; +using Avalonia.Controls; +using Avalonia.Interactivity; + +namespace SourceGit.Views +{ + public class LauncherTabSelectedEventArgs : RoutedEventArgs + { + public ViewModels.LauncherPage Page { get; } + + public LauncherTabSelectedEventArgs(ViewModels.LauncherPage page) + { + RoutedEvent = LauncherTabsSelector.PageSelectedEvent; + Page = page; + } + } + + public partial class LauncherTabsSelector : UserControl + { + public static readonly StyledProperty> PagesProperty = + AvaloniaProperty.Register>(nameof(Pages)); + + public AvaloniaList Pages + { + get => GetValue(PagesProperty); + set => SetValue(PagesProperty, value); + } + + public static readonly StyledProperty SearchFilterProperty = + AvaloniaProperty.Register(nameof(SearchFilter)); + + public string SearchFilter + { + get => GetValue(SearchFilterProperty); + set => SetValue(SearchFilterProperty, value); + } + + public static readonly RoutedEvent PageSelectedEvent = + RoutedEvent.Register(nameof(PageSelected), RoutingStrategies.Tunnel | RoutingStrategies.Bubble); + + public event EventHandler PageSelected + { + add { AddHandler(PageSelectedEvent, value); } + remove { RemoveHandler(PageSelectedEvent, value); } + } + + public AvaloniaList VisiblePages + { + get; + private set; + } + + public LauncherTabsSelector() + { + VisiblePages = new AvaloniaList(); + InitializeComponent(); + } + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + + if (change.Property == PagesProperty || change.Property == SearchFilterProperty) + UpdateVisiblePages(); + } + + private void OnClearSearchFilter(object sender, RoutedEventArgs e) + { + SearchFilter = string.Empty; + } + + private void OnPageSelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (sender is ListBox { SelectedItem: ViewModels.LauncherPage page }) + { + _isProcessingSelection = true; + RaiseEvent(new LauncherTabSelectedEventArgs(page)); + _isProcessingSelection = false; + } + + e.Handled = true; + } + + private void UpdateVisiblePages() + { + if (_isProcessingSelection) + return; + + VisiblePages.Clear(); + + if (Pages == null) + return; + + var filter = SearchFilter?.Trim() ?? ""; + if (string.IsNullOrEmpty(filter)) + { + foreach (var p in Pages) + VisiblePages.Add(p); + + return; + } + + foreach (var page in Pages) + { + if (!page.Node.IsRepository) + continue; + + if (page.Node.Name.Contains(filter, StringComparison.OrdinalIgnoreCase) || + page.Node.Id.Contains(filter, StringComparison.OrdinalIgnoreCase)) + VisiblePages.Add(page); + } + } + + private bool _isProcessingSelection = false; + } +} + diff --git a/src/Views/WorkspaceSwitcher.axaml b/src/Views/WorkspaceSwitcher.axaml index 4a324f3e..49fed451 100644 --- a/src/Views/WorkspaceSwitcher.axaml +++ b/src/Views/WorkspaceSwitcher.axaml @@ -7,15 +7,15 @@ mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="SourceGit.Views.WorkspaceSwitcher" x:DataType="vm:WorkspaceSwitcher"> - + + HorizontalAlignment="Center" VerticalAlignment="Top"/> - +