From 7917a8b3884f2997cfc9f8c72f008700119f11a7 Mon Sep 17 00:00:00 2001 From: Geoffroy BONNEVILLE Date: Tue, 28 Apr 2020 20:14:18 +0200 Subject: [PATCH] Updated release notes Moved ViewModelLocator WIP ModernKeePass10 --- ModernKeePass.sln | 12 +- ModernKeePass/App.xaml.cs | 3 +- ModernKeePass/DependencyInjection.cs | 1 - .../ViewModels/ViewModelLocator.cs | 0 ModernKeePass/Win81App.csproj | 1 + .../en-us/baselisting/releaseNotes.txt | 6 +- .../fr-fr/baselisting/releaseNotes.txt | 12 +- ModernKeePass10/App.xaml.cs | 172 +++++++++++++----- ModernKeePass10/DependencyInjection.cs | 39 ++++ ModernKeePass10/Win10App.csproj | 99 +++++++++- ModernKeePass10/packages.config | 45 +++++ WinAppCommon/WinAppCommon.projitems | 1 - 12 files changed, 323 insertions(+), 68 deletions(-) rename {WinAppCommon => ModernKeePass}/ViewModels/ViewModelLocator.cs (100%) create mode 100644 ModernKeePass10/DependencyInjection.cs create mode 100644 ModernKeePass10/packages.config diff --git a/ModernKeePass.sln b/ModernKeePass.sln index ac51e9a..9b93f70 100644 --- a/ModernKeePass.sln +++ b/ModernKeePass.sln @@ -103,8 +103,8 @@ Global {42353562-5E43-459C-8E3E-2F21E575261D}.Debug|ARM.Build.0 = Debug|ARM {42353562-5E43-459C-8E3E-2F21E575261D}.Debug|x64.ActiveCfg = Debug|x64 {42353562-5E43-459C-8E3E-2F21E575261D}.Debug|x64.Build.0 = Debug|x64 - {42353562-5E43-459C-8E3E-2F21E575261D}.Debug|x86.ActiveCfg = Debug|Any CPU - {42353562-5E43-459C-8E3E-2F21E575261D}.Debug|x86.Build.0 = Debug|Any CPU + {42353562-5E43-459C-8E3E-2F21E575261D}.Debug|x86.ActiveCfg = Debug|x86 + {42353562-5E43-459C-8E3E-2F21E575261D}.Debug|x86.Build.0 = Debug|x86 {42353562-5E43-459C-8E3E-2F21E575261D}.Release|Any CPU.ActiveCfg = Release|Any CPU {42353562-5E43-459C-8E3E-2F21E575261D}.Release|Any CPU.Build.0 = Release|Any CPU {42353562-5E43-459C-8E3E-2F21E575261D}.Release|ARM.ActiveCfg = Release|ARM @@ -119,8 +119,8 @@ Global {9A0759F1-9069-4841-99E3-3BEC44E17356}.Debug|ARM.Build.0 = Debug|ARM {9A0759F1-9069-4841-99E3-3BEC44E17356}.Debug|x64.ActiveCfg = Debug|x64 {9A0759F1-9069-4841-99E3-3BEC44E17356}.Debug|x64.Build.0 = Debug|x64 - {9A0759F1-9069-4841-99E3-3BEC44E17356}.Debug|x86.ActiveCfg = Debug|Any CPU - {9A0759F1-9069-4841-99E3-3BEC44E17356}.Debug|x86.Build.0 = Debug|Any CPU + {9A0759F1-9069-4841-99E3-3BEC44E17356}.Debug|x86.ActiveCfg = Debug|x86 + {9A0759F1-9069-4841-99E3-3BEC44E17356}.Debug|x86.Build.0 = Debug|x86 {9A0759F1-9069-4841-99E3-3BEC44E17356}.Release|Any CPU.ActiveCfg = Release|Any CPU {9A0759F1-9069-4841-99E3-3BEC44E17356}.Release|Any CPU.Build.0 = Release|Any CPU {9A0759F1-9069-4841-99E3-3BEC44E17356}.Release|ARM.ActiveCfg = Release|ARM @@ -135,8 +135,8 @@ Global {09577E4C-4899-45B9-BF80-1803D617CCAE}.Debug|ARM.Build.0 = Debug|ARM {09577E4C-4899-45B9-BF80-1803D617CCAE}.Debug|x64.ActiveCfg = Debug|x64 {09577E4C-4899-45B9-BF80-1803D617CCAE}.Debug|x64.Build.0 = Debug|x64 - {09577E4C-4899-45B9-BF80-1803D617CCAE}.Debug|x86.ActiveCfg = Debug|Any CPU - {09577E4C-4899-45B9-BF80-1803D617CCAE}.Debug|x86.Build.0 = Debug|Any CPU + {09577E4C-4899-45B9-BF80-1803D617CCAE}.Debug|x86.ActiveCfg = Debug|x86 + {09577E4C-4899-45B9-BF80-1803D617CCAE}.Debug|x86.Build.0 = Debug|x86 {09577E4C-4899-45B9-BF80-1803D617CCAE}.Release|Any CPU.ActiveCfg = Release|Any CPU {09577E4C-4899-45B9-BF80-1803D617CCAE}.Release|Any CPU.Build.0 = Release|Any CPU {09577E4C-4899-45B9-BF80-1803D617CCAE}.Release|ARM.ActiveCfg = Release|ARM diff --git a/ModernKeePass/App.xaml.cs b/ModernKeePass/App.xaml.cs index 6590e6e..61019f2 100644 --- a/ModernKeePass/App.xaml.cs +++ b/ModernKeePass/App.xaml.cs @@ -24,7 +24,6 @@ using ModernKeePass.Common; using ModernKeePass.Domain.Dtos; using ModernKeePass.Domain.Exceptions; using ModernKeePass.Infrastructure; -using ModernKeePass.Views; // The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227 @@ -187,7 +186,7 @@ namespace ModernKeePass } catch (Exception) { - currentFrame?.Navigate(typeof(MainPage)); + _navigation.NavigateTo(Constants.Navigation.MainPage); #if DEBUG _notification.Show("App resumed", "Nothing to do, no previous database opened"); #endif diff --git a/ModernKeePass/DependencyInjection.cs b/ModernKeePass/DependencyInjection.cs index 646338c..0854bfc 100644 --- a/ModernKeePass/DependencyInjection.cs +++ b/ModernKeePass/DependencyInjection.cs @@ -1,6 +1,5 @@ using System.Reflection; using AutoMapper; -using GalaSoft.MvvmLight.Messaging; using GalaSoft.MvvmLight.Views; using Microsoft.Extensions.DependencyInjection; using Microsoft.HockeyApp; diff --git a/WinAppCommon/ViewModels/ViewModelLocator.cs b/ModernKeePass/ViewModels/ViewModelLocator.cs similarity index 100% rename from WinAppCommon/ViewModels/ViewModelLocator.cs rename to ModernKeePass/ViewModels/ViewModelLocator.cs diff --git a/ModernKeePass/Win81App.csproj b/ModernKeePass/Win81App.csproj index 19b32c4..ed6ec2c 100644 --- a/ModernKeePass/Win81App.csproj +++ b/ModernKeePass/Win81App.csproj @@ -94,6 +94,7 @@ + DonatePage.xaml diff --git a/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt b/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt index 2cbde5e..9473ccd 100644 --- a/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt +++ b/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt @@ -1,5 +1,7 @@ -Database corruption issues should now be a thing of the past ! +Database corruption issues should now be a thing of the past: + Database integrity is checked after each save + Data is written to the filesystem using a transactional model (meaning: if an error occurs, the original file is left untouched) + Auto-save on suspend/exit is now only active when database has changes and its size is under 1MB Added the ability to move entries and groups -Edits are now in a popup instead of inline Allows restoring and deleting from entry history Updated KeePass lib to version 2.44 \ No newline at end of file diff --git a/ModernKeePass/appMetadata/fr-fr/baselisting/releaseNotes.txt b/ModernKeePass/appMetadata/fr-fr/baselisting/releaseNotes.txt index 507719d..50b536b 100644 --- a/ModernKeePass/appMetadata/fr-fr/baselisting/releaseNotes.txt +++ b/ModernKeePass/appMetadata/fr-fr/baselisting/releaseNotes.txt @@ -1,5 +1,7 @@ -Amelioration de la recherche -Changer l'icone d'une entree cree un historique -Correction de crash lors du lancement avec certaines versions de Windows -Le bouton de suppression d'une entree apparait bien desormais -La liste des icones n'affiche desormais que des valeurs valables \ No newline at end of file +Les problemes de corruption de bases de données sont maintenant totalement corrigees : + L'integrite de la base de donnees est verfiee apres chaque sauvegarde + Les donnees sont ecrites dans le systeme de fichiers en utilisant un modele transactionnel (autrement dit, s'il y a une erreur, le fichier original n'est pas modifie) + L'auto-sauvegarde lors de la suspension/sortie ne se fait que lorsqu'il y a eu des changements et que la taille de la base de donnees est inferieure a 1MB +Possibilite de deplacer des groupes et des entree +Possibilite de supprimer et restaurer des versions de l'historique d'entrees +Libraire mise a jour en version 2.44 \ No newline at end of file diff --git a/ModernKeePass10/App.xaml.cs b/ModernKeePass10/App.xaml.cs index 33de2b3..4d7dadb 100644 --- a/ModernKeePass10/App.xaml.cs +++ b/ModernKeePass10/App.xaml.cs @@ -10,13 +10,22 @@ using Windows.Storage.Pickers; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; -using UnhandledExceptionEventArgs = Windows.UI.Xaml.UnhandledExceptionEventArgs; +using GalaSoft.MvvmLight.Views; +using MediatR; using Microsoft.AppCenter; using Microsoft.AppCenter.Analytics; +using Microsoft.AppCenter.Crashes; +using Microsoft.Extensions.DependencyInjection; +using ModernKeePass.Application; +using ModernKeePass.Application.Common.Interfaces; +using ModernKeePass.Application.Database.Commands.CloseDatabase; +using ModernKeePass.Application.Database.Commands.SaveDatabase; +using ModernKeePass.Application.Database.Queries.GetDatabase; +using ModernKeePass.Application.Database.Queries.ReOpenDatabase; using ModernKeePass.Common; using ModernKeePass.Domain.Dtos; using ModernKeePass.Domain.Exceptions; -using ModernKeePass.Domain.Interfaces; +using ModernKeePass.Infrastructure; using ModernKeePass.Views; // The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227 @@ -28,26 +37,53 @@ namespace ModernKeePass /// sealed partial class App { + private readonly IResourceProxy _resource; + private readonly IMediator _mediator; + private readonly ISettingsProxy _settings; + private readonly INavigationService _navigation; + private readonly IAppCenterService _appCenter; + private readonly IDialogService _dialog; + private readonly INotificationService _notification; + + public static IServiceProvider Services { get; private set; } + /// /// Initializes the singleton application object. This is the first line of authored code /// executed, and as such is the logical equivalent of main() or WinMain(). /// public App() { - AppCenter.Start("79d23520-a486-4f63-af81-8d90bf4e1bea", typeof(Analytics)); + // Setup DI + IServiceCollection serviceCollection = new ServiceCollection(); + serviceCollection.AddApplication(); + serviceCollection.AddInfrastructureCommon(); + serviceCollection.AddInfrastructureKeePass(); + serviceCollection.AddInfrastructureUwp(); + serviceCollection.AddWin10App(); + Services = serviceCollection.BuildServiceProvider(); + + _mediator = Services.GetService(); + _resource = Services.GetService(); + _settings = Services.GetService(); + _navigation = Services.GetService(); + _dialog = Services.GetService(); + _notification = Services.GetService(); + +#if DEBUG + AppCenter.Start("029ab91d-1e4b-4d4d-9661-5d438dd671a5", + typeof(Analytics), typeof(Crashes)); +#else + AppCenter.Start("79d23520-a486-4f63-af81-8d90bf4e1bea", typeof(Analytics)); +#endif InitializeComponent(); Suspending += OnSuspending; Resuming += OnResuming; UnhandledException += OnUnhandledException; - - // Setup DI - } #region Event Handlers - // TODO: do something else here instead of showing dialog and handle save issues directly where it happens private async void OnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs) { // Save the argument exception because it's cleared on first access @@ -58,33 +94,40 @@ namespace ModernKeePass ? exception.InnerException : exception; - var resource = Container.Resolve(); if (realException is SaveException) { unhandledExceptionEventArgs.Handled = true; - await MessageDialogHelper.ShowActionDialog(resource.GetResourceValue("MessageDialogSaveErrorTitle"), - realException.InnerException.Message, - resource.GetResourceValue("MessageDialogSaveErrorButtonSaveAs"), - resource.GetResourceValue("MessageDialogSaveErrorButtonDiscard"), - async command => + //_hockey.TrackException(realException); + await _dialog.ShowMessage(realException.Message, + _resource.GetResourceValue("MessageDialogSaveErrorTitle"), + _resource.GetResourceValue("MessageDialogSaveErrorButtonSaveAs"), + _resource.GetResourceValue("MessageDialogSaveErrorButtonDiscard"), + async isOk => { - var savePicker = new FileSavePicker + if (isOk) { - SuggestedStartLocation = PickerLocationId.DocumentsLibrary, - SuggestedFileName = $"{_databaseService.Name} - copy" - }; - savePicker.FileTypeChoices.Add(resource.GetResourceValue("MessageDialogSaveErrorFileTypeDesc"), - new List {".kdbx"}); + var database = await _mediator.Send(new GetDatabaseQuery()); + var savePicker = new FileSavePicker + { + SuggestedStartLocation = PickerLocationId.DocumentsLibrary, + SuggestedFileName = $"{database.Name} - copy" + }; + savePicker.FileTypeChoices.Add( + _resource.GetResourceValue("MessageDialogSaveErrorFileTypeDesc"), + new List { ".kdbx" }); - var file = await savePicker.PickSaveFileAsync(); - var token = StorageApplicationPermissions.FutureAccessList.Add(file); - var fileInfo = new FileInfo - { - Path = token, - Name = file.DisplayName - }; - await _databaseService.SaveAs(fileInfo); - }, null); + var file = await savePicker.PickSaveFileAsync().AsTask(); + if (file != null) + { + var token = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name); + await _mediator.Send(new SaveDatabaseCommand { FilePath = token }); + } + } + }); + } + else + { + await _dialog.ShowError(realException, realException.Message, "OK", () => { }); } } @@ -96,6 +139,7 @@ namespace ModernKeePass protected override async void OnLaunched(LaunchActivatedEventArgs args) { await OnLaunchOrActivated(args); + //await _hockey.SendCrashesAsync(/* sendWithoutAsking: true */); } protected override async void OnActivated(IActivatedEventArgs args) @@ -105,12 +149,14 @@ namespace ModernKeePass private async Task OnLaunchOrActivated(IActivatedEventArgs e) { + var rootFrame = Window.Current.Content as Frame; + // Do not repeat app initialization when the Window already has content, // just ensure that the window is active - if (!(Window.Current.Content is Frame rootFrame)) + if (rootFrame == null) { // Create a Frame to act as the navigation context and navigate to the first page - rootFrame = new Frame(); + rootFrame = new Frame { Language = Windows.Globalization.ApplicationLanguages.Languages[0] }; // Set the default language rootFrame.NavigationFailed += OnNavigationFailed; @@ -120,7 +166,7 @@ namespace ModernKeePass // Load state from previously terminated application await SuspensionManager.RestoreAsync(); #if DEBUG - await MessageDialogHelper.ShowNotificationDialog("App terminated", "Windows or an error made the app terminate"); + await _dialog.ShowMessage("Windows or an error made the app terminate", "App terminated"); #endif } @@ -128,31 +174,30 @@ namespace ModernKeePass Window.Current.Content = rootFrame; } - if (e is LaunchActivatedEventArgs lauchActivatedEventArgs && rootFrame.Content == null) - { - rootFrame.Navigate(typeof(MainPage10), lauchActivatedEventArgs.Arguments); - } + var launchActivatedEventArgs = e as LaunchActivatedEventArgs; + if (launchActivatedEventArgs != null && rootFrame.Content == null) + _navigation.NavigateTo(Constants.Navigation.MainPage, launchActivatedEventArgs.Arguments); // Ensure the current window is active Window.Current.Activate(); } - private void OnResuming(object sender, object e) + private async void OnResuming(object sender, object e) { var currentFrame = Window.Current.Content as Frame; try { - //_databaseService.ReOpen(); + await _mediator.Send(new ReOpenDatabaseQuery()); #if DEBUG - ToastNotificationHelper.ShowGenericToast(_databaseService.Name, "Database reopened (changes were saved)"); + _notification.Show("App resumed", "Database reopened (changes were saved)"); #endif } catch (Exception) { currentFrame?.Navigate(typeof(MainPage10)); #if DEBUG - ToastNotificationHelper.ShowGenericToast("App resumed", "Nothing to do, no previous database opened"); + _notification.Show("App resumed", "Nothing to do, no previous database opened"); #endif } } @@ -177,21 +222,31 @@ namespace ModernKeePass private async void OnSuspending(object sender, SuspendingEventArgs e) { var deferral = e.SuspendingOperation.GetDeferral(); - var settings = Container.Resolve(); try { - // TODO: definitely do something about this to avoid DB corruption if app closes before save has completed - if (settings.GetSetting("SaveSuspend", true)) await _databaseService.Save(); - _databaseService.Close(); + var database = await _mediator.Send(new GetDatabaseQuery()); + if (database.IsOpen) + { + if (database.Size < Constants.File.OneMegaByte && database.IsDirty && + _settings.GetSetting(Constants.Settings.SaveSuspend, true)) + { + await _mediator.Send(new SaveDatabaseCommand()).ConfigureAwait(false); + } + + await _mediator.Send(new CloseDatabaseCommand()).ConfigureAwait(false); + } } catch (Exception exception) { - ToastNotificationHelper.ShowErrorToast(exception); + _notification.Show(exception.Source, exception.Message); + } + finally + { + await SuspensionManager.SaveAsync().ConfigureAwait(false); + deferral.Complete(); } - await SuspensionManager.SaveAsync(); - deferral.Complete(); } - + /// /// Invoked when application is launched from opening a file in Windows Explorer /// @@ -200,11 +255,30 @@ namespace ModernKeePass { base.OnFileActivated(args); var rootFrame = new Frame(); - rootFrame.Navigate(typeof(MainPage10), args.Files[0] as StorageFile); + var file = args.Files[0] as StorageFile; + Window.Current.Content = rootFrame; + + if (file != null) + { + // TODO: use service + var token = StorageApplicationPermissions.MostRecentlyUsedList.Add(file, file.Path); + var fileInfo = new FileInfo + { + Id = token, + Name = file.DisplayName, + Path = file.Path + }; + _navigation.NavigateTo(Constants.Navigation.MainPage, fileInfo); + } + else + { + _navigation.NavigateTo(Constants.Navigation.MainPage); + } + Window.Current.Activate(); } - + #endregion } } diff --git a/ModernKeePass10/DependencyInjection.cs b/ModernKeePass10/DependencyInjection.cs new file mode 100644 index 0000000..280f719 --- /dev/null +++ b/ModernKeePass10/DependencyInjection.cs @@ -0,0 +1,39 @@ +using System.Reflection; +using AutoMapper; +using GalaSoft.MvvmLight.Views; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AppCenter; +using Microsoft.AppCenter.Analytics; +using Microsoft.AppCenter.Crashes; +using ModernKeePass.Common; +using ModernKeePass.Views; + +namespace ModernKeePass +{ + public static class DependencyInjection + { + public static IServiceCollection AddWin10App(this IServiceCollection services) + { + var applicationAssembly = typeof(Application.DependencyInjection).GetTypeInfo().Assembly; + var infrastructureAssembly = typeof(Infrastructure.DependencyInjection).GetTypeInfo().Assembly; + services.AddAutoMapper(applicationAssembly, infrastructureAssembly); + + services.AddSingleton(provider => + { + var nav = new NavigationService(); + nav.Configure(Constants.Navigation.MainPage, typeof(MainPage10)); + nav.Configure(Constants.Navigation.EntryPage, typeof(EntryPage)); + nav.Configure(Constants.Navigation.GroupPage, typeof(EntriesPage)); + return nav; + }); + services.AddTransient(typeof(IDialogService), typeof(DialogService)); + + services.AddSingleton(provider => + { + + }); + + return services; + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Win10App.csproj b/ModernKeePass10/Win10App.csproj index 4226156..2e4a7a1 100644 --- a/ModernKeePass10/Win10App.csproj +++ b/ModernKeePass10/Win10App.csproj @@ -1,5 +1,19 @@  + + + + + + + + + + + + + + Debug @@ -12,8 +26,8 @@ ModernKeePass en-US true - 10.0.14393.0 - 10.0.14393.0 + 10.0.18362.0 + 10.0.17763.0 14 512 {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} @@ -99,6 +113,7 @@ App.xaml + UpdateCredentialsUserControl.xaml @@ -448,11 +463,91 @@ Infrastructure + + + + + + ..\packages\AutoMapper.Extensions.Microsoft.DependencyInjection.7.0.0\lib\netstandard2.0\AutoMapper.Extensions.Microsoft.DependencyInjection.dll + True + + + ..\packages\Microsoft.AppCenter.Crashes.3.2.1\lib\uap10.0\Microsoft.AppCenter.Crashes.dll + True + + + ..\packages\SQLitePCLRaw.bundle_green.2.0.2\lib\netstandard2.0\SQLitePCLRaw.batteries_v2.dll + True + + + ..\packages\SQLitePCLRaw.core.2.0.2\lib\netstandard2.0\SQLitePCLRaw.core.dll + True + + + ..\packages\SQLitePCLRaw.provider.e_sqlite3.2.0.2\lib\uap10.0\SQLitePCLRaw.provider.e_sqlite3.dll + True + + + ..\packages\System.Reflection.Emit.4.7.0\lib\netcore50\System.Reflection.Emit.dll + True + + + ..\packages\System.Reflection.Emit.ILGeneration.4.7.0\lib\netcore50\System.Reflection.Emit.ILGeneration.dll + True + + 14.0 + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +