diff --git a/ModernKeePass/App.xaml.cs b/ModernKeePass/App.xaml.cs index 10980aa..89a17db 100644 --- a/ModernKeePass/App.xaml.cs +++ b/ModernKeePass/App.xaml.cs @@ -1,8 +1,10 @@ using System; +using System.Collections.Generic; using System.Reflection; using Windows.ApplicationModel; using Windows.ApplicationModel.Activation; using Windows.Storage; +using Windows.Storage.Pickers; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; @@ -47,15 +49,28 @@ namespace ModernKeePass ? exception.InnerException : exception; + var database = DatabaseService.Instance; + var resource = new ResourcesService(); if (realException is SaveException) { unhandledExceptionEventArgs.Handled = true; - MessageDialogHelper.SaveErrorDialog(realException as SaveException, DatabaseService.Instance); - } - else if (realException is DatabaseOpenedException) - { - unhandledExceptionEventArgs.Handled = true; - MessageDialogHelper.SaveUnchangedDialog(realException as DatabaseOpenedException, DatabaseService.Instance); + MessageDialogHelper.ShowActionDialog(resource.GetResourceValue("MessageDialogSaveErrorTitle"), + realException.InnerException.Message, + resource.GetResourceValue("MessageDialogSaveErrorButtonSaveAs"), + resource.GetResourceValue("MessageDialogSaveErrorButtonDiscard"), + async command => + { + 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(); + if (file != null) database.Save(file); + }, null); } } @@ -110,17 +125,9 @@ namespace ModernKeePass } var lauchActivatedEventArgs = e as LaunchActivatedEventArgs; - if (lauchActivatedEventArgs != null) - { - if (rootFrame.Content == null) - { - // When the navigation stack isn't restored navigate to the first page, - // configuring the new page by passing required information as a navigation - // parameter - rootFrame.Navigate(typeof(MainPage), lauchActivatedEventArgs.Arguments); - } - } - + if (lauchActivatedEventArgs != null && rootFrame.Content == null) + rootFrame.Navigate(typeof(MainPage), lauchActivatedEventArgs.Arguments); + // Ensure the current window is active Window.Current.Activate(); } @@ -129,7 +136,7 @@ namespace ModernKeePass { var currentFrame = Window.Current.Content as Frame; var database = DatabaseService.Instance; - if (database.DatabaseFile == null) + if (!database.IsOpen) { #if DEBUG ToastNotificationHelper.ShowGenericToast("App suspended", "Nothing to do, no previous database opened"); @@ -191,8 +198,8 @@ namespace ModernKeePass { base.OnFileActivated(args); var rootFrame = new Frame(); - DatabaseService.Instance.DatabaseFile = args.Files[0] as StorageFile; - rootFrame.Navigate(typeof(MainPage), args); + var file = args.Files[0] as StorageFile; + rootFrame.Navigate(typeof(OpenDatabasePage), file); Window.Current.Content = rootFrame; Window.Current.Activate(); } diff --git a/ModernKeePass/Common/MessageDialogHelper.cs b/ModernKeePass/Common/MessageDialogHelper.cs index 72772d0..3d182cb 100644 --- a/ModernKeePass/Common/MessageDialogHelper.cs +++ b/ModernKeePass/Common/MessageDialogHelper.cs @@ -1,15 +1,10 @@ using System; -using System.Collections.Generic; -using Windows.Storage.Pickers; using Windows.UI.Popups; -using ModernKeePass.Exceptions; -using ModernKeePass.Interfaces; namespace ModernKeePass.Common { public static class MessageDialogHelper { - // TODO: include resources public static async void ShowActionDialog(string title, string contentText, string actionButtonText, string cancelButtonText, UICommandInvokedHandler actionCommand, UICommandInvokedHandler cancelCommand) { // Create the message dialog and set its content @@ -21,36 +16,7 @@ namespace ModernKeePass.Common // Show the message dialog await messageDialog.ShowAsync(); } - - public static void SaveErrorDialog(SaveException exception, IDatabaseService database) - { - ShowActionDialog("Save error", exception.InnerException.Message, "Save as", "Discard", async command => - { - var savePicker = new FileSavePicker - { - SuggestedStartLocation = PickerLocationId.DocumentsLibrary, - SuggestedFileName = $"{database.DatabaseFile.DisplayName} - copy" - }; - savePicker.FileTypeChoices.Add("KeePass 2.x database", new List { ".kdbx" }); - - var file = await savePicker.PickSaveFileAsync(); - if (file != null) database.Save(file); - }, null); - } - - public static void SaveUnchangedDialog(DatabaseOpenedException exception, IDatabaseService database) - { - ShowActionDialog("Opened database", $"Database {database.Name} is currently opened. What to you wish to do?", "Save changes", "Discard", command => - { - database.Save(); - database.Close(); - }, - command => - { - database.Close(); - }); - } - + public static async void ShowErrorDialog(Exception exception) { if (exception == null) return; diff --git a/ModernKeePass/Interfaces/IDatabaseService.cs b/ModernKeePass/Interfaces/IDatabaseService.cs index 36b071b..23bbe7c 100644 --- a/ModernKeePass/Interfaces/IDatabaseService.cs +++ b/ModernKeePass/Interfaces/IDatabaseService.cs @@ -1,5 +1,4 @@ -using System.Threading.Tasks; -using Windows.Storage; +using Windows.Storage; using ModernKeePass.ViewModels; using ModernKeePassLib; using ModernKeePassLib.Cryptography.KeyDerivation; @@ -13,17 +12,14 @@ namespace ModernKeePass.Interfaces bool RecycleBinEnabled { get; set; } GroupVm RootGroup { get; set; } GroupVm RecycleBin { get; set; } - StorageFile DatabaseFile { get; set; } CompositeKey CompositeKey { get; set; } PwUuid DataCipher { get; set; } PwCompressionAlgorithm CompressionAlgorithm { get; set; } KdfParameters KeyDerivation { get; set; } bool IsOpen { get; } - bool IsFileOpen { get; } - bool IsClosed { get; } bool HasChanged { get; set; } - void Open(CompositeKey key, bool createNew = false); + void Open(StorageFile databaseFile, CompositeKey key, bool createNew = false); void ReOpen(); void Save(); void Save(StorageFile file); diff --git a/ModernKeePass/Services/DatabaseService.cs b/ModernKeePass/Services/DatabaseService.cs index 53b06ac..99a6c07 100644 --- a/ModernKeePass/Services/DatabaseService.cs +++ b/ModernKeePass/Services/DatabaseService.cs @@ -33,26 +33,13 @@ namespace ModernKeePass.Services } } - public string Name => DatabaseFile?.Name; + public string Name => _databaseFile?.Name; public bool RecycleBinEnabled { get { return _pwDatabase.RecycleBinEnabled; } set { _pwDatabase.RecycleBinEnabled = value; } } - - public StorageFile DatabaseFile - { - get { return _databaseFile; } - set - { - if (IsOpen && HasChanged) - { - throw new DatabaseOpenedException(); - } - _databaseFile = value; - } - } public CompositeKey CompositeKey { get; set; } @@ -92,10 +79,11 @@ namespace ModernKeePass.Services /// /// Open a KeePass database /// + /// The database file /// The database composite key /// True to create a new database before opening it /// An error message, if any - public void Open(CompositeKey key, bool createNew = false) + public void Open(StorageFile databaseFile, CompositeKey key, bool createNew = false) { try { @@ -105,7 +93,7 @@ namespace ModernKeePass.Services } CompositeKey = key; - var ioConnection = IOConnectionInfo.FromFile(DatabaseFile); + var ioConnection = IOConnectionInfo.FromFile(databaseFile); if (createNew) { _pwDatabase.New(ioConnection, key); @@ -121,7 +109,8 @@ namespace ModernKeePass.Services } } else _pwDatabase.Open(ioConnection, key, new NullStatusLogger()); - + + _databaseFile = databaseFile; RootGroup = new GroupVm(_pwDatabase.RootGroup, null, RecycleBinEnabled ? _pwDatabase.RecycleBinUuid : null); } catch (InvalidCompositeKeyException ex) @@ -133,7 +122,7 @@ namespace ModernKeePass.Services public void ReOpen() { - Open(CompositeKey); + Open(_databaseFile, CompositeKey); } /// @@ -158,15 +147,15 @@ namespace ModernKeePass.Services /// The new database file public void Save(StorageFile file) { - var oldFile = DatabaseFile; - DatabaseFile = file; + var oldFile = _databaseFile; + _databaseFile = file; try { - _pwDatabase.SaveAs(IOConnectionInfo.FromFile(DatabaseFile), true, new NullStatusLogger()); + _pwDatabase.SaveAs(IOConnectionInfo.FromFile(_databaseFile), true, new NullStatusLogger()); } catch { - DatabaseFile = oldFile; + _databaseFile = oldFile; throw; } } @@ -177,7 +166,7 @@ namespace ModernKeePass.Services public void Close(bool releaseFile = true) { _pwDatabase?.Close(); - if (releaseFile) DatabaseFile = null; + if (releaseFile) _databaseFile = null; } public void AddDeletedItem(PwUuid id) diff --git a/ModernKeePass/Strings/en-US/CodeBehind.resw b/ModernKeePass/Strings/en-US/CodeBehind.resw index e3273cf..dc123e7 100644 --- a/ModernKeePass/Strings/en-US/CodeBehind.resw +++ b/ModernKeePass/Strings/en-US/CodeBehind.resw @@ -270,4 +270,28 @@ Current + + Discard + + + Save changes + + + Database {0} is currently opened. What would you wish to do? + + + Opened database + + + Discard + + + Save as + + + KeePass 2.x database + + + Save error + \ No newline at end of file diff --git a/ModernKeePass/Strings/fr-FR/CodeBehind.resw b/ModernKeePass/Strings/fr-FR/CodeBehind.resw index afbcc62..18ab9bd 100644 --- a/ModernKeePass/Strings/fr-FR/CodeBehind.resw +++ b/ModernKeePass/Strings/fr-FR/CodeBehind.resw @@ -270,4 +270,28 @@ Courante + + Abandonner + + + Sauvegarder + + + La base de données {0} est actuellement ouverte. Que souhaitez-vous faire ? + + + Base de données ouverte + + + Abandonner + + + Sauvegarder sous + + + Base de données KeePass 2.x + + + Erreur de sauvegarde + \ No newline at end of file diff --git a/ModernKeePass/ViewModels/CompositeKeyVm.cs b/ModernKeePass/ViewModels/CompositeKeyVm.cs index 2115226..8e9ebe1 100644 --- a/ModernKeePass/ViewModels/CompositeKeyVm.cs +++ b/ModernKeePass/ViewModels/CompositeKeyVm.cs @@ -3,6 +3,7 @@ using System.Text; using System.Threading.Tasks; using Windows.Storage; using ModernKeePass.Common; +using ModernKeePass.Exceptions; using ModernKeePass.Interfaces; using ModernKeePass.Services; using ModernKeePassLib.Cryptography; @@ -120,12 +121,12 @@ namespace ModernKeePass.ViewModels Database = database; } - public async Task OpenDatabase(bool createNew) + public async Task OpenDatabase(StorageFile databaseFile, bool createNew) { try { _isOpening = true; - Database.Open(CreateCompositeKey(), createNew); + Database.Open(databaseFile, CreateCompositeKey(), createNew); await Task.Run(() => RootGroup = Database.RootGroup); return true; } diff --git a/ModernKeePass/ViewModels/Items/RecentItemVm.cs b/ModernKeePass/ViewModels/Items/RecentItemVm.cs index 52ebff2..f9cbd60 100644 --- a/ModernKeePass/ViewModels/Items/RecentItemVm.cs +++ b/ModernKeePass/ViewModels/Items/RecentItemVm.cs @@ -27,17 +27,7 @@ namespace ModernKeePass.ViewModels Name = metadata; DatabaseFile = file as StorageFile; } - - public void OpenDatabaseFile() - { - OpenDatabaseFile(DatabaseService.Instance); - } - - public void OpenDatabaseFile(IDatabaseService database) - { - database.DatabaseFile = DatabaseFile; - } - + public void UpdateAccessTime() { UpdateAccessTime(RecentService.Instance); diff --git a/ModernKeePass/ViewModels/MainVm.cs b/ModernKeePass/ViewModels/MainVm.cs index 8fffd94..7443dc1 100644 --- a/ModernKeePass/ViewModels/MainVm.cs +++ b/ModernKeePass/ViewModels/MainVm.cs @@ -60,8 +60,7 @@ namespace ModernKeePass.ViewModels PageType = typeof(OpenDatabasePage), Destination = destinationFrame, Parameter = referenceFrame, - SymbolIcon = Symbol.Page2, - IsSelected = database != null && database.IsFileOpen && !database.IsOpen + SymbolIcon = Symbol.Page2 }, new MainMenuItemVm { @@ -89,7 +88,7 @@ namespace ModernKeePass.ViewModels Parameter = referenceFrame, SymbolIcon = Symbol.Copy, IsSelected = - (database == null || database.IsClosed) && + (database == null || !database.IsOpen) && recent.EntryCount > 0, IsEnabled = recent.EntryCount > 0 }, diff --git a/ModernKeePass/ViewModels/OpenVm.cs b/ModernKeePass/ViewModels/OpenVm.cs index 0559587..1b77f4f 100644 --- a/ModernKeePass/ViewModels/OpenVm.cs +++ b/ModernKeePass/ViewModels/OpenVm.cs @@ -7,19 +7,18 @@ namespace ModernKeePass.ViewModels { public class OpenVm: NotifyPropertyChangedBase { - public bool ShowPasswordBox => _database.IsFileOpen; + public bool IsFileSelected => DatabaseFile != null; - public string Name => _database?.Name; + public string Name => DatabaseFile.DisplayName; - private readonly IDatabaseService _database; + public StorageFile DatabaseFile { get; private set; } - public OpenVm() : this(DatabaseService.Instance) { } + public OpenVm() : this(null) { } - public OpenVm(IDatabaseService database) + public OpenVm(StorageFile file) { - _database = database; - if (database == null || !database.IsFileOpen) return; - OpenFile(database.DatabaseFile); + if (!IsFileSelected) return; + OpenFile(file); } public void OpenFile(StorageFile file) @@ -29,9 +28,9 @@ namespace ModernKeePass.ViewModels public void OpenFile(StorageFile file, IRecentService recent) { - _database.DatabaseFile = file; + DatabaseFile = file; OnPropertyChanged("Name"); - OnPropertyChanged("ShowPasswordBox"); + OnPropertyChanged("IsFileSelected"); AddToRecentList(file, recent); } diff --git a/ModernKeePass/Views/MainPage.xaml.cs b/ModernKeePass/Views/MainPage.xaml.cs index 021b876..a38dbfb 100644 --- a/ModernKeePass/Views/MainPage.xaml.cs +++ b/ModernKeePass/Views/MainPage.xaml.cs @@ -23,6 +23,7 @@ namespace ModernKeePass.Views private new void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) { base.ListView_SelectionChanged(sender, e); + var selectedItem = Model.SelectedItem as MainMenuItemVm; if (selectedItem == null) MenuFrame.Navigate(typeof(WelcomePage)); else selectedItem.Destination.Navigate(selectedItem.PageType, selectedItem.Parameter); diff --git a/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml b/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml index 2de06f1..59bab03 100644 --- a/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml +++ b/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml @@ -23,7 +23,7 @@ - + diff --git a/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml b/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml index 28c8c13..a5e058a 100644 --- a/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml +++ b/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml @@ -24,7 +24,7 @@ - + diff --git a/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml.cs b/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml.cs index 2464840..28764af 100644 --- a/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml.cs +++ b/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml.cs @@ -1,7 +1,7 @@ using System; +using Windows.Storage; using Windows.Storage.Pickers; using Windows.UI.Xaml; -using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; using ModernKeePass.ViewModels; @@ -14,8 +14,6 @@ namespace ModernKeePass.Views /// public sealed partial class OpenDatabasePage { - private Frame _mainFrame; - public OpenVm Model => (OpenVm)DataContext; public OpenDatabasePage() @@ -26,7 +24,11 @@ namespace ModernKeePass.Views protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); - _mainFrame = e.Parameter as Frame; + var file = e.Parameter as StorageFile; + if (file != null) + { + Model.OpenFile(file); + } } private async void ButtonBase_OnClick(object sender, RoutedEventArgs e) diff --git a/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml b/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml index c45764e..ec60627 100644 --- a/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml +++ b/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml @@ -45,8 +45,8 @@ Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroungBrushConverter}}" Visibility="{Binding ShowComplexityIndicator, ElementName=UserControl, Converter={StaticResource BooleanToVisibilityConverter}}" /> - - + + diff --git a/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs b/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs index fcc1b7c..fdebffd 100644 --- a/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs +++ b/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs @@ -1,11 +1,15 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; +using Windows.Storage; using Windows.Storage.Pickers; using Windows.System; using Windows.UI.Xaml; using Windows.UI.Xaml.Input; +using ModernKeePass.Common; using ModernKeePass.Events; using ModernKeePass.Extensions; +using ModernKeePass.Interfaces; using ModernKeePass.Services; using ModernKeePass.ViewModels; @@ -53,6 +57,17 @@ namespace ModernKeePass.Views.UserControls typeof(CompositeKeyUserControl), new PropertyMetadata("OK", (o, args) => { })); + public StorageFile DatabaseFile + { + get { return (StorageFile)GetValue(DatabaseFileProperty); } + set { SetValue(DatabaseFileProperty, value); } + } + public static readonly DependencyProperty DatabaseFileProperty = + DependencyProperty.Register( + "DatabaseFile", + typeof(StorageFile), + typeof(CompositeKeyUserControl), + new PropertyMetadata(null, (o, args) => { })); public bool ShowComplexityIndicator => CreateNew || UpdateKey; @@ -77,14 +92,30 @@ namespace ModernKeePass.Views.UserControls } else { + var database = DatabaseService.Instance; var resource = new ResourcesService(); - var oldLabel = ButtonLabel; - ButtonLabel = resource.GetResourceValue("CompositeKeyOpening"); - if (await Dispatcher.RunTaskAsync(async () => await Model.OpenDatabase(CreateNew))) + if (database.IsOpen) { - ValidationChecked?.Invoke(this, new PasswordEventArgs(Model.RootGroup)); + MessageDialogHelper.ShowActionDialog(resource.GetResourceValue("MessageDialogDBOpenTitle"), + string.Format(resource.GetResourceValue("MessageDialogDBOpenDesc"), database.Name), + resource.GetResourceValue("MessageDialogDBOpenButtonSave"), + resource.GetResourceValue("MessageDialogDBOpenButtonDiscard"), + async command => + { + database.Save(); + database.Close(false); + await OpenDatabase(resource); + }, + async command => + { + database.Close(false); + await OpenDatabase(resource); + }); + } + else + { + await OpenDatabase(resource); } - ButtonLabel = oldLabel; } } @@ -128,5 +159,17 @@ namespace ModernKeePass.Views.UserControls Model.CreateKeyFile(file); } + + private async Task OpenDatabase(IResourceService resource) + { + var oldLabel = ButtonLabel; + ButtonLabel = resource.GetResourceValue("CompositeKeyOpening"); + if (await Dispatcher.RunTaskAsync(async () => await Model.OpenDatabase(DatabaseFile, CreateNew))) + { + ValidationChecked?.Invoke(this, new PasswordEventArgs(Model.RootGroup)); + } + + ButtonLabel = oldLabel; + } } } diff --git a/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt b/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt index 37b6e66..7031cb7 100644 --- a/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt +++ b/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt @@ -1,2 +1,3 @@ +Entry history feature added Design improvements KeePassLib version bump to 2.39.1 \ 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 55d4ef2..46fdffa 100644 --- a/ModernKeePass/appMetadata/fr-fr/baselisting/releaseNotes.txt +++ b/ModernKeePass/appMetadata/fr-fr/baselisting/releaseNotes.txt @@ -1,2 +1,3 @@ +Ajout de la fonctionnalite d'historique des entrees Ameliorations de design Version de la KeePassLib passe a 2.39.1 \ No newline at end of file