diff --git a/src/App/Pages/GroupingsPage/GroupingsPage.xaml b/src/App/Pages/GroupingsPage/GroupingsPage.xaml
index c099a1f22..b2240dc7d 100644
--- a/src/App/Pages/GroupingsPage/GroupingsPage.xaml
+++ b/src/App/Pages/GroupingsPage/GroupingsPage.xaml
@@ -57,14 +57,22 @@
+ ItemTemplate="{StaticResource listItemDataTemplateSelector}"
+ IsGroupingEnabled="True">
+
+
+
+
+
+
+
diff --git a/src/App/Pages/GroupingsPage/GroupingsPage.xaml.cs b/src/App/Pages/GroupingsPage/GroupingsPage.xaml.cs
index 87256590b..c6d6198bc 100644
--- a/src/App/Pages/GroupingsPage/GroupingsPage.xaml.cs
+++ b/src/App/Pages/GroupingsPage/GroupingsPage.xaml.cs
@@ -1,4 +1,6 @@
-using System;
+using Bit.Core.Abstractions;
+using Bit.Core.Utilities;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -10,18 +12,48 @@ namespace Bit.App.Pages
{
public partial class GroupingsPage : ContentPage
{
- private GroupingsPageViewModel _viewModel;
+ private readonly IBroadcasterService _broadcasterService;
+ private readonly ISyncService _syncService;
+ private readonly GroupingsPageViewModel _viewModel;
public GroupingsPage()
{
InitializeComponent();
+ _broadcasterService = ServiceContainer.Resolve("broadcasterService");
+ _syncService = ServiceContainer.Resolve("syncService");
_viewModel = BindingContext as GroupingsPageViewModel;
}
protected async override void OnAppearing()
{
base.OnAppearing();
- await _viewModel.LoadAsync();
+ _broadcasterService.Subscribe(nameof(GroupingsPage), async (message) =>
+ {
+ if(message.Command == "syncCompleted")
+ {
+ await Task.Delay(500);
+ // await _viewModel.LoadAsync();
+ }
+ });
+
+ if(!_syncService.SyncInProgress)
+ {
+ await _viewModel.LoadAsync();
+ }
+ else
+ {
+ await Task.Delay(5000);
+ if(!_viewModel.Loaded)
+ {
+ await _viewModel.LoadAsync();
+ }
+ }
+ }
+
+ protected override void OnDisappearing()
+ {
+ base.OnDisappearing();
+ _broadcasterService.Unsubscribe(nameof(GroupingsPage));
}
}
}
diff --git a/src/App/Pages/GroupingsPage/GroupingsPageListGroup.cs b/src/App/Pages/GroupingsPage/GroupingsPageListGroup.cs
new file mode 100644
index 000000000..4963e1447
--- /dev/null
+++ b/src/App/Pages/GroupingsPage/GroupingsPageListGroup.cs
@@ -0,0 +1,27 @@
+using System.Collections.Generic;
+
+namespace Bit.App.Pages
+{
+ public class GroupingsPageListGroup : List
+ {
+ public GroupingsPageListGroup(List groupItems, string name, bool doUpper = true)
+ {
+ AddRange(groupItems);
+ if(string.IsNullOrWhiteSpace(name))
+ {
+ Name = "-";
+ }
+ else if(doUpper)
+ {
+ Name = name.ToUpperInvariant();
+ }
+ else
+ {
+ Name = name;
+ }
+ }
+
+ public string Name { get; set; }
+ public string NameShort => string.IsNullOrWhiteSpace(Name) || Name.Length == 0 ? "-" : Name[0].ToString();
+ }
+}
diff --git a/src/App/Pages/GroupingsPage/GroupingsPageListItem.cs b/src/App/Pages/GroupingsPage/GroupingsPageListItem.cs
index 16d61d640..c0adddcb9 100644
--- a/src/App/Pages/GroupingsPage/GroupingsPageListItem.cs
+++ b/src/App/Pages/GroupingsPage/GroupingsPageListItem.cs
@@ -5,7 +5,7 @@ namespace Bit.App.Pages
public class GroupingsPageListItem
{
public FolderView Folder { get; set; }
- public Core.Models.View.CollectionView Collection { get; set; }
+ public CollectionView Collection { get; set; }
public CipherView Cipher { get; set; }
}
}
diff --git a/src/App/Pages/GroupingsPage/GroupingsPageViewModel.cs b/src/App/Pages/GroupingsPage/GroupingsPageViewModel.cs
index 608454241..03732a8e6 100644
--- a/src/App/Pages/GroupingsPage/GroupingsPageViewModel.cs
+++ b/src/App/Pages/GroupingsPage/GroupingsPageViewModel.cs
@@ -1,6 +1,10 @@
-using Bit.Core.Models.View;
+using Bit.App.Resources;
+using Bit.Core.Abstractions;
+using Bit.Core.Models.Domain;
+using Bit.Core.Models.View;
using Bit.Core.Utilities;
using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
using Xamarin.Forms;
@@ -9,78 +13,133 @@ namespace Bit.App.Pages
public class GroupingsPageViewModel : BaseViewModel
{
private bool _loading = false;
+ private bool _loaded = false;
+ private List _allCiphers;
+
+ private readonly ICipherService _cipherService;
+ private readonly IFolderService _folderService;
+ private readonly ICollectionService _collectionService;
+ private readonly ISyncService _syncService;
public GroupingsPageViewModel()
{
+ _cipherService = ServiceContainer.Resolve("cipherService");
+ _folderService = ServiceContainer.Resolve("folderService");
+ _collectionService = ServiceContainer.Resolve("collectionService");
+ _syncService = ServiceContainer.Resolve("syncService");
+
PageTitle = "My Vault";
- Items = new ExtendedObservableCollection();
+ GroupedItems = new ExtendedObservableCollection();
LoadCommand = new Command(async () => await LoadAsync());
}
+ public bool ShowFavorites { get; set; } = true;
+ public bool ShowFolders { get; set; } = true;
+ public bool ShowCollections { get; set; } = true;
+
+ public List Ciphers { get; set; }
+ public List FavoriteCiphers { get; set; }
+ public List NoFolderCiphers { get; set; }
+ public List Folders { get; set; }
+ public List> NestedFolders { get; set; }
+ public List Collections { get; set; }
+ public List> NestedCollections { get; set; }
+
public bool Loading
{
get => _loading;
set => SetProperty(ref _loading, value);
}
- public ExtendedObservableCollection Items { get; set; }
+ public bool Loaded
+ {
+ get => _loaded;
+ set
+ {
+ SetProperty(ref _loaded, value);
+ SetProperty(ref _loading, !value);
+ }
+ }
+ public ExtendedObservableCollection GroupedItems { get; set; }
public Command LoadCommand { get; set; }
- public Task LoadAsync()
+ public async Task LoadAsync()
{
- if(Loading)
- {
- return Task.FromResult(0);
- }
- Loading = true;
-
try
{
- Items.ResetWithRange(new List
+ await LoadFoldersAsync();
+ await LoadCollectionsAsync();
+ await LoadCiphersAsync();
+
+ var favListItems = FavoriteCiphers?.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 groupedItems = new List();
+ if(favListItems?.Any() ?? false)
{
- new GroupingsPageListItem
- {
- Cipher = new CipherView { Name = "Cipher 1" }
- },
- new GroupingsPageListItem
- {
- Cipher = new CipherView { Name = "Cipher 2" }
- },
- new GroupingsPageListItem
- {
- Cipher = new CipherView { Name = "Cipher 3" }
- },
- new GroupingsPageListItem
- {
- Cipher = new CipherView { Name = "Cipher 4" }
- },
- new GroupingsPageListItem
- {
- Folder = new FolderView { Name = "Folder 1" }
- },
- new GroupingsPageListItem
- {
- Folder = new FolderView { Name = "Folder 2" }
- },
- new GroupingsPageListItem
- {
- Folder = new FolderView { Name = "Folder 3" }
- },
- new GroupingsPageListItem
- {
- Collection = new Core.Models.View.CollectionView { Name = "Collection 1" }
- },
- new GroupingsPageListItem
- {
- Collection = new Core.Models.View.CollectionView { Name = "Collection 2" }
- },
- });
+ groupedItems.Add(new GroupingsPageListGroup(favListItems, AppResources.Favorites));
+ }
+ if(folderListItems?.Any() ?? false)
+ {
+ groupedItems.Add(new GroupingsPageListGroup(folderListItems, AppResources.Folders));
+ }
+ if(collectionListItems?.Any() ?? false)
+ {
+ groupedItems.Add(new GroupingsPageListGroup(collectionListItems, AppResources.Collections));
+ }
+ GroupedItems.ResetWithRange(groupedItems);
}
finally
{
- Loading = false;
+ Loaded = true;
}
+ }
- return Task.FromResult(0);
+ private async Task LoadFoldersAsync()
+ {
+ if(!ShowFolders)
+ {
+ return;
+ }
+ Folders = await _folderService.GetAllDecryptedAsync();
+ NestedFolders = await _folderService.GetAllNestedAsync();
+ }
+
+ private async Task LoadCollectionsAsync()
+ {
+ if(!ShowCollections)
+ {
+ return;
+ }
+ Collections = await _collectionService.GetAllDecryptedAsync();
+ NestedCollections = await _collectionService.GetAllNestedAsync(Collections);
+ }
+
+ private async Task LoadCiphersAsync()
+ {
+ _allCiphers = await _cipherService.GetAllDecryptedAsync();
+ Ciphers = _allCiphers;
+ 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();
}
}
}