mirror of
https://github.com/bitwarden/mobile.git
synced 2024-12-17 15:27:43 +01:00
grouping counts
This commit is contained in:
parent
ba9605383d
commit
c8368a2190
@ -28,7 +28,7 @@
|
|||||||
<StackLayout Orientation="Horizontal"
|
<StackLayout Orientation="Horizontal"
|
||||||
StyleClass="list-row, list-row-platform">
|
StyleClass="list-row, list-row-platform">
|
||||||
<controls:FaLabel Text="{Binding Icon, Mode=OneWay}"
|
<controls:FaLabel Text="{Binding Icon, Mode=OneWay}"
|
||||||
HorizontalOptions="Center"
|
HorizontalOptions="Start"
|
||||||
VerticalOptions="Center"
|
VerticalOptions="Center"
|
||||||
StyleClass="list-icon" />
|
StyleClass="list-icon" />
|
||||||
<Label Text="{Binding Name, Mode=OneWay}"
|
<Label Text="{Binding Name, Mode=OneWay}"
|
||||||
@ -36,6 +36,10 @@
|
|||||||
HorizontalOptions="StartAndExpand"
|
HorizontalOptions="StartAndExpand"
|
||||||
VerticalOptions="CenterAndExpand"
|
VerticalOptions="CenterAndExpand"
|
||||||
StyleClass="list-title"/>
|
StyleClass="list-title"/>
|
||||||
|
<Label Text="{Binding ItemCount, Mode=OneWay}"
|
||||||
|
HorizontalOptions="End"
|
||||||
|
HorizontalTextAlignment="End"
|
||||||
|
StyleClass="list-sub"/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ViewCell>
|
</ViewCell>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
@ -75,6 +79,8 @@
|
|||||||
<StackLayout StyleClass="list-row-header">
|
<StackLayout StyleClass="list-row-header">
|
||||||
<Label Text="{Binding Name}"
|
<Label Text="{Binding Name}"
|
||||||
StyleClass="list-header, list-header-platform" />
|
StyleClass="list-header, list-header-platform" />
|
||||||
|
<Label Text="{Binding ItemCount}"
|
||||||
|
StyleClass="list-header-sub" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ViewCell>
|
</ViewCell>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
@ -4,11 +4,12 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
public class GroupingsPageListGroup : List<GroupingsPageListItem>
|
public class GroupingsPageListGroup : List<GroupingsPageListItem>
|
||||||
{
|
{
|
||||||
public GroupingsPageListGroup(string name, bool doUpper = true)
|
public GroupingsPageListGroup(string name, int count, bool doUpper = true)
|
||||||
: this(new List<GroupingsPageListItem>(), name, doUpper)
|
: this(new List<GroupingsPageListItem>(), name, count, doUpper)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public GroupingsPageListGroup(List<GroupingsPageListItem> groupItems, string name, bool doUpper = true)
|
public GroupingsPageListGroup(List<GroupingsPageListItem> groupItems, string name, int count,
|
||||||
|
bool doUpper = true)
|
||||||
{
|
{
|
||||||
AddRange(groupItems);
|
AddRange(groupItems);
|
||||||
if(string.IsNullOrWhiteSpace(name))
|
if(string.IsNullOrWhiteSpace(name))
|
||||||
@ -23,9 +24,11 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
}
|
}
|
||||||
|
ItemCount = count.ToString("N0");
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string NameShort => string.IsNullOrWhiteSpace(Name) || Name.Length == 0 ? "-" : Name[0].ToString();
|
public string NameShort => string.IsNullOrWhiteSpace(Name) || Name.Length == 0 ? "-" : Name[0].ToString();
|
||||||
|
public string ItemCount { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ namespace Bit.App.Pages
|
|||||||
public CollectionView Collection { get; set; }
|
public CollectionView Collection { get; set; }
|
||||||
public CipherView Cipher { get; set; }
|
public CipherView Cipher { get; set; }
|
||||||
public CipherType? Type { get; set; }
|
public CipherType? Type { get; set; }
|
||||||
|
public string ItemCount { get; set; }
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,9 @@ namespace Bit.App.Pages
|
|||||||
private bool _showList;
|
private bool _showList;
|
||||||
private string _noDataText;
|
private string _noDataText;
|
||||||
private List<CipherView> _allCiphers;
|
private List<CipherView> _allCiphers;
|
||||||
|
private Dictionary<string, int> _folderCounts = new Dictionary<string, int>();
|
||||||
|
private Dictionary<string, int> _collectionCounts = new Dictionary<string, int>();
|
||||||
|
private Dictionary<CipherType, int> _typeCounts = new Dictionary<CipherType, int>();
|
||||||
|
|
||||||
private readonly ICipherService _cipherService;
|
private readonly ICipherService _cipherService;
|
||||||
private readonly IFolderService _folderService;
|
private readonly IFolderService _folderService;
|
||||||
@ -116,40 +119,72 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
var favListItems = FavoriteCiphers?.Select(c => new GroupingsPageListItem { Cipher = c }).ToList();
|
var favListItems = FavoriteCiphers?.Select(c => new GroupingsPageListItem { Cipher = c }).ToList();
|
||||||
var ciphersListItems = Ciphers?.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 folderListItems = NestedFolders?.Select(f =>
|
||||||
var collectionListItems = NestedCollections?.Select(c =>
|
{
|
||||||
new GroupingsPageListItem { Collection = c.Node }).ToList();
|
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)
|
if(favListItems?.Any() ?? false)
|
||||||
{
|
{
|
||||||
groupedItems.Add(new GroupingsPageListGroup(favListItems, AppResources.Favorites,
|
groupedItems.Add(new GroupingsPageListGroup(favListItems, AppResources.Favorites,
|
||||||
Device.RuntimePlatform == Device.iOS));
|
favListItems.Count, Device.RuntimePlatform == Device.iOS));
|
||||||
}
|
}
|
||||||
if(MainPage)
|
if(MainPage)
|
||||||
{
|
{
|
||||||
groupedItems.Add(new GroupingsPageListGroup(
|
groupedItems.Add(new GroupingsPageListGroup(
|
||||||
AppResources.Types, Device.RuntimePlatform == Device.iOS)
|
AppResources.Types, 4, Device.RuntimePlatform == Device.iOS)
|
||||||
{
|
{
|
||||||
new GroupingsPageListItem { Type = CipherType.Login },
|
new GroupingsPageListItem
|
||||||
new GroupingsPageListItem { Type = CipherType.Card },
|
{
|
||||||
new GroupingsPageListItem { Type = CipherType.Identity },
|
Type = CipherType.Login,
|
||||||
new GroupingsPageListItem { Type = CipherType.SecureNote }
|
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)
|
if(folderListItems?.Any() ?? false)
|
||||||
{
|
{
|
||||||
groupedItems.Add(new GroupingsPageListGroup(folderListItems, AppResources.Folders,
|
groupedItems.Add(new GroupingsPageListGroup(folderListItems, AppResources.Folders,
|
||||||
Device.RuntimePlatform == Device.iOS));
|
folderListItems.Count, Device.RuntimePlatform == Device.iOS));
|
||||||
}
|
}
|
||||||
if(collectionListItems?.Any() ?? false)
|
if(collectionListItems?.Any() ?? false)
|
||||||
{
|
{
|
||||||
groupedItems.Add(new GroupingsPageListGroup(collectionListItems, AppResources.Collections,
|
groupedItems.Add(new GroupingsPageListGroup(collectionListItems, AppResources.Collections,
|
||||||
Device.RuntimePlatform == Device.iOS));
|
collectionListItems.Count, Device.RuntimePlatform == Device.iOS));
|
||||||
}
|
}
|
||||||
if(ciphersListItems?.Any() ?? false)
|
if(ciphersListItems?.Any() ?? false)
|
||||||
{
|
{
|
||||||
groupedItems.Add(new GroupingsPageListGroup(ciphersListItems, AppResources.Items,
|
groupedItems.Add(new GroupingsPageListGroup(ciphersListItems, AppResources.Items,
|
||||||
Device.RuntimePlatform == Device.iOS));
|
ciphersListItems.Count, Device.RuntimePlatform == Device.iOS));
|
||||||
}
|
}
|
||||||
GroupedItems.ResetWithRange(groupedItems);
|
GroupedItems.ResetWithRange(groupedItems);
|
||||||
}
|
}
|
||||||
@ -209,6 +244,12 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
NoDataText = AppResources.NoItems;
|
NoDataText = AppResources.NoItems;
|
||||||
_allCiphers = await _cipherService.GetAllDecryptedAsync();
|
_allCiphers = await _cipherService.GetAllDecryptedAsync();
|
||||||
|
FavoriteCiphers?.Clear();
|
||||||
|
NoFolderCiphers?.Clear();
|
||||||
|
_folderCounts.Clear();
|
||||||
|
_collectionCounts.Clear();
|
||||||
|
_typeCounts.Clear();
|
||||||
|
|
||||||
if(MainPage)
|
if(MainPage)
|
||||||
{
|
{
|
||||||
if(ShowFolders)
|
if(ShowFolders)
|
||||||
@ -221,27 +262,6 @@ namespace Bit.App.Pages
|
|||||||
Collections = await _collectionService.GetAllDecryptedAsync();
|
Collections = await _collectionService.GetAllDecryptedAsync();
|
||||||
NestedCollections = await _collectionService.GetAllNestedAsync(Collections);
|
NestedCollections = await _collectionService.GetAllNestedAsync(Collections);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(var c in _allCiphers)
|
|
||||||
{
|
|
||||||
if(c.Favorite)
|
|
||||||
{
|
|
||||||
if(FavoriteCiphers == null)
|
|
||||||
{
|
|
||||||
FavoriteCiphers = new List<CipherView>();
|
|
||||||
}
|
|
||||||
FavoriteCiphers.Add(c);
|
|
||||||
}
|
|
||||||
if(c.FolderId == null)
|
|
||||||
{
|
|
||||||
if(NoFolderCiphers == null)
|
|
||||||
{
|
|
||||||
NoFolderCiphers = new List<CipherView>();
|
|
||||||
}
|
|
||||||
NoFolderCiphers.Add(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FavoriteCiphers = _allCiphers.Where(c => c.Favorite).ToList();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -285,6 +305,63 @@ namespace Bit.App.Pages
|
|||||||
Ciphers = _allCiphers;
|
Ciphers = _allCiphers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach(var c in _allCiphers)
|
||||||
|
{
|
||||||
|
if(MainPage)
|
||||||
|
{
|
||||||
|
if(c.Favorite)
|
||||||
|
{
|
||||||
|
if(FavoriteCiphers == null)
|
||||||
|
{
|
||||||
|
FavoriteCiphers = new List<CipherView>();
|
||||||
|
}
|
||||||
|
FavoriteCiphers.Add(c);
|
||||||
|
}
|
||||||
|
if(c.FolderId == null)
|
||||||
|
{
|
||||||
|
if(NoFolderCiphers == null)
|
||||||
|
{
|
||||||
|
NoFolderCiphers = new List<CipherView>();
|
||||||
|
}
|
||||||
|
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)
|
private async void CipherOptionsAsync(CipherView cipher)
|
||||||
|
@ -55,9 +55,30 @@
|
|||||||
Class="list-row-header">
|
Class="list-row-header">
|
||||||
<Setter Property="Padding"
|
<Setter Property="Padding"
|
||||||
Value="10, 12" />
|
Value="10, 12" />
|
||||||
|
<Setter Property="Orientation"
|
||||||
|
Value="Horizontal" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style TargetType="Label"
|
<Style TargetType="Label"
|
||||||
Class="list-header">
|
Class="list-header">
|
||||||
|
<Setter Property="HorizontalOptions"
|
||||||
|
Value="StartAndExpand" />
|
||||||
|
<Setter Property="VerticalOptions"
|
||||||
|
Value="CenterAndExpand" />
|
||||||
|
<Setter Property="VerticalTextAlignment"
|
||||||
|
Value="Center" />
|
||||||
|
</Style>
|
||||||
|
<Style TargetType="Label"
|
||||||
|
Class="list-header-sub">
|
||||||
|
<Setter Property="HorizontalTextAlignment"
|
||||||
|
Value="End" />
|
||||||
|
<Setter Property="VerticalTextAlignment"
|
||||||
|
Value="Center" />
|
||||||
|
<Setter Property="TextColor"
|
||||||
|
Value="{StaticResource MutedColor}" />
|
||||||
|
<Setter Property="HorizontalOptions"
|
||||||
|
Value="End" />
|
||||||
|
<Setter Property="VerticalOptions"
|
||||||
|
Value="CenterAndExpand" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style TargetType="StackLayout"
|
<Style TargetType="StackLayout"
|
||||||
Class="list-row">
|
Class="list-row">
|
||||||
@ -72,6 +93,11 @@
|
|||||||
<Style TargetType="Label"
|
<Style TargetType="Label"
|
||||||
Class="list-title">
|
Class="list-title">
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style TargetType="Label"
|
||||||
|
Class="list-sub">
|
||||||
|
<Setter Property="TextColor"
|
||||||
|
Value="{StaticResource MutedColor}" />
|
||||||
|
</Style>
|
||||||
<Style TargetType="Label"
|
<Style TargetType="Label"
|
||||||
ApplyToDerivedTypes="True"
|
ApplyToDerivedTypes="True"
|
||||||
Class="list-title-icon">
|
Class="list-title-icon">
|
||||||
|
Loading…
Reference in New Issue
Block a user