filtered results for groupings and favorites

This commit is contained in:
Kyle Spearrin 2017-11-27 09:47:49 -05:00
parent 09412f0b78
commit 4879d906d9
7 changed files with 91 additions and 12 deletions

View file

@ -7,6 +7,7 @@ namespace Bit.App.Abstractions
public interface ICipherCollectionRepository
{
Task<IEnumerable<CipherCollectionData>> GetAllByUserIdAsync(string userId);
Task<IEnumerable<CipherCollectionData>> GetAllByUserIdCollectionAsync(string userId, string collectionId);
Task InsertAsync(CipherCollectionData obj);
Task DeleteAsync(CipherCollectionData obj);
Task DeleteByUserIdAsync(string userId);

View file

@ -12,6 +12,8 @@ namespace Bit.App.Abstractions
Task<Cipher> GetByIdAsync(string id);
Task<IEnumerable<Cipher>> GetAllAsync();
Task<IEnumerable<Cipher>> GetAllAsync(bool favorites);
Task<IEnumerable<Cipher>> GetAllByFolderAsync(string folderId);
Task<IEnumerable<Cipher>> GetAllByCollectionAsync(string collectionId);
Task<Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>, IEnumerable<Cipher>>> GetAllAsync(string uriString);
Task<ApiResult<CipherResponse>> SaveAsync(Cipher cipher);
Task UpsertDataAsync(CipherData cipher);

View file

@ -1,6 +1,5 @@
using System;
using Bit.App.Controls;
using Bit.App.Resources;
using Xamarin.Forms;
namespace Bit.App.Pages
@ -12,7 +11,7 @@ namespace Bit.App.Pages
TintColor = Color.FromHex("3c8dbc");
var settingsNavigation = new ExtendedNavigationPage(new SettingsPage());
var favoritesNavigation = new ExtendedNavigationPage(new VaultListCiphersPage(true));
var favoritesNavigation = new ExtendedNavigationPage(new VaultSearchCiphersPage(favorites: true));
var vaultNavigation = new ExtendedNavigationPage(new VaultListGroupingsPage());
var toolsNavigation = new ExtendedNavigationPage(new ToolsPage());

View file

@ -214,7 +214,7 @@ namespace Bit.App.Pages
return cts;
}
private void GroupingSelected(object sender, SelectedItemChangedEventArgs e)
private async void GroupingSelected(object sender, SelectedItemChangedEventArgs e)
{
var grouping = e.SelectedItem as Grouping;
if(grouping == null)
@ -222,6 +222,17 @@ namespace Bit.App.Pages
return;
}
Page page;
if(grouping.Folder)
{
page = new VaultSearchCiphersPage(folder: true, folderId: grouping.Id, groupingName: grouping.Name);
}
else
{
page = new VaultSearchCiphersPage(collectionId: grouping.Id, groupingName: grouping.Name);
}
await Navigation.PushAsync(page);
((ListView)sender).SelectedItem = null;
}

View file

@ -11,6 +11,7 @@ using Plugin.Settings.Abstractions;
using Plugin.Connectivity.Abstractions;
using System.Threading;
using static Bit.App.Models.Page.VaultListPageModel;
using System.Collections.Generic;
namespace Bit.App.Pages
{
@ -24,10 +25,22 @@ namespace Bit.App.Pages
private readonly IAppSettingsService _appSettingsService;
private readonly IGoogleAnalyticsService _googleAnalyticsService;
private CancellationTokenSource _filterResultsCancellationTokenSource;
private readonly bool _favorites = false;
private readonly bool _folder = false;
private readonly string _folderId = null;
private readonly string _collectionId = null;
private readonly string _groupingName = null;
public VaultSearchCiphersPage()
public VaultSearchCiphersPage(bool folder = false, string folderId = null,
string collectionId = null, string groupingName = null, bool favorites = false)
: base(true)
{
_folder = folder;
_folderId = folderId;
_collectionId = collectionId;
_favorites = favorites;
_groupingName = groupingName;
_cipherService = Resolver.Resolve<ICipherService>();
_connectivity = Resolver.Resolve<IConnectivity>();
_syncService = Resolver.Resolve<ISyncService>();
@ -83,7 +96,19 @@ namespace Bit.App.Pages
Spacing = 0
};
Title = AppResources.SearchVault;
if(!string.IsNullOrWhiteSpace(_groupingName))
{
Title = _groupingName;
}
else if(_favorites)
{
Title = AppResources.Favorites;
}
else
{
Title = AppResources.SearchVault;
}
Content = new ActivityIndicator
{
IsRunning = true,
@ -177,7 +202,11 @@ namespace Bit.App.Pages
Search.TextChanged += SearchBar_TextChanged;
Search.SearchButtonPressed += SearchBar_SearchButtonPressed;
_filterResultsCancellationTokenSource = FetchAndLoadVault();
Search.FocusWithDelay();
if(!_folder && string.IsNullOrWhiteSpace(_folderId) && string.IsNullOrWhiteSpace(_collectionId) && !_favorites)
{
Search.FocusWithDelay();
}
}
protected override void OnDisappearing()
@ -202,7 +231,23 @@ namespace Bit.App.Pages
Task.Run(async () =>
{
var ciphers = await _cipherService.GetAllAsync();
IEnumerable<Models.Cipher> ciphers;
if(_folder || !string.IsNullOrWhiteSpace(_folderId))
{
ciphers = await _cipherService.GetAllByFolderAsync(_folderId);
}
else if(!string.IsNullOrWhiteSpace(_collectionId))
{
ciphers = await _cipherService.GetAllByCollectionAsync(_collectionId);
}
else if(_favorites)
{
ciphers = await _cipherService.GetAllAsync(true);
}
else
{
ciphers = await _cipherService.GetAllAsync();
}
Ciphers = ciphers
.Select(s => new Cipher(s, _appSettingsService))

View file

@ -19,6 +19,13 @@ namespace Bit.App.Repositories
return Task.FromResult(cipherCollections);
}
public Task<IEnumerable<CipherCollectionData>> GetAllByUserIdCollectionAsync(string userId, string collectionId)
{
var cipherCollections = Connection.Table<CipherCollectionData>().Where(
f => f.UserId == userId && f.CollectionId == collectionId).Cast<CipherCollectionData>();
return Task.FromResult(cipherCollections);
}
public virtual Task InsertAsync(CipherCollectionData obj)
{
Connection.Insert(obj);

View file

@ -16,6 +16,7 @@ namespace Bit.App.Services
private readonly string[] _ignoredSearchTerms = new string[] { "com", "net", "org", "android",
"io", "co", "uk", "au", "nz", "fr", "de", "tv", "info", "app", "apps", "eu", "me", "dev", "jp", "mobile" };
private readonly ICipherRepository _cipherRepository;
private readonly ICipherCollectionRepository _cipherCollectionRepository;
private readonly IAttachmentRepository _attachmentRepository;
private readonly IAuthService _authService;
private readonly ICipherApiRepository _cipherApiRepository;
@ -26,6 +27,7 @@ namespace Bit.App.Services
public CipherService(
ICipherRepository cipherRepository,
ICipherCollectionRepository cipherCollectionRepository,
IAttachmentRepository attachmentRepository,
IAuthService authService,
ICipherApiRepository cipherApiRepository,
@ -33,6 +35,7 @@ namespace Bit.App.Services
ICryptoService cryptoService)
{
_cipherRepository = cipherRepository;
_cipherCollectionRepository = cipherCollectionRepository;
_attachmentRepository = attachmentRepository;
_authService = authService;
_cipherApiRepository = cipherApiRepository;
@ -71,11 +74,22 @@ namespace Bit.App.Services
public async Task<IEnumerable<Cipher>> GetAllAsync(bool favorites)
{
var attachmentData = await _attachmentRepository.GetAllByUserIdAsync(_authService.UserId);
var attachmentDict = attachmentData.GroupBy(a => a.LoginId).ToDictionary(g => g.Key, g => g.ToList());
var data = await _cipherRepository.GetAllByUserIdAsync(_authService.UserId, favorites);
var cipher = data.Select(f => new Cipher(f, attachmentDict.ContainsKey(f.Id) ? attachmentDict[f.Id] : null));
return cipher;
var ciphers = await GetAllAsync();
return ciphers.Where(c => c.Favorite == favorites);
}
public async Task<IEnumerable<Cipher>> GetAllByFolderAsync(string folderId)
{
var ciphers = await GetAllAsync();
return ciphers.Where(c => c.FolderId == folderId);
}
public async Task<IEnumerable<Cipher>> GetAllByCollectionAsync(string collectionId)
{
var assoc = await _cipherCollectionRepository.GetAllByUserIdCollectionAsync(_authService.UserId, collectionId);
var cipherIds = new HashSet<string>(assoc.Select(c => c.CipherId));
var ciphers = await GetAllAsync();
return ciphers.Where(c => cipherIds.Contains(c.Id));
}
public async Task<Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>, IEnumerable<Cipher>>> GetAllAsync(string uriString)