diff --git a/src/App/App.csproj b/src/App/App.csproj index 33f7945b5..b178d6813 100644 --- a/src/App/App.csproj +++ b/src/App/App.csproj @@ -41,6 +41,9 @@ GeneratorHistoryPage.xaml + + FolderAddEditPage.xaml + FoldersPage.xaml diff --git a/src/App/Pages/Settings/FolderAddEditPage.xaml b/src/App/Pages/Settings/FolderAddEditPage.xaml new file mode 100644 index 000000000..ac1dfcd4a --- /dev/null +++ b/src/App/Pages/Settings/FolderAddEditPage.xaml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/App/Pages/Settings/FolderAddEditPage.xaml.cs b/src/App/Pages/Settings/FolderAddEditPage.xaml.cs new file mode 100644 index 000000000..41a6c47fc --- /dev/null +++ b/src/App/Pages/Settings/FolderAddEditPage.xaml.cs @@ -0,0 +1,51 @@ +namespace Bit.App.Pages +{ + public partial class FolderAddEditPage : BaseContentPage + { + private FolderAddEditPageViewModel _vm; + + public FolderAddEditPage( + string folderId = null) + { + InitializeComponent(); + _vm = BindingContext as FolderAddEditPageViewModel; + _vm.Page = this; + _vm.FolderId = folderId; + _vm.Init(); + SetActivityIndicator(); + if(!_vm.EditMode) + { + ToolbarItems.Remove(_deleteItem); + } + } + + protected override async void OnAppearing() + { + base.OnAppearing(); + await LoadOnAppearedAsync(_scrollView, true, async () => + { + await _vm.LoadAsync(); + if(!_vm.EditMode) + { + RequestFocus(_nameEntry); + } + }); + } + + private async void Save_Clicked(object sender, System.EventArgs e) + { + if(DoOnce()) + { + await _vm.SubmitAsync(); + } + } + + private async void Delete_Clicked(object sender, System.EventArgs e) + { + if(DoOnce()) + { + await _vm.DeleteAsync(); + } + } + } +} diff --git a/src/App/Pages/Settings/FolderAddEditPageViewModel.cs b/src/App/Pages/Settings/FolderAddEditPageViewModel.cs new file mode 100644 index 000000000..4350a307a --- /dev/null +++ b/src/App/Pages/Settings/FolderAddEditPageViewModel.cs @@ -0,0 +1,109 @@ +using Bit.App.Abstractions; +using Bit.App.Resources; +using Bit.Core.Abstractions; +using Bit.Core.Exceptions; +using Bit.Core.Models.View; +using Bit.Core.Utilities; +using System.Threading.Tasks; + +namespace Bit.App.Pages +{ + public class FolderAddEditPageViewModel : BaseViewModel + { + private readonly IDeviceActionService _deviceActionService; + private readonly IFolderService _folderService; + private readonly IPlatformUtilsService _platformUtilsService; + private FolderView _folder; + + public FolderAddEditPageViewModel() + { + _deviceActionService = ServiceContainer.Resolve("deviceActionService"); + _folderService = ServiceContainer.Resolve("folderService"); + _platformUtilsService = ServiceContainer.Resolve("platformUtilsService"); + } + + public string FolderId { get; set; } + public FolderView Folder + { + get => _folder; + set => SetProperty(ref _folder, value); + } + public bool EditMode => !string.IsNullOrWhiteSpace(FolderId); + + public void Init() + { + PageTitle = EditMode ? AppResources.EditFolder : AppResources.AddFolder; + } + + public async Task LoadAsync() + { + if(Folder == null) + { + if(EditMode) + { + var folder = await _folderService.GetAsync(FolderId); + Folder = await folder.DecryptAsync(); + } + else + { + Folder = new FolderView(); + } + } + } + + public async Task SubmitAsync() + { + if(string.IsNullOrWhiteSpace(Folder.Name)) + { + await Page.DisplayAlert(AppResources.AnErrorHasOccurred, + string.Format(AppResources.ValidationFieldRequired, AppResources.Name), + AppResources.Ok); + return false; + } + + var folder = await _folderService.EncryptAsync(Folder); + try + { + await _deviceActionService.ShowLoadingAsync(AppResources.Saving); + await _folderService.SaveWithServerAsync(folder); + Folder.Id = folder.Id; + await _deviceActionService.HideLoadingAsync(); + _platformUtilsService.ShowToast("success", null, + EditMode ? AppResources.FolderUpdated : AppResources.FolderCreated); + await Page.Navigation.PopModalAsync(); + return true; + } + catch(ApiException e) + { + await _deviceActionService.HideLoadingAsync(); + await Page.DisplayAlert(AppResources.AnErrorHasOccurred, e.Error.GetSingleMessage(), AppResources.Ok); + } + return false; + } + + public async Task DeleteAsync() + { + var confirmed = await _platformUtilsService.ShowDialogAsync(AppResources.DoYouReallyWantToDelete, + null, AppResources.Yes, AppResources.No); + if(!confirmed) + { + return false; + } + try + { + await _deviceActionService.ShowLoadingAsync(AppResources.Deleting); + await _folderService.DeleteWithServerAsync(Folder.Id); + await _deviceActionService.HideLoadingAsync(); + _platformUtilsService.ShowToast("success", null, AppResources.FolderDeleted); + await Page.Navigation.PopModalAsync(); + return true; + } + catch(ApiException e) + { + await _deviceActionService.HideLoadingAsync(); + await Page.DisplayAlert(AppResources.AnErrorHasOccurred, e.Error.GetSingleMessage(), AppResources.Ok); + } + return false; + } + } +} diff --git a/src/App/Pages/Settings/FoldersPage.xaml b/src/App/Pages/Settings/FoldersPage.xaml index 5af7b1e4c..ff0369474 100644 --- a/src/App/Pages/Settings/FoldersPage.xaml +++ b/src/App/Pages/Settings/FoldersPage.xaml @@ -31,7 +31,7 @@ ItemsSource="{Binding Folders}" VerticalOptions="FillAndExpand" CachingStrategy="RecycleElement" - SelectedItem="Row_Selected" + ItemSelected="RowSelected" StyleClass="list, list-platform"> diff --git a/src/App/Pages/Settings/FoldersPage.xaml.cs b/src/App/Pages/Settings/FoldersPage.xaml.cs index 63e868702..eb3aa7f27 100644 --- a/src/App/Pages/Settings/FoldersPage.xaml.cs +++ b/src/App/Pages/Settings/FoldersPage.xaml.cs @@ -1,4 +1,5 @@ -using System; +using Bit.Core.Models.View; +using System; using Xamarin.Forms; namespace Bit.App.Pages @@ -35,12 +36,23 @@ namespace Bit.App.Pages private async void RowSelected(object sender, SelectedItemChangedEventArgs e) { - + ((ListView)sender).SelectedItem = null; + if(!DoOnce()) + { + return; + } + if(!(e.SelectedItem is FolderView folder)) + { + return; + } + var page = new FolderAddEditPage(folder.Id); + await Navigation.PushModalAsync(new NavigationPage(page)); } private async void AddButton_Clicked(object sender, EventArgs e) { - + var page = new FolderAddEditPage(); + await Navigation.PushModalAsync(new NavigationPage(page)); } } } diff --git a/src/App/Pages/Vault/AddEditPageViewModel.cs b/src/App/Pages/Vault/AddEditPageViewModel.cs index ea02bdd40..0ff5807db 100644 --- a/src/App/Pages/Vault/AddEditPageViewModel.cs +++ b/src/App/Pages/Vault/AddEditPageViewModel.cs @@ -408,6 +408,7 @@ namespace Bit.App.Pages await _deviceActionService.HideLoadingAsync(); _platformUtilsService.ShowToast("success", null, AppResources.ItemDeleted); _messagingService.Send("deletedCipher"); + await Page.Navigation.PopModalAsync(); return true; } catch(ApiException e)