diff --git a/ModernKeePass/Actions/ToastAction.cs b/ModernKeePass/Actions/ToastAction.cs new file mode 100644 index 0000000..e6da006 --- /dev/null +++ b/ModernKeePass/Actions/ToastAction.cs @@ -0,0 +1,33 @@ +using Windows.UI.Xaml; +using Microsoft.Xaml.Interactivity; +using ModernKeePass.Common; + +namespace ModernKeePass.Actions +{ + public class ToastAction : DependencyObject, IAction + { + public string Title + { + get { return (string)GetValue(TitleProperty); } + set { SetValue(TitleProperty, value); } + } + + public static readonly DependencyProperty TitleProperty = + DependencyProperty.Register("Title", typeof(string), typeof(ToastAction), new PropertyMetadata(string.Empty)); + + public string Message + { + get { return (string)GetValue(MessageProperty); } + set { SetValue(MessageProperty, value); } + } + + public static readonly DependencyProperty MessageProperty = + DependencyProperty.Register("Message", typeof(string), typeof(ToastAction), new PropertyMetadata(string.Empty)); + + public object Execute(object sender, object parameter) + { + ToastNotificationHelper.ShowGenericToast(Title, Message); + return null; + } + } +} \ No newline at end of file diff --git a/ModernKeePass/App.xaml.cs b/ModernKeePass/App.xaml.cs index 4d4957d..6255ae4 100644 --- a/ModernKeePass/App.xaml.cs +++ b/ModernKeePass/App.xaml.cs @@ -114,7 +114,8 @@ namespace ModernKeePass if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) { - //TODO: Load state from previously terminated application + // Load state from previously terminated application + await SuspensionManager.RestoreAsync(); #if DEBUG await MessageDialogHelper.ShowNotificationDialog("App terminated", "Windows or an error made the app terminate"); #endif @@ -164,7 +165,7 @@ namespace ModernKeePass /// Details about the navigation failure void OnNavigationFailed(object sender, NavigationFailedEventArgs e) { - throw new Exception("Failed to load Page " + e.SourcePageType.FullName); + throw new NavigationException(e.SourcePageType); } /// @@ -174,7 +175,7 @@ namespace ModernKeePass /// /// The source of the suspend request. /// Details about the suspend request. - private void OnSuspending(object sender, SuspendingEventArgs e) + private async void OnSuspending(object sender, SuspendingEventArgs e) { var deferral = e.SuspendingOperation.GetDeferral(); var database = DatabaseService.Instance; @@ -187,6 +188,7 @@ namespace ModernKeePass { ToastNotificationHelper.ShowErrorToast(exception); } + await SuspensionManager.SaveAsync(); deferral.Complete(); } diff --git a/ModernKeePass/Common/SuspensionManager.cs b/ModernKeePass/Common/SuspensionManager.cs index da57a4e..3b00613 100644 --- a/ModernKeePass/Common/SuspensionManager.cs +++ b/ModernKeePass/Common/SuspensionManager.cs @@ -17,7 +17,7 @@ namespace ModernKeePass.Common /// carry across sessions, but that should be discarded when an application crashes or is /// upgraded. /// - internal sealed class SuspensionManager + internal static class SuspensionManager { private static Dictionary _sessionState = new Dictionary(); private static readonly List _knownTypes = new List(); diff --git a/ModernKeePass/Exceptions/DatabaseOpenedException.cs b/ModernKeePass/Exceptions/DatabaseOpenedException.cs deleted file mode 100644 index 52f2b01..0000000 --- a/ModernKeePass/Exceptions/DatabaseOpenedException.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace ModernKeePass.Exceptions -{ - public class DatabaseOpenedException: Exception - { - - } -} diff --git a/ModernKeePass/Exceptions/NavigationException.cs b/ModernKeePass/Exceptions/NavigationException.cs new file mode 100644 index 0000000..a42109f --- /dev/null +++ b/ModernKeePass/Exceptions/NavigationException.cs @@ -0,0 +1,11 @@ +using System; + +namespace ModernKeePass.Exceptions +{ + public class NavigationException: Exception + { + public NavigationException(Type pageType) : base($"Failed to load Page {pageType.FullName}") + { + } + } +} \ No newline at end of file diff --git a/ModernKeePass/ModernKeePass.App.csproj b/ModernKeePass/ModernKeePass.App.csproj index c889842..2f71684 100644 --- a/ModernKeePass/ModernKeePass.App.csproj +++ b/ModernKeePass/ModernKeePass.App.csproj @@ -111,11 +111,12 @@ + App.xaml - + diff --git a/ModernKeePass/Strings/en-US/CodeBehind.resw b/ModernKeePass/Strings/en-US/CodeBehind.resw index dc123e7..5314966 100644 --- a/ModernKeePass/Strings/en-US/CodeBehind.resw +++ b/ModernKeePass/Strings/en-US/CodeBehind.resw @@ -294,4 +294,7 @@ Save error + + Database successfully saved! + \ No newline at end of file diff --git a/ModernKeePass/Strings/en-US/Resources.resw b/ModernKeePass/Strings/en-US/Resources.resw index 1a15826..2359568 100644 --- a/ModernKeePass/Strings/en-US/Resources.resw +++ b/ModernKeePass/Strings/en-US/Resources.resw @@ -387,4 +387,13 @@ History + + Login successfully copied! + + + Password successfully copied! + + + URL successfully copied! + \ No newline at end of file diff --git a/ModernKeePass/Strings/fr-FR/CodeBehind.resw b/ModernKeePass/Strings/fr-FR/CodeBehind.resw index 18ab9bd..c7e8214 100644 --- a/ModernKeePass/Strings/fr-FR/CodeBehind.resw +++ b/ModernKeePass/Strings/fr-FR/CodeBehind.resw @@ -187,7 +187,7 @@ Attention - Suprression + Suppression Restauré @@ -208,10 +208,10 @@ Entrée replacée dans son groupe d'origine - Groupe supprimé défnitivement + Groupe supprimé définitivement - Êtes-vous sûr de vouloir supprimer ce group et toutes ses entrées ? + Êtes-vous sûr de vouloir supprimer ce groupe et toutes ses entrées ? Groupe placé dans la Corbeille @@ -294,4 +294,7 @@ Erreur de sauvegarde + + Base de données sauvegardée avec succès ! + \ No newline at end of file diff --git a/ModernKeePass/Strings/fr-FR/Resources.resw b/ModernKeePass/Strings/fr-FR/Resources.resw index b33fda5..9845612 100644 --- a/ModernKeePass/Strings/fr-FR/Resources.resw +++ b/ModernKeePass/Strings/fr-FR/Resources.resw @@ -387,4 +387,13 @@ Historique + + Login copié avec succès ! + + + Mot de passe copié avec succès ! + + + URL copié avec succès ! + \ No newline at end of file diff --git a/ModernKeePass/Views/GroupDetailPage.xaml b/ModernKeePass/Views/GroupDetailPage.xaml index 0464e7b..ee6c65f 100644 --- a/ModernKeePass/Views/GroupDetailPage.xaml +++ b/ModernKeePass/Views/GroupDetailPage.xaml @@ -153,6 +153,7 @@ + @@ -160,6 +161,7 @@ + @@ -167,6 +169,7 @@ + diff --git a/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs b/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs index a476e34..c7253aa 100644 --- a/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs +++ b/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs @@ -103,6 +103,9 @@ namespace ModernKeePass.Views.UserControls async command => { database.Save(); + ToastNotificationHelper.ShowGenericToast( + database.Name, + resource.GetResourceValue("ToastSavedMessage")); database.Close(false); await OpenDatabase(resource); }, diff --git a/ModernKeePassApp.Test/DatabaseTests.cs b/ModernKeePassApp.Test/DatabaseTests.cs index 77965ac..cf5286f 100644 --- a/ModernKeePassApp.Test/DatabaseTests.cs +++ b/ModernKeePassApp.Test/DatabaseTests.cs @@ -17,9 +17,8 @@ namespace ModernKeePassApp.Test public void TestCreate() { Assert.IsTrue(_database.IsClosed); - _database.DatabaseFile = ApplicationData.Current.TemporaryFolder.CreateFileAsync("NewDatabase.kdbx").GetAwaiter().GetResult(); - Assert.IsTrue(_database.IsFileOpen); - OpenOrCreateDatabase(true); + var databaseFile = ApplicationData.Current.TemporaryFolder.CreateFileAsync("NewDatabase.kdbx").GetAwaiter().GetResult(); + OpenOrCreateDatabase(databaseFile, true); _database.Close(); Assert.IsTrue(_database.IsClosed); } @@ -28,9 +27,8 @@ namespace ModernKeePassApp.Test public void TestOpen() { Assert.IsTrue(_database.IsClosed); - _database.DatabaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Data\TestDatabase.kdbx").GetAwaiter().GetResult(); - Assert.IsTrue(_database.IsFileOpen); - OpenOrCreateDatabase(false); + var databaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Data\TestDatabase.kdbx").GetAwaiter().GetResult(); + OpenOrCreateDatabase(databaseFile, false); } [TestMethod] @@ -44,16 +42,16 @@ namespace ModernKeePassApp.Test TestOpen(); } - private void OpenOrCreateDatabase(bool createNew) + private void OpenOrCreateDatabase(StorageFile databaseFile, bool createNew) { Assert.ThrowsException( - () => _database.Open(null, createNew)); + () => _database.Open(databaseFile, null, createNew)); var compositeKey = new CompositeKeyVm(_database, new ResourceServiceMock()) { HasPassword = true, Password = "test" }; - compositeKey.OpenDatabase(createNew).GetAwaiter().GetResult(); + compositeKey.OpenDatabase(databaseFile, createNew).GetAwaiter().GetResult(); Assert.IsTrue(_database.IsOpen); } } diff --git a/ModernKeePassApp.Test/Mock/DatabaseServiceMock.cs b/ModernKeePassApp.Test/Mock/DatabaseServiceMock.cs index 767f5c5..20f6731 100644 --- a/ModernKeePassApp.Test/Mock/DatabaseServiceMock.cs +++ b/ModernKeePassApp.Test/Mock/DatabaseServiceMock.cs @@ -11,13 +11,11 @@ namespace ModernKeePassApp.Test.Mock public class DatabaseServiceMock : IDatabaseService { private bool _isOpen; - private bool _isClosed; private CompositeKey _compositeKey; - + private StorageFile _databaseFile; + public PwCompressionAlgorithm CompressionAlgorithm { get; set; } - - public StorageFile DatabaseFile { get; set; } - + public CompositeKey CompositeKey { get { return _compositeKey; } @@ -30,10 +28,6 @@ namespace ModernKeePassApp.Test.Mock public bool IsOpen => _isOpen; - public bool IsFileOpen => DatabaseFile != null; - - public bool IsClosed => _isClosed; - public bool HasChanged { get; set; } public string Name => "MockDatabase"; @@ -51,7 +45,6 @@ namespace ModernKeePassApp.Test.Mock public void Close(bool releaseFile = true) { - _isClosed = true; _isOpen = false; } @@ -59,17 +52,17 @@ namespace ModernKeePassApp.Test.Mock { throw new NotImplementedException(); } - - public void Open(CompositeKey key, bool createNew = false) + + public void Open(StorageFile databaseFile, CompositeKey key, bool createNew = false) { + _databaseFile = databaseFile; _compositeKey = key; _isOpen = true; - _isClosed = false; } public void ReOpen() { - Open(_compositeKey); + Open(_databaseFile, _compositeKey); } public void Save() diff --git a/ModernKeePassApp.Test/ViewModelsTests.cs b/ModernKeePassApp.Test/ViewModelsTests.cs index 056d743..affb584 100644 --- a/ModernKeePassApp.Test/ViewModelsTests.cs +++ b/ModernKeePassApp.Test/ViewModelsTests.cs @@ -31,15 +31,15 @@ namespace ModernKeePassApp.Test var mainVm = new MainVm(null, null, database, _resource, _recent); Assert.AreEqual(1, mainVm.MainMenuItems.Count()); var firstGroup = mainVm.MainMenuItems.FirstOrDefault(); - Assert.AreEqual(7, firstGroup.Count()); + Assert.AreEqual(7, firstGroup?.Count()); - database.DatabaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Data\TestDatabase.kdbx") + var databaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Data\TestDatabase.kdbx") .GetAwaiter().GetResult(); - mainVm = new MainVm(null, null, database, _resource, _recent); + mainVm = new MainVm(null, null, database, _resource, _recent, databaseFile); Assert.IsNotNull(mainVm.SelectedItem); Assert.AreEqual(typeof(OpenDatabasePage), ((MainMenuItemVm) mainVm.SelectedItem).PageType); - database.Open(null); + database.Open(databaseFile, null); mainVm = new MainVm(null, null, database, _resource, _recent); Assert.IsNotNull(mainVm.SelectedItem); Assert.AreEqual(2, mainVm.MainMenuItems.Count()); @@ -51,7 +51,7 @@ namespace ModernKeePassApp.Test { var database = new DatabaseServiceMock(); var compositeKeyVm = new CompositeKeyVm(database, _resource); - Assert.IsTrue(compositeKeyVm.OpenDatabase(false).GetAwaiter().GetResult()); + Assert.IsTrue(compositeKeyVm.OpenDatabase(null, false).GetAwaiter().GetResult()); compositeKeyVm.StatusType = 1; compositeKeyVm.Password = "test"; Assert.AreEqual(0, compositeKeyVm.StatusType); @@ -61,13 +61,10 @@ namespace ModernKeePassApp.Test [TestMethod] public void TestOpenVm() { - var database = new DatabaseServiceMock - { - DatabaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Data\TestDatabase.kdbx") - .GetAwaiter().GetResult() - }; - var openVm = new OpenVm(database); - Assert.IsTrue(openVm.ShowPasswordBox); + var databaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Data\TestDatabase.kdbx") + .GetAwaiter().GetResult(); + var openVm = new OpenVm(databaseFile); + Assert.IsTrue(openVm.IsFileSelected); Assert.AreEqual("MockDatabase", openVm.Name); } @@ -94,7 +91,7 @@ namespace ModernKeePassApp.Test { var database = new DatabaseServiceMock(); var saveVm = new SaveVm(database); - database.Open(null); + database.Open(null, null); saveVm.Save(false); Assert.IsTrue(database.IsOpen); saveVm.Save(); @@ -108,7 +105,7 @@ namespace ModernKeePassApp.Test Assert.AreEqual(1, settingsVm.MenuItems.Count()); var firstGroup = settingsVm.MenuItems.FirstOrDefault(); // All groups have an empty title, so all settings are put inside the empty group - Assert.AreEqual(4, firstGroup.Count()); + Assert.AreEqual(4, firstGroup?.Count()); Assert.IsNotNull(settingsVm.SelectedItem); var selectedItem = (ListMenuItemVm) settingsVm.SelectedItem; Assert.AreEqual(typeof(SettingsNewDatabasePage), selectedItem.PageType);