diff --git a/src/Android/MainActivity.cs b/src/Android/MainActivity.cs index deb9eda28..74cd3ffdd 100644 --- a/src/Android/MainActivity.cs +++ b/src/Android/MainActivity.cs @@ -36,7 +36,6 @@ namespace Bit.Droid private IUserService _userService; private IAppIdService _appIdService; private IStorageService _storageService; - private IStateService _stateService; private IEventService _eventService; private PendingIntent _lockAlarmPendingIntent; private PendingIntent _clearClipboardPendingIntent; @@ -67,7 +66,6 @@ namespace Bit.Droid _userService = ServiceContainer.Resolve("userService"); _appIdService = ServiceContainer.Resolve("appIdService"); _storageService = ServiceContainer.Resolve("storageService"); - _stateService = ServiceContainer.Resolve("stateService"); _eventService = ServiceContainer.Resolve("eventService"); TabLayoutResource = Resource.Layout.Tabbar; diff --git a/src/App/App.xaml.cs b/src/App/App.xaml.cs index 8dff50671..699ddac3e 100644 --- a/src/App/App.xaml.cs +++ b/src/App/App.xaml.cs @@ -89,18 +89,7 @@ namespace Bit.App } else if(message.Command == "locked") { - await _stateService.PurgeAsync(); - var autoPromptFingerprint = !(message.Data as bool?).GetValueOrDefault(); - if(autoPromptFingerprint && Device.RuntimePlatform == Device.iOS) - { - var lockOptions = await _storageService.GetAsync(Constants.LockOptionKey); - if(lockOptions == 0) - { - autoPromptFingerprint = false; - } - } - var lockPage = new LockPage(_appOptions, autoPromptFingerprint); - Device.BeginInvokeOnMainThread(() => Current.MainPage = new NavigationPage(lockPage)); + await LockedAsync(!(message.Data as bool?).GetValueOrDefault()); } else if(message.Command == "lockVault") { @@ -398,5 +387,45 @@ namespace Bit.App await _storageService.RemoveAsync(Constants.ClearCiphersCacheKey); } } + + private async Task LockedAsync(bool autoPromptFingerprint) + { + await _stateService.PurgeAsync(); + if(autoPromptFingerprint && Device.RuntimePlatform == Device.iOS) + { + var lockOptions = await _storageService.GetAsync(Constants.LockOptionKey); + if(lockOptions == 0) + { + autoPromptFingerprint = false; + } + } + PreviousPageInfo lastPageBeforeLock = null; + if(Current.MainPage is TabbedPage tabbedPage && tabbedPage.Navigation.ModalStack.Count > 0) + { + var topPage = tabbedPage.Navigation.ModalStack[tabbedPage.Navigation.ModalStack.Count - 1]; + if(topPage is NavigationPage navPage) + { + if(navPage.CurrentPage is ViewPage viewPage) + { + lastPageBeforeLock = new PreviousPageInfo + { + Page = "view", + CipherId = viewPage.ViewModel.CipherId + }; + } + else if(navPage.CurrentPage is AddEditPage addEditPage && addEditPage.ViewModel.EditMode) + { + lastPageBeforeLock = new PreviousPageInfo + { + Page = "edit", + CipherId = addEditPage.ViewModel.CipherId + }; + } + } + } + await _storageService.SaveAsync(Constants.PreviousPageKey, lastPageBeforeLock); + var lockPage = new LockPage(_appOptions, autoPromptFingerprint); + Device.BeginInvokeOnMainThread(() => Current.MainPage = new NavigationPage(lockPage)); + } } } diff --git a/src/App/Models/PreviousPageInfo.cs b/src/App/Models/PreviousPageInfo.cs new file mode 100644 index 000000000..59cfff9a3 --- /dev/null +++ b/src/App/Models/PreviousPageInfo.cs @@ -0,0 +1,9 @@ +namespace Bit.App.Models +{ + public class PreviousPageInfo + { + public string Page { get; set; } + public string CipherId { get; set; } + public string SearchText { get; set; } + } +} diff --git a/src/App/Pages/Accounts/LockPage.xaml.cs b/src/App/Pages/Accounts/LockPage.xaml.cs index ee50ed745..9e1fe7442 100644 --- a/src/App/Pages/Accounts/LockPage.xaml.cs +++ b/src/App/Pages/Accounts/LockPage.xaml.cs @@ -1,4 +1,7 @@ using Bit.App.Models; +using Bit.Core; +using Bit.Core.Abstractions; +using Bit.Core.Utilities; using System; using System.Threading.Tasks; using Xamarin.Forms; @@ -7,6 +10,7 @@ namespace Bit.App.Pages { public partial class LockPage : BaseContentPage { + private readonly IStorageService _storageService; private readonly AppOptions _appOptions; private readonly bool _autoPromptFingerprint; private readonly LockPageViewModel _vm; @@ -16,28 +20,13 @@ namespace Bit.App.Pages public LockPage(AppOptions appOptions = null, bool autoPromptFingerprint = true) { + _storageService = ServiceContainer.Resolve("storageService"); _appOptions = appOptions; _autoPromptFingerprint = autoPromptFingerprint; InitializeComponent(); _vm = BindingContext as LockPageViewModel; _vm.Page = this; - _vm.UnlockedAction = () => Device.BeginInvokeOnMainThread(() => - { - if(_appOptions != null) - { - if(_appOptions.FromAutofillFramework && _appOptions.SaveType.HasValue) - { - Application.Current.MainPage = new NavigationPage(new AddEditPage(appOptions: _appOptions)); - return; - } - else if(_appOptions.Uri != null) - { - Application.Current.MainPage = new NavigationPage(new AutofillCiphersPage(_appOptions)); - return; - } - } - Application.Current.MainPage = new TabsPage(_appOptions); - }); + _vm.UnlockedAction = () => Device.BeginInvokeOnMainThread(async () => await UnlockedAsync()); MasterPasswordEntry = _masterPassword; PinEntry = _pin; } @@ -107,5 +96,28 @@ namespace Bit.App.Pages await _vm.PromptFingerprintAsync(); } } + + private async Task UnlockedAsync() + { + if(_appOptions != null) + { + if(_appOptions.FromAutofillFramework && _appOptions.SaveType.HasValue) + { + Application.Current.MainPage = new NavigationPage(new AddEditPage(appOptions: _appOptions)); + return; + } + else if(_appOptions.Uri != null) + { + Application.Current.MainPage = new NavigationPage(new AutofillCiphersPage(_appOptions)); + return; + } + } + var previousPage = await _storageService.GetAsync(Constants.PreviousPageKey); + if(previousPage != null) + { + await _storageService.RemoveAsync(Constants.PreviousPageKey); + } + Application.Current.MainPage = new TabsPage(_appOptions, previousPage); + } } } diff --git a/src/App/Pages/TabsPage.cs b/src/App/Pages/TabsPage.cs index b3a239da9..ddf4c6115 100644 --- a/src/App/Pages/TabsPage.cs +++ b/src/App/Pages/TabsPage.cs @@ -10,9 +10,9 @@ namespace Bit.App.Pages private NavigationPage _groupingsPage; private NavigationPage _generatorPage; - public TabsPage(AppOptions appOptions = null) + public TabsPage(AppOptions appOptions = null, PreviousPageInfo previousPage = null) { - _groupingsPage = new NavigationPage(new GroupingsPage(true)) + _groupingsPage = new NavigationPage(new GroupingsPage(true, previousPage: previousPage)) { Title = AppResources.MyVault, Icon = "lock.png" diff --git a/src/App/Pages/Vault/AddEditPage.xaml.cs b/src/App/Pages/Vault/AddEditPage.xaml.cs index 4d8cc8496..3348311e5 100644 --- a/src/App/Pages/Vault/AddEditPage.xaml.cs +++ b/src/App/Pages/Vault/AddEditPage.xaml.cs @@ -131,6 +131,7 @@ namespace Bit.App.Pages } public bool FromAutofillFramework { get; set; } + public AddEditPageViewModel ViewModel => _vm; protected override async void OnAppearing() { diff --git a/src/App/Pages/Vault/GroupingsPage/GroupingsPage.xaml.cs b/src/App/Pages/Vault/GroupingsPage/GroupingsPage.xaml.cs index f95d550ec..6335eef2d 100644 --- a/src/App/Pages/Vault/GroupingsPage/GroupingsPage.xaml.cs +++ b/src/App/Pages/Vault/GroupingsPage/GroupingsPage.xaml.cs @@ -1,5 +1,6 @@ using Bit.App.Abstractions; using Bit.App.Controls; +using Bit.App.Models; using Bit.App.Resources; using Bit.Core; using Bit.Core.Abstractions; @@ -22,8 +23,10 @@ namespace Bit.App.Pages private readonly GroupingsPageViewModel _vm; private readonly string _pageName; + private PreviousPageInfo _previousPage; + public GroupingsPage(bool mainPage, CipherType? type = null, string folderId = null, - string collectionId = null, string pageTitle = null) + string collectionId = null, string pageTitle = null, PreviousPageInfo previousPage = null) { _pageName = string.Concat(nameof(GroupingsPage), "_", DateTime.UtcNow.Ticks); InitializeComponent(); @@ -41,6 +44,7 @@ namespace Bit.App.Pages _vm.Type = type; _vm.FolderId = folderId; _vm.CollectionId = collectionId; + _previousPage = previousPage; if(pageTitle != null) { _vm.PageTitle = pageTitle; @@ -125,6 +129,7 @@ namespace Bit.App.Pages await _syncService.FullSyncAsync(true); } } + await ShowPreviousPageAsync(); }, _mainContent); if(!_vm.MainPage) @@ -244,5 +249,22 @@ namespace Bit.App.Pages await Navigation.PushModalAsync(new NavigationPage(page)); } } + + private async Task ShowPreviousPageAsync() + { + if(_previousPage == null) + { + return; + } + if(_previousPage.Page == "view" && !string.IsNullOrWhiteSpace(_previousPage.CipherId)) + { + await Navigation.PushModalAsync(new NavigationPage(new ViewPage(_previousPage.CipherId))); + } + else if(_previousPage.Page == "edit" && !string.IsNullOrWhiteSpace(_previousPage.CipherId)) + { + await Navigation.PushModalAsync(new NavigationPage(new AddEditPage(_previousPage.CipherId))); + } + _previousPage = null; + } } } diff --git a/src/App/Pages/Vault/ViewPage.xaml.cs b/src/App/Pages/Vault/ViewPage.xaml.cs index 485f51ef7..77ec6d07b 100644 --- a/src/App/Pages/Vault/ViewPage.xaml.cs +++ b/src/App/Pages/Vault/ViewPage.xaml.cs @@ -39,6 +39,8 @@ namespace Bit.App.Pages } } + public ViewPageViewModel ViewModel => _vm; + protected override async void OnAppearing() { base.OnAppearing(); diff --git a/src/Core/Constants.cs b/src/Core/Constants.cs index 56547444e..03c53db89 100644 --- a/src/Core/Constants.cs +++ b/src/Core/Constants.cs @@ -32,6 +32,7 @@ public static string MigratedFromV1AutofillPromptShown = "migratedV1AutofillPromptShown"; public static string TriedV1Resync = "triedV1Resync"; public static string EventCollectionKey = "eventCollection"; + public static string PreviousPageKey = "previousPage"; public const int SelectFileRequestCode = 42; public const int SelectFilePermissionRequestCode = 43; }