diff --git a/src/App/Pages/Vault/GroupingsPage/GroupingsPage.xaml b/src/App/Pages/Vault/GroupingsPage/GroupingsPage.xaml index f569ddd15..80107a19c 100644 --- a/src/App/Pages/Vault/GroupingsPage/GroupingsPage.xaml +++ b/src/App/Pages/Vault/GroupingsPage/GroupingsPage.xaml @@ -28,7 +28,7 @@ @@ -75,6 +79,8 @@ diff --git a/src/App/Pages/Vault/GroupingsPage/GroupingsPageListGroup.cs b/src/App/Pages/Vault/GroupingsPage/GroupingsPageListGroup.cs index 3a556349b..b216b6d0a 100644 --- a/src/App/Pages/Vault/GroupingsPage/GroupingsPageListGroup.cs +++ b/src/App/Pages/Vault/GroupingsPage/GroupingsPageListGroup.cs @@ -4,11 +4,12 @@ namespace Bit.App.Pages { public class GroupingsPageListGroup : List { - public GroupingsPageListGroup(string name, bool doUpper = true) - : this(new List(), name, doUpper) + public GroupingsPageListGroup(string name, int count, bool doUpper = true) + : this(new List(), name, count, doUpper) { } - public GroupingsPageListGroup(List groupItems, string name, bool doUpper = true) + public GroupingsPageListGroup(List groupItems, string name, int count, + bool doUpper = true) { AddRange(groupItems); if(string.IsNullOrWhiteSpace(name)) @@ -23,9 +24,11 @@ namespace Bit.App.Pages { Name = name; } + ItemCount = count.ToString("N0"); } public string Name { get; set; } public string NameShort => string.IsNullOrWhiteSpace(Name) || Name.Length == 0 ? "-" : Name[0].ToString(); + public string ItemCount { get; set; } } } diff --git a/src/App/Pages/Vault/GroupingsPage/GroupingsPageListItem.cs b/src/App/Pages/Vault/GroupingsPage/GroupingsPageListItem.cs index 48f5a4053..fcd5c2edc 100644 --- a/src/App/Pages/Vault/GroupingsPage/GroupingsPageListItem.cs +++ b/src/App/Pages/Vault/GroupingsPage/GroupingsPageListItem.cs @@ -13,6 +13,7 @@ namespace Bit.App.Pages public CollectionView Collection { get; set; } public CipherView Cipher { get; set; } public CipherType? Type { get; set; } + public string ItemCount { get; set; } public string Name { diff --git a/src/App/Pages/Vault/GroupingsPage/GroupingsPageViewModel.cs b/src/App/Pages/Vault/GroupingsPage/GroupingsPageViewModel.cs index 4cae844f5..14f579239 100644 --- a/src/App/Pages/Vault/GroupingsPage/GroupingsPageViewModel.cs +++ b/src/App/Pages/Vault/GroupingsPage/GroupingsPageViewModel.cs @@ -21,6 +21,9 @@ namespace Bit.App.Pages private bool _showList; private string _noDataText; private List _allCiphers; + private Dictionary _folderCounts = new Dictionary(); + private Dictionary _collectionCounts = new Dictionary(); + private Dictionary _typeCounts = new Dictionary(); private readonly ICipherService _cipherService; private readonly IFolderService _folderService; @@ -116,40 +119,72 @@ namespace Bit.App.Pages var favListItems = FavoriteCiphers?.Select(c => new GroupingsPageListItem { Cipher = c }).ToList(); var ciphersListItems = Ciphers?.Select(c => new GroupingsPageListItem { Cipher = c }).ToList(); - var folderListItems = NestedFolders?.Select(f => new GroupingsPageListItem { Folder = f.Node }).ToList(); - var collectionListItems = NestedCollections?.Select(c => - new GroupingsPageListItem { Collection = c.Node }).ToList(); + var folderListItems = NestedFolders?.Select(f => + { + var fId = f.Node.Id ?? "none"; + return new GroupingsPageListItem + { + Folder = f.Node, + ItemCount = (_folderCounts.ContainsKey(fId) ? _folderCounts[fId] : 0).ToString("N0") + }; + }).ToList(); + var collectionListItems = NestedCollections?.Select(c => new GroupingsPageListItem + { + Collection = c.Node, + ItemCount = (_collectionCounts.ContainsKey(c.Node.Id) ? + _collectionCounts[c.Node.Id] : 0).ToString("N0") + }).ToList(); if(favListItems?.Any() ?? false) { groupedItems.Add(new GroupingsPageListGroup(favListItems, AppResources.Favorites, - Device.RuntimePlatform == Device.iOS)); + favListItems.Count, Device.RuntimePlatform == Device.iOS)); } if(MainPage) { groupedItems.Add(new GroupingsPageListGroup( - AppResources.Types, Device.RuntimePlatform == Device.iOS) + AppResources.Types, 4, Device.RuntimePlatform == Device.iOS) { - new GroupingsPageListItem { Type = CipherType.Login }, - new GroupingsPageListItem { Type = CipherType.Card }, - new GroupingsPageListItem { Type = CipherType.Identity }, - new GroupingsPageListItem { Type = CipherType.SecureNote } + new GroupingsPageListItem + { + Type = CipherType.Login, + ItemCount = (_typeCounts.ContainsKey(CipherType.Login) ? + _typeCounts[CipherType.Login] : 0).ToString("N0") + }, + new GroupingsPageListItem + { + Type = CipherType.Card, + ItemCount = (_typeCounts.ContainsKey(CipherType.Card) ? + _typeCounts[CipherType.Card] : 0).ToString("N0") + }, + new GroupingsPageListItem + { + Type = CipherType.Identity, + ItemCount = (_typeCounts.ContainsKey(CipherType.Identity) ? + _typeCounts[CipherType.Identity] : 0).ToString("N0") + }, + new GroupingsPageListItem + { + Type = CipherType.SecureNote, + ItemCount = (_typeCounts.ContainsKey(CipherType.SecureNote) ? + _typeCounts[CipherType.SecureNote] : 0).ToString("N0") + }, }); } if(folderListItems?.Any() ?? false) { groupedItems.Add(new GroupingsPageListGroup(folderListItems, AppResources.Folders, - Device.RuntimePlatform == Device.iOS)); + folderListItems.Count, Device.RuntimePlatform == Device.iOS)); } if(collectionListItems?.Any() ?? false) { groupedItems.Add(new GroupingsPageListGroup(collectionListItems, AppResources.Collections, - Device.RuntimePlatform == Device.iOS)); + collectionListItems.Count, Device.RuntimePlatform == Device.iOS)); } if(ciphersListItems?.Any() ?? false) { groupedItems.Add(new GroupingsPageListGroup(ciphersListItems, AppResources.Items, - Device.RuntimePlatform == Device.iOS)); + ciphersListItems.Count, Device.RuntimePlatform == Device.iOS)); } GroupedItems.ResetWithRange(groupedItems); } @@ -209,6 +244,12 @@ namespace Bit.App.Pages { NoDataText = AppResources.NoItems; _allCiphers = await _cipherService.GetAllDecryptedAsync(); + FavoriteCiphers?.Clear(); + NoFolderCiphers?.Clear(); + _folderCounts.Clear(); + _collectionCounts.Clear(); + _typeCounts.Clear(); + if(MainPage) { if(ShowFolders) @@ -221,27 +262,6 @@ namespace Bit.App.Pages Collections = await _collectionService.GetAllDecryptedAsync(); NestedCollections = await _collectionService.GetAllNestedAsync(Collections); } - - foreach(var c in _allCiphers) - { - if(c.Favorite) - { - if(FavoriteCiphers == null) - { - FavoriteCiphers = new List(); - } - FavoriteCiphers.Add(c); - } - if(c.FolderId == null) - { - if(NoFolderCiphers == null) - { - NoFolderCiphers = new List(); - } - NoFolderCiphers.Add(c); - } - } - FavoriteCiphers = _allCiphers.Where(c => c.Favorite).ToList(); } else { @@ -285,6 +305,63 @@ namespace Bit.App.Pages Ciphers = _allCiphers; } } + + foreach(var c in _allCiphers) + { + if(MainPage) + { + if(c.Favorite) + { + if(FavoriteCiphers == null) + { + FavoriteCiphers = new List(); + } + FavoriteCiphers.Add(c); + } + if(c.FolderId == null) + { + if(NoFolderCiphers == null) + { + NoFolderCiphers = new List(); + } + NoFolderCiphers.Add(c); + } + + if(_typeCounts.ContainsKey(c.Type)) + { + _typeCounts[c.Type] = _typeCounts[c.Type] + 1; + } + else + { + _typeCounts.Add(c.Type, 1); + } + } + + var fId = c.FolderId ?? "none"; + if(_folderCounts.ContainsKey(fId)) + { + _folderCounts[fId] = _folderCounts[fId] + 1; + } + else + { + _folderCounts.Add(fId, 1); + } + + if(c.CollectionIds != null) + { + foreach(var colId in c.CollectionIds) + { + if(_collectionCounts.ContainsKey(colId)) + { + _collectionCounts[colId] = _collectionCounts[colId] + 1; + } + else + { + _collectionCounts.Add(colId, 1); + } + } + } + } } private async void CipherOptionsAsync(CipherView cipher) diff --git a/src/App/Styles/Base.xaml b/src/App/Styles/Base.xaml index d6296273f..58aa6406c 100644 --- a/src/App/Styles/Base.xaml +++ b/src/App/Styles/Base.xaml @@ -55,9 +55,30 @@ Class="list-row-header"> + + +