added search to vault list page.

This commit is contained in:
Kyle Spearrin 2016-07-11 01:12:31 -04:00
parent f2ed6a4d33
commit f9fd53c733
2 changed files with 93 additions and 26 deletions

View file

@ -10,10 +10,10 @@ namespace Bit.App.Models.Page
{ {
public class Site public class Site
{ {
public Site(Models.Site site, string folderId) public Site(Models.Site site)
{ {
Id = site.Id; Id = site.Id;
FolderId = folderId; FolderId = site.FolderId;
Name = site.Name?.Decrypt(); Name = site.Name?.Decrypt();
Username = site.Username?.Decrypt() ?? " "; Username = site.Username?.Decrypt() ?? " ";
Password = new Lazy<string>(() => site.Password?.Decrypt()); Password = new Lazy<string>(() => site.Password?.Decrypt());
@ -30,19 +30,17 @@ namespace Bit.App.Models.Page
public class Folder : List<Site> public class Folder : List<Site>
{ {
public Folder(IEnumerable<Models.Site> sites, string folderId = null) public Folder(Models.Folder folder)
{
var pageSites = sites.Select(s => new Site(s, folderId)).OrderBy(s => s.Name);
AddRange(pageSites);
}
public Folder(Models.Folder folder, IEnumerable<Models.Site> sites)
: this(sites, folder.Id)
{ {
Id = folder.Id; Id = folder.Id;
Name = folder.Name?.Decrypt(); Name = folder.Name?.Decrypt();
} }
public Folder(IEnumerable<Site> sites)
{
AddRange(sites);
}
public string Id { get; set; } public string Id { get; set; }
public string Name { get; set; } = AppResources.FolderNone; public string Name { get; set; } = AppResources.FolderNone;
} }

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 Bit.App.Models;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@ -42,13 +43,17 @@ namespace Bit.App.Pages
Init(); Init();
} }
public ExtendedObservableCollection<VaultListPageModel.Folder> Folders { get; private set; } = new ExtendedObservableCollection<VaultListPageModel.Folder>(); public ExtendedObservableCollection<VaultListPageModel.Folder> PresentationFolders { get; private set; }
= new ExtendedObservableCollection<VaultListPageModel.Folder>();
public ListView ListView { get; set; }
public IEnumerable<VaultListPageModel.Site> Sites { get; set; } = new List<VaultListPageModel.Site>();
public IEnumerable<VaultListPageModel.Folder> Folders { get; set; } = new List<VaultListPageModel.Folder>();
private void Init() private void Init()
{ {
MessagingCenter.Subscribe<Application>(Application.Current, "SyncCompleted", async (sender) => MessagingCenter.Subscribe<Application>(Application.Current, "SyncCompleted", async (sender) =>
{ {
await LoadFoldersAsync(); await FetchAndLoadVaultAsync();
}); });
if(!_favorites) if(!_favorites)
@ -56,10 +61,10 @@ namespace Bit.App.Pages
ToolbarItems.Add(new AddSiteToolBarItem(this)); ToolbarItems.Add(new AddSiteToolBarItem(this));
} }
var listView = new ListView ListView = new ListView
{ {
IsGroupingEnabled = true, IsGroupingEnabled = true,
ItemsSource = Folders, ItemsSource = PresentationFolders,
HasUnevenRows = true, HasUnevenRows = true,
GroupHeaderTemplate = new DataTemplate(() => new VaultListHeaderViewCell(this)), GroupHeaderTemplate = new DataTemplate(() => new VaultListHeaderViewCell(this)),
ItemTemplate = new DataTemplate(() => new VaultListViewCell(this)) ItemTemplate = new DataTemplate(() => new VaultListViewCell(this))
@ -67,19 +72,62 @@ namespace Bit.App.Pages
if(Device.OS == TargetPlatform.iOS) if(Device.OS == TargetPlatform.iOS)
{ {
listView.RowHeight = -1; ListView.RowHeight = -1;
} }
listView.ItemSelected += SiteSelected; ListView.ItemSelected += SiteSelected;
var searchBar = new SearchBar
{
Placeholder = "Search vault...",
BackgroundColor = Color.FromHex("efeff4")
};
searchBar.TextChanged += SearchBar_TextChanged;
searchBar.SearchButtonPressed += SearchBar_SearchButtonPressed;
Title = _favorites ? AppResources.Favorites : AppResources.MyVault; Title = _favorites ? AppResources.Favorites : AppResources.MyVault;
Content = listView; Content = new StackLayout
{
Children = { searchBar, ListView },
Spacing = 0
};
}
private void SearchBar_SearchButtonPressed(object sender, EventArgs e)
{
FilterResults(((SearchBar)sender).Text);
}
private void SearchBar_TextChanged(object sender, TextChangedEventArgs e)
{
var oldLength = e.OldTextValue?.Length ?? 0;
var newLength = e.NewTextValue?.Length ?? 0;
if(oldLength < 2 && newLength < 2 && oldLength < newLength)
{
return;
}
FilterResults(e.NewTextValue);
}
private void FilterResults(string searchFilter)
{
if(string.IsNullOrWhiteSpace(searchFilter))
{
LoadFolders(Sites);
}
else
{
searchFilter = searchFilter.ToLower();
var filteredSites = Sites.Where(s => s.Name.ToLower().Contains(searchFilter) || s.Username.ToLower().Contains(searchFilter));
LoadFolders(filteredSites);
}
} }
protected async override void OnAppearing() protected async override void OnAppearing()
{ {
base.OnAppearing(); base.OnAppearing();
LoadFoldersAsync().Wait(); await FetchAndLoadVaultAsync();
if(_connectivity.IsConnected && Device.OS == TargetPlatform.iOS && !_favorites) if(_connectivity.IsConnected && Device.OS == TargetPlatform.iOS && !_favorites)
{ {
@ -101,17 +149,38 @@ namespace Bit.App.Pages
} }
} }
private async Task LoadFoldersAsync() private async Task FetchAndLoadVaultAsync()
{ {
var folders = await _folderService.GetAllAsync(); var foldersTask = _folderService.GetAllAsync();
var sites = _favorites ? await _siteService.GetAllAsync(true) : await _siteService.GetAllAsync(); var sitesTask = _favorites ? _siteService.GetAllAsync(true) : _siteService.GetAllAsync();
await Task.WhenAll(foldersTask, sitesTask);
var folders = await foldersTask;
var sites = await sitesTask;
Folders = folders.Select(f => new VaultListPageModel.Folder(f));
Sites = sites.Select(s => new VaultListPageModel.Site(s));
LoadFolders(Sites);
}
private void LoadFolders(IEnumerable<VaultListPageModel.Site> sites)
{
var folders = new List<VaultListPageModel.Folder>(Folders);
foreach(var folder in folders)
{
if(folder.Any())
{
folder.Clear();
}
folder.AddRange(sites.Where(s => s.FolderId == folder.Id));
}
var pageFolders = folders.Select(f => new VaultListPageModel.Folder(f,
sites.Where(s => s.FolderId == f.Id))).OrderBy(f => f.Name).ToList();
var noneFolder = new VaultListPageModel.Folder(sites.Where(s => s.FolderId == null)); var noneFolder = new VaultListPageModel.Folder(sites.Where(s => s.FolderId == null));
pageFolders.Add(noneFolder); folders.Add(noneFolder);
Folders.ResetWithRange(pageFolders.Where(f => f.Any())); PresentationFolders.ResetWithRange(folders.Where(f => f.Any()));
} }
private void SiteSelected(object sender, SelectedItemChangedEventArgs e) private void SiteSelected(object sender, SelectedItemChangedEventArgs e)
@ -182,7 +251,7 @@ namespace Bit.App.Pages
if(deleteCall.Succeeded) if(deleteCall.Succeeded)
{ {
var folder = Folders.Single(f => f.Id == site.FolderId); var folder = PresentationFolders.Single(f => f.Id == site.FolderId);
var siteIndex = folder.Select((s, i) => new { s, i }).First(s => s.s.Id == site.Id).i; var siteIndex = folder.Select((s, i) => new { s, i }).First(s => s.s.Id == site.Id).i;
folder.RemoveAt(siteIndex); folder.RemoveAt(siteIndex);
_userDialogs.SuccessToast(AppResources.SiteDeleted); _userDialogs.SuccessToast(AppResources.SiteDeleted);