From 4593894d08f49f056066c12e632620e097bb9b32 Mon Sep 17 00:00:00 2001 From: Torben Kohlmeier Date: Wed, 26 Feb 2025 08:38:54 +0100 Subject: [PATCH] focus to be selected package --- .../SoftwarePages/AbstractPackagesPage.xaml | 9 +- .../AbstractPackagesPage.xaml.cs | 99 ++++++++++++++++--- 2 files changed, 89 insertions(+), 19 deletions(-) diff --git a/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml b/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml index a44affa94..197dce2c5 100644 --- a/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml +++ b/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml @@ -12,8 +12,7 @@ mc:Ignorable="d" Name="ABSTRACT_PAGE" NavigationCacheMode="Required" - xmlns:animations="using:CommunityToolkit.WinUI.Animations" xmlns:pkgClasses="using:UniGetUI.PackageEngine.PackageClasses" - CharacterReceived="{x:Bind PackageList_CharacterReceived}"> + xmlns:animations="using:CommunityToolkit.WinUI.Animations" xmlns:pkgClasses="using:UniGetUI.PackageEngine.PackageClasses"> @@ -504,7 +503,8 @@ Package="{x:Bind Package}" Wrapper="{x:Bind Self}" RightTapped="PackageItemContainer_RightTapped" DoubleTapped="PackageItemContainer_DoubleTapped" - KeyUp="PackageItemContainer_KeyUp"> + KeyUp="PackageItemContainer_KeyUp" + PreviewKeyDown="PackageItemContainer_PreviewKeyDown"> @@ -907,7 +907,8 @@ + CanBeScrollAnchor="False" + CharacterReceived="{x:Bind PackageList_CharacterReceived}"> diff --git a/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs b/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs index c85d969fe..bb1798803 100644 --- a/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs +++ b/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs @@ -13,9 +13,11 @@ using UniGetUI.PackageEngine.PackageLoader; using Windows.System; using Windows.UI.Core; +using CommunityToolkit.WinUI; using UniGetUI.Interface.Pages; using UniGetUI.Interface.Telemetry; using UniGetUI.Pages.DialogPages; +using DispatcherQueuePriority = Microsoft.UI.Dispatching.DispatcherQueuePriority; // To learn more about WinUI, the WinUI project structure, // and more about our project templates, see: http://aka.ms/winui-project-info. @@ -480,14 +482,61 @@ protected async Task LoadPackages(ReloadReason reason) Loader_PackagesChanged(this, EventArgs.Empty); } - private void SelectAndScrollTo(int index) + private void SelectAndScrollTo(int index, bool focus) { + if (index < 0 || index >= FilteredPackages.Count) + return; + PackageList.Select(index); - PackageList.ScrollView?.ScrollTo(0, Math.Max(0, (index - 3) * 39), new ScrollingScrollOptions - ( - ScrollingAnimationMode.Disabled, - ScrollingSnapPointsMode.Ignore - )); + + if (PackageList.ScrollView?.VerticalOffset > index * 39) + { + PackageList.ScrollView.ScrollTo(0, index * 39, new ScrollingScrollOptions( + ScrollingAnimationMode.Disabled, + ScrollingSnapPointsMode.Ignore + )); + } + else if (PackageList.ScrollView?.VerticalOffset + PackageList.ScrollView?.ViewportHeight < (index + 1) * 39) + { + PackageList.ScrollView?.ScrollTo(0, (index + 1) * 39 - PackageList.ScrollView.ViewportHeight, new ScrollingScrollOptions( + ScrollingAnimationMode.Disabled, + ScrollingSnapPointsMode.Ignore + )); + } + + if (focus) + Focus(FilteredPackages[index].Package); + } + + private void Focus(IPackage packageToFocus, int retryCount = 0) + { + if (retryCount > 20) + return; + + DispatcherQueue.TryEnqueue( + DispatcherQueuePriority.Low, + () => + { + PackageItemContainer? containerToFocus = PackageList.FindDescendant(c => c.Package?.Equals(packageToFocus) == true); + if (containerToFocus == null) + { + Focus(packageToFocus, ++retryCount); + return; + } + + if (!containerToFocus.IsSelected) + { + PackageItemContainer? selectedContainer = PackageList.FindDescendant(c => c.IsSelected); + if (selectedContainer?.Package?.Equals(packageToFocus) == true) + containerToFocus = selectedContainer; + else + { + Focus(packageToFocus, ++retryCount); + return; + } + } + containerToFocus.Focus(FocusState.Keyboard); + }); } public void PackageList_CharacterReceived(object sender, CharacterReceivedRoutedEventArgs e) @@ -514,7 +563,7 @@ public void PackageList_CharacterReceived(object sender, CharacterReceivedRouted { if (FilteredPackages[i].Package.Name.ToLower().StartsWith(TypeQuery)) { - SelectAndScrollTo(i); + SelectAndScrollTo(i, true); SelectedPackage = true; break; } @@ -566,11 +615,11 @@ public void PackageList_CharacterReceived(object sender, CharacterReceivedRouted } } - SelectAndScrollTo(FirstIdx + (IndexOffset % (LastIdx - FirstIdx + 1))); + SelectAndScrollTo(FirstIdx + (IndexOffset % (LastIdx - FirstIdx + 1)), true); } else if (QueryIndex > -1) { - SelectAndScrollTo(QueryIndex); + SelectAndScrollTo(QueryIndex, true); } } } @@ -696,12 +745,7 @@ public void FilterPackages() { if (FilteredPackages[i].Package.Equals(previousSelection.Package)) { - PackageList.Select(i); - PackageList.ScrollView?.ScrollTo(0, Math.Max(0, (i - 3) * 39), new ScrollingScrollOptions - ( - ScrollingAnimationMode.Disabled, - ScrollingSnapPointsMode.Ignore - )); + SelectAndScrollTo(i, false); break; } } @@ -887,6 +931,7 @@ private void PackageItemContainer_RightTapped(object sender, RightTappedRoutedEv if (sender is PackageItemContainer container && container.Package is not null) { PackageList.Select(container.Wrapper.Index); + container.Focus(FocusState.Keyboard); WhenShowingContextMenu(container.Package); } } @@ -896,6 +941,7 @@ private void PackageItemContainer_DoubleTapped(object sender, DoubleTappedRouted if (sender is PackageItemContainer container && container.Package is not null) { PackageList.Select(container.Wrapper.Index); + container.Focus(FocusState.Keyboard); TEL_InstallReferral referral = TEL_InstallReferral.ALREADY_INSTALLED; if (PAGE_NAME == "Bundles") referral = TEL_InstallReferral.FROM_BUNDLE; @@ -1069,5 +1115,28 @@ public void OnLeave() Visibility = Visibility.Collapsed; IsEnabled = false; } + + private void PackageItemContainer_PreviewKeyDown(object sender, KeyRoutedEventArgs e) + { + if (e.Key is not (VirtualKey.Up or VirtualKey.Down or VirtualKey.Home or VirtualKey.End) || + sender is not PackageItemContainer packageItemContainer) + { + return; + } + + int index = FilteredPackages.IndexOf(packageItemContainer.Wrapper); + switch (e.Key) + { + case VirtualKey.Up when index > 0: + SelectAndScrollTo(index - 1, true); break; + case VirtualKey.Down when index < FilteredPackages.Count - 1: + SelectAndScrollTo(index + 1, true); break; + case VirtualKey.Home when index > 0: + SelectAndScrollTo(0, true); break; + case VirtualKey.End when index < FilteredPackages.Count - 1: + SelectAndScrollTo(FilteredPackages.Count - 1, true); break; + } + e.Handled = true; + } } }