-
-
Notifications
You must be signed in to change notification settings - Fork 447
Remember selected position #3480
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
Changes from 3 commits
b28814f
675581f
cc8b9e6
4d6dba4
b544f20
f3ded21
a97561e
ca947b0
73af44d
ab35149
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,7 @@ public partial class MainViewModel : BaseModel, ISavable, IDisposable | |
private bool _isQueryRunning; | ||
private Query _lastQuery; | ||
private string _queryTextBeforeLeaveResults; | ||
private bool _blockQueryExecution = false; | ||
|
||
private readonly FlowLauncherJsonStorage<History> _historyItemsStorage; | ||
private readonly FlowLauncherJsonStorage<UserSelectedRecord> _userSelectedRecordStorage; | ||
|
@@ -638,35 +639,44 @@ private void DecreaseMaxResult() | |
/// </summary> | ||
/// <param name="queryText"></param> | ||
/// <param name="isReQuery">Force query even when Query Text doesn't change</param> | ||
public void ChangeQueryText(string queryText, bool isReQuery = false) | ||
public void ChangeQueryText(string queryText, bool isReQuery = false, bool suppressQueryExecution = false) | ||
{ | ||
_ = ChangeQueryTextAsync(queryText, isReQuery); | ||
_ = ChangeQueryTextAsync(queryText, isReQuery, suppressQueryExecution); | ||
} | ||
|
||
/// <summary> | ||
/// Async version of <see cref="ChangeQueryText"/> | ||
/// </summary> | ||
private async Task ChangeQueryTextAsync(string queryText, bool isReQuery = false) | ||
private async Task ChangeQueryTextAsync(string queryText, bool isReQuery = false, bool suppressQueryExecution = false) | ||
{ | ||
// Must check access so that we will not block the UI thread which cause window visibility issue | ||
if (!Application.Current.Dispatcher.CheckAccess()) | ||
{ | ||
await Application.Current.Dispatcher.InvokeAsync(() => ChangeQueryText(queryText, isReQuery)); | ||
await Application.Current.Dispatcher.InvokeAsync(() => ChangeQueryText(queryText, isReQuery, suppressQueryExecution)); | ||
return; | ||
} | ||
|
||
if (QueryText != queryText) | ||
{ | ||
// Change query text first | ||
QueryText = queryText; | ||
// When we are changing query from codes, we should not delay the query | ||
await QueryAsync(false, isReQuery: false); | ||
|
||
if (string.IsNullOrEmpty(queryText)) | ||
{ | ||
Results.ResetSelectedIndex(); | ||
} | ||
|
||
// Check if we are in the process of changing query text | ||
if (!suppressQueryExecution) | ||
{ | ||
// When we are changing query from codes, we should not delay the query | ||
await QueryAsync(false, isReQuery: false); | ||
} | ||
|
||
// set to false so the subsequent set true triggers | ||
// PropertyChanged and MoveQueryTextToEnd is called | ||
QueryTextCursorMovedToEnd = false; | ||
} | ||
else if (isReQuery) | ||
else if (isReQuery && !suppressQueryExecution) | ||
{ | ||
// When we are re-querying, we should not delay the query | ||
await QueryAsync(false, isReQuery: true); | ||
|
@@ -681,6 +691,8 @@ private async Task ChangeQueryTextAsync(string queryText, bool isReQuery = false | |
public bool QueryTextCursorMovedToEnd { get; set; } | ||
|
||
private ResultsViewModel _selectedResults; | ||
private ResultViewModel _lastSelectedResultItem; | ||
private int _lastSelectedResultIndex = -1; | ||
|
||
private ResultsViewModel SelectedResults | ||
{ | ||
|
@@ -690,6 +702,14 @@ private ResultsViewModel SelectedResults | |
var isReturningFromQueryResults = QueryResultsSelected(); | ||
var isReturningFromContextMenu = ContextMenuSelected(); | ||
var isReturningFromHistory = HistorySelected(); | ||
|
||
// save the index of the selected index before changing the selected results | ||
if (QueryResultsSelected() && value != Results) | ||
{ | ||
_lastSelectedResultItem = Results.SelectedItem; | ||
_lastSelectedResultIndex = Results.SelectedIndex; | ||
} | ||
|
||
_selectedResults = value; | ||
if (QueryResultsSelected()) | ||
{ | ||
|
@@ -701,11 +721,31 @@ private ResultsViewModel SelectedResults | |
// result from the one that was selected before going into the context menu to the first result. | ||
// The code below correctly restores QueryText and puts the text caret at the end without | ||
// running the query again when returning from the context menu. | ||
if (isReturningFromContextMenu) | ||
if (isReturningFromContextMenu && _lastSelectedResultItem != null) | ||
{ | ||
_queryText = _queryTextBeforeLeaveResults; | ||
OnPropertyChanged(nameof(QueryText)); | ||
QueryTextCursorMovedToEnd = true; | ||
try | ||
{ | ||
_blockQueryExecution = true; | ||
// Set querytext without running the query for keep index. if not use this, index will be 0. | ||
_queryText = _queryTextBeforeLeaveResults; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not just change QueryText There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I noted this in the PR description: If you simply update the
Even if the selected index is correctly remembered and restored at step 3, it becomes pointless because restoring the |
||
OnPropertyChanged(nameof(QueryText)); | ||
QueryTextCursorMovedToEnd = true; | ||
} | ||
finally | ||
{ | ||
_blockQueryExecution = false; | ||
} | ||
// restore selected item | ||
if (Results.Results.Contains(_lastSelectedResultItem)) | ||
|
||
{ | ||
Results.SelectedItem = _lastSelectedResultItem; | ||
Results.SelectedIndex = Results.Results.IndexOf(_lastSelectedResultItem); | ||
} | ||
else if (_lastSelectedResultIndex >= 0 && _lastSelectedResultIndex < Results.Results.Count) | ||
{ | ||
Results.SelectedIndex = _lastSelectedResultIndex; | ||
Results.SelectedItem = Results.Results[_lastSelectedResultIndex]; | ||
} | ||
} | ||
else | ||
{ | ||
|
@@ -1055,6 +1095,8 @@ public void Query(bool searchDelay, bool isReQuery = false) | |
|
||
private async Task QueryAsync(bool searchDelay, bool isReQuery = false) | ||
{ | ||
if (_blockQueryExecution) | ||
return; | ||
if (QueryResultsSelected()) | ||
{ | ||
await QueryResultsAsync(searchDelay, isReQuery); | ||
|
@@ -1620,67 +1662,27 @@ public void Save() | |
/// </summary> | ||
public void UpdateResultView(ICollection<ResultsForUpdate> resultsForUpdates) | ||
{ | ||
if (!resultsForUpdates.Any()) | ||
if (resultsForUpdates == null || !resultsForUpdates.Any()) | ||
return; | ||
|
||
// Block the query execution when Open ContextMenu is called | ||
if (!QueryResultsSelected()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand here. Query shouldn't be executed when context menu is called? It will only call QueryContextMenu? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I already mentioned this in the PR description. If you open the context menu while results are still loading, both the context menu and the results panel end up being shown once the loading finishes. Please read the PR description before review. |
||
return; | ||
CancellationToken token; | ||
|
||
CancellationToken token; | ||
try | ||
{ | ||
// Don't know why sometimes even resultsForUpdates is empty, the method won't return; | ||
token = resultsForUpdates.Select(r => r.Token).Distinct().SingleOrDefault(); | ||
} | ||
#if DEBUG | ||
catch | ||
{ | ||
throw new ArgumentException("Unacceptable token"); | ||
} | ||
#else | ||
catch | ||
{ | ||
token = default; | ||
} | ||
#endif | ||
|
||
foreach (var metaResults in resultsForUpdates) | ||
{ | ||
foreach (var result in metaResults.Results) | ||
{ | ||
if (_topMostRecord.IsTopMost(result)) | ||
{ | ||
result.Score = Result.MaxScore; | ||
} | ||
else | ||
{ | ||
var priorityScore = metaResults.Metadata.Priority * 150; | ||
if (result.AddSelectedCount) | ||
{ | ||
if ((long)result.Score + _userSelectedRecord.GetSelectedCount(result) + priorityScore > Result.MaxScore) | ||
{ | ||
result.Score = Result.MaxScore; | ||
} | ||
else | ||
{ | ||
result.Score += _userSelectedRecord.GetSelectedCount(result) + priorityScore; | ||
} | ||
} | ||
else | ||
{ | ||
if ((long)result.Score + priorityScore > Result.MaxScore) | ||
{ | ||
result.Score = Result.MaxScore; | ||
} | ||
else | ||
{ | ||
result.Score += priorityScore; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
// it should be the same for all results | ||
// Reselect the first result if the first result is selected | ||
bool reSelect = resultsForUpdates.First().ReSelectFirstResult; | ||
|
||
// Update results while remembering the currently selected item | ||
Results.AddResults(resultsForUpdates, token, reSelect); | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.