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(); } } }