mirror of
https://github.com/bitwarden/android.git
synced 2024-12-26 02:48:29 +03:00
Additional logic around filter display (#1951)
This commit is contained in:
parent
e51233bf9b
commit
448758a697
4 changed files with 144 additions and 154 deletions
|
@ -3,14 +3,11 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Input;
|
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.App.Resources;
|
using Bit.App.Resources;
|
||||||
using Bit.Core;
|
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
using Bit.Core.Models.Domain;
|
|
||||||
using Bit.Core.Models.View;
|
using Bit.Core.Models.View;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Xamarin.CommunityToolkit.ObjectModel;
|
using Xamarin.CommunityToolkit.ObjectModel;
|
||||||
|
@ -18,7 +15,7 @@ using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
public class CiphersPageViewModel : BaseViewModel
|
public class CiphersPageViewModel : VaultFilterViewModel
|
||||||
{
|
{
|
||||||
private readonly IPlatformUtilsService _platformUtilsService;
|
private readonly IPlatformUtilsService _platformUtilsService;
|
||||||
private readonly ICipherService _cipherService;
|
private readonly ICipherService _cipherService;
|
||||||
|
@ -31,12 +28,9 @@ namespace Bit.App.Pages
|
||||||
private CancellationTokenSource _searchCancellationTokenSource;
|
private CancellationTokenSource _searchCancellationTokenSource;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
private bool _showVaultFilter;
|
|
||||||
private string _vaultFilterSelection;
|
|
||||||
private bool _showNoData;
|
private bool _showNoData;
|
||||||
private bool _showList;
|
private bool _showList;
|
||||||
private bool _websiteIconsEnabled;
|
private bool _websiteIconsEnabled;
|
||||||
private List<Organization> _organizations;
|
|
||||||
|
|
||||||
public CiphersPageViewModel()
|
public CiphersPageViewModel()
|
||||||
{
|
{
|
||||||
|
@ -52,18 +46,19 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
Ciphers = new ExtendedObservableCollection<CipherView>();
|
Ciphers = new ExtendedObservableCollection<CipherView>();
|
||||||
CipherOptionsCommand = new Command<CipherView>(CipherOptionsAsync);
|
CipherOptionsCommand = new Command<CipherView>(CipherOptionsAsync);
|
||||||
VaultFilterCommand = new AsyncCommand(VaultFilterOptionsAsync,
|
|
||||||
onException: ex => _logger.Exception(ex),
|
|
||||||
allowsMultipleExecutions: false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Command CipherOptionsCommand { get; set; }
|
public Command CipherOptionsCommand { get; set; }
|
||||||
public ICommand VaultFilterCommand { get; }
|
|
||||||
public ExtendedObservableCollection<CipherView> Ciphers { get; set; }
|
public ExtendedObservableCollection<CipherView> Ciphers { get; set; }
|
||||||
public Func<CipherView, bool> Filter { get; set; }
|
public Func<CipherView, bool> Filter { get; set; }
|
||||||
public string AutofillUrl { get; set; }
|
public string AutofillUrl { get; set; }
|
||||||
public bool Deleted { get; set; }
|
public bool Deleted { get; set; }
|
||||||
|
|
||||||
|
protected override ICipherService cipherService => _cipherService;
|
||||||
|
protected override IPolicyService policyService => _policyService;
|
||||||
|
protected override IOrganizationService organizationService => _organizationService;
|
||||||
|
protected override ILogger logger => _logger;
|
||||||
|
|
||||||
public bool ShowNoData
|
public bool ShowNoData
|
||||||
{
|
{
|
||||||
get => _showNoData;
|
get => _showNoData;
|
||||||
|
@ -81,23 +76,6 @@ namespace Bit.App.Pages
|
||||||
nameof(ShowSearchDirection)
|
nameof(ShowSearchDirection)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public bool ShowVaultFilter
|
|
||||||
{
|
|
||||||
get => _showVaultFilter;
|
|
||||||
set => SetProperty(ref _showVaultFilter, value);
|
|
||||||
}
|
|
||||||
public string VaultFilterDescription
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_vaultFilterSelection == null || _vaultFilterSelection == AppResources.AllVaults)
|
|
||||||
{
|
|
||||||
return string.Format(AppResources.VaultFilterDescription, AppResources.All);
|
|
||||||
}
|
|
||||||
return string.Format(AppResources.VaultFilterDescription, _vaultFilterSelection);
|
|
||||||
}
|
|
||||||
set => SetProperty(ref _vaultFilterSelection, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ShowSearchDirection => !ShowList && !ShowNoData;
|
public bool ShowSearchDirection => !ShowList && !ShowNoData;
|
||||||
|
|
||||||
|
@ -109,12 +87,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
public async Task InitAsync()
|
public async Task InitAsync()
|
||||||
{
|
{
|
||||||
_organizations = await _organizationService.GetAllAsync();
|
await InitVaultFilterAsync();
|
||||||
ShowVaultFilter = await _policyService.ShouldShowVaultFilterAsync();
|
|
||||||
if (ShowVaultFilter && _vaultFilterSelection == null)
|
|
||||||
{
|
|
||||||
_vaultFilterSelection = AppResources.AllVaults;
|
|
||||||
}
|
|
||||||
WebsiteIconsEnabled = !(await _stateService.GetDisableFaviconAsync()).GetValueOrDefault();
|
WebsiteIconsEnabled = !(await _stateService.GetDisableFaviconAsync()).GetValueOrDefault();
|
||||||
PerformSearchIfPopulated();
|
PerformSearchIfPopulated();
|
||||||
}
|
}
|
||||||
|
@ -237,50 +210,11 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task VaultFilterOptionsAsync()
|
protected override async Task OnVaultFilterSelectedAsync()
|
||||||
{
|
{
|
||||||
var options = new List<string> { AppResources.AllVaults, AppResources.MyVault };
|
|
||||||
if (_organizations.Any())
|
|
||||||
{
|
|
||||||
options.AddRange(_organizations.OrderBy(o => o.Name).Select(o => o.Name));
|
|
||||||
}
|
|
||||||
var selection = await Page.DisplayActionSheet(AppResources.FilterByVault, AppResources.Cancel, null,
|
|
||||||
options.ToArray());
|
|
||||||
if (selection == null || selection == AppResources.Cancel ||
|
|
||||||
(_vaultFilterSelection == null && selection == AppResources.AllVaults) ||
|
|
||||||
(_vaultFilterSelection != null && _vaultFilterSelection == selection))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
VaultFilterDescription = selection;
|
|
||||||
PerformSearchIfPopulated();
|
PerformSearchIfPopulated();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<List<CipherView>> GetAllCiphersAsync()
|
|
||||||
{
|
|
||||||
var decCiphers = await _cipherService.GetAllDecryptedAsync();
|
|
||||||
if (IsVaultFilterMyVault)
|
|
||||||
{
|
|
||||||
return decCiphers.Where(c => c.OrganizationId == null).ToList();
|
|
||||||
}
|
|
||||||
if (IsVaultFilterOrgVault)
|
|
||||||
{
|
|
||||||
var orgId = GetVaultFilterOrgId();
|
|
||||||
return decCiphers.Where(c => c.OrganizationId == orgId).ToList();
|
|
||||||
}
|
|
||||||
return decCiphers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsVaultFilterMyVault => _vaultFilterSelection == AppResources.MyVault;
|
|
||||||
|
|
||||||
private bool IsVaultFilterOrgVault => _vaultFilterSelection != AppResources.AllVaults &&
|
|
||||||
_vaultFilterSelection != AppResources.MyVault;
|
|
||||||
|
|
||||||
private string GetVaultFilterOrgId()
|
|
||||||
{
|
|
||||||
return _organizations?.FirstOrDefault(o => o.Name == _vaultFilterSelection)?.Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void CipherOptionsAsync(CipherView cipher)
|
private async void CipherOptionsAsync(CipherView cipher)
|
||||||
{
|
{
|
||||||
if ((Page as BaseContentPage).DoOnce())
|
if ((Page as BaseContentPage).DoOnce())
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Input;
|
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.App.Controls;
|
using Bit.App.Controls;
|
||||||
using Bit.App.Resources;
|
using Bit.App.Resources;
|
||||||
|
@ -17,7 +16,7 @@ using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
public class GroupingsPageViewModel : BaseViewModel
|
public class GroupingsPageViewModel : VaultFilterViewModel
|
||||||
{
|
{
|
||||||
private const int NoFolderListSize = 100;
|
private const int NoFolderListSize = 100;
|
||||||
|
|
||||||
|
@ -30,10 +29,7 @@ namespace Bit.App.Pages
|
||||||
private bool _showList;
|
private bool _showList;
|
||||||
private bool _websiteIconsEnabled;
|
private bool _websiteIconsEnabled;
|
||||||
private bool _syncRefreshing;
|
private bool _syncRefreshing;
|
||||||
private bool _showVaultFilter;
|
|
||||||
private string _vaultFilterSelection;
|
|
||||||
private string _noDataText;
|
private string _noDataText;
|
||||||
private List<Organization> _organizations;
|
|
||||||
private List<CipherView> _allCiphers;
|
private List<CipherView> _allCiphers;
|
||||||
private Dictionary<string, int> _folderCounts = new Dictionary<string, int>();
|
private Dictionary<string, int> _folderCounts = new Dictionary<string, int>();
|
||||||
private Dictionary<string, int> _collectionCounts = new Dictionary<string, int>();
|
private Dictionary<string, int> _collectionCounts = new Dictionary<string, int>();
|
||||||
|
@ -78,9 +74,6 @@ namespace Bit.App.Pages
|
||||||
await LoadAsync();
|
await LoadAsync();
|
||||||
});
|
});
|
||||||
CipherOptionsCommand = new Command<CipherView>(CipherOptionsAsync);
|
CipherOptionsCommand = new Command<CipherView>(CipherOptionsAsync);
|
||||||
VaultFilterCommand = new AsyncCommand(VaultFilterOptionsAsync,
|
|
||||||
onException: ex => _logger.Exception(ex),
|
|
||||||
allowsMultipleExecutions: false);
|
|
||||||
|
|
||||||
AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger)
|
AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger)
|
||||||
{
|
{
|
||||||
|
@ -108,6 +101,11 @@ namespace Bit.App.Pages
|
||||||
public List<Core.Models.View.CollectionView> Collections { get; set; }
|
public List<Core.Models.View.CollectionView> Collections { get; set; }
|
||||||
public List<TreeNode<Core.Models.View.CollectionView>> NestedCollections { get; set; }
|
public List<TreeNode<Core.Models.View.CollectionView>> NestedCollections { get; set; }
|
||||||
|
|
||||||
|
protected override ICipherService cipherService => _cipherService;
|
||||||
|
protected override IPolicyService policyService => _policyService;
|
||||||
|
protected override IOrganizationService organizationService => _organizationService;
|
||||||
|
protected override ILogger logger => _logger;
|
||||||
|
|
||||||
public bool Refreshing
|
public bool Refreshing
|
||||||
{
|
{
|
||||||
get => _refreshing;
|
get => _refreshing;
|
||||||
|
@ -153,30 +151,12 @@ namespace Bit.App.Pages
|
||||||
get => _websiteIconsEnabled;
|
get => _websiteIconsEnabled;
|
||||||
set => SetProperty(ref _websiteIconsEnabled, value);
|
set => SetProperty(ref _websiteIconsEnabled, value);
|
||||||
}
|
}
|
||||||
public bool ShowVaultFilter
|
|
||||||
{
|
|
||||||
get => _showVaultFilter;
|
|
||||||
set => SetProperty(ref _showVaultFilter, value);
|
|
||||||
}
|
|
||||||
public string VaultFilterDescription
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_vaultFilterSelection == null || _vaultFilterSelection == AppResources.AllVaults)
|
|
||||||
{
|
|
||||||
return string.Format(AppResources.VaultFilterDescription, AppResources.All);
|
|
||||||
}
|
|
||||||
return string.Format(AppResources.VaultFilterDescription, _vaultFilterSelection);
|
|
||||||
}
|
|
||||||
set => SetProperty(ref _vaultFilterSelection, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AccountSwitchingOverlayViewModel AccountSwitchingOverlayViewModel { get; }
|
public AccountSwitchingOverlayViewModel AccountSwitchingOverlayViewModel { get; }
|
||||||
|
|
||||||
public ObservableRangeCollection<IGroupingsPageListItem> GroupedItems { get; set; }
|
public ObservableRangeCollection<IGroupingsPageListItem> GroupedItems { get; set; }
|
||||||
public Command RefreshCommand { get; set; }
|
public Command RefreshCommand { get; set; }
|
||||||
public Command<CipherView> CipherOptionsCommand { get; set; }
|
public Command<CipherView> CipherOptionsCommand { get; set; }
|
||||||
public ICommand VaultFilterCommand { get; }
|
|
||||||
public bool LoadedOnce { get; set; }
|
public bool LoadedOnce { get; set; }
|
||||||
|
|
||||||
public async Task LoadAsync()
|
public async Task LoadAsync()
|
||||||
|
@ -201,14 +181,9 @@ namespace Bit.App.Pages
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_organizations = await _organizationService.GetAllAsync();
|
|
||||||
if (MainPage)
|
if (MainPage)
|
||||||
{
|
{
|
||||||
ShowVaultFilter = await _policyService.ShouldShowVaultFilterAsync();
|
await InitVaultFilterAsync();
|
||||||
if (ShowVaultFilter && _vaultFilterSelection == null)
|
|
||||||
{
|
|
||||||
_vaultFilterSelection = AppResources.AllVaults;
|
|
||||||
}
|
|
||||||
PageTitle = ShowVaultFilter ? AppResources.Vaults : AppResources.MyVault;
|
PageTitle = ShowVaultFilter ? AppResources.Vaults : AppResources.MyVault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,30 +369,11 @@ namespace Bit.App.Pages
|
||||||
SyncRefreshing = false;
|
SyncRefreshing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task VaultFilterOptionsAsync()
|
protected override async Task OnVaultFilterSelectedAsync()
|
||||||
{
|
{
|
||||||
var options = new List<string> { AppResources.AllVaults, AppResources.MyVault };
|
|
||||||
if (_organizations.Any())
|
|
||||||
{
|
|
||||||
options.AddRange(_organizations.OrderBy(o => o.Name).Select(o => o.Name));
|
|
||||||
}
|
|
||||||
var selection = await Page.DisplayActionSheet(AppResources.FilterByVault, AppResources.Cancel, null,
|
|
||||||
options.ToArray());
|
|
||||||
if (selection == null || selection == AppResources.Cancel ||
|
|
||||||
(_vaultFilterSelection == null && selection == AppResources.AllVaults) ||
|
|
||||||
(_vaultFilterSelection != null && _vaultFilterSelection == selection))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
VaultFilterDescription = selection;
|
|
||||||
await LoadAsync();
|
await LoadAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetVaultFilterOrgId()
|
|
||||||
{
|
|
||||||
return _organizations?.FirstOrDefault(o => o.Name == _vaultFilterSelection)?.Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SelectCipherAsync(CipherView cipher)
|
public async Task SelectCipherAsync(CipherView cipher)
|
||||||
{
|
{
|
||||||
var page = new ViewPage(cipher.Id);
|
var page = new ViewPage(cipher.Id);
|
||||||
|
@ -501,8 +457,8 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
private async Task LoadDataAsync()
|
private async Task LoadDataAsync()
|
||||||
{
|
{
|
||||||
var orgId = await FillAllCiphersAndGetOrgIdIfNeededAsync();
|
|
||||||
NoDataText = AppResources.NoItems;
|
NoDataText = AppResources.NoItems;
|
||||||
|
_allCiphers = await GetAllCiphersAsync();
|
||||||
HasCiphers = _allCiphers.Any();
|
HasCiphers = _allCiphers.Any();
|
||||||
FavoriteCiphers?.Clear();
|
FavoriteCiphers?.Clear();
|
||||||
NoFolderCiphers?.Clear();
|
NoFolderCiphers?.Clear();
|
||||||
|
@ -516,7 +472,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
if (MainPage)
|
if (MainPage)
|
||||||
{
|
{
|
||||||
await FillFoldersAndCollectionsAsync(orgId);
|
await FillFoldersAndCollectionsAsync();
|
||||||
NestedFolders = await _folderService.GetAllNestedAsync(Folders);
|
NestedFolders = await _folderService.GetAllNestedAsync(Folders);
|
||||||
HasFolders = NestedFolders.Any(f => f.Node?.Id != null);
|
HasFolders = NestedFolders.Any(f => f.Node?.Id != null);
|
||||||
NestedCollections = Collections != null ? await _collectionService.GetAllNestedAsync(Collections) : null;
|
NestedCollections = Collections != null ? await _collectionService.GetAllNestedAsync(Collections) : null;
|
||||||
|
@ -640,28 +596,9 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> FillAllCiphersAndGetOrgIdIfNeededAsync()
|
private async Task FillFoldersAndCollectionsAsync()
|
||||||
{
|
|
||||||
string orgId = null;
|
|
||||||
var decCiphers = await _cipherService.GetAllDecryptedAsync();
|
|
||||||
if (IsVaultFilterMyVault)
|
|
||||||
{
|
|
||||||
_allCiphers = decCiphers.Where(c => c.OrganizationId == null).ToList();
|
|
||||||
}
|
|
||||||
else if (IsVaultFilterOrgVault)
|
|
||||||
{
|
|
||||||
orgId = GetVaultFilterOrgId();
|
|
||||||
_allCiphers = decCiphers.Where(c => c.OrganizationId == orgId).ToList();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_allCiphers = decCiphers;
|
|
||||||
}
|
|
||||||
return orgId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task FillFoldersAndCollectionsAsync(string orgId)
|
|
||||||
{
|
{
|
||||||
|
var orgId = GetVaultFilterOrgId();
|
||||||
var decFolders = await _folderService.GetAllDecryptedAsync();
|
var decFolders = await _folderService.GetAllDecryptedAsync();
|
||||||
var decCollections = await _collectionService.GetAllDecryptedAsync();
|
var decCollections = await _collectionService.GetAllDecryptedAsync();
|
||||||
if (IsVaultFilterMyVault)
|
if (IsVaultFilterMyVault)
|
||||||
|
@ -681,11 +618,6 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsVaultFilterMyVault => _vaultFilterSelection == AppResources.MyVault;
|
|
||||||
|
|
||||||
private bool IsVaultFilterOrgVault => _vaultFilterSelection != AppResources.AllVaults &&
|
|
||||||
_vaultFilterSelection != AppResources.MyVault;
|
|
||||||
|
|
||||||
private List<FolderView> BuildFolders(List<FolderView> decFolders)
|
private List<FolderView> BuildFolders(List<FolderView> decFolders)
|
||||||
{
|
{
|
||||||
var folders = decFolders.Where(f => _allCiphers.Any(c => c.FolderId == f.Id)).ToList();
|
var folders = decFolders.Where(f => _allCiphers.Any(c => c.FolderId == f.Id)).ToList();
|
||||||
|
|
118
src/App/Pages/VaultFilterViewModel.cs
Normal file
118
src/App/Pages/VaultFilterViewModel.cs
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using Bit.App.Resources;
|
||||||
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models.Domain;
|
||||||
|
using Bit.Core.Models.View;
|
||||||
|
using Xamarin.CommunityToolkit.ObjectModel;
|
||||||
|
|
||||||
|
namespace Bit.App.Pages
|
||||||
|
{
|
||||||
|
public abstract class VaultFilterViewModel : BaseViewModel
|
||||||
|
{
|
||||||
|
protected abstract ICipherService cipherService { get; }
|
||||||
|
protected abstract IPolicyService policyService { get; }
|
||||||
|
protected abstract IOrganizationService organizationService { get; }
|
||||||
|
protected abstract ILogger logger { get; }
|
||||||
|
|
||||||
|
protected bool _showVaultFilter;
|
||||||
|
protected bool _hideMyVaultFilterOption;
|
||||||
|
protected string _vaultFilterSelection;
|
||||||
|
protected List<Organization> _organizations;
|
||||||
|
|
||||||
|
public VaultFilterViewModel()
|
||||||
|
{
|
||||||
|
VaultFilterCommand = new AsyncCommand(VaultFilterOptionsAsync,
|
||||||
|
onException: ex => logger.Exception(ex),
|
||||||
|
allowsMultipleExecutions: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICommand VaultFilterCommand { get; set; }
|
||||||
|
|
||||||
|
public bool ShowVaultFilter
|
||||||
|
{
|
||||||
|
get => _showVaultFilter;
|
||||||
|
set => SetProperty(ref _showVaultFilter, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string VaultFilterDescription
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_vaultFilterSelection == null || _vaultFilterSelection == AppResources.AllVaults)
|
||||||
|
{
|
||||||
|
return string.Format(AppResources.VaultFilterDescription, AppResources.All);
|
||||||
|
}
|
||||||
|
return string.Format(AppResources.VaultFilterDescription, _vaultFilterSelection);
|
||||||
|
}
|
||||||
|
set => SetProperty(ref _vaultFilterSelection, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetVaultFilterOrgId()
|
||||||
|
{
|
||||||
|
return _organizations?.FirstOrDefault(o => o.Name == _vaultFilterSelection)?.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool IsVaultFilterMyVault => _vaultFilterSelection == AppResources.MyVault;
|
||||||
|
|
||||||
|
protected bool IsVaultFilterOrgVault => _vaultFilterSelection != AppResources.AllVaults &&
|
||||||
|
_vaultFilterSelection != AppResources.MyVault;
|
||||||
|
|
||||||
|
protected async Task InitVaultFilterAsync()
|
||||||
|
{
|
||||||
|
_organizations = await organizationService.GetAllAsync();
|
||||||
|
ShowVaultFilter = await policyService.ShouldShowVaultFilterAsync();
|
||||||
|
if (ShowVaultFilter)
|
||||||
|
{
|
||||||
|
_hideMyVaultFilterOption = await policyService.PolicyAppliesToUser(PolicyType.PersonalOwnership);
|
||||||
|
if (_vaultFilterSelection == null)
|
||||||
|
{
|
||||||
|
_vaultFilterSelection = AppResources.AllVaults;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task<List<CipherView>> GetAllCiphersAsync()
|
||||||
|
{
|
||||||
|
var decCiphers = await cipherService.GetAllDecryptedAsync();
|
||||||
|
if (IsVaultFilterMyVault)
|
||||||
|
{
|
||||||
|
return decCiphers.Where(c => c.OrganizationId == null).ToList();
|
||||||
|
}
|
||||||
|
if (IsVaultFilterOrgVault)
|
||||||
|
{
|
||||||
|
var orgId = GetVaultFilterOrgId();
|
||||||
|
return decCiphers.Where(c => c.OrganizationId == orgId).ToList();
|
||||||
|
}
|
||||||
|
return decCiphers;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task VaultFilterOptionsAsync()
|
||||||
|
{
|
||||||
|
var options = new List<string> { AppResources.AllVaults };
|
||||||
|
if (!_hideMyVaultFilterOption)
|
||||||
|
{
|
||||||
|
options.Add(AppResources.MyVault);
|
||||||
|
}
|
||||||
|
if (_organizations.Any())
|
||||||
|
{
|
||||||
|
options.AddRange(_organizations.OrderBy(o => o.Name).Select(o => o.Name));
|
||||||
|
}
|
||||||
|
var selection = await Page.DisplayActionSheet(AppResources.FilterByVault, AppResources.Cancel, null,
|
||||||
|
options.ToArray());
|
||||||
|
if (selection == null || selection == AppResources.Cancel ||
|
||||||
|
(_vaultFilterSelection == null && selection == AppResources.AllVaults) ||
|
||||||
|
(_vaultFilterSelection != null && _vaultFilterSelection == selection))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
VaultFilterDescription = selection;
|
||||||
|
await OnVaultFilterSelectedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Task OnVaultFilterSelectedAsync();
|
||||||
|
}
|
||||||
|
}
|
|
@ -249,6 +249,12 @@ namespace Bit.Core.Services
|
||||||
|
|
||||||
public async Task<bool> ShouldShowVaultFilterAsync()
|
public async Task<bool> ShouldShowVaultFilterAsync()
|
||||||
{
|
{
|
||||||
|
var personalOwnershipPolicyApplies = await PolicyAppliesToUser(PolicyType.PersonalOwnership);
|
||||||
|
var singleOrgPolicyApplies = await PolicyAppliesToUser(PolicyType.OnlyOrg);
|
||||||
|
if (personalOwnershipPolicyApplies && singleOrgPolicyApplies)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
var organizations = await _organizationService.GetAllAsync();
|
var organizations = await _organizationService.GetAllAsync();
|
||||||
return organizations?.Any() ?? false;
|
return organizations?.Any() ?? false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue