Repository navigation
Fix PageUp and PageDown wrapping past result boundaries #4719
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
DavidGBrett
merged 6 commits into
Flow-Launcher:dev
from
yundeyideyun:fix/page-navigation-boundaries
Oct 24, 2026
Merged
Changes from 2 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
889f515
Fix page navigation wrapping past result boundaries
yundeyideyun 6303333
Preserve existing source file UTF-8 encoding
yundeyideyun f23fa71
Synchronize result-count snapshot during page navigation
yundeyideyun 0982ed1
Keep page selection synchronized with result refresh
yundeyideyun efd11da
Keep refresh selection and page navigation in one collection transaction
yundeyideyun 51a0b78
Preserve UTF-8 BOM and existing LF file endings
yundeyideyun File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| using System.Threading; | ||
| using Flow.Launcher.Infrastructure.UserSettings; | ||
| using Flow.Launcher.Plugin; | ||
| using Flow.Launcher.ViewModel; | ||
| using NUnit.Framework; | ||
|
|
||
| namespace Flow.Launcher.Test; | ||
|
|
||
| [TestFixture] | ||
| [Apartment(ApartmentState.STA)] | ||
| public class ResultsViewModelNavigationTest | ||
| { | ||
| [TestCase(17, 15, 0, 15)] | ||
| [TestCase(17, 15, 15, 16)] | ||
| [TestCase(17, 15, 16, 16)] | ||
| [TestCase(3, 15, 0, 2)] | ||
| [TestCase(1, 15, 0, 0)] | ||
| [TestCase(0, 15, -1, -1)] | ||
| public void NextPageStopsAtLastResult(int count, int pageSize, int selectedIndex, int expected) | ||
| { | ||
| var viewModel = CreateViewModel(count, pageSize, selectedIndex); | ||
|
|
||
| viewModel.SelectNextPage(); | ||
|
|
||
| Assert.That(viewModel.SelectedIndex, Is.EqualTo(expected)); | ||
| } | ||
|
|
||
| [TestCase(17, 15, 16, 1)] | ||
| [TestCase(17, 15, 1, 0)] | ||
| [TestCase(17, 15, 0, 0)] | ||
| [TestCase(3, 15, 2, 0)] | ||
| [TestCase(1, 15, 0, 0)] | ||
| [TestCase(0, 15, -1, -1)] | ||
| public void PreviousPageStopsAtFirstResult(int count, int pageSize, int selectedIndex, int expected) | ||
| { | ||
| var viewModel = CreateViewModel(count, pageSize, selectedIndex); | ||
|
|
||
| viewModel.SelectPrevPage(); | ||
|
|
||
| Assert.That(viewModel.SelectedIndex, Is.EqualTo(expected)); | ||
| } | ||
|
|
||
| [Test] | ||
| public void RepeatedPageDownReachesAndKeepsLastResult() | ||
| { | ||
| var viewModel = CreateViewModel(17, 15, 0); | ||
|
|
||
| viewModel.SelectNextPage(); | ||
| Assert.That(viewModel.SelectedIndex, Is.EqualTo(15)); | ||
| viewModel.SelectNextPage(); | ||
| Assert.That(viewModel.SelectedIndex, Is.EqualTo(16)); | ||
| viewModel.SelectNextPage(); | ||
| Assert.That(viewModel.SelectedIndex, Is.EqualTo(16)); | ||
| } | ||
|
|
||
| [Test] | ||
| public void RepeatedPageUpReachesAndKeepsFirstResult() | ||
| { | ||
| var viewModel = CreateViewModel(17, 15, 16); | ||
|
|
||
| viewModel.SelectPrevPage(); | ||
| Assert.That(viewModel.SelectedIndex, Is.EqualTo(1)); | ||
| viewModel.SelectPrevPage(); | ||
| Assert.That(viewModel.SelectedIndex, Is.Zero); | ||
| viewModel.SelectPrevPage(); | ||
| Assert.That(viewModel.SelectedIndex, Is.Zero); | ||
| } | ||
|
|
||
| [Test] | ||
| public void DownArrowStillWrapsFromLastResult() | ||
| { | ||
| var viewModel = CreateViewModel(17, 15, 16); | ||
|
|
||
| viewModel.SelectNextResult(); | ||
|
|
||
| Assert.That(viewModel.SelectedIndex, Is.Zero); | ||
| } | ||
|
|
||
| [Test] | ||
| public void UpArrowStillWrapsFromFirstResult() | ||
| { | ||
| var viewModel = CreateViewModel(17, 15, 0); | ||
|
|
||
| viewModel.SelectPrevResult(); | ||
|
|
||
| Assert.That(viewModel.SelectedIndex, Is.EqualTo(16)); | ||
| } | ||
|
|
||
| private static ResultsViewModel CreateViewModel(int count, int pageSize, int selectedIndex) | ||
| { | ||
| var settings = new Settings { MaxResultsToShow = pageSize }; | ||
| var viewModel = new ResultsViewModel(settings, null); | ||
| for (var index = 0; index < count; index++) | ||
| { | ||
| viewModel.Results.Add(new ResultViewModel(new Result { Title = $"Result {index}" }, settings)); | ||
| } | ||
|
|
||
| viewModel.SelectedIndex = selectedIndex; | ||
| return viewModel; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.