Added task cancellation to vault list so that search filtering tasks do not stack.

This commit is contained in:
Kyle Spearrin 2016-08-14 01:42:18 -04:00
parent 2180fb6728
commit ee867df0be

View file

@ -14,6 +14,7 @@ using PushNotification.Plugin.Abstractions;
using Plugin.Settings.Abstractions; using Plugin.Settings.Abstractions;
using Plugin.Connectivity.Abstractions; using Plugin.Connectivity.Abstractions;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@ -29,6 +30,7 @@ namespace Bit.App.Pages
private readonly ISettings _settings; private readonly ISettings _settings;
private readonly bool _favorites; private readonly bool _favorites;
private bool _loadExistingData; private bool _loadExistingData;
private CancellationTokenSource _filterResultsCancellationTokenSource;
public VaultListSitesPage(bool favorites) public VaultListSitesPage(bool favorites)
: base(true) : base(true)
@ -62,7 +64,7 @@ namespace Bit.App.Pages
{ {
if(success) if(success)
{ {
FetchAndLoadVault(); _filterResultsCancellationTokenSource = FetchAndLoadVault();
} }
}); });
@ -106,7 +108,7 @@ namespace Bit.App.Pages
private void SearchBar_SearchButtonPressed(object sender, EventArgs e) private void SearchBar_SearchButtonPressed(object sender, EventArgs e)
{ {
FilterResultsBackground(((SearchBar)sender).Text); _filterResultsCancellationTokenSource = FilterResultsBackground(((SearchBar)sender).Text, _filterResultsCancellationTokenSource);
} }
private void SearchBar_TextChanged(object sender, TextChangedEventArgs e) private void SearchBar_TextChanged(object sender, TextChangedEventArgs e)
@ -118,11 +120,12 @@ namespace Bit.App.Pages
return; return;
} }
FilterResultsBackground(e.NewTextValue); _filterResultsCancellationTokenSource = FilterResultsBackground(e.NewTextValue, _filterResultsCancellationTokenSource);
} }
private void FilterResultsBackground(string searchFilter) private CancellationTokenSource FilterResultsBackground(string searchFilter, CancellationTokenSource previousCts)
{ {
var cts = new CancellationTokenSource();
Task.Run(async () => Task.Run(async () =>
{ {
if(!string.IsNullOrWhiteSpace(searchFilter)) if(!string.IsNullOrWhiteSpace(searchFilter))
@ -132,23 +135,47 @@ namespace Bit.App.Pages
{ {
return; return;
} }
} else
FilterResults(searchFilter);
});
}
private void FilterResults(string searchFilter)
{ {
previousCts?.Cancel();
}
}
try
{
FilterResults(searchFilter, cts.Token);
}
catch(OperationCanceledException) { }
}, cts.Token);
return cts;
}
private void FilterResults(string searchFilter, CancellationToken ct)
{
if(ct.IsCancellationRequested)
{
throw new OperationCanceledException(ct);
}
if(string.IsNullOrWhiteSpace(searchFilter)) if(string.IsNullOrWhiteSpace(searchFilter))
{ {
LoadFolders(Sites); LoadFolders(Sites, ct);
} }
else else
{ {
searchFilter = searchFilter.ToLower(); searchFilter = searchFilter.ToLower();
var filteredSites = Sites.Where(s => s.Name.ToLower().Contains(searchFilter) || s.Username.ToLower().Contains(searchFilter)); var filteredSites = Sites
LoadFolders(filteredSites); .Where(s => s.Name.ToLower().Contains(searchFilter) || s.Username.ToLower().Contains(searchFilter))
.TakeWhile(s => !ct.IsCancellationRequested)
.ToList();
if(ct.IsCancellationRequested)
{
throw new OperationCanceledException(ct);
}
LoadFolders(filteredSites, ct);
} }
} }
@ -157,7 +184,7 @@ namespace Bit.App.Pages
base.OnAppearing(); base.OnAppearing();
if(_loadExistingData) if(_loadExistingData)
{ {
FetchAndLoadVault(); _filterResultsCancellationTokenSource = FetchAndLoadVault();
} }
if(_connectivity.IsConnected && Device.OS == TargetPlatform.iOS && !_favorites) if(_connectivity.IsConnected && Device.OS == TargetPlatform.iOS && !_favorites)
@ -192,14 +219,15 @@ namespace Bit.App.Pages
} }
} }
private void FetchAndLoadVault() private CancellationTokenSource FetchAndLoadVault()
{ {
var cts = new CancellationTokenSource();
_settings.AddOrUpdateValue(Constants.FirstVaultLoad, false); _settings.AddOrUpdateValue(Constants.FirstVaultLoad, false);
_loadExistingData = true; _loadExistingData = true;
if(PresentationFolders.Count > 0 && _syncService.SyncInProgress) if(PresentationFolders.Count > 0 && _syncService.SyncInProgress)
{ {
return; return cts;
} }
Task.Run(async () => Task.Run(async () =>
@ -214,11 +242,17 @@ namespace Bit.App.Pages
Folders = folders.Select(f => new VaultListPageModel.Folder(f)).OrderBy(s => s.Name); Folders = folders.Select(f => new VaultListPageModel.Folder(f)).OrderBy(s => s.Name);
Sites = sites.Select(s => new VaultListPageModel.Site(s)).OrderBy(s => s.Name).ThenBy(s => s.Username); Sites = sites.Select(s => new VaultListPageModel.Site(s)).OrderBy(s => s.Name).ThenBy(s => s.Username);
FilterResults(Search.Text); try
}); {
FilterResults(Search.Text, cts.Token);
}
catch(OperationCanceledException) { }
}, cts.Token);
return cts;
} }
private void LoadFolders(IEnumerable<VaultListPageModel.Site> sites) private void LoadFolders(IEnumerable<VaultListPageModel.Site> sites, CancellationToken ct)
{ {
var folders = new List<VaultListPageModel.Folder>(Folders); var folders = new List<VaultListPageModel.Folder>(Folders);
@ -228,13 +262,44 @@ namespace Bit.App.Pages
{ {
folder.Clear(); folder.Clear();
} }
folder.AddRange(sites.Where(s => s.FolderId == folder.Id));
var sitesToAdd = sites
.Where(s => s.FolderId == folder.Id)
.TakeWhile(s => !ct.IsCancellationRequested)
.ToList();
if(ct.IsCancellationRequested)
{
throw new OperationCanceledException(ct);
} }
var noneFolder = new VaultListPageModel.Folder(sites.Where(s => s.FolderId == null)); folder.AddRange(sitesToAdd);
}
var noneToAdd = sites
.Where(s => s.FolderId == null)
.TakeWhile(s => !ct.IsCancellationRequested)
.ToList();
if(ct.IsCancellationRequested)
{
throw new OperationCanceledException(ct);
}
var noneFolder = new VaultListPageModel.Folder(noneToAdd);
folders.Add(noneFolder); folders.Add(noneFolder);
PresentationFolders.ResetWithRange(folders.Where(f => f.Any())); var foldersToAdd = folders
.Where(f => f.Any())
.TakeWhile(s => !ct.IsCancellationRequested)
.ToList();
if(ct.IsCancellationRequested)
{
throw new OperationCanceledException(ct);
}
PresentationFolders.ResetWithRange(foldersToAdd);
} }
private void SiteSelected(object sender, SelectedItemChangedEventArgs e) private void SiteSelected(object sender, SelectedItemChangedEventArgs e)