mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 23:25:45 +03:00
collections page
This commit is contained in:
parent
253217cf20
commit
2b2787b187
7 changed files with 191 additions and 5 deletions
|
@ -38,6 +38,9 @@
|
||||||
<Compile Update="Pages\Generator\GeneratorPage.xaml.cs">
|
<Compile Update="Pages\Generator\GeneratorPage.xaml.cs">
|
||||||
<DependentUpon>GeneratorPage.xaml</DependentUpon>
|
<DependentUpon>GeneratorPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Update="Pages\Vault\CollectionsPage.xaml.cs">
|
||||||
|
<DependentUpon>CollectionsPage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Update="Pages\Vault\SharePage.xaml.cs">
|
<Compile Update="Pages\Vault\SharePage.xaml.cs">
|
||||||
<DependentUpon>SharePage.xaml</DependentUpon>
|
<DependentUpon>SharePage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
|
@ -124,11 +124,12 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Collections_Clicked(object sender, System.EventArgs e)
|
private async void Collections_Clicked(object sender, System.EventArgs e)
|
||||||
{
|
{
|
||||||
if(DoOnce())
|
if(DoOnce())
|
||||||
{
|
{
|
||||||
// TODO
|
var page = new CollectionsPage(_vm.CipherId);
|
||||||
|
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
57
src/App/Pages/Vault/CollectionsPage.xaml
Normal file
57
src/App/Pages/Vault/CollectionsPage.xaml
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<pages:BaseContentPage
|
||||||
|
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
x:Class="Bit.App.Pages.CollectionsPage"
|
||||||
|
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||||
|
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||||
|
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||||
|
x:DataType="pages:CollectionsPageViewModel"
|
||||||
|
x:Name="_page"
|
||||||
|
Title="{Binding PageTitle}">
|
||||||
|
<ContentPage.BindingContext>
|
||||||
|
<pages:CollectionsPageViewModel />
|
||||||
|
</ContentPage.BindingContext>
|
||||||
|
|
||||||
|
<ContentPage.ToolbarItems>
|
||||||
|
<ToolbarItem Text="{u:I18n Save}" Clicked="Save_Clicked" />
|
||||||
|
</ContentPage.ToolbarItems>
|
||||||
|
|
||||||
|
<ContentPage.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<u:InverseBoolConverter x:Key="inverseBool" />
|
||||||
|
<u:IsNotNullConverter x:Key="notNull" />
|
||||||
|
</ResourceDictionary>
|
||||||
|
</ContentPage.Resources>
|
||||||
|
|
||||||
|
<ScrollView x:Name="_scrollView">
|
||||||
|
<StackLayout Spacing="20">
|
||||||
|
<StackLayout StyleClass="box">
|
||||||
|
<StackLayout StyleClass="box-row"
|
||||||
|
IsVisible="{Binding HasCollections, Converter={StaticResource inverseBool}}">
|
||||||
|
<Label Text="{u:I18n NoCollectionsToList}" />
|
||||||
|
</StackLayout>
|
||||||
|
<controls:RepeaterView ItemsSource="{Binding Collections}" IsVisible="{Binding HasCollections}">
|
||||||
|
<controls:RepeaterView.ItemTemplate>
|
||||||
|
<DataTemplate x:DataType="pages:CollectionViewModel">
|
||||||
|
<StackLayout Spacing="0" Padding="0">
|
||||||
|
<StackLayout StyleClass="box-row, box-row-switch">
|
||||||
|
<Label
|
||||||
|
Text="{Binding Collection.Name}"
|
||||||
|
StyleClass="box-label, box-label-regular"
|
||||||
|
HorizontalOptions="StartAndExpand" />
|
||||||
|
<Switch
|
||||||
|
IsToggled="{Binding Checked}"
|
||||||
|
StyleClass="box-value"
|
||||||
|
HorizontalOptions="End" />
|
||||||
|
</StackLayout>
|
||||||
|
<BoxView StyleClass="box-row-separator" />
|
||||||
|
</StackLayout>
|
||||||
|
</DataTemplate>
|
||||||
|
</controls:RepeaterView.ItemTemplate>
|
||||||
|
</controls:RepeaterView>
|
||||||
|
</StackLayout>
|
||||||
|
</StackLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
</pages:BaseContentPage>
|
37
src/App/Pages/Vault/CollectionsPage.xaml.cs
Normal file
37
src/App/Pages/Vault/CollectionsPage.xaml.cs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Bit.App.Pages
|
||||||
|
{
|
||||||
|
public partial class CollectionsPage : BaseContentPage
|
||||||
|
{
|
||||||
|
private CollectionsPageViewModel _vm;
|
||||||
|
|
||||||
|
public CollectionsPage(string cipherId)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
_vm = BindingContext as CollectionsPageViewModel;
|
||||||
|
_vm.Page = this;
|
||||||
|
_vm.CipherId = cipherId;
|
||||||
|
SetActivityIndicator();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async void OnAppearing()
|
||||||
|
{
|
||||||
|
base.OnAppearing();
|
||||||
|
await LoadOnAppearedAsync(_scrollView, true, () => _vm.LoadAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDisappearing()
|
||||||
|
{
|
||||||
|
base.OnDisappearing();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void Save_Clicked(object sender, System.EventArgs e)
|
||||||
|
{
|
||||||
|
if(DoOnce())
|
||||||
|
{
|
||||||
|
await _vm.SubmitAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
87
src/App/Pages/Vault/CollectionsPageViewModel.cs
Normal file
87
src/App/Pages/Vault/CollectionsPageViewModel.cs
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
using Bit.App.Abstractions;
|
||||||
|
using Bit.App.Resources;
|
||||||
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Exceptions;
|
||||||
|
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;
|
||||||
|
|
||||||
|
namespace Bit.App.Pages
|
||||||
|
{
|
||||||
|
public class CollectionsPageViewModel : BaseViewModel
|
||||||
|
{
|
||||||
|
private readonly IDeviceActionService _deviceActionService;
|
||||||
|
private readonly ICipherService _cipherService;
|
||||||
|
private readonly ICollectionService _collectionService;
|
||||||
|
private readonly IPlatformUtilsService _platformUtilsService;
|
||||||
|
private CipherView _cipher;
|
||||||
|
private Cipher _cipherDomain;
|
||||||
|
private bool _hasCollections;
|
||||||
|
|
||||||
|
public CollectionsPageViewModel()
|
||||||
|
{
|
||||||
|
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||||
|
_cipherService = ServiceContainer.Resolve<ICipherService>("cipherService");
|
||||||
|
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
||||||
|
_collectionService = ServiceContainer.Resolve<ICollectionService>("collectionService");
|
||||||
|
Collections = new ExtendedObservableCollection<CollectionViewModel>();
|
||||||
|
PageTitle = AppResources.Collections;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CipherId { get; set; }
|
||||||
|
public ExtendedObservableCollection<CollectionViewModel> Collections { get; set; }
|
||||||
|
public bool HasCollections
|
||||||
|
{
|
||||||
|
get => _hasCollections;
|
||||||
|
set => SetProperty(ref _hasCollections, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LoadAsync()
|
||||||
|
{
|
||||||
|
_cipherDomain = await _cipherService.GetAsync(CipherId);
|
||||||
|
var collectionIds = _cipherDomain.CollectionIds;
|
||||||
|
_cipher = await _cipherDomain.DecryptAsync();
|
||||||
|
var allCollections = await _collectionService.GetAllDecryptedAsync();
|
||||||
|
var collections = allCollections
|
||||||
|
.Where(c => !c.ReadOnly && c.OrganizationId == _cipher.OrganizationId)
|
||||||
|
.Select(c => new CollectionViewModel
|
||||||
|
{
|
||||||
|
Collection = c,
|
||||||
|
Checked = collectionIds.Contains(c.Id)
|
||||||
|
}).ToList();
|
||||||
|
Collections.ResetWithRange(collections);
|
||||||
|
HasCollections = Collections.Any();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> SubmitAsync()
|
||||||
|
{
|
||||||
|
if(!Collections.Any(c => c.Checked))
|
||||||
|
{
|
||||||
|
await Page.DisplayAlert(AppResources.AnErrorHasOccurred, AppResources.SelectOneCollection,
|
||||||
|
AppResources.Ok);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cipherDomain.CollectionIds = new HashSet<string>(
|
||||||
|
Collections.Where(c => c.Checked).Select(c => c.Collection.Id));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _deviceActionService.ShowLoadingAsync(AppResources.Saving);
|
||||||
|
await _cipherService.SaveCollectionsWithServerAsync(_cipherDomain);
|
||||||
|
await _deviceActionService.HideLoadingAsync();
|
||||||
|
_platformUtilsService.ShowToast("success", null, AppResources.ItemUpdated);
|
||||||
|
await Page.Navigation.PopModalAsync();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(ApiException e)
|
||||||
|
{
|
||||||
|
await _deviceActionService.HideLoadingAsync();
|
||||||
|
await Page.DisplayAlert(AppResources.AnErrorHasOccurred, e.Error.GetSingleMessage(), AppResources.Ok);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
private SharePageViewModel _vm;
|
private SharePageViewModel _vm;
|
||||||
|
|
||||||
public SharePage(string cipherId = null)
|
public SharePage(string cipherId)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_vm = BindingContext as SharePageViewModel;
|
_vm = BindingContext as SharePageViewModel;
|
||||||
|
|
|
@ -130,11 +130,12 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Collections_Clicked(object sender, System.EventArgs e)
|
private async void Collections_Clicked(object sender, System.EventArgs e)
|
||||||
{
|
{
|
||||||
if(DoOnce())
|
if(DoOnce())
|
||||||
{
|
{
|
||||||
// TODO
|
var page = new CollectionsPage(_vm.CipherId);
|
||||||
|
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue