From 1e63647889a789d7fd0e09f9b7147eaf4f491681 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 21 Aug 2026 22:38:52 +0000 Subject: [PATCH 1/2] fix: Explorer-style tile-pane arrows, Page, and Tab (0.8.4-beta1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Up/Down stay in the same visual column (including across date-section headers). PageUp/PageDown move one viewport and keep the same column at the same screen Y. Tab cycles only tree ↔ tile pane and does not change either selection; the ribbon is not a Tab stop. Co-authored-by: Paul Smith --- CHANGELOG.md | 14 + src/Aperture.App/Aperture.App.csproj | 2 +- src/Aperture.App/LibraryPaneFocus.cs | 9 + src/Aperture.App/MainWindow.xaml | 27 +- src/Aperture.App/MainWindow.xaml.cs | 367 +++++++++++++++++- src/Aperture.App/TileSpatialNavigation.cs | 198 ++++++++++ src/Aperture.App/ViewModels/MainViewModel.cs | 89 ++++- .../LibraryPaneFocusTests.cs | 20 + .../TileSpatialNavigationTests.cs | 164 ++++++++ 9 files changed, 859 insertions(+), 31 deletions(-) create mode 100644 src/Aperture.App/TileSpatialNavigation.cs create mode 100644 tests/Aperture.Core.Tests/TileSpatialNavigationTests.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index bac15df..d96803c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to Aperture Image Viewer are documented here. The format fol ## [Unreleased] +## [0.8.4-beta1] - 2026-08-21 + +### Fixed +- **Tile-pane Up/Down** move in the same visual column (Explorer-style), including + across date-section headers, instead of jumping by linear item index. An empty + cell (short last row) lands on the nearest tile in that column, then the nearest + in the row — not a section header and not a random index. +- **PageUp/PageDown** scroll roughly one viewport (regardless of zoom / tile size) + and keep the selection in the same column at the same screen Y. They no longer + skip N items or jump to a date-section header. +- **Tab / Shift+Tab** cycle only the folder tree and the tile pane, do not change + either pane's selection, and skip the ribbon (hamburger / command bar / search). + Search stays on `/` and Ctrl+F. + ## [0.8.3-beta1] - 2026-08-21 ### Fixed diff --git a/src/Aperture.App/Aperture.App.csproj b/src/Aperture.App/Aperture.App.csproj index 2f98a89..874e3f9 100644 --- a/src/Aperture.App/Aperture.App.csproj +++ b/src/Aperture.App/Aperture.App.csproj @@ -16,7 +16,7 @@ true Assets\aperture.ico Aperture - 0.8.3-beta1 + 0.8.4-beta1 Aperture Image Viewer Aperture Image Viewer A fast local image & video browser for Windows. diff --git a/src/Aperture.App/LibraryPaneFocus.cs b/src/Aperture.App/LibraryPaneFocus.cs index 6bca3bc..bbd7ca0 100644 --- a/src/Aperture.App/LibraryPaneFocus.cs +++ b/src/Aperture.App/LibraryPaneFocus.cs @@ -38,6 +38,15 @@ internal enum Hit public static bool ShouldFocusContentsPane(DependencyObject? originalSource, IInputElement? currentFocus) => ShouldFocusContentsPane(Classify(originalSource, currentFocus)); + /// + /// True when keyboard focus is arriving from outside a pane onto an item + /// that is not the current selection. WPF / + /// often focus (and therefore select) the first + /// item on entry — redirect so Tab does not change the pane's selection. + /// + public static bool ShouldKeepExistingSelection(bool fromOutside, bool newFocusIsItem, bool newFocusIsSelected) => + fromOutside && newFocusIsItem && !newFocusIsSelected; + public static Hit Classify(DependencyObject? originalSource, IInputElement? currentFocus) { // A dialog keeps focus even if the click somehow reached the pane diff --git a/src/Aperture.App/MainWindow.xaml b/src/Aperture.App/MainWindow.xaml index 4eb60bf..c1e8f0a 100644 --- a/src/Aperture.App/MainWindow.xaml +++ b/src/Aperture.App/MainWindow.xaml @@ -287,11 +287,12 @@ + BorderThickness="0,0,0,1" KeyboardNavigation.TabNavigation="None"> @@ -314,12 +315,13 @@