From 56d93a5187d695e62d3a24e53a2ee37176b3204c Mon Sep 17 00:00:00 2001 From: Geoffroy BONNEVILLE Date: Mon, 6 Apr 2020 20:20:45 +0200 Subject: [PATCH] Moved application code to the Application layer Imported Win10 project Code cleanup WIP - Use common UWP services for Win8.1 and Win10 --- .../Common/Interfaces/IDatabaseProxy.cs | 18 +- .../Common/Interfaces/IImportFormat.cs | 2 +- .../CloseDatabase/CloseDatabaseCommand.cs | 10 +- .../CreateDatabase/CreateDatabaseCommand.cs | 14 +- .../SaveDatabase/SaveDatabaseCommand.cs | 22 +- .../UpdateCredentialsCommand.cs | 17 +- .../Queries/GetDatabase/GetDatabaseQuery.cs | 1 - .../Queries/OpenDatabase/OpenDatabaseQuery.cs | 15 +- .../ReOpenDatabase/ReOpenDatabaseQuery.cs | 7 +- .../DeleteEntry/DeleteEntryCommand.cs | 16 +- .../DeleteGroup/DeleteGroupCommand.cs | 16 +- .../SetRecycleBin/SetRecycleBinCommand.cs | 2 +- ModernKeePass.Domain/Domain.csproj | 1 + ModernKeePass.Domain/Dtos/Credentials.cs | 2 +- .../Interfaces/IImportFormat.cs | 10 + .../DependencyInjection.cs | 19 +- .../File/CsvImportFormat.cs | 13 +- .../KeePass/KeePassDatabaseClient.cs | 171 +- .../AboutViewModelTests.cs | 17 + .../ModernKeePassApp.ViewModelTest.csproj | 25 + ModernKeePass.sln | 42 + ModernKeePass/Actions/DeleteEntityAction.cs | 6 +- ModernKeePass/App.xaml.cs | 58 +- ModernKeePass/Common/NavigationHelper.cs | 4 - .../Common/NotifyPropertyChangedBase.cs | 28 - .../ResourceHelper.cs} | 7 +- .../Common/ToastNotificationHelper.cs | 1 - .../ImportFormats/CsvImportFormat.cs | 35 - .../ImportFormats/NullImportFormat.cs | 16 - ModernKeePass/Interfaces/IFormat.cs | 11 - .../Interfaces/IProxyInvocationHandler.cs | 9 - ModernKeePass/Interfaces/IRecentItem.cs | 11 - ModernKeePass/Interfaces/IRecentService.cs | 15 - ModernKeePass/Interfaces/IResourceService.cs | 7 - ModernKeePass/Interfaces/ISettingsService.cs | 8 - ModernKeePass/Services/DatabaseService.cs | 194 - ModernKeePass/Services/ImportService.cs | 25 - ModernKeePass/Services/RecentService.cs | 50 - ModernKeePass/Services/SettingsService.cs | 31 - .../Services/SingletonServiceBase.cs | 12 - ModernKeePass/ViewModels/CompositeKeyVm.cs | 50 +- ModernKeePass/ViewModels/EntryDetailVm.cs | 34 +- ModernKeePass/ViewModels/GroupDetailVm.cs | 4 +- .../ViewModels/Items/ListMenuItemVm.cs | 3 +- .../ViewModels/Items/RecentItemVm.cs | 33 +- .../ViewModels/Items/SettingsDatabaseVm.cs | 5 +- .../ViewModels/Items/SettingsNewVm.cs | 10 +- .../ViewModels/Items/SettingsSaveVm.cs | 10 +- ModernKeePass/ViewModels/MainVm.cs | 14 +- ModernKeePass/ViewModels/NewVm.cs | 12 +- ModernKeePass/ViewModels/OpenVm.cs | 38 +- ModernKeePass/ViewModels/RecentVm.cs | 19 +- ModernKeePass/ViewModels/SaveVm.cs | 3 +- ModernKeePass/ViewModels/SettingsVm.cs | 9 +- .../Views/BasePages/LayoutAwarePageBase.cs | 1 - ModernKeePass/Views/MainPage.xaml.cs | 6 +- .../Views/MainPageFrames/NewDatabasePage.xaml | 2 +- .../MainPageFrames/NewDatabasePage.xaml.cs | 22 +- .../MainPageFrames/OpenDatabasePage.xaml | 11 +- .../MainPageFrames/OpenDatabasePage.xaml.cs | 19 +- .../MainPageFrames/RecentDatabasesPage.xaml | 2 +- .../UserControls/CompositeKeyUserControl.xaml | 4 +- .../CompositeKeyUserControl.xaml.cs | 56 +- ModernKeePass/Win81App.csproj | 15 +- ModernKeePass10/.gitignore | 37 + .../conf/0/ProjectOutFolderPath.txt | 1 + .../conf/SonarQubeAnalysisConfig.xml | 171 + .../conf/SonarQubeRoslyn-cs.ruleset | 348 + .../conf/SonarQubeRoslyn-vbnet.ruleset | 74 + .../.sonarqube/conf/cs/SonarLint.xml | 695 + .../.sonarqube/conf/vbnet/SonarLint.xml | 186 + .../.sonarqube/out/.sonar/.sonar_lock | 0 .../.sonarqube/out/.sonar/report-task.txt | 7 + .../.sonarqube/out/0/FilesToAnalyze.txt | Bin 0 -> 32608 bytes .../.sonarqube/out/0/ProjectInfo.xml | 18 + .../.sonarqube/out/0/output-cs/encoding.pb | 85 + .../out/0/output-cs/file-metadata.pb | 139 + .../.sonarqube/out/0/output-cs/metrics.pb | 180 + .../.sonarqube/out/0/output-cs/symrefs.pb | 2912 ++ .../.sonarqube/out/0/output-cs/token-cpd.pb | 24951 ++++++++++++++++ .../.sonarqube/out/0/output-cs/token-type.pb | 2160 ++ .../.sonarqube/out/sonar-project.properties | 210 + ModernKeePass10/.sonarqube/out/summary.md | 3 + ModernKeePass10/Actions/ClipboardAction.cs | 27 + ModernKeePass10/Actions/DeleteEntityAction.cs | 65 + .../Actions/NavigateToUrlAction.cs | 33 + ModernKeePass10/Actions/SetupFocusAction.cs | 27 + ModernKeePass10/Actions/ToastAction.cs | 33 + ModernKeePass10/App.xaml | 20 + ModernKeePass10/App.xaml.cs | 221 + ModernKeePass10/Assets/Logo.scale-100.png | Bin 0 -> 1907 bytes ModernKeePass10/Assets/Logo.scale-140.png | Bin 0 -> 2552 bytes ModernKeePass10/Assets/Logo.scale-180.png | Bin 0 -> 3238 bytes ModernKeePass10/Assets/Logo.scale-80.png | Bin 0 -> 1569 bytes .../ModernKeePass-SmallLogo.scale-100.png | Bin 0 -> 700 bytes .../ModernKeePass-SmallLogo.scale-140.png | Bin 0 -> 907 bytes .../ModernKeePass-SmallLogo.scale-180.png | Bin 0 -> 1059 bytes .../ModernKeePass-SmallLogo.scale-80.png | Bin 0 -> 607 bytes .../ModernKeePass-SmallLogo.targetsize-16.png | Bin 0 -> 463 bytes ...ModernKeePass-SmallLogo.targetsize-256.png | Bin 0 -> 3772 bytes .../ModernKeePass-SmallLogo.targetsize-32.png | Bin 0 -> 736 bytes .../ModernKeePass-SmallLogo.targetsize-48.png | Bin 0 -> 980 bytes .../ModernKeePass-SplashScreen.scale-100.png | Bin 0 -> 4751 bytes .../ModernKeePass-SplashScreen.scale-140.png | Bin 0 -> 6856 bytes .../ModernKeePass-SplashScreen.scale-180.png | Bin 0 -> 9459 bytes .../Assets/SmallLogo.scale-100.png | Bin 0 -> 700 bytes .../Assets/SmallLogo.scale-140.png | Bin 0 -> 907 bytes .../Assets/SmallLogo.scale-180.png | Bin 0 -> 1059 bytes ModernKeePass10/Assets/SmallLogo.scale-80.png | Bin 0 -> 607 bytes .../Assets/SmallLogo.targetsize-16.png | Bin 0 -> 463 bytes .../Assets/SmallLogo.targetsize-256.png | Bin 0 -> 3772 bytes .../Assets/SmallLogo.targetsize-32.png | Bin 0 -> 736 bytes .../Assets/SmallLogo.targetsize-48.png | Bin 0 -> 980 bytes .../Assets/SplashScreen.scale-100.png | Bin 0 -> 4751 bytes .../Assets/SplashScreen.scale-140.png | Bin 0 -> 6856 bytes .../Assets/SplashScreen.scale-180.png | Bin 0 -> 9459 bytes .../Assets/Square310x310Logo.scale-100.png | Bin 0 -> 3556 bytes .../Assets/Square310x310Logo.scale-140.png | Bin 0 -> 5137 bytes .../Assets/Square310x310Logo.scale-180.png | Bin 0 -> 6864 bytes .../Assets/Square310x310Logo.scale-80.png | Bin 0 -> 2910 bytes .../Assets/Square70x70Logo.scale-100.png | Bin 0 -> 1217 bytes .../Assets/Square70x70Logo.scale-140.png | Bin 0 -> 1508 bytes .../Assets/Square70x70Logo.scale-180.png | Bin 0 -> 1776 bytes .../Assets/Square70x70Logo.scale-80.png | Bin 0 -> 1039 bytes .../Assets/StoreLogo.scale-100.png | Bin 0 -> 728 bytes .../Assets/StoreLogo.scale-140.png | Bin 0 -> 961 bytes .../Assets/StoreLogo.scale-180.png | Bin 0 -> 1097 bytes .../Assets/Wide310x150Logo.scale-100.png | Bin 0 -> 2393 bytes .../Assets/Wide310x150Logo.scale-140.png | Bin 0 -> 3348 bytes .../Assets/Wide310x150Logo.scale-180.png | Bin 0 -> 4484 bytes .../Assets/Wide310x150Logo.scale-80.png | Bin 0 -> 2076 bytes .../Backup/ModernKeePassApp.csproj | 489 + ModernKeePass10/Backup/project.json | 24 + ModernKeePass10/Common/MessageDialogHelper.cs | 56 + ModernKeePass10/Common/NavigationHelper.cs | 433 + .../Common/ObservableDictionary.cs | 141 + ModernKeePass10/Common/RelayCommand.cs | 78 + ModernKeePass10/Common/ResourceHelper.cs | 16 + ModernKeePass10/Common/SuspensionManager.cs | 260 + .../Common/ToastNotificationHelper.cs | 53 + .../Controls/ListViewWithDisable.cs | 20 + ModernKeePass10/Controls/TextBoxWithButton.cs | 56 + .../BooleanToVisibilityConverter.cs | 29 + .../Converters/ColorToBrushConverter.cs | 22 + .../DiscreteIntToSolidColorBrushConverter.cs | 27 + .../DoubleToSolidColorBrushConverter.cs | 31 + .../EmptyStringToVisibilityConverter.cs | 20 + .../Converters/IconToSymbolConverter.cs | 122 + .../InverseBooleanToVisibilityConverter.cs | 28 + .../Converters/NullToBooleanConverter.cs | 18 + .../Converters/PluralizationConverter.cs | 24 + .../ProgressBarLegalValuesConverter.cs | 27 + .../Converters/TextToWidthConverter.cs | 20 + ModernKeePass10/Events/PasswordEventArgs.cs | 15 + .../Extensions/DispatcherTaskExtensions.cs | 32 + ModernKeePass10/Package.StoreAssociation.xml | 368 + ModernKeePass10/Package.appxmanifest | 55 + ModernKeePass10/Properties/Annotations.cs | 1065 + ModernKeePass10/Properties/AssemblyInfo.cs | 28 + ModernKeePass10/Properties/default.rd.xml | 9 + .../HamburgerButtonStyle.xaml | 60 + .../ListViewLeftIndicatorStyle.xaml | 399 + .../MasterDetailsView.xaml | 197 + .../NoBorderButtonStyle.xaml | 115 + .../NoBorderToggleButtonStyle.xaml | 204 + .../ResourceDictionaries/Styles.xaml | 1986 ++ .../TextBoxWithButtonStyle.xaml | 253 + ModernKeePass10/Strings/en-US/CodeBehind.resw | 222 + ModernKeePass10/Strings/en-US/Resources.resw | 555 + ModernKeePass10/Strings/fr-FR/CodeBehind.resw | 222 + ModernKeePass10/Strings/fr-FR/Resources.resw | 558 + .../FirstItemDataTemplateSelector.cs | 18 + .../SelectableDataTemplateSelector.cs | 18 + ModernKeePass10/ViewModels/AboutViewModel.cs | 27 + .../ViewModels/EntriesViewModel.cs | 71 + ModernKeePass10/ViewModels/GroupsViewModel.cs | 57 + .../ListItems/EntryItemViewModel.cs | 147 + .../ListItems/GroupItemViewModel.cs | 101 + .../ListItems/ListMenuItemViewModel.cs | 31 + .../ListItems/MainMenuItemViewModel.cs | 10 + .../ListItems/RecentItemViewModel.cs | 36 + .../ListItems/SettingsDatabaseViewModel.cs | 101 + .../ListItems/SettingsNewViewModel.cs | 33 + .../ListItems/SettingsSaveViewModel.cs | 24 + ModernKeePass10/ViewModels/MainViewModel.cs | 30 + ModernKeePass10/ViewModels/NewViewModel.cs | 99 + ModernKeePass10/ViewModels/Old/EntryVm.cs | 322 + ModernKeePass10/ViewModels/Old/GroupVm.cs | 257 + ModernKeePass10/ViewModels/OpenViewModel.cs | 44 + ModernKeePass10/ViewModels/RecentViewModel.cs | 69 + ModernKeePass10/ViewModels/SaveViewModel.cs | 31 + .../ViewModels/SettingsViewModel.cs | 20 + .../UserControls/CredentialsViewModel.cs | 149 + .../UpdateCredentialsViewModel.cs | 93 + .../Views/BasePages/LayoutAwarePageBase.cs | 206 + ModernKeePass10/Views/EntriesPage.xaml | 266 + ModernKeePass10/Views/EntriesPage.xaml.cs | 94 + ModernKeePass10/Views/EntryPage.xaml | 168 + ModernKeePass10/Views/EntryPage.xaml.cs | 21 + ModernKeePass10/Views/GroupsPage.xaml | 249 + ModernKeePass10/Views/GroupsPage.xaml.cs | 194 + ModernKeePass10/Views/MainPage10.xaml | 36 + ModernKeePass10/Views/MainPage10.xaml.cs | 95 + .../Views/MainPageFrames/AboutPage.xaml | 39 + .../Views/MainPageFrames/AboutPage.xaml.cs | 15 + .../Views/MainPageFrames/DonatePage.xaml | 20 + .../Views/MainPageFrames/DonatePage.xaml.cs | 15 + .../MainPageFrames/ImportExportPage.xaml | 37 + .../MainPageFrames/ImportExportPage.xaml.cs | 35 + .../Views/MainPageFrames/NewDatabasePage.xaml | 47 + .../MainPageFrames/NewDatabasePage.xaml.cs | 101 + .../MainPageFrames/OpenDatabasePage.xaml | 30 + .../MainPageFrames/OpenDatabasePage.xaml.cs | 58 + .../MainPageFrames/RecentDatabasesPage.xaml | 70 + .../RecentDatabasesPage.xaml.cs | 20 + .../MainPageFrames/SaveDatabasePage.xaml | 15 + .../MainPageFrames/SaveDatabasePage.xaml.cs | 57 + .../Views/MainPageFrames/WelcomePage.xaml | 19 + .../Views/MainPageFrames/WelcomePage.xaml.cs | 15 + .../Views/Old/EntryDetailPage.xaml | 572 + .../Views/Old/EntryDetailPage.xaml.cs | 78 + .../Views/Old/GroupDetailPage.xaml | 326 + .../Views/Old/GroupDetailPage.xaml.cs | 142 + ModernKeePass10/Views/Old/MainPage.xaml | 148 + ModernKeePass10/Views/Old/MainPage.xaml.cs | 40 + ModernKeePass10/Views/Old/SettingsPage.xaml | 147 + .../Views/Old/SettingsPage.xaml.cs | 31 + ModernKeePass10/Views/SettingsPage10.xaml | 33 + ModernKeePass10/Views/SettingsPage10.xaml.cs | 67 + .../SettingsDatabasePage.xaml | 23 + .../SettingsDatabasePage.xaml.cs | 20 + .../SettingsNewDatabasePage.xaml | 37 + .../SettingsNewDatabasePage.xaml.cs | 20 + .../SettingsPageFrames/SettingsSavePage.xaml | 14 + .../SettingsSavePage.xaml.cs | 19 + .../SettingsSecurityPage.xaml | 28 + .../SettingsSecurityPage.xaml.cs | 15 + .../SettingsWelcomePage.xaml | 14 + .../SettingsWelcomePage.xaml.cs | 15 + .../UserControls/BreadCrumbUserControl.xaml | 46 + .../BreadCrumbUserControl.xaml.cs | 29 + .../UserControls/ColorPickerUserControl.xaml | 24 + .../ColorPickerUserControl.xaml.cs | 61 + .../UserControls/CredentialsUserControl.xaml | 55 + .../CredentialsUserControl.xaml.cs | 126 + .../HamburgerMenuUserControl.xaml | 119 + .../HamburgerMenuUserControl.xaml.cs | 115 + .../UserControls/SymbolPickerUserControl.xaml | 24 + .../SymbolPickerUserControl.xaml.cs | 40 + .../UserControls/TopMenuUserControl.xaml | 101 + .../UserControls/TopMenuUserControl.xaml.cs | 195 + .../UpdateCredentialsUserControl.xaml | 72 + .../UpdateCredentialsUserControl.xaml.cs | 87 + ModernKeePass10/Win10App.csproj | 527 + .../en-us/baselisting/description.txt | 6 + .../baselisting/images/Screenshot/Entry.png | Bin 0 -> 36486 bytes .../baselisting/images/Screenshot/Group.png | Bin 0 -> 35447 bytes .../baselisting/images/Screenshot/New.png | Bin 0 -> 23177 bytes .../baselisting/images/Screenshot/Open.png | Bin 0 -> 22794 bytes .../baselisting/images/Screenshot/Recent.png | Bin 0 -> 22992 bytes .../images/Screenshot/Semantic.png | Bin 0 -> 26308 bytes .../images/Screenshot/Settings.png | Bin 0 -> 18109 bytes .../images/Screenshot/description.Entry.txt | 1 + .../images/Screenshot/description.Group.txt | 1 + .../images/Screenshot/description.New.txt | 1 + .../images/Screenshot/description.Open.txt | 1 + .../images/Screenshot/description.Recent.txt | 1 + .../Screenshot/description.Semantic.txt | 1 + .../Screenshot/description.Settings.txt | 1 + .../en-us/baselisting/keywords.txt | 4 + .../en-us/baselisting/privacyPolicy.txt | 1 + .../en-us/baselisting/releaseNotes.txt | 1 + .../en-us/baselisting/websiteUrl.txt | 1 + .../fr-fr/baselisting/description.txt | 6 + .../baselisting/images/Screenshot/Entry.png | Bin 0 -> 37658 bytes .../baselisting/images/Screenshot/Group.png | Bin 0 -> 36161 bytes .../baselisting/images/Screenshot/New.png | Bin 0 -> 25595 bytes .../baselisting/images/Screenshot/Open.png | Bin 0 -> 25099 bytes .../baselisting/images/Screenshot/Recent.png | Bin 0 -> 23304 bytes .../images/Screenshot/Semantic.png | Bin 0 -> 27299 bytes .../images/Screenshot/Settings.png | Bin 0 -> 19809 bytes .../images/Screenshot/description.Entry.txt | 1 + .../images/Screenshot/description.Group.txt | 1 + .../images/Screenshot/description.New.txt | 1 + .../images/Screenshot/description.Open.txt | 1 + .../images/Screenshot/description.Recent.txt | 1 + .../Screenshot/description.Semantic.txt | 1 + .../Screenshot/description.Settings.txt | 1 + .../fr-fr/baselisting/keywords.txt | 5 + .../fr-fr/baselisting/privacyPolicy.txt | 1 + .../fr-fr/baselisting/releaseNotes.txt | 1 + .../fr-fr/baselisting/websiteUrl.txt | 1 + 292 files changed, 48614 insertions(+), 837 deletions(-) create mode 100644 ModernKeePass.Domain/Interfaces/IImportFormat.cs create mode 100644 ModernKeePass.ViewModelTest/AboutViewModelTests.cs create mode 100644 ModernKeePass.ViewModelTest/ModernKeePassApp.ViewModelTest.csproj delete mode 100644 ModernKeePass/Common/NotifyPropertyChangedBase.cs rename ModernKeePass/{Services/ResourcesService.cs => Common/ResourceHelper.cs} (77%) delete mode 100644 ModernKeePass/ImportFormats/CsvImportFormat.cs delete mode 100644 ModernKeePass/ImportFormats/NullImportFormat.cs delete mode 100644 ModernKeePass/Interfaces/IFormat.cs delete mode 100644 ModernKeePass/Interfaces/IProxyInvocationHandler.cs delete mode 100644 ModernKeePass/Interfaces/IRecentItem.cs delete mode 100644 ModernKeePass/Interfaces/IRecentService.cs delete mode 100644 ModernKeePass/Interfaces/IResourceService.cs delete mode 100644 ModernKeePass/Interfaces/ISettingsService.cs delete mode 100644 ModernKeePass/Services/DatabaseService.cs delete mode 100644 ModernKeePass/Services/ImportService.cs delete mode 100644 ModernKeePass/Services/RecentService.cs delete mode 100644 ModernKeePass/Services/SettingsService.cs delete mode 100644 ModernKeePass/Services/SingletonServiceBase.cs create mode 100644 ModernKeePass10/.gitignore create mode 100644 ModernKeePass10/.sonarqube/conf/0/ProjectOutFolderPath.txt create mode 100644 ModernKeePass10/.sonarqube/conf/SonarQubeAnalysisConfig.xml create mode 100644 ModernKeePass10/.sonarqube/conf/SonarQubeRoslyn-cs.ruleset create mode 100644 ModernKeePass10/.sonarqube/conf/SonarQubeRoslyn-vbnet.ruleset create mode 100644 ModernKeePass10/.sonarqube/conf/cs/SonarLint.xml create mode 100644 ModernKeePass10/.sonarqube/conf/vbnet/SonarLint.xml create mode 100644 ModernKeePass10/.sonarqube/out/.sonar/.sonar_lock create mode 100644 ModernKeePass10/.sonarqube/out/.sonar/report-task.txt create mode 100644 ModernKeePass10/.sonarqube/out/0/FilesToAnalyze.txt create mode 100644 ModernKeePass10/.sonarqube/out/0/ProjectInfo.xml create mode 100644 ModernKeePass10/.sonarqube/out/0/output-cs/encoding.pb create mode 100644 ModernKeePass10/.sonarqube/out/0/output-cs/file-metadata.pb create mode 100644 ModernKeePass10/.sonarqube/out/0/output-cs/metrics.pb create mode 100644 ModernKeePass10/.sonarqube/out/0/output-cs/symrefs.pb create mode 100644 ModernKeePass10/.sonarqube/out/0/output-cs/token-cpd.pb create mode 100644 ModernKeePass10/.sonarqube/out/0/output-cs/token-type.pb create mode 100644 ModernKeePass10/.sonarqube/out/sonar-project.properties create mode 100644 ModernKeePass10/.sonarqube/out/summary.md create mode 100644 ModernKeePass10/Actions/ClipboardAction.cs create mode 100644 ModernKeePass10/Actions/DeleteEntityAction.cs create mode 100644 ModernKeePass10/Actions/NavigateToUrlAction.cs create mode 100644 ModernKeePass10/Actions/SetupFocusAction.cs create mode 100644 ModernKeePass10/Actions/ToastAction.cs create mode 100644 ModernKeePass10/App.xaml create mode 100644 ModernKeePass10/App.xaml.cs create mode 100644 ModernKeePass10/Assets/Logo.scale-100.png create mode 100644 ModernKeePass10/Assets/Logo.scale-140.png create mode 100644 ModernKeePass10/Assets/Logo.scale-180.png create mode 100644 ModernKeePass10/Assets/Logo.scale-80.png create mode 100644 ModernKeePass10/Assets/ModernKeePass-SmallLogo.scale-100.png create mode 100644 ModernKeePass10/Assets/ModernKeePass-SmallLogo.scale-140.png create mode 100644 ModernKeePass10/Assets/ModernKeePass-SmallLogo.scale-180.png create mode 100644 ModernKeePass10/Assets/ModernKeePass-SmallLogo.scale-80.png create mode 100644 ModernKeePass10/Assets/ModernKeePass-SmallLogo.targetsize-16.png create mode 100644 ModernKeePass10/Assets/ModernKeePass-SmallLogo.targetsize-256.png create mode 100644 ModernKeePass10/Assets/ModernKeePass-SmallLogo.targetsize-32.png create mode 100644 ModernKeePass10/Assets/ModernKeePass-SmallLogo.targetsize-48.png create mode 100644 ModernKeePass10/Assets/ModernKeePass-SplashScreen.scale-100.png create mode 100644 ModernKeePass10/Assets/ModernKeePass-SplashScreen.scale-140.png create mode 100644 ModernKeePass10/Assets/ModernKeePass-SplashScreen.scale-180.png create mode 100644 ModernKeePass10/Assets/SmallLogo.scale-100.png create mode 100644 ModernKeePass10/Assets/SmallLogo.scale-140.png create mode 100644 ModernKeePass10/Assets/SmallLogo.scale-180.png create mode 100644 ModernKeePass10/Assets/SmallLogo.scale-80.png create mode 100644 ModernKeePass10/Assets/SmallLogo.targetsize-16.png create mode 100644 ModernKeePass10/Assets/SmallLogo.targetsize-256.png create mode 100644 ModernKeePass10/Assets/SmallLogo.targetsize-32.png create mode 100644 ModernKeePass10/Assets/SmallLogo.targetsize-48.png create mode 100644 ModernKeePass10/Assets/SplashScreen.scale-100.png create mode 100644 ModernKeePass10/Assets/SplashScreen.scale-140.png create mode 100644 ModernKeePass10/Assets/SplashScreen.scale-180.png create mode 100644 ModernKeePass10/Assets/Square310x310Logo.scale-100.png create mode 100644 ModernKeePass10/Assets/Square310x310Logo.scale-140.png create mode 100644 ModernKeePass10/Assets/Square310x310Logo.scale-180.png create mode 100644 ModernKeePass10/Assets/Square310x310Logo.scale-80.png create mode 100644 ModernKeePass10/Assets/Square70x70Logo.scale-100.png create mode 100644 ModernKeePass10/Assets/Square70x70Logo.scale-140.png create mode 100644 ModernKeePass10/Assets/Square70x70Logo.scale-180.png create mode 100644 ModernKeePass10/Assets/Square70x70Logo.scale-80.png create mode 100644 ModernKeePass10/Assets/StoreLogo.scale-100.png create mode 100644 ModernKeePass10/Assets/StoreLogo.scale-140.png create mode 100644 ModernKeePass10/Assets/StoreLogo.scale-180.png create mode 100644 ModernKeePass10/Assets/Wide310x150Logo.scale-100.png create mode 100644 ModernKeePass10/Assets/Wide310x150Logo.scale-140.png create mode 100644 ModernKeePass10/Assets/Wide310x150Logo.scale-180.png create mode 100644 ModernKeePass10/Assets/Wide310x150Logo.scale-80.png create mode 100644 ModernKeePass10/Backup/ModernKeePassApp.csproj create mode 100644 ModernKeePass10/Backup/project.json create mode 100644 ModernKeePass10/Common/MessageDialogHelper.cs create mode 100644 ModernKeePass10/Common/NavigationHelper.cs create mode 100644 ModernKeePass10/Common/ObservableDictionary.cs create mode 100644 ModernKeePass10/Common/RelayCommand.cs create mode 100644 ModernKeePass10/Common/ResourceHelper.cs create mode 100644 ModernKeePass10/Common/SuspensionManager.cs create mode 100644 ModernKeePass10/Common/ToastNotificationHelper.cs create mode 100644 ModernKeePass10/Controls/ListViewWithDisable.cs create mode 100644 ModernKeePass10/Controls/TextBoxWithButton.cs create mode 100644 ModernKeePass10/Converters/BooleanToVisibilityConverter.cs create mode 100644 ModernKeePass10/Converters/ColorToBrushConverter.cs create mode 100644 ModernKeePass10/Converters/DiscreteIntToSolidColorBrushConverter.cs create mode 100644 ModernKeePass10/Converters/DoubleToSolidColorBrushConverter.cs create mode 100644 ModernKeePass10/Converters/EmptyStringToVisibilityConverter.cs create mode 100644 ModernKeePass10/Converters/IconToSymbolConverter.cs create mode 100644 ModernKeePass10/Converters/InverseBooleanToVisibilityConverter.cs create mode 100644 ModernKeePass10/Converters/NullToBooleanConverter.cs create mode 100644 ModernKeePass10/Converters/PluralizationConverter.cs create mode 100644 ModernKeePass10/Converters/ProgressBarLegalValuesConverter.cs create mode 100644 ModernKeePass10/Converters/TextToWidthConverter.cs create mode 100644 ModernKeePass10/Events/PasswordEventArgs.cs create mode 100644 ModernKeePass10/Extensions/DispatcherTaskExtensions.cs create mode 100644 ModernKeePass10/Package.StoreAssociation.xml create mode 100644 ModernKeePass10/Package.appxmanifest create mode 100644 ModernKeePass10/Properties/Annotations.cs create mode 100644 ModernKeePass10/Properties/AssemblyInfo.cs create mode 100644 ModernKeePass10/Properties/default.rd.xml create mode 100644 ModernKeePass10/ResourceDictionaries/HamburgerButtonStyle.xaml create mode 100644 ModernKeePass10/ResourceDictionaries/ListViewLeftIndicatorStyle.xaml create mode 100644 ModernKeePass10/ResourceDictionaries/MasterDetailsView.xaml create mode 100644 ModernKeePass10/ResourceDictionaries/NoBorderButtonStyle.xaml create mode 100644 ModernKeePass10/ResourceDictionaries/NoBorderToggleButtonStyle.xaml create mode 100644 ModernKeePass10/ResourceDictionaries/Styles.xaml create mode 100644 ModernKeePass10/ResourceDictionaries/TextBoxWithButtonStyle.xaml create mode 100644 ModernKeePass10/Strings/en-US/CodeBehind.resw create mode 100644 ModernKeePass10/Strings/en-US/Resources.resw create mode 100644 ModernKeePass10/Strings/fr-FR/CodeBehind.resw create mode 100644 ModernKeePass10/Strings/fr-FR/Resources.resw create mode 100644 ModernKeePass10/TemplateSelectors/FirstItemDataTemplateSelector.cs create mode 100644 ModernKeePass10/TemplateSelectors/SelectableDataTemplateSelector.cs create mode 100644 ModernKeePass10/ViewModels/AboutViewModel.cs create mode 100644 ModernKeePass10/ViewModels/EntriesViewModel.cs create mode 100644 ModernKeePass10/ViewModels/GroupsViewModel.cs create mode 100644 ModernKeePass10/ViewModels/ListItems/EntryItemViewModel.cs create mode 100644 ModernKeePass10/ViewModels/ListItems/GroupItemViewModel.cs create mode 100644 ModernKeePass10/ViewModels/ListItems/ListMenuItemViewModel.cs create mode 100644 ModernKeePass10/ViewModels/ListItems/MainMenuItemViewModel.cs create mode 100644 ModernKeePass10/ViewModels/ListItems/RecentItemViewModel.cs create mode 100644 ModernKeePass10/ViewModels/ListItems/SettingsDatabaseViewModel.cs create mode 100644 ModernKeePass10/ViewModels/ListItems/SettingsNewViewModel.cs create mode 100644 ModernKeePass10/ViewModels/ListItems/SettingsSaveViewModel.cs create mode 100644 ModernKeePass10/ViewModels/MainViewModel.cs create mode 100644 ModernKeePass10/ViewModels/NewViewModel.cs create mode 100644 ModernKeePass10/ViewModels/Old/EntryVm.cs create mode 100644 ModernKeePass10/ViewModels/Old/GroupVm.cs create mode 100644 ModernKeePass10/ViewModels/OpenViewModel.cs create mode 100644 ModernKeePass10/ViewModels/RecentViewModel.cs create mode 100644 ModernKeePass10/ViewModels/SaveViewModel.cs create mode 100644 ModernKeePass10/ViewModels/SettingsViewModel.cs create mode 100644 ModernKeePass10/ViewModels/UserControls/CredentialsViewModel.cs create mode 100644 ModernKeePass10/ViewModels/UserControls/UpdateCredentialsViewModel.cs create mode 100644 ModernKeePass10/Views/BasePages/LayoutAwarePageBase.cs create mode 100644 ModernKeePass10/Views/EntriesPage.xaml create mode 100644 ModernKeePass10/Views/EntriesPage.xaml.cs create mode 100644 ModernKeePass10/Views/EntryPage.xaml create mode 100644 ModernKeePass10/Views/EntryPage.xaml.cs create mode 100644 ModernKeePass10/Views/GroupsPage.xaml create mode 100644 ModernKeePass10/Views/GroupsPage.xaml.cs create mode 100644 ModernKeePass10/Views/MainPage10.xaml create mode 100644 ModernKeePass10/Views/MainPage10.xaml.cs create mode 100644 ModernKeePass10/Views/MainPageFrames/AboutPage.xaml create mode 100644 ModernKeePass10/Views/MainPageFrames/AboutPage.xaml.cs create mode 100644 ModernKeePass10/Views/MainPageFrames/DonatePage.xaml create mode 100644 ModernKeePass10/Views/MainPageFrames/DonatePage.xaml.cs create mode 100644 ModernKeePass10/Views/MainPageFrames/ImportExportPage.xaml create mode 100644 ModernKeePass10/Views/MainPageFrames/ImportExportPage.xaml.cs create mode 100644 ModernKeePass10/Views/MainPageFrames/NewDatabasePage.xaml create mode 100644 ModernKeePass10/Views/MainPageFrames/NewDatabasePage.xaml.cs create mode 100644 ModernKeePass10/Views/MainPageFrames/OpenDatabasePage.xaml create mode 100644 ModernKeePass10/Views/MainPageFrames/OpenDatabasePage.xaml.cs create mode 100644 ModernKeePass10/Views/MainPageFrames/RecentDatabasesPage.xaml create mode 100644 ModernKeePass10/Views/MainPageFrames/RecentDatabasesPage.xaml.cs create mode 100644 ModernKeePass10/Views/MainPageFrames/SaveDatabasePage.xaml create mode 100644 ModernKeePass10/Views/MainPageFrames/SaveDatabasePage.xaml.cs create mode 100644 ModernKeePass10/Views/MainPageFrames/WelcomePage.xaml create mode 100644 ModernKeePass10/Views/MainPageFrames/WelcomePage.xaml.cs create mode 100644 ModernKeePass10/Views/Old/EntryDetailPage.xaml create mode 100644 ModernKeePass10/Views/Old/EntryDetailPage.xaml.cs create mode 100644 ModernKeePass10/Views/Old/GroupDetailPage.xaml create mode 100644 ModernKeePass10/Views/Old/GroupDetailPage.xaml.cs create mode 100644 ModernKeePass10/Views/Old/MainPage.xaml create mode 100644 ModernKeePass10/Views/Old/MainPage.xaml.cs create mode 100644 ModernKeePass10/Views/Old/SettingsPage.xaml create mode 100644 ModernKeePass10/Views/Old/SettingsPage.xaml.cs create mode 100644 ModernKeePass10/Views/SettingsPage10.xaml create mode 100644 ModernKeePass10/Views/SettingsPage10.xaml.cs create mode 100644 ModernKeePass10/Views/SettingsPageFrames/SettingsDatabasePage.xaml create mode 100644 ModernKeePass10/Views/SettingsPageFrames/SettingsDatabasePage.xaml.cs create mode 100644 ModernKeePass10/Views/SettingsPageFrames/SettingsNewDatabasePage.xaml create mode 100644 ModernKeePass10/Views/SettingsPageFrames/SettingsNewDatabasePage.xaml.cs create mode 100644 ModernKeePass10/Views/SettingsPageFrames/SettingsSavePage.xaml create mode 100644 ModernKeePass10/Views/SettingsPageFrames/SettingsSavePage.xaml.cs create mode 100644 ModernKeePass10/Views/SettingsPageFrames/SettingsSecurityPage.xaml create mode 100644 ModernKeePass10/Views/SettingsPageFrames/SettingsSecurityPage.xaml.cs create mode 100644 ModernKeePass10/Views/SettingsPageFrames/SettingsWelcomePage.xaml create mode 100644 ModernKeePass10/Views/SettingsPageFrames/SettingsWelcomePage.xaml.cs create mode 100644 ModernKeePass10/Views/UserControls/BreadCrumbUserControl.xaml create mode 100644 ModernKeePass10/Views/UserControls/BreadCrumbUserControl.xaml.cs create mode 100644 ModernKeePass10/Views/UserControls/ColorPickerUserControl.xaml create mode 100644 ModernKeePass10/Views/UserControls/ColorPickerUserControl.xaml.cs create mode 100644 ModernKeePass10/Views/UserControls/CredentialsUserControl.xaml create mode 100644 ModernKeePass10/Views/UserControls/CredentialsUserControl.xaml.cs create mode 100644 ModernKeePass10/Views/UserControls/HamburgerMenuUserControl.xaml create mode 100644 ModernKeePass10/Views/UserControls/HamburgerMenuUserControl.xaml.cs create mode 100644 ModernKeePass10/Views/UserControls/SymbolPickerUserControl.xaml create mode 100644 ModernKeePass10/Views/UserControls/SymbolPickerUserControl.xaml.cs create mode 100644 ModernKeePass10/Views/UserControls/TopMenuUserControl.xaml create mode 100644 ModernKeePass10/Views/UserControls/TopMenuUserControl.xaml.cs create mode 100644 ModernKeePass10/Views/UserControls/UpdateCredentialsUserControl.xaml create mode 100644 ModernKeePass10/Views/UserControls/UpdateCredentialsUserControl.xaml.cs create mode 100644 ModernKeePass10/Win10App.csproj create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/description.txt create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/images/Screenshot/Entry.png create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/images/Screenshot/Group.png create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/images/Screenshot/New.png create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/images/Screenshot/Open.png create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/images/Screenshot/Recent.png create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/images/Screenshot/Semantic.png create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/images/Screenshot/Settings.png create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/images/Screenshot/description.Entry.txt create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/images/Screenshot/description.Group.txt create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/images/Screenshot/description.New.txt create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/images/Screenshot/description.Open.txt create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/images/Screenshot/description.Recent.txt create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/images/Screenshot/description.Semantic.txt create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/images/Screenshot/description.Settings.txt create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/keywords.txt create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/privacyPolicy.txt create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/releaseNotes.txt create mode 100644 ModernKeePass10/appMetadata/en-us/baselisting/websiteUrl.txt create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/description.txt create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/images/Screenshot/Entry.png create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/images/Screenshot/Group.png create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/images/Screenshot/New.png create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/images/Screenshot/Open.png create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/images/Screenshot/Recent.png create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/images/Screenshot/Semantic.png create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/images/Screenshot/Settings.png create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/images/Screenshot/description.Entry.txt create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/images/Screenshot/description.Group.txt create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/images/Screenshot/description.New.txt create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/images/Screenshot/description.Open.txt create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/images/Screenshot/description.Recent.txt create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/images/Screenshot/description.Semantic.txt create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/images/Screenshot/description.Settings.txt create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/keywords.txt create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/privacyPolicy.txt create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/releaseNotes.txt create mode 100644 ModernKeePass10/appMetadata/fr-fr/baselisting/websiteUrl.txt diff --git a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs index bbbe5b1..1a14dd0 100644 --- a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs +++ b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs @@ -7,6 +7,7 @@ namespace ModernKeePass.Application.Common.Interfaces { public interface IDatabaseProxy { + string ZeroId { get; } bool IsOpen { get; } string Name { get; } string RootGroupId { get; } @@ -15,14 +16,14 @@ namespace ModernKeePass.Application.Common.Interfaces string KeyDerivationId { get; set; } string Compression { get; set; } bool IsRecycleBinEnabled { get; set; } + string FileAccessToken { get; set; } - Task Open(FileInfo fileInfo, Credentials credentials); - Task ReOpen(); - Task Create(FileInfo fileInfo, Credentials credentials, DatabaseVersion version = DatabaseVersion.V2); - Task SaveDatabase(); - Task SaveDatabase(string filePath); - void SetRecycleBin(string id); - Task UpdateCredentials(Credentials credentials); + Task Open(byte[] file, Credentials credentials); + Task ReOpen(byte[] file); + Task Create(byte[] file, Credentials credentials, DatabaseVersion version = DatabaseVersion.V2); + Task SaveDatabase(); + Task SaveDatabase(byte[] newFileContents); + void UpdateCredentials(Credentials credentials); void CloseDatabase(); Task AddEntry(string parentGroupId, string entryId); @@ -32,8 +33,7 @@ namespace ModernKeePass.Application.Common.Interfaces void UpdateGroup(string groupId); Task RemoveEntry(string parentGroupId, string entryId); Task RemoveGroup(string parentGroupId, string groupId); - Task DeleteEntry(string parentGroupId, string entryId, string recycleBinName); - Task DeleteGroup(string parentGroupId, string groupId, string recycleBinName); + void DeleteEntity(string entityId); EntryEntity CreateEntry(string parentGroupId); GroupEntity CreateGroup(string parentGroupId, string nameId, bool isRecycleBin = false); void SortEntries(string groupId); diff --git a/ModernKeePass.Application/Common/Interfaces/IImportFormat.cs b/ModernKeePass.Application/Common/Interfaces/IImportFormat.cs index f581762..302adba 100644 --- a/ModernKeePass.Application/Common/Interfaces/IImportFormat.cs +++ b/ModernKeePass.Application/Common/Interfaces/IImportFormat.cs @@ -5,6 +5,6 @@ namespace ModernKeePass.Application.Common.Interfaces { public interface IImportFormat { - Task>> Import(string path); + Task>> Import(IList fileContents); } } \ No newline at end of file diff --git a/ModernKeePass.Application/Database/Commands/CloseDatabase/CloseDatabaseCommand.cs b/ModernKeePass.Application/Database/Commands/CloseDatabase/CloseDatabaseCommand.cs index 55db080..f7f99d2 100644 --- a/ModernKeePass.Application/Database/Commands/CloseDatabase/CloseDatabaseCommand.cs +++ b/ModernKeePass.Application/Database/Commands/CloseDatabase/CloseDatabaseCommand.cs @@ -9,15 +9,19 @@ namespace ModernKeePass.Application.Database.Commands.CloseDatabase public class CloseDatabaseCommandHandler : IRequestHandler { private readonly IDatabaseProxy _database; + private readonly IFileProxy _file; - public CloseDatabaseCommandHandler(IDatabaseProxy database) + public CloseDatabaseCommandHandler(IDatabaseProxy database, IFileProxy file) { _database = database; + _file = file; } public void Handle(CloseDatabaseCommand message) { - if (_database.IsOpen) _database.CloseDatabase(); - else throw new DatabaseClosedException(); + if (!_database.IsOpen) throw new DatabaseClosedException(); + _database.CloseDatabase(); + _file.ReleaseFile(_database.FileAccessToken); + _database.FileAccessToken = null; } } } diff --git a/ModernKeePass.Application/Database/Commands/CreateDatabase/CreateDatabaseCommand.cs b/ModernKeePass.Application/Database/Commands/CreateDatabase/CreateDatabaseCommand.cs index 4888c06..12df1e9 100644 --- a/ModernKeePass.Application/Database/Commands/CreateDatabase/CreateDatabaseCommand.cs +++ b/ModernKeePass.Application/Database/Commands/CreateDatabase/CreateDatabaseCommand.cs @@ -15,26 +15,26 @@ namespace ModernKeePass.Application.Database.Commands.CreateDatabase public class CreateDatabaseCommandHandler : IAsyncRequestHandler { private readonly IDatabaseProxy _database; + private readonly IFileProxy _file; - public CreateDatabaseCommandHandler(IDatabaseProxy database) + public CreateDatabaseCommandHandler(IDatabaseProxy database, IFileProxy file) { _database = database; + _file = file; } public async Task Handle(CreateDatabaseCommand message) { if (_database.IsOpen) throw new DatabaseOpenException(); - await _database.Create( - new FileInfo - { - Path = message.FilePath - }, + var file = await _file.OpenBinaryFile(message.FilePath); + await _database.Create(file, new Credentials { - KeyFilePath = message.KeyFilePath, + KeyFileContents = await _file.OpenBinaryFile(message.KeyFilePath), Password = message.Password }); + _database.FileAccessToken = message.FilePath; } } diff --git a/ModernKeePass.Application/Database/Commands/SaveDatabase/SaveDatabaseCommand.cs b/ModernKeePass.Application/Database/Commands/SaveDatabase/SaveDatabaseCommand.cs index 71d4785..78f32e1 100644 --- a/ModernKeePass.Application/Database/Commands/SaveDatabase/SaveDatabaseCommand.cs +++ b/ModernKeePass.Application/Database/Commands/SaveDatabase/SaveDatabaseCommand.cs @@ -12,18 +12,34 @@ namespace ModernKeePass.Application.Database.Commands.SaveDatabase public class SaveDatabaseCommandHandler : IAsyncRequestHandler { private readonly IDatabaseProxy _database; + private readonly IFileProxy _file; - public SaveDatabaseCommandHandler(IDatabaseProxy database) + public SaveDatabaseCommandHandler(IDatabaseProxy database, IFileProxy file) { _database = database; + _file = file; } public async Task Handle(SaveDatabaseCommand message) { if (!_database.IsOpen) throw new DatabaseClosedException(); - if (string.IsNullOrEmpty(message.FilePath)) await _database.SaveDatabase(); - else await _database.SaveDatabase(message.FilePath); + byte[] contents; + if (string.IsNullOrEmpty(message.FilePath)) + { + contents = await _database.SaveDatabase(); + await _file.WriteBinaryContentsToFile(_database.FileAccessToken, contents); + } + else + { + var newFileContents = await _file.OpenBinaryFile(message.FilePath); + contents = await _database.SaveDatabase(newFileContents); + await _file.WriteBinaryContentsToFile(message.FilePath, contents); + + _file.ReleaseFile(_database.FileAccessToken); + _database.FileAccessToken = message.FilePath; + } + } } } diff --git a/ModernKeePass.Application/Database/Commands/UpdateCredentials/UpdateCredentialsCommand.cs b/ModernKeePass.Application/Database/Commands/UpdateCredentials/UpdateCredentialsCommand.cs index 7d08e09..7f0ef75 100644 --- a/ModernKeePass.Application/Database/Commands/UpdateCredentials/UpdateCredentialsCommand.cs +++ b/ModernKeePass.Application/Database/Commands/UpdateCredentials/UpdateCredentialsCommand.cs @@ -14,23 +14,22 @@ namespace ModernKeePass.Application.Database.Commands.UpdateCredentials public class UpdateCredentialsCommandHandler : IAsyncRequestHandler { private readonly IDatabaseProxy _database; + private readonly IFileProxy _file; - public UpdateCredentialsCommandHandler(IDatabaseProxy database) + public UpdateCredentialsCommandHandler(IDatabaseProxy database, IFileProxy file) { _database = database; + _file = file; } public async Task Handle(UpdateCredentialsCommand message) { - if (_database.IsOpen) + if (!_database.IsOpen) throw new DatabaseClosedException(); + _database.UpdateCredentials(new Credentials { - await _database.UpdateCredentials(new Credentials - { - KeyFilePath = message.KeyFilePath, - Password = message.Password - }); - } - else throw new DatabaseClosedException(); + KeyFileContents = await _file.OpenBinaryFile(message.KeyFilePath), + Password = message.Password + }); } } } diff --git a/ModernKeePass.Application/Database/Queries/GetDatabase/GetDatabaseQuery.cs b/ModernKeePass.Application/Database/Queries/GetDatabase/GetDatabaseQuery.cs index 8835b71..6a76065 100644 --- a/ModernKeePass.Application/Database/Queries/GetDatabase/GetDatabaseQuery.cs +++ b/ModernKeePass.Application/Database/Queries/GetDatabase/GetDatabaseQuery.cs @@ -2,7 +2,6 @@ using MediatR; using ModernKeePass.Application.Common.Interfaces; using ModernKeePass.Application.Database.Models; -using ModernKeePass.Application.Group.Models; namespace ModernKeePass.Application.Database.Queries.GetDatabase { diff --git a/ModernKeePass.Application/Database/Queries/OpenDatabase/OpenDatabaseQuery.cs b/ModernKeePass.Application/Database/Queries/OpenDatabase/OpenDatabaseQuery.cs index 50fad37..c66d446 100644 --- a/ModernKeePass.Application/Database/Queries/OpenDatabase/OpenDatabaseQuery.cs +++ b/ModernKeePass.Application/Database/Queries/OpenDatabase/OpenDatabaseQuery.cs @@ -15,26 +15,25 @@ namespace ModernKeePass.Application.Database.Queries.OpenDatabase public class OpenDatabaseQueryHandler : IAsyncRequestHandler { private readonly IDatabaseProxy _database; + private readonly IFileProxy _file; - public OpenDatabaseQueryHandler(IDatabaseProxy database) + public OpenDatabaseQueryHandler(IDatabaseProxy database, IFileProxy file) { _database = database; + _file = file; } public async Task Handle(OpenDatabaseQuery request) { if (_database.IsOpen) throw new DatabaseOpenException(); - await _database.Open( - new FileInfo + var file = await _file.OpenBinaryFile(request.FilePath); + await _database.Open(file, new Credentials { - Path = request.FilePath - }, - new Credentials - { - KeyFilePath = request.KeyFilePath, + KeyFileContents = await _file.OpenBinaryFile(request.KeyFilePath), Password = request.Password }); + _database.FileAccessToken = request.FilePath; } } diff --git a/ModernKeePass.Application/Database/Queries/ReOpenDatabase/ReOpenDatabaseQuery.cs b/ModernKeePass.Application/Database/Queries/ReOpenDatabase/ReOpenDatabaseQuery.cs index 1911118..aed9273 100644 --- a/ModernKeePass.Application/Database/Queries/ReOpenDatabase/ReOpenDatabaseQuery.cs +++ b/ModernKeePass.Application/Database/Queries/ReOpenDatabase/ReOpenDatabaseQuery.cs @@ -10,17 +10,20 @@ namespace ModernKeePass.Application.Database.Queries.ReOpenDatabase public class ReOpenDatabaseQueryHandler : IAsyncRequestHandler { private readonly IDatabaseProxy _database; + private readonly IFileProxy _file; - public ReOpenDatabaseQueryHandler(IDatabaseProxy database) + public ReOpenDatabaseQueryHandler(IDatabaseProxy database, IFileProxy file) { _database = database; + _file = file; } public async Task Handle(ReOpenDatabaseQuery request) { if (!_database.IsOpen) throw new DatabaseClosedException(); - await _database.ReOpen(); + var file = await _file.OpenBinaryFile(_database.FileAccessToken); + await _database.ReOpen(file); } } } diff --git a/ModernKeePass.Application/Group/Commands/DeleteEntry/DeleteEntryCommand.cs b/ModernKeePass.Application/Group/Commands/DeleteEntry/DeleteEntryCommand.cs index 9a6b00c..73f47fd 100644 --- a/ModernKeePass.Application/Group/Commands/DeleteEntry/DeleteEntryCommand.cs +++ b/ModernKeePass.Application/Group/Commands/DeleteEntry/DeleteEntryCommand.cs @@ -24,7 +24,21 @@ namespace ModernKeePass.Application.Group.Commands.DeleteEntry { if (!_database.IsOpen) throw new DatabaseClosedException(); - await _database.DeleteEntry(message.ParentGroupId, message.EntryId, message.RecycleBinName); + if (_database.IsRecycleBinEnabled && (string.IsNullOrEmpty(_database.RecycleBinId) || _database.RecycleBinId.Equals(_database.ZeroId))) + { + _database.CreateGroup(_database.RootGroupId, message.RecycleBinName, true); + } + + if (!_database.IsRecycleBinEnabled || message.ParentGroupId.Equals(_database.RecycleBinId)) + { + _database.DeleteEntity(message.EntryId); + } + else + { + await _database.AddEntry(_database.RecycleBinId, message.EntryId); + } + + await _database.RemoveEntry(message.ParentGroupId, message.EntryId); } } } diff --git a/ModernKeePass.Application/Group/Commands/DeleteGroup/DeleteGroupCommand.cs b/ModernKeePass.Application/Group/Commands/DeleteGroup/DeleteGroupCommand.cs index cde3cf6..0b09268 100644 --- a/ModernKeePass.Application/Group/Commands/DeleteGroup/DeleteGroupCommand.cs +++ b/ModernKeePass.Application/Group/Commands/DeleteGroup/DeleteGroupCommand.cs @@ -24,7 +24,21 @@ namespace ModernKeePass.Application.Group.Commands.DeleteGroup { if (!_database.IsOpen) throw new DatabaseClosedException(); - await _database.DeleteEntry(message.ParentGroupId, message.GroupId, message.RecycleBinName); + if (_database.IsRecycleBinEnabled && (string.IsNullOrEmpty(_database.RecycleBinId) || _database.RecycleBinId.Equals(_database.ZeroId))) + { + _database.CreateGroup(_database.RootGroupId, message.RecycleBinName, true); + } + + if (!_database.IsRecycleBinEnabled || message.ParentGroupId.Equals(_database.RecycleBinId)) + { + _database.DeleteEntity(message.GroupId); + } + else + { + await _database.AddGroup(_database.RecycleBinId, message.GroupId); + } + + await _database.RemoveGroup(message.ParentGroupId, message.GroupId); } } } diff --git a/ModernKeePass.Application/Parameters/Commands/SetRecycleBin/SetRecycleBinCommand.cs b/ModernKeePass.Application/Parameters/Commands/SetRecycleBin/SetRecycleBinCommand.cs index 552047f..2725adb 100644 --- a/ModernKeePass.Application/Parameters/Commands/SetRecycleBin/SetRecycleBinCommand.cs +++ b/ModernKeePass.Application/Parameters/Commands/SetRecycleBin/SetRecycleBinCommand.cs @@ -19,7 +19,7 @@ namespace ModernKeePass.Application.Parameters.Commands.SetRecycleBin public void Handle(SetRecycleBinCommand message) { - if (_database.IsOpen) _database.SetRecycleBin(message.RecycleBinId); + if (_database.IsOpen) _database.RecycleBinId = message.RecycleBinId; else throw new DatabaseClosedException(); } } diff --git a/ModernKeePass.Domain/Domain.csproj b/ModernKeePass.Domain/Domain.csproj index 5c2c667..2ebabc4 100644 --- a/ModernKeePass.Domain/Domain.csproj +++ b/ModernKeePass.Domain/Domain.csproj @@ -57,6 +57,7 @@ + diff --git a/ModernKeePass.Domain/Dtos/Credentials.cs b/ModernKeePass.Domain/Dtos/Credentials.cs index bdb3091..1cde25c 100644 --- a/ModernKeePass.Domain/Dtos/Credentials.cs +++ b/ModernKeePass.Domain/Dtos/Credentials.cs @@ -3,7 +3,7 @@ public class Credentials { public string Password { get; set; } - public string KeyFilePath { get; set; } + public byte[] KeyFileContents { get; set; } // TODO: add Windows Hello } } \ No newline at end of file diff --git a/ModernKeePass.Domain/Interfaces/IImportFormat.cs b/ModernKeePass.Domain/Interfaces/IImportFormat.cs new file mode 100644 index 0000000..ab5b834 --- /dev/null +++ b/ModernKeePass.Domain/Interfaces/IImportFormat.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace ModernKeePass.Domain.Interfaces +{ + public interface IImportFormat + { + Task>> Import(string path); + } +} \ No newline at end of file diff --git a/ModernKeePass.Infrastructure/DependencyInjection.cs b/ModernKeePass.Infrastructure/DependencyInjection.cs index c1b50ce..6751248 100644 --- a/ModernKeePass.Infrastructure/DependencyInjection.cs +++ b/ModernKeePass.Infrastructure/DependencyInjection.cs @@ -9,16 +9,25 @@ namespace ModernKeePass.Infrastructure { public static class DependencyInjection { - public static IServiceCollection AddInfrastructure(this IServiceCollection services) + public static IServiceCollection AddInfrastructureCommon(this IServiceCollection services) + { + services.AddTransient(typeof(IDateTime), typeof(MachineDateTime)); + return services; + } + + public static IServiceCollection AddInfrastructureKeePass(this IServiceCollection services) { services.AddSingleton(typeof(IDatabaseProxy), typeof(KeePassDatabaseClient)); services.AddTransient(typeof(ICryptographyClient), typeof(KeePassCryptographyClient)); services.AddTransient(typeof(IPasswordProxy), typeof(KeePassPasswordClient)); - /*services.AddTransient(typeof(IResourceProxy), typeof(UwpResourceClient)); - services.AddTransient(typeof(ISettingsProxy), typeof(UwpSettingsClient)); - services.AddTransient(typeof(IRecentProxy), typeof(UwpRecentFilesClient));*/ + return services; + } + + public static IServiceCollection AddInfrastructureUwp(this IServiceCollection services) + { services.AddScoped(typeof(IFileProxy), typeof(StorageFileClient)); - services.AddTransient(typeof(IDateTime), typeof(MachineDateTime)); + services.AddTransient(typeof(ISettingsProxy), typeof(UwpSettingsClient)); + services.AddTransient(typeof(IRecentProxy), typeof(UwpRecentFilesClient)); return services; } } diff --git a/ModernKeePass.Infrastructure/File/CsvImportFormat.cs b/ModernKeePass.Infrastructure/File/CsvImportFormat.cs index a240a50..92db98a 100644 --- a/ModernKeePass.Infrastructure/File/CsvImportFormat.cs +++ b/ModernKeePass.Infrastructure/File/CsvImportFormat.cs @@ -6,21 +6,14 @@ namespace ModernKeePass.Infrastructure.File { public class CsvImportFormat: IImportFormat { - private readonly IFileProxy _fileService; private const bool HasHeaderRow = true; private const char Delimiter = ';'; private const char LineDelimiter = '\n'; - - public CsvImportFormat(IFileProxy fileService) - { - _fileService = fileService; - } - - public async Task>> Import(string path) + + public async Task>> Import(IList fileContents) { var parsedResult = new List>(); - var content = await _fileService.OpenTextFile(path); - foreach (var line in content) + foreach (var line in fileContents) { var fields = line.Split(Delimiter); var recordItem = new Dictionary(); diff --git a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs index c649523..16266f6 100644 --- a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs +++ b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs @@ -18,19 +18,20 @@ using ModernKeePassLib.Utility; namespace ModernKeePass.Infrastructure.KeePass { - public class KeePassDatabaseClient: IDatabaseProxy + public class KeePassDatabaseClient: IDatabaseProxy, IDisposable { - private readonly IFileProxy _fileService; private readonly IMapper _mapper; private readonly IDateTime _dateTime; private readonly PwDatabase _pwDatabase = new PwDatabase(); - private string _fileAccessToken; private Credentials _credentials; + public string ZeroId => PwUuid.Zero.ToHexString(); + // Main information public bool IsOpen => (_pwDatabase?.IsOpen).GetValueOrDefault(); public string Name => _pwDatabase?.Name; public string RootGroupId => _pwDatabase?.RootGroup.Uuid.ToHexString(); + public string FileAccessToken { get; set; } // Settings public bool IsRecycleBinEnabled @@ -50,7 +51,11 @@ namespace ModernKeePass.Infrastructure.KeePass return null; } - set { _pwDatabase.RecycleBinUuid = BuildIdFromString(value); } + set + { + _pwDatabase.RecycleBinUuid = BuildIdFromString(value); + _pwDatabase.RecycleBinChanged = _dateTime.Now; + } } public string CipherId @@ -75,24 +80,25 @@ namespace ModernKeePass.Infrastructure.KeePass set { _pwDatabase.Compression = (PwCompressionAlgorithm) Enum.Parse(typeof(PwCompressionAlgorithm), value); } } - public KeePassDatabaseClient(IFileProxy fileService, IMapper mapper, IDateTime dateTime) + public KeePassDatabaseClient(IMapper mapper, IDateTime dateTime) { - _fileService = fileService; _mapper = mapper; _dateTime = dateTime; } - public async Task Open(FileInfo fileInfo, Credentials credentials) + public async Task Open(byte[] file, Credentials credentials) { try { - var compositeKey = await CreateCompositeKey(credentials); - var ioConnection = await BuildConnectionInfo(fileInfo); + await Task.Run(() => + { + var compositeKey = CreateCompositeKey(credentials); + var ioConnection = IOConnectionInfo.FromByteArray(file); - _pwDatabase.Open(ioConnection, compositeKey, new NullStatusLogger()); + _pwDatabase.Open(ioConnection, compositeKey, new NullStatusLogger()); - _credentials = credentials; - _fileAccessToken = fileInfo.Path; + _credentials = credentials; + }); } catch (InvalidCompositeKeyException ex) { @@ -100,35 +106,45 @@ namespace ModernKeePass.Infrastructure.KeePass } } - public async Task ReOpen() - { - await Open(new FileInfo {Path = _fileAccessToken}, _credentials); + public async Task ReOpen(byte[] file) + { + await Open(file, _credentials); } - public async Task Create(FileInfo fileInfo, Credentials credentials, DatabaseVersion version = DatabaseVersion.V2) + public async Task Create(byte[] file, Credentials credentials, DatabaseVersion version = DatabaseVersion.V2) { - var compositeKey = await CreateCompositeKey(credentials); - var ioConnection = await BuildConnectionInfo(fileInfo); - - _pwDatabase.New(ioConnection, compositeKey); - - switch (version) - { - case DatabaseVersion.V4: - _pwDatabase.KdfParameters = KdfPool.Get("Argon2").GetDefaultParameters(); - break; - } - - _fileAccessToken = fileInfo.Path; - } - - public async Task SaveDatabase() - { - if (!_pwDatabase.IsOpen) return; try { - _pwDatabase.Save(new NullStatusLogger()); - await _fileService.WriteBinaryContentsToFile(_fileAccessToken, _pwDatabase.IOConnectionInfo.Bytes); + await Task.Run(() => + { + var compositeKey = CreateCompositeKey(credentials); + var ioConnection = IOConnectionInfo.FromByteArray(file); + + _pwDatabase.New(ioConnection, compositeKey); + + switch (version) + { + case DatabaseVersion.V4: + _pwDatabase.KdfParameters = KdfPool.Get("Argon2").GetDefaultParameters(); + break; + } + }); + } + catch (Exception ex) + { + throw new ArgumentException(ex.Message, ex); + } + } + + public async Task SaveDatabase() + { + try + { + return await Task.Run(() => + { + _pwDatabase.Save(new NullStatusLogger()); + return _pwDatabase.IOConnectionInfo.Bytes; + }); } catch (Exception e) { @@ -136,33 +152,25 @@ namespace ModernKeePass.Infrastructure.KeePass } } - public async Task SaveDatabase(string filePath) + public async Task SaveDatabase(byte[] newFileContents) { try { - var newFileContents = await _fileService.OpenBinaryFile(filePath); - _pwDatabase.SaveAs(IOConnectionInfo.FromByteArray(newFileContents), true, new NullStatusLogger()); - await _fileService.WriteBinaryContentsToFile(filePath, _pwDatabase.IOConnectionInfo.Bytes); - - _fileService.ReleaseFile(_fileAccessToken); - _fileAccessToken = filePath; + return await Task.Run(() => + { + _pwDatabase.SaveAs(IOConnectionInfo.FromByteArray(newFileContents), true, new NullStatusLogger()); + return _pwDatabase.IOConnectionInfo.Bytes; + }); } catch (Exception e) { throw new SaveException(e); } } - - public void SetRecycleBin(string id) - { - _pwDatabase.RecycleBinUuid = BuildIdFromString(id); - _pwDatabase.RecycleBinChanged = _dateTime.Now; - } - + public void CloseDatabase() { _pwDatabase?.Close(); - _fileService.ReleaseFile(_fileAccessToken); } public async Task AddEntry(string parentGroupId, string entryId) @@ -214,42 +222,9 @@ namespace ModernKeePass.Infrastructure.KeePass }); } - public async Task DeleteEntry(string parentGroupId, string entryId, string recycleBinName) + public void DeleteEntity(string entityId) { - if (IsRecycleBinEnabled && (string.IsNullOrEmpty(RecycleBinId) || _pwDatabase.RecycleBinUuid.Equals(PwUuid.Zero))) - { - CreateGroup(RootGroupId, recycleBinName, true); - } - - if (!IsRecycleBinEnabled || parentGroupId.Equals(RecycleBinId)) - { - _pwDatabase.DeletedObjects.Add(new PwDeletedObject(BuildIdFromString(entryId), _dateTime.Now)); - } - else - { - await AddEntry(RecycleBinId, entryId); - } - - await RemoveEntry(parentGroupId, entryId); - } - - public async Task DeleteGroup(string parentGroupId, string groupId, string recycleBinName) - { - if (IsRecycleBinEnabled && (string.IsNullOrEmpty(RecycleBinId) || _pwDatabase.RecycleBinUuid.Equals(PwUuid.Zero))) - { - CreateGroup(RootGroupId, recycleBinName, true); - } - - if (!IsRecycleBinEnabled || parentGroupId.Equals(RecycleBinId)) - { - _pwDatabase.DeletedObjects.Add(new PwDeletedObject(BuildIdFromString(groupId), _dateTime.Now)); - } - else - { - await AddEntry(RecycleBinId, groupId); - } - - await RemoveGroup(parentGroupId, groupId); + _pwDatabase.DeletedObjects.Add(new PwDeletedObject(BuildIdFromString(entityId), _dateTime.Now)); } public void UpdateEntry(string entryId, string fieldName, object fieldValue) @@ -328,32 +303,30 @@ namespace ModernKeePass.Infrastructure.KeePass return _mapper.Map(pwGroup); } - public async Task UpdateCredentials(Credentials credentials) + public void UpdateCredentials(Credentials credentials) { - _pwDatabase.MasterKey = await CreateCompositeKey(credentials); + _pwDatabase.MasterKey = CreateCompositeKey(credentials); } - private async Task CreateCompositeKey(Credentials credentials) + private CompositeKey CreateCompositeKey(Credentials credentials) { var compositeKey = new CompositeKey(); if (!string.IsNullOrEmpty(credentials.Password)) compositeKey.AddUserKey(new KcpPassword(credentials.Password)); - if (!string.IsNullOrEmpty(credentials.KeyFilePath)) + if (credentials.KeyFileContents != null) { - var kcpFileContents = await _fileService.OpenBinaryFile(credentials.KeyFilePath); - compositeKey.AddUserKey(new KcpKeyFile(IOConnectionInfo.FromByteArray(kcpFileContents))); + compositeKey.AddUserKey(new KcpKeyFile(IOConnectionInfo.FromByteArray(credentials.KeyFileContents))); } return compositeKey; } - - private async Task BuildConnectionInfo(FileInfo fileInfo) - { - var fileContents = await _fileService.OpenBinaryFile(fileInfo.Path); - return IOConnectionInfo.FromByteArray(fileContents); - } - + private PwUuid BuildIdFromString(string id) { return new PwUuid(MemUtil.HexStringToByteArray(id)); } + + public void Dispose() + { + if (IsOpen) CloseDatabase(); + } } } \ No newline at end of file diff --git a/ModernKeePass.ViewModelTest/AboutViewModelTests.cs b/ModernKeePass.ViewModelTest/AboutViewModelTests.cs new file mode 100644 index 0000000..bfde99c --- /dev/null +++ b/ModernKeePass.ViewModelTest/AboutViewModelTests.cs @@ -0,0 +1,17 @@ +using ModernKeePass.ViewModels; +using NUnit.Framework; +using Windows.ApplicationModel; + +namespace ModernKeePassApp.ViewModelTest +{ + [TestFixture] + public class AboutViewModelTests + { + [Test] + public void Should_Display_App_Version() + { + var aboutVm = new AboutViewModel(Package.Current); + Assert.AreEqual("1.0", aboutVm.Version); + } + } +} \ No newline at end of file diff --git a/ModernKeePass.ViewModelTest/ModernKeePassApp.ViewModelTest.csproj b/ModernKeePass.ViewModelTest/ModernKeePassApp.ViewModelTest.csproj new file mode 100644 index 0000000..13af2bb --- /dev/null +++ b/ModernKeePass.ViewModelTest/ModernKeePassApp.ViewModelTest.csproj @@ -0,0 +1,25 @@ + + + + netcoreapp3.0 + + false + + + + + + + + + + + + + + + C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.18362.0\Windows.winmd + + + + diff --git a/ModernKeePass.sln b/ModernKeePass.sln index dd2b003..dccec74 100644 --- a/ModernKeePass.sln +++ b/ModernKeePass.sln @@ -28,6 +28,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure", "ModernKee EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ModernKeePass.KeePassDatabaseTests", "ModernKeePass.KeePassDatabaseTests\ModernKeePass.KeePassDatabaseTests.csproj", "{52FEA1EE-2FA7-4862-85FE-CB05893D439E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Win10App", "ModernKeePass10\Win10App.csproj", "{D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ModernKeePassApp.ViewModelTest", "ModernKeePass.ViewModelTest\ModernKeePassApp.ViewModelTest.csproj", "{D978E25B-028C-446C-8143-D85563ECA914}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -152,6 +156,42 @@ Global {52FEA1EE-2FA7-4862-85FE-CB05893D439E}.Release|x64.Build.0 = Release|Any CPU {52FEA1EE-2FA7-4862-85FE-CB05893D439E}.Release|x86.ActiveCfg = Release|Any CPU {52FEA1EE-2FA7-4862-85FE-CB05893D439E}.Release|x86.Build.0 = Release|Any CPU + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Debug|Any CPU.ActiveCfg = Debug|x86 + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Debug|ARM.ActiveCfg = Debug|ARM + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Debug|ARM.Build.0 = Debug|ARM + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Debug|ARM.Deploy.0 = Debug|ARM + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Debug|x64.ActiveCfg = Debug|x64 + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Debug|x64.Build.0 = Debug|x64 + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Debug|x64.Deploy.0 = Debug|x64 + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Debug|x86.ActiveCfg = Debug|x86 + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Debug|x86.Build.0 = Debug|x86 + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Debug|x86.Deploy.0 = Debug|x86 + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Release|Any CPU.ActiveCfg = Release|x86 + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Release|ARM.ActiveCfg = Release|ARM + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Release|ARM.Build.0 = Release|ARM + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Release|ARM.Deploy.0 = Release|ARM + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Release|x64.ActiveCfg = Release|x64 + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Release|x64.Build.0 = Release|x64 + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Release|x64.Deploy.0 = Release|x64 + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Release|x86.ActiveCfg = Release|x86 + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Release|x86.Build.0 = Release|x86 + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF}.Release|x86.Deploy.0 = Release|x86 + {D978E25B-028C-446C-8143-D85563ECA914}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D978E25B-028C-446C-8143-D85563ECA914}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D978E25B-028C-446C-8143-D85563ECA914}.Debug|ARM.ActiveCfg = Debug|Any CPU + {D978E25B-028C-446C-8143-D85563ECA914}.Debug|ARM.Build.0 = Debug|Any CPU + {D978E25B-028C-446C-8143-D85563ECA914}.Debug|x64.ActiveCfg = Debug|Any CPU + {D978E25B-028C-446C-8143-D85563ECA914}.Debug|x64.Build.0 = Debug|Any CPU + {D978E25B-028C-446C-8143-D85563ECA914}.Debug|x86.ActiveCfg = Debug|Any CPU + {D978E25B-028C-446C-8143-D85563ECA914}.Debug|x86.Build.0 = Debug|Any CPU + {D978E25B-028C-446C-8143-D85563ECA914}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D978E25B-028C-446C-8143-D85563ECA914}.Release|Any CPU.Build.0 = Release|Any CPU + {D978E25B-028C-446C-8143-D85563ECA914}.Release|ARM.ActiveCfg = Release|Any CPU + {D978E25B-028C-446C-8143-D85563ECA914}.Release|ARM.Build.0 = Release|Any CPU + {D978E25B-028C-446C-8143-D85563ECA914}.Release|x64.ActiveCfg = Release|Any CPU + {D978E25B-028C-446C-8143-D85563ECA914}.Release|x64.Build.0 = Release|Any CPU + {D978E25B-028C-446C-8143-D85563ECA914}.Release|x86.ActiveCfg = Release|Any CPU + {D978E25B-028C-446C-8143-D85563ECA914}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -164,6 +204,8 @@ Global {9A0759F1-9069-4841-99E3-3BEC44E17356} = {0B30588B-07B8-4A88-A268-F58D06EA1627} {09577E4C-4899-45B9-BF80-1803D617CCAE} = {0B30588B-07B8-4A88-A268-F58D06EA1627} {52FEA1EE-2FA7-4862-85FE-CB05893D439E} = {107C7C00-56F4-41B0-A8CC-0156C46A3650} + {D16CAFF7-4187-45A8-A69E-D0658B7AC5BF} = {C7DB9A6F-77A8-4FE5-83CB-9C11F7100647} + {D978E25B-028C-446C-8143-D85563ECA914} = {107C7C00-56F4-41B0-A8CC-0156C46A3650} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0ADC1BC6-B1CA-427D-A97C-3CA40AAB0428} diff --git a/ModernKeePass/Actions/DeleteEntityAction.cs b/ModernKeePass/Actions/DeleteEntityAction.cs index d99ddbf..b0032be 100644 --- a/ModernKeePass/Actions/DeleteEntityAction.cs +++ b/ModernKeePass/Actions/DeleteEntityAction.cs @@ -1,11 +1,11 @@ using System.Windows.Input; using Windows.UI.Xaml; using MediatR; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Xaml.Interactivity; using ModernKeePass.Application.Database.Queries.GetDatabase; using ModernKeePass.Common; using ModernKeePass.Interfaces; -using ModernKeePass.Services; using ModernKeePass.ViewModels; namespace ModernKeePass.Actions @@ -34,7 +34,7 @@ namespace ModernKeePass.Actions DependencyProperty.Register("Command", typeof(ICommand), typeof(DeleteEntityAction), new PropertyMetadata(null)); - public DeleteEntityAction() : this(App.Mediator) { } + public DeleteEntityAction() : this(App.Services.GetService()) { } public DeleteEntityAction(IMediator mediator) { @@ -43,7 +43,7 @@ namespace ModernKeePass.Actions public object Execute(object sender, object parameter) { - var resource = new ResourcesService(); + var resource = new ResourceHelper(); var type = Entity is GroupDetailVm ? "Group" : "Entry"; var isRecycleOnDelete = _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult().IsRecycleBinEnabled; diff --git a/ModernKeePass/App.xaml.cs b/ModernKeePass/App.xaml.cs index 5956fb2..20b2421 100644 --- a/ModernKeePass/App.xaml.cs +++ b/ModernKeePass/App.xaml.cs @@ -14,14 +14,15 @@ using MediatR; using Microsoft.Extensions.DependencyInjection; using Microsoft.HockeyApp; 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.Infrastructure; -using ModernKeePass.Services; using ModernKeePass.Views; // The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227 @@ -33,9 +34,11 @@ namespace ModernKeePass /// sealed partial class App { - public IServiceProvider Services { get; } + private readonly IResourceProxy _resource; + private readonly IMediator _mediator; + private readonly ISettingsProxy _settings; - public static IMediator Mediator { get; private set; } + public static IServiceProvider Services { get; private set; } /// /// Initializes the singleton application object. This is the first line of authored code @@ -56,10 +59,15 @@ namespace ModernKeePass // Setup DI IServiceCollection serviceCollection = new ServiceCollection(); serviceCollection.AddApplication(); - serviceCollection.AddInfrastructure(); + serviceCollection.AddInfrastructureCommon(); + serviceCollection.AddInfrastructureKeePass(); + serviceCollection.AddInfrastructureUwp(); serviceCollection.AddAppAutomapper(); Services = serviceCollection.BuildServiceProvider(); - Mediator = Services.GetService(); + + _mediator = Services.GetService(); + _resource = Services.GetService(); + _settings = Services.GetService(); } #region Event Handlers @@ -74,30 +82,29 @@ namespace ModernKeePass ? exception.InnerException : exception; - var resource = new ResourcesService(); if (realException is SaveException) { unhandledExceptionEventArgs.Handled = true; - await MessageDialogHelper.ShowActionDialog(resource.GetResourceValue("MessageDialogSaveErrorTitle"), + await MessageDialogHelper.ShowActionDialog(_resource.GetResourceValue("MessageDialogSaveErrorTitle"), realException.InnerException.Message, - resource.GetResourceValue("MessageDialogSaveErrorButtonSaveAs"), - resource.GetResourceValue("MessageDialogSaveErrorButtonDiscard"), + _resource.GetResourceValue("MessageDialogSaveErrorButtonSaveAs"), + _resource.GetResourceValue("MessageDialogSaveErrorButtonDiscard"), async command => { - var database = await Mediator.Send(new GetDatabaseQuery()); + var database = await _mediator.Send(new GetDatabaseQuery()); var savePicker = new FileSavePicker { SuggestedStartLocation = PickerLocationId.DocumentsLibrary, SuggestedFileName = $"{database.Name} - copy" }; - savePicker.FileTypeChoices.Add(resource.GetResourceValue("MessageDialogSaveErrorFileTypeDesc"), + savePicker.FileTypeChoices.Add(_resource.GetResourceValue("MessageDialogSaveErrorFileTypeDesc"), new List {".kdbx"}); var file = await savePicker.PickSaveFileAsync(); if (file != null) { var token = StorageApplicationPermissions.FutureAccessList.Add(file); - await Mediator.Send(new SaveDatabaseCommand { FilePath = token }); + await _mediator.Send(new SaveDatabaseCommand { FilePath = token }); } }, null); } @@ -124,7 +131,7 @@ namespace ModernKeePass #if DEBUG if (System.Diagnostics.Debugger.IsAttached) { - //DebugSettings.EnableFrameRateCounter = true; + DebugSettings.EnableFrameRateCounter = true; } #endif @@ -167,7 +174,7 @@ namespace ModernKeePass try { - await Mediator.Send(new ReOpenDatabaseQuery()); + await _mediator.Send(new ReOpenDatabaseQuery()); #if DEBUG ToastNotificationHelper.ShowGenericToast("App resumed", "Database reopened (changes were saved)"); #endif @@ -203,11 +210,11 @@ namespace ModernKeePass var deferral = e.SuspendingOperation.GetDeferral(); try { - if (SettingsService.Instance.GetSetting("SaveSuspend", true)) + if (_settings.GetSetting("SaveSuspend", true)) { - await Mediator.Send(new SaveDatabaseCommand()); + await _mediator.Send(new SaveDatabaseCommand()); } - await Mediator.Send(new CloseDatabaseCommand()); + await _mediator.Send(new CloseDatabaseCommand()); } catch (Exception exception) { @@ -226,7 +233,22 @@ namespace ModernKeePass base.OnFileActivated(args); var rootFrame = new Frame(); var file = args.Files[0] as StorageFile; - rootFrame.Navigate(typeof(MainPage), file); + + if (file != null) + { + var token = StorageApplicationPermissions.FutureAccessList.Add(file); + var fileInfo = new FileInfo + { + Path = token, + Name = file.DisplayName + }; + rootFrame.Navigate(typeof(MainPage), fileInfo); + } + else + { + rootFrame.Navigate(typeof(MainPage)); + } + Window.Current.Content = rootFrame; Window.Current.Activate(); } diff --git a/ModernKeePass/Common/NavigationHelper.cs b/ModernKeePass/Common/NavigationHelper.cs index dd35221..f0f9bc4 100644 --- a/ModernKeePass/Common/NavigationHelper.cs +++ b/ModernKeePass/Common/NavigationHelper.cs @@ -1,9 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Input; using Windows.System; using Windows.UI.Core; using Windows.UI.Xaml; diff --git a/ModernKeePass/Common/NotifyPropertyChangedBase.cs b/ModernKeePass/Common/NotifyPropertyChangedBase.cs deleted file mode 100644 index ed71053..0000000 --- a/ModernKeePass/Common/NotifyPropertyChangedBase.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel; -using System.Runtime.CompilerServices; - -namespace ModernKeePass.Common -{ - public class NotifyPropertyChangedBase : INotifyPropertyChanged - { - public event PropertyChangedEventHandler PropertyChanged; - - protected void OnPropertyChanged(string propertyName = "") - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - - protected bool SetProperty(ref T property, T value, [CallerMemberName] string propertyName = "") - { - if (EqualityComparer.Default.Equals(property, value)) - { - return false; - } - - property = value; - OnPropertyChanged(propertyName); - return true; - } - } -} diff --git a/ModernKeePass/Services/ResourcesService.cs b/ModernKeePass/Common/ResourceHelper.cs similarity index 77% rename from ModernKeePass/Services/ResourcesService.cs rename to ModernKeePass/Common/ResourceHelper.cs index 3630fc4..14d6800 100644 --- a/ModernKeePass/Services/ResourcesService.cs +++ b/ModernKeePass/Common/ResourceHelper.cs @@ -1,9 +1,8 @@ using Windows.ApplicationModel.Resources; -using ModernKeePass.Interfaces; -namespace ModernKeePass.Services +namespace ModernKeePass.Common { - public class ResourcesService: IResourceService + public class ResourceHelper { private const string ResourceFileName = "CodeBehind"; private readonly ResourceLoader _resourceLoader = ResourceLoader.GetForCurrentView(); @@ -14,4 +13,4 @@ namespace ModernKeePass.Services return resource; } } -} +} \ No newline at end of file diff --git a/ModernKeePass/Common/ToastNotificationHelper.cs b/ModernKeePass/Common/ToastNotificationHelper.cs index 9b2592e..8d18c5a 100644 --- a/ModernKeePass/Common/ToastNotificationHelper.cs +++ b/ModernKeePass/Common/ToastNotificationHelper.cs @@ -3,7 +3,6 @@ using Windows.Data.Json; using Windows.Data.Xml.Dom; using Windows.UI.Notifications; using ModernKeePass.Interfaces; -using ModernKeePass.ViewModels; namespace ModernKeePass.Common { diff --git a/ModernKeePass/ImportFormats/CsvImportFormat.cs b/ModernKeePass/ImportFormats/CsvImportFormat.cs deleted file mode 100644 index 6a323e9..0000000 --- a/ModernKeePass/ImportFormats/CsvImportFormat.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Windows.Storage; -using ModernKeePass.Interfaces; - -namespace ModernKeePass.ImportFormats -{ - public class CsvImportFormat: IFormat - { - public bool HasHeaderRow { get; set; } = true; - public char Delimiter { get; set; } = ';'; - public char LineDelimiter { get; set; } = '\n'; - - public async Task>> Import(IStorageFile source) - { - var parsedResult = new List>(); - var content = await FileIO.ReadLinesAsync(source); - foreach (var line in content) - { - var fields = line.Split(Delimiter); - var recordItem = new Dictionary(); - var i = 0; - foreach (var field in fields) - { - recordItem.Add(i.ToString(), field); - i++; - } - parsedResult.Add(recordItem); - } - - return parsedResult; - } - } -} \ No newline at end of file diff --git a/ModernKeePass/ImportFormats/NullImportFormat.cs b/ModernKeePass/ImportFormats/NullImportFormat.cs deleted file mode 100644 index 1f8cb7e..0000000 --- a/ModernKeePass/ImportFormats/NullImportFormat.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Windows.Storage; -using ModernKeePass.Interfaces; -using System; -using System.Threading.Tasks; -using System.Collections.Generic; - -namespace ModernKeePass.ImportFormats -{ - public class NullImportFormat: IFormat - { - public Task>> Import(IStorageFile source) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/ModernKeePass/Interfaces/IFormat.cs b/ModernKeePass/Interfaces/IFormat.cs deleted file mode 100644 index a53567f..0000000 --- a/ModernKeePass/Interfaces/IFormat.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Windows.Storage; - -namespace ModernKeePass.Interfaces -{ - public interface IFormat - { - Task>> Import(IStorageFile source); - } -} \ No newline at end of file diff --git a/ModernKeePass/Interfaces/IProxyInvocationHandler.cs b/ModernKeePass/Interfaces/IProxyInvocationHandler.cs deleted file mode 100644 index 5781e23..0000000 --- a/ModernKeePass/Interfaces/IProxyInvocationHandler.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Reflection; - -namespace ModernKeePass.Interfaces -{ - public interface IProxyInvocationHandler - { - object Invoke(object proxy, MethodInfo method, object[] parameters); - } -} \ No newline at end of file diff --git a/ModernKeePass/Interfaces/IRecentItem.cs b/ModernKeePass/Interfaces/IRecentItem.cs deleted file mode 100644 index e468539..0000000 --- a/ModernKeePass/Interfaces/IRecentItem.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Windows.Storage; - -namespace ModernKeePass.Interfaces -{ - public interface IRecentItem - { - StorageFile DatabaseFile { get; } - string Token { get; } - string Name { get; } - } -} \ No newline at end of file diff --git a/ModernKeePass/Interfaces/IRecentService.cs b/ModernKeePass/Interfaces/IRecentService.cs deleted file mode 100644 index 5f66aa5..0000000 --- a/ModernKeePass/Interfaces/IRecentService.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.ObjectModel; -using System.Threading.Tasks; -using Windows.Storage; - -namespace ModernKeePass.Interfaces -{ - public interface IRecentService - { - int EntryCount { get; } - Task GetFileAsync(string token); - ObservableCollection GetAllFiles(bool removeIfNonExistant = true); - void Add(IStorageItem file, string metadata); - void ClearAll(); - } -} \ No newline at end of file diff --git a/ModernKeePass/Interfaces/IResourceService.cs b/ModernKeePass/Interfaces/IResourceService.cs deleted file mode 100644 index 72a35c4..0000000 --- a/ModernKeePass/Interfaces/IResourceService.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ModernKeePass.Interfaces -{ - public interface IResourceService - { - string GetResourceValue(string key); - } -} diff --git a/ModernKeePass/Interfaces/ISettingsService.cs b/ModernKeePass/Interfaces/ISettingsService.cs deleted file mode 100644 index 5b6b147..0000000 --- a/ModernKeePass/Interfaces/ISettingsService.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace ModernKeePass.Interfaces -{ - public interface ISettingsService - { - T GetSetting(string property, T defaultValue = default(T)); - void PutSetting(string property, T value); - } -} \ No newline at end of file diff --git a/ModernKeePass/Services/DatabaseService.cs b/ModernKeePass/Services/DatabaseService.cs deleted file mode 100644 index 6fda7af..0000000 --- a/ModernKeePass/Services/DatabaseService.cs +++ /dev/null @@ -1,194 +0,0 @@ -using System; -using System.Runtime.InteropServices.WindowsRuntime; -using System.Threading.Tasks; -using Windows.Storage; -using Microsoft.HockeyApp; -using ModernKeePass.Domain.Exceptions; -using ModernKeePass.Interfaces; -using ModernKeePass.ViewModels; -using ModernKeePassLib; -using ModernKeePassLib.Cryptography.KeyDerivation; -using ModernKeePassLib.Interfaces; -using ModernKeePassLib.Keys; -using ModernKeePassLib.Serialization; - -namespace ModernKeePass.Services -{ - public class DatabaseService: SingletonServiceBase, IDatabaseService - { - private readonly PwDatabase _pwDatabase = new PwDatabase(); - private readonly ISettingsService _settings; - private StorageFile _databaseFile; - private GroupVm _recycleBin; - private CompositeKey _compositeKey; - - public GroupVm RootGroup { get; set; } - - public GroupVm RecycleBin - { - get { return _recycleBin; } - set - { - _recycleBin = value; - _pwDatabase.RecycleBinUuid = _recycleBin?.IdUuid; - } - } - - public string Name => _databaseFile?.Name; - - public bool RecycleBinEnabled - { - get { return _pwDatabase.RecycleBinEnabled; } - set { _pwDatabase.RecycleBinEnabled = value; } - } - - public PwUuid DataCipher - { - get { return _pwDatabase.DataCipherUuid; } - set { _pwDatabase.DataCipherUuid = value; } - } - - public PwCompressionAlgorithm CompressionAlgorithm - { - get { return _pwDatabase.Compression; } - set { _pwDatabase.Compression = value; } - } - - public KdfParameters KeyDerivation - { - get { return _pwDatabase.KdfParameters; } - set { _pwDatabase.KdfParameters = value; } - } - - public bool IsOpen => _pwDatabase.IsOpen; - public bool IsFileOpen => !_pwDatabase.IsOpen && _databaseFile != null; - public bool IsClosed => _databaseFile == null; - public bool HasChanged { get; set; } - - public DatabaseService() : this(SettingsService.Instance) - { - } - - public DatabaseService(ISettingsService settings) - { - _settings = settings; - } - - - /// - /// 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 async Task Open(StorageFile databaseFile, CompositeKey key, bool createNew = false) - { - try - { - if (databaseFile == null) - { - throw new ArgumentNullException(nameof(databaseFile)); - } - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - _compositeKey = key; - var fileContents = await FileIO.ReadBufferAsync(databaseFile); - var ioConnection = IOConnectionInfo.FromByteArray(fileContents.ToArray()); - if (createNew) - { - _pwDatabase.New(ioConnection, key); - - var fileFormat = _settings.GetSetting("DefaultFileFormat"); - switch (fileFormat) - { - case "4": - KeyDerivation = KdfPool.Get("Argon2").GetDefaultParameters(); - break; - } - } - else _pwDatabase.Open(ioConnection, key, new NullStatusLogger()); - - _databaseFile = databaseFile; - RootGroup = new GroupVm(_pwDatabase.RootGroup, null, RecycleBinEnabled ? _pwDatabase.RecycleBinUuid : null); - } - catch (InvalidCompositeKeyException ex) - { - HockeyClient.Current.TrackException(ex); - throw new ArgumentException(ex.Message, ex); - } - } - - public async Task ReOpen() - { - await Open(_databaseFile, _compositeKey); - } - - /// - /// Commit the changes to the currently opened database to file - /// - public void Save() - { - if (!IsOpen) return; - try - { - _pwDatabase.Save(new NullStatusLogger()); - } - catch (Exception e) - { - throw new SaveException(e); - } - } - - /// - /// Save the current database to another file and open it - /// - /// The new database file - public async Task Save(StorageFile file) - { - var oldFile = _databaseFile; - _databaseFile = file; - try - { - var fileContents = await FileIO.ReadBufferAsync(file); - _pwDatabase.SaveAs(IOConnectionInfo.FromByteArray(fileContents.ToArray()), true, new NullStatusLogger()); - } - catch - { - _databaseFile = oldFile; - throw; - } - } - - /// - /// Close the currently opened database - /// - public void Close(bool releaseFile = true) - { - _pwDatabase?.Close(); - if (releaseFile) _databaseFile = null; - } - - public void AddDeletedItem(PwUuid id) - { - _pwDatabase.DeletedObjects.Add(new PwDeletedObject(id, DateTime.UtcNow)); - } - - public void CreateRecycleBin(string title) - { - RecycleBin = RootGroup.AddNewGroup(title); - RecycleBin.IsSelected = true; - RecycleBin.IconId = (int)PwIcon.TrashBin; - } - - public void UpdateCompositeKey(CompositeKey newCompositeKey) - { - if (newCompositeKey == null) return; - _compositeKey = newCompositeKey; - _pwDatabase.MasterKey = newCompositeKey; - } - } -} diff --git a/ModernKeePass/Services/ImportService.cs b/ModernKeePass/Services/ImportService.cs deleted file mode 100644 index baa718f..0000000 --- a/ModernKeePass/Services/ImportService.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Threading.Tasks; -using Windows.Storage; -using ModernKeePass.Interfaces; -using ModernKeePass.ViewModels; - -namespace ModernKeePass.Services -{ - public class ImportService : IImportService - { - public async Task Import(IFormat format, IStorageFile source, GroupVm group) - { - var data = await format.Import(source); - - foreach (var entity in data) - { - var entry = group.AddNewEntry(); - entry.Title = entity["0"]; - entry.UserName = entity["1"]; - entry.Password = entity["2"]; - if (entity.Count > 3) entry.Url = entity["3"]; - if (entity.Count > 4) entry.Notes = entity["4"]; - } - } - } -} \ No newline at end of file diff --git a/ModernKeePass/Services/RecentService.cs b/ModernKeePass/Services/RecentService.cs deleted file mode 100644 index b5155b4..0000000 --- a/ModernKeePass/Services/RecentService.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using System.Threading.Tasks; -using ModernKeePass.Interfaces; -using Windows.Storage; -using Windows.Storage.AccessCache; -using ModernKeePass.ViewModels; - -namespace ModernKeePass.Services -{ - public class RecentService : SingletonServiceBase, IRecentService - { - private readonly StorageItemMostRecentlyUsedList _mru = StorageApplicationPermissions.MostRecentlyUsedList; - - public int EntryCount => _mru.Entries.Count; - - public ObservableCollection GetAllFiles(bool removeIfNonExistant = true) - { - var result = new ObservableCollection(); - foreach (var entry in _mru.Entries) - { - try - { - var file = _mru.GetFileAsync(entry.Token, AccessCacheOptions.SuppressAccessTimeUpdate).GetAwaiter().GetResult(); - result.Add(new RecentItemVm(entry.Token, entry.Metadata, file)); - } - catch (Exception) - { - if (removeIfNonExistant) _mru.Remove(entry.Token); - } - } - return result; - } - - public void Add(IStorageItem file, string metadata) - { - _mru.Add(file, metadata); - } - - public void ClearAll() - { - _mru.Clear(); - } - - public async Task GetFileAsync(string token) - { - return await _mru.GetFileAsync(token); - } - } -} diff --git a/ModernKeePass/Services/SettingsService.cs b/ModernKeePass/Services/SettingsService.cs deleted file mode 100644 index 817bcbd..0000000 --- a/ModernKeePass/Services/SettingsService.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using Windows.Foundation.Collections; -using Windows.Storage; -using ModernKeePass.Interfaces; - -namespace ModernKeePass.Services -{ - public class SettingsService : SingletonServiceBase, ISettingsService - { - private readonly IPropertySet _values = ApplicationData.Current.LocalSettings.Values; - - public T GetSetting(string property, T defaultValue = default(T)) - { - try - { - return (T)Convert.ChangeType(_values[property], typeof(T)); - } - catch (InvalidCastException) - { - return defaultValue; - } - } - - public void PutSetting(string property, T value) - { - if (_values.ContainsKey(property)) - _values[property] = value; - else _values.Add(property, value); - } - } -} diff --git a/ModernKeePass/Services/SingletonServiceBase.cs b/ModernKeePass/Services/SingletonServiceBase.cs deleted file mode 100644 index 21e8758..0000000 --- a/ModernKeePass/Services/SingletonServiceBase.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace ModernKeePass.Services -{ - public abstract class SingletonServiceBase where T : new() - { - private static readonly Lazy LazyInstance = - new Lazy(() => new T()); - - public static T Instance => LazyInstance.Value; - } -} diff --git a/ModernKeePass/ViewModels/CompositeKeyVm.cs b/ModernKeePass/ViewModels/CompositeKeyVm.cs index fb03ba9..683a1c6 100644 --- a/ModernKeePass/ViewModels/CompositeKeyVm.cs +++ b/ModernKeePass/ViewModels/CompositeKeyVm.cs @@ -1,17 +1,16 @@ using System; using System.Text; using System.Threading.Tasks; -using Windows.Storage; -using Windows.Storage.AccessCache; using MediatR; +using Microsoft.Extensions.DependencyInjection; using ModernKeePass.Application.Database.Commands.UpdateCredentials; using ModernKeePass.Application.Database.Queries.GetDatabase; using ModernKeePass.Application.Database.Queries.OpenDatabase; using ModernKeePass.Application.Security.Commands.GenerateKeyFile; using ModernKeePass.Application.Security.Queries.EstimatePasswordComplexity; +using ModernKeePass.Domain.AOP; +using ModernKeePass.Domain.Dtos; using ModernKeePass.Common; -using ModernKeePass.Interfaces; -using ModernKeePass.Services; namespace ModernKeePass.ViewModels { @@ -55,7 +54,7 @@ namespace ModernKeePass.ViewModels } } - public bool IsValid => !_isOpening && (HasPassword || HasKeyFile && KeyFile != null || HasUserAccount); + public bool IsValid => !_isOpening && (HasPassword || HasKeyFile && KeyFilePath != null || HasUserAccount); public string Status { @@ -75,20 +74,19 @@ namespace ModernKeePass.ViewModels set { _password = value; - OnPropertyChanged("PasswordComplexityIndicator"); + OnPropertyChanged(nameof(PasswordComplexityIndicator)); StatusType = (int)StatusTypes.Normal; Status = string.Empty; } } - public StorageFile KeyFile + public string KeyFilePath { - get { return _keyFile; } + get { return _keyFilePath; } set { - _keyFile = value; - KeyFileText = value?.Name; - OnPropertyChanged("IsValid"); + _keyFilePath = value; + OnPropertyChanged(nameof(IsValid)); } } @@ -109,21 +107,21 @@ namespace ModernKeePass.ViewModels private string _password = string.Empty; private string _status; private StatusTypes _statusType; - private StorageFile _keyFile; + private string _keyFilePath; private string _keyFileText; private readonly IMediator _mediator; - private readonly IResourceService _resource; + private readonly ResourceHelper _resource; - public CompositeKeyVm() : this(App.Mediator, new ResourcesService()) { } + public CompositeKeyVm() : this(App.Services.GetService()) { } - public CompositeKeyVm(IMediator mediator, IResourceService resource) + public CompositeKeyVm(IMediator mediator) { _mediator = mediator; - _resource = resource; + _resource = new ResourceHelper(); _keyFileText = _resource.GetResourceValue("CompositeKeyDefaultKeyFile"); } - public async Task OpenDatabase(StorageFile databaseFile, bool createNew) + public async Task OpenDatabase(string databaseFilePath, bool createNew) { try { @@ -131,9 +129,9 @@ namespace ModernKeePass.ViewModels OnPropertyChanged(nameof(IsValid)); await _mediator.Send(new OpenDatabaseQuery { - FilePath = StorageApplicationPermissions.FutureAccessList.Add(databaseFile), - KeyFilePath = HasKeyFile && KeyFile != null ? StorageApplicationPermissions.FutureAccessList.Add(KeyFile) : null, - Password = Password = HasPassword ? Password : null, + FilePath = databaseFilePath, + KeyFilePath = HasKeyFile ? KeyFilePath : null, + Password = HasPassword ? Password : null, }); RootGroupId = (await _mediator.Send(new GetDatabaseQuery())).RootGroupId; return true; @@ -163,18 +161,18 @@ namespace ModernKeePass.ViewModels { await _mediator.Send(new UpdateCredentialsCommand { - KeyFilePath = HasKeyFile && KeyFile != null ? StorageApplicationPermissions.FutureAccessList.Add(KeyFile) : null, - Password = Password = HasPassword ? Password : null, + KeyFilePath = HasKeyFile ? KeyFilePath : null, + Password = HasPassword ? Password : null, }); UpdateStatus(_resource.GetResourceValue("CompositeKeyUpdated"), StatusTypes.Success); } - public async Task CreateKeyFile(StorageFile file) + public async Task CreateKeyFile(FileInfo file) { - var token = StorageApplicationPermissions.FutureAccessList.Add(file); // TODO: implement entropy generator - await _mediator.Send(new GenerateKeyFileCommand {KeyFilePath = token}); - KeyFile = file; + await _mediator.Send(new GenerateKeyFileCommand {KeyFilePath = file.Path}); + KeyFilePath = file.Path; + KeyFileText = file.Name; } private void UpdateStatus(string text, StatusTypes type) diff --git a/ModernKeePass/ViewModels/EntryDetailVm.cs b/ModernKeePass/ViewModels/EntryDetailVm.cs index 664dab9..64bf4c7 100644 --- a/ModernKeePass/ViewModels/EntryDetailVm.cs +++ b/ModernKeePass/ViewModels/EntryDetailVm.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using System.Windows.Input; using Windows.UI.Xaml.Controls; using MediatR; +using Microsoft.Extensions.DependencyInjection; using ModernKeePass.Application.Database.Commands.SaveDatabase; using ModernKeePass.Application.Database.Models; using ModernKeePass.Application.Database.Queries.GetDatabase; @@ -22,6 +23,7 @@ using ModernKeePass.Domain.Enums; using ModernKeePass.Domain.Interfaces; using ModernKeePass.Interfaces; using ModernKeePass.Application.Group.Models; +using ModernKeePass.Domain.AOP; namespace ModernKeePass.ViewModels { @@ -49,21 +51,13 @@ namespace ModernKeePass.ViewModels public bool IsSelected { get { return _isSelected; } - set - { - _isSelected = value; - OnPropertyChanged(); - } + set { SetProperty(ref _isSelected, value); } } public double PasswordLength { get { return _passwordLength; } - set - { - _passwordLength = value; - OnPropertyChanged(); - } + set { SetProperty(ref _passwordLength, value); } } public string Title @@ -191,31 +185,19 @@ namespace ModernKeePass.ViewModels public bool IsEditMode { get { return IsSelected && _isEditMode; } - set - { - _isEditMode = value; - OnPropertyChanged(); - } + set { SetProperty(ref _isEditMode, value); } } public bool IsVisible { get { return _isVisible; } - set - { - _isVisible = value; - OnPropertyChanged(); - } + set { SetProperty(ref _isVisible, value); } } public bool IsRevealPassword { get { return _isRevealPassword; } - set - { - _isRevealPassword = value; - OnPropertyChanged(); - } + set { SetProperty(ref _isRevealPassword, value); } } public bool CanRestore => _entry.ParentGroupId == _database.RecycleBinId; @@ -237,7 +219,7 @@ namespace ModernKeePass.ViewModels public EntryDetailVm() { } - internal EntryDetailVm(string entryId, bool isNewEntry = false) : this(entryId, App.Mediator, isNewEntry) { } + internal EntryDetailVm(string entryId, bool isNewEntry = false) : this(entryId, App.Services.GetService(), isNewEntry) { } public EntryDetailVm(string entryId, IMediator mediator, bool isNewEntry = false) { diff --git a/ModernKeePass/ViewModels/GroupDetailVm.cs b/ModernKeePass/ViewModels/GroupDetailVm.cs index ec148c7..df5159e 100644 --- a/ModernKeePass/ViewModels/GroupDetailVm.cs +++ b/ModernKeePass/ViewModels/GroupDetailVm.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using System.Windows.Input; using Windows.UI.Xaml.Controls; using MediatR; +using Microsoft.Extensions.DependencyInjection; using ModernKeePass.Application.Database.Commands.SaveDatabase; using ModernKeePass.Application.Database.Models; using ModernKeePass.Application.Database.Queries.GetDatabase; @@ -23,6 +24,7 @@ using ModernKeePass.Application.Group.Commands.SortGroups; using ModernKeePass.Application.Group.Models; using ModernKeePass.Application.Group.Queries.GetGroup; using ModernKeePass.Common; +using ModernKeePass.Domain.AOP; using ModernKeePass.Domain.Enums; using ModernKeePass.Domain.Interfaces; using ModernKeePass.Interfaces; @@ -122,7 +124,7 @@ namespace ModernKeePass.ViewModels public GroupDetailVm() {} - internal GroupDetailVm(string groupId) : this(groupId, App.Mediator) + internal GroupDetailVm(string groupId) : this(groupId, App.Services.GetService()) { } public GroupDetailVm(string groupId, IMediator mediator, bool isEditMode = false) diff --git a/ModernKeePass/ViewModels/Items/ListMenuItemVm.cs b/ModernKeePass/ViewModels/Items/ListMenuItemVm.cs index 4385de4..a83b0a1 100644 --- a/ModernKeePass/ViewModels/Items/ListMenuItemVm.cs +++ b/ModernKeePass/ViewModels/Items/ListMenuItemVm.cs @@ -1,8 +1,7 @@ using System; using Windows.UI.Xaml.Controls; -using ModernKeePass.Common; +using ModernKeePass.Domain.AOP; using ModernKeePass.Domain.Interfaces; -using ModernKeePass.Interfaces; namespace ModernKeePass.ViewModels { diff --git a/ModernKeePass/ViewModels/Items/RecentItemVm.cs b/ModernKeePass/ViewModels/Items/RecentItemVm.cs index c301537..2482049 100644 --- a/ModernKeePass/ViewModels/Items/RecentItemVm.cs +++ b/ModernKeePass/ViewModels/Items/RecentItemVm.cs @@ -1,20 +1,20 @@ using System.Threading.Tasks; -using Windows.Storage; -using ModernKeePass.Common; +using Microsoft.Extensions.DependencyInjection; +using ModernKeePass.Application.Common.Interfaces; +using ModernKeePass.Domain.AOP; +using ModernKeePass.Domain.Dtos; using ModernKeePass.Domain.Interfaces; -using ModernKeePass.Interfaces; -using ModernKeePass.Services; namespace ModernKeePass.ViewModels { - public class RecentItemVm: NotifyPropertyChangedBase, ISelectableModel, IRecentItem + public class RecentItemVm: NotifyPropertyChangedBase, ISelectableModel { + private readonly IRecentProxy _recent; private bool _isSelected; - public StorageFile DatabaseFile { get; } public string Token { get; } public string Name { get; } - public string Path => DatabaseFile?.Path; + public string Path => string.Empty; public bool IsSelected { @@ -22,22 +22,17 @@ namespace ModernKeePass.ViewModels set { SetProperty(ref _isSelected, value); } } - public RecentItemVm() {} - public RecentItemVm(string token, string metadata, IStorageItem file) + public RecentItemVm(FileInfo file): this(App.Services.GetService(), file) {} + public RecentItemVm(IRecentProxy recent, FileInfo file) { - Token = token; - Name = metadata; - DatabaseFile = file as StorageFile; + _recent = recent; + Token = file.Path; + Name = file.Name; } - public void UpdateAccessTime() + public async Task UpdateAccessTime() { - UpdateAccessTime(RecentService.Instance).Wait(); - } - - public async Task UpdateAccessTime(IRecentService recent) - { - await recent.GetFileAsync(Token); + await _recent.Get(Token); } } } diff --git a/ModernKeePass/ViewModels/Items/SettingsDatabaseVm.cs b/ModernKeePass/ViewModels/Items/SettingsDatabaseVm.cs index 5fabe41..3037fd0 100644 --- a/ModernKeePass/ViewModels/Items/SettingsDatabaseVm.cs +++ b/ModernKeePass/ViewModels/Items/SettingsDatabaseVm.cs @@ -2,6 +2,7 @@ using System.Collections.ObjectModel; using System.Linq; using MediatR; +using Microsoft.Extensions.DependencyInjection; using ModernKeePass.Application.Common.Interfaces; using ModernKeePass.Application.Database.Models; using ModernKeePass.Application.Database.Queries.GetDatabase; @@ -15,7 +16,7 @@ using ModernKeePass.Application.Parameters.Models; using ModernKeePass.Application.Parameters.Queries.GetCiphers; using ModernKeePass.Application.Parameters.Queries.GetCompressions; using ModernKeePass.Application.Parameters.Queries.GetKeyDerivations; -using ModernKeePass.Common; +using ModernKeePass.Domain.AOP; namespace ModernKeePass.ViewModels { @@ -73,7 +74,7 @@ namespace ModernKeePass.ViewModels set { _mediator.Send(new SetRecycleBinCommand { RecycleBinId = value.Id}).Wait(); } } - public SettingsDatabaseVm() : this(App.Mediator) { } + public SettingsDatabaseVm() : this(App.Services.GetService()) { } public SettingsDatabaseVm(IMediator mediator) { diff --git a/ModernKeePass/ViewModels/Items/SettingsNewVm.cs b/ModernKeePass/ViewModels/Items/SettingsNewVm.cs index a9a050d..c44074a 100644 --- a/ModernKeePass/ViewModels/Items/SettingsNewVm.cs +++ b/ModernKeePass/ViewModels/Items/SettingsNewVm.cs @@ -1,17 +1,17 @@ using System.Collections.Generic; -using ModernKeePass.Interfaces; -using ModernKeePass.Services; +using Microsoft.Extensions.DependencyInjection; +using ModernKeePass.Application.Common.Interfaces; namespace ModernKeePass.ViewModels { public class SettingsNewVm { - private readonly ISettingsService _settings; + private readonly ISettingsProxy _settings; - public SettingsNewVm() : this(SettingsService.Instance) + public SettingsNewVm() : this(App.Services.GetService()) { } - public SettingsNewVm(ISettingsService settings) + public SettingsNewVm(ISettingsProxy settings) { _settings = settings; } diff --git a/ModernKeePass/ViewModels/Items/SettingsSaveVm.cs b/ModernKeePass/ViewModels/Items/SettingsSaveVm.cs index a306d42..9da7961 100644 --- a/ModernKeePass/ViewModels/Items/SettingsSaveVm.cs +++ b/ModernKeePass/ViewModels/Items/SettingsSaveVm.cs @@ -1,16 +1,16 @@ -using ModernKeePass.Interfaces; -using ModernKeePass.Services; +using Microsoft.Extensions.DependencyInjection; +using ModernKeePass.Application.Common.Interfaces; namespace ModernKeePass.ViewModels { public class SettingsSaveVm { - private readonly ISettingsService _settings; + private readonly ISettingsProxy _settings; - public SettingsSaveVm() : this(SettingsService.Instance) + public SettingsSaveVm() : this(App.Services.GetService()) { } - public SettingsSaveVm(ISettingsService settings) + public SettingsSaveVm(ISettingsProxy settings) { _settings = settings; } diff --git a/ModernKeePass/ViewModels/MainVm.cs b/ModernKeePass/ViewModels/MainVm.cs index e3d2ce1..22f4ab0 100644 --- a/ModernKeePass/ViewModels/MainVm.cs +++ b/ModernKeePass/ViewModels/MainVm.cs @@ -1,14 +1,15 @@ using System.Collections.ObjectModel; using System.Linq; using Windows.ApplicationModel; -using Windows.Storage; using Windows.UI.Xaml.Controls; using MediatR; +using Microsoft.Extensions.DependencyInjection; +using ModernKeePass.Application.Common.Interfaces; using ModernKeePass.Application.Database.Queries.GetDatabase; using ModernKeePass.Common; +using ModernKeePass.Domain.AOP; +using ModernKeePass.Domain.Dtos; using ModernKeePass.Domain.Interfaces; -using ModernKeePass.Interfaces; -using ModernKeePass.Services; using ModernKeePass.Views; namespace ModernKeePass.ViewModels @@ -48,12 +49,13 @@ namespace ModernKeePass.ViewModels public MainVm() {} - internal MainVm(Frame referenceFrame, Frame destinationFrame, StorageFile databaseFile = null) : this(referenceFrame, destinationFrame, - App.Mediator, new ResourcesService(), RecentService.Instance, databaseFile) + internal MainVm(Frame referenceFrame, Frame destinationFrame, FileInfo databaseFile = null) : this(referenceFrame, destinationFrame, + App.Services.GetService(), App.Services.GetService(), databaseFile) { } - public MainVm(Frame referenceFrame, Frame destinationFrame, IMediator mediator, IResourceService resource, IRecentService recent, StorageFile databaseFile = null) + public MainVm(Frame referenceFrame, Frame destinationFrame, IMediator mediator, IRecentProxy recent, FileInfo databaseFile = null) { + var resource = new ResourceHelper(); var database = mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult(); var mainMenuItems = new ObservableCollection diff --git a/ModernKeePass/ViewModels/NewVm.cs b/ModernKeePass/ViewModels/NewVm.cs index 8b20fa0..7d521cb 100644 --- a/ModernKeePass/ViewModels/NewVm.cs +++ b/ModernKeePass/ViewModels/NewVm.cs @@ -1,6 +1,8 @@ using System.Threading.Tasks; using Windows.Storage; using MediatR; +using Microsoft.Extensions.DependencyInjection; +using ModernKeePass.Application.Common.Interfaces; using ModernKeePass.Application.Database.Queries.GetDatabase; using ModernKeePass.Application.Entry.Commands.SetFieldValue; using ModernKeePass.Application.Group.Commands.CreateEntry; @@ -8,15 +10,13 @@ using ModernKeePass.Application.Group.Commands.CreateGroup; using ModernKeePass.Application.Group.Models; using ModernKeePass.Application.Group.Queries.GetGroup; using ModernKeePass.Domain.Enums; -using ModernKeePass.Interfaces; -using ModernKeePass.Services; namespace ModernKeePass.ViewModels { public class NewVm : OpenVm { private readonly IMediator _mediator; - private readonly ISettingsService _settings; + private readonly ISettingsProxy _settings; private string _importFormatHelp; public string Password { get; set; } @@ -26,7 +26,7 @@ namespace ModernKeePass.ViewModels public string ImportFileExtensionFilter { get; set; } = "*"; - public IFormat ImportFormat { get; set; } + public IImportFormat ImportFormat { get; set; } public string ImportFormatHelp { @@ -38,9 +38,9 @@ namespace ModernKeePass.ViewModels } } - public NewVm(): this(App.Mediator, new SettingsService()) { } + public NewVm(): this(App.Services.GetService(), App.Services.GetService()) { } - public NewVm(IMediator mediator, ISettingsService settings) + public NewVm(IMediator mediator, ISettingsProxy settings) { _mediator = mediator; _settings = settings; diff --git a/ModernKeePass/ViewModels/OpenVm.cs b/ModernKeePass/ViewModels/OpenVm.cs index b8161c4..752518e 100644 --- a/ModernKeePass/ViewModels/OpenVm.cs +++ b/ModernKeePass/ViewModels/OpenVm.cs @@ -1,38 +1,38 @@ -using Windows.Storage; -using ModernKeePass.Common; -using ModernKeePass.Interfaces; -using ModernKeePass.Services; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using ModernKeePass.Application.Common.Interfaces; +using ModernKeePass.Domain.AOP; +using ModernKeePass.Domain.Dtos; namespace ModernKeePass.ViewModels { public class OpenVm: NotifyPropertyChangedBase { - private readonly IRecentService _recent; - public bool IsFileSelected => DatabaseFile != null; + private readonly IRecentProxy _recent; + public bool IsFileSelected => !string.IsNullOrEmpty(Path); - public string Name => DatabaseFile?.DisplayName; + public string Name { get; private set; } + public string Path { get; private set; } - public StorageFile DatabaseFile { get; private set; } + public OpenVm(): this(App.Services.GetService()) { } - public OpenVm(): this(new RecentService()) { } - - public OpenVm(IRecentService recent) + public OpenVm(IRecentProxy recent) { _recent = recent; } - public void OpenFile(StorageFile file) + public async Task OpenFile(FileInfo file) { - DatabaseFile = file; - OnPropertyChanged("Name"); - OnPropertyChanged("IsFileSelected"); - OnPropertyChanged("DatabaseFile"); - AddToRecentList(file); + Name = file.Name; + Path = file.Path; + OnPropertyChanged(nameof(Name)); + OnPropertyChanged(nameof(IsFileSelected)); + await AddToRecentList(file); } - private void AddToRecentList(StorageFile file) + private async Task AddToRecentList(FileInfo file) { - _recent.Add(file, file.DisplayName); + await _recent.Add(file); } } } diff --git a/ModernKeePass/ViewModels/RecentVm.cs b/ModernKeePass/ViewModels/RecentVm.cs index 179c2a7..36bb79c 100644 --- a/ModernKeePass/ViewModels/RecentVm.cs +++ b/ModernKeePass/ViewModels/RecentVm.cs @@ -1,19 +1,21 @@ using System.Collections.ObjectModel; +using System.Linq; using System.Windows.Input; +using Microsoft.Extensions.DependencyInjection; +using ModernKeePass.Application.Common.Interfaces; using ModernKeePass.Common; +using ModernKeePass.Domain.AOP; using ModernKeePass.Domain.Interfaces; -using ModernKeePass.Interfaces; -using ModernKeePass.Services; namespace ModernKeePass.ViewModels { public class RecentVm : NotifyPropertyChangedBase, IHasSelectableObject { - private readonly IRecentService _recent; + private readonly IRecentProxy _recent; private ISelectableModel _selectedItem; - private ObservableCollection _recentItems = new ObservableCollection(); + private ObservableCollection _recentItems; - public ObservableCollection RecentItems + public ObservableCollection RecentItems { get { return _recentItems; } set { SetProperty(ref _recentItems, value); } @@ -39,15 +41,16 @@ namespace ModernKeePass.ViewModels public ICommand ClearAllCommand { get; } - public RecentVm() : this (RecentService.Instance) + public RecentVm() : this (App.Services.GetService()) { } - public RecentVm(IRecentService recent) + public RecentVm(IRecentProxy recent) { _recent = recent; ClearAllCommand = new RelayCommand(ClearAll); - RecentItems = _recent.GetAllFiles(); + RecentItems = new ObservableCollection(_recent.GetAll().GetAwaiter().GetResult() + .Select(r => new RecentItemVm(r))); if (RecentItems.Count > 0) SelectedItem = RecentItems[0] as RecentItemVm; } diff --git a/ModernKeePass/ViewModels/SaveVm.cs b/ModernKeePass/ViewModels/SaveVm.cs index 8ac3f78..91bb274 100644 --- a/ModernKeePass/ViewModels/SaveVm.cs +++ b/ModernKeePass/ViewModels/SaveVm.cs @@ -2,6 +2,7 @@ using Windows.Storage; using Windows.Storage.AccessCache; using MediatR; +using Microsoft.Extensions.DependencyInjection; using ModernKeePass.Application.Database.Commands.CloseDatabase; using ModernKeePass.Application.Database.Commands.SaveDatabase; @@ -10,7 +11,7 @@ namespace ModernKeePass.ViewModels public class SaveVm { private readonly IMediator _mediator; - public SaveVm() : this(App.Mediator) { } + public SaveVm() : this(App.Services.GetService()) { } public SaveVm(IMediator mediator) { diff --git a/ModernKeePass/ViewModels/SettingsVm.cs b/ModernKeePass/ViewModels/SettingsVm.cs index a62f87c..89f6cdc 100644 --- a/ModernKeePass/ViewModels/SettingsVm.cs +++ b/ModernKeePass/ViewModels/SettingsVm.cs @@ -2,12 +2,12 @@ using System.Linq; using Windows.UI.Xaml.Controls; using MediatR; +using Microsoft.Extensions.DependencyInjection; using ModernKeePass.Application.Database.Queries.GetDatabase; using ModernKeePass.Common; +using ModernKeePass.Domain.AOP; using ModernKeePass.Domain.Interfaces; -using ModernKeePass.Interfaces; using ModernKeePass.Views; -using ModernKeePass.Services; namespace ModernKeePass.ViewModels { @@ -43,10 +43,11 @@ namespace ModernKeePass.ViewModels } } - public SettingsVm() : this(App.Mediator, new ResourcesService()) { } + public SettingsVm() : this(App.Services.GetService()) { } - public SettingsVm(IMediator mediator, IResourceService resource) + public SettingsVm(IMediator mediator) { + var resource = new ResourceHelper(); var database = mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult(); var menuItems = new ObservableCollection { diff --git a/ModernKeePass/Views/BasePages/LayoutAwarePageBase.cs b/ModernKeePass/Views/BasePages/LayoutAwarePageBase.cs index 5c10ba3..5c57c53 100644 --- a/ModernKeePass/Views/BasePages/LayoutAwarePageBase.cs +++ b/ModernKeePass/Views/BasePages/LayoutAwarePageBase.cs @@ -5,7 +5,6 @@ using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Navigation; using ModernKeePass.Common; using ModernKeePass.Domain.Interfaces; -using ModernKeePass.Interfaces; namespace ModernKeePass.Views.BasePages { diff --git a/ModernKeePass/Views/MainPage.xaml.cs b/ModernKeePass/Views/MainPage.xaml.cs index 8747bb3..3a1e315 100644 --- a/ModernKeePass/Views/MainPage.xaml.cs +++ b/ModernKeePass/Views/MainPage.xaml.cs @@ -1,6 +1,6 @@ -using Windows.Storage; -using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; +using ModernKeePass.Domain.Dtos; using ModernKeePass.ViewModels; // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 @@ -33,7 +33,7 @@ namespace ModernKeePass.Views protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); - var file = e.Parameter as StorageFile; + var file = e.Parameter as FileInfo; DataContext = new MainVm(Frame, MenuFrame, file); } } diff --git a/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml b/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml index a4c2649..55dbb39 100644 --- a/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml +++ b/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml @@ -21,7 +21,7 @@ - + diff --git a/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml.cs b/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml.cs index 749fc90..2e53719 100644 --- a/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml.cs +++ b/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml.cs @@ -1,12 +1,14 @@ using System; using System.Collections.Generic; +using Windows.Storage.AccessCache; using Windows.Storage.Pickers; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; +using ModernKeePass.Common; +using ModernKeePass.Domain.Dtos; using ModernKeePass.Events; -using ModernKeePass.ImportFormats; -using ModernKeePass.Services; +using ModernKeePass.Infrastructure.File; using ModernKeePass.ViewModels; // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 @@ -44,22 +46,26 @@ namespace ModernKeePass.Views var file = await savePicker.PickSaveFileAsync(); if (file == null) return; - Model.OpenFile(file); + + var token = StorageApplicationPermissions.FutureAccessList.Add(file); + var fileInfo = new FileInfo + { + Path = token, + Name = file.DisplayName + }; + await Model.OpenFile(fileInfo); } private void ImportFormatComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { - var resources = new ResourcesService(); + var resource = new ResourceHelper(); var comboBox = sender as ComboBox; switch (comboBox?.SelectedIndex) { case 0: Model.ImportFormat = new CsvImportFormat(); Model.ImportFileExtensionFilter = ".csv"; - Model.ImportFormatHelp = resources.GetResourceValue("NewImportFormatHelpCSV"); - break; - default: - Model.ImportFormat = new NullImportFormat(); + Model.ImportFormatHelp = resource.GetResourceValue("NewImportFormatHelpCSV"); break; } } diff --git a/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml b/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml index a948209..c9f60d1 100644 --- a/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml +++ b/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml @@ -5,7 +5,8 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:viewModels="using:ModernKeePass.ViewModels" xmlns:converters="using:ModernKeePass.Converters" - xmlns:interactivity="using:Microsoft.Xaml.Interactivity" xmlns:Core="using:Microsoft.Xaml.Interactions.Core" + xmlns:interactivity="using:Microsoft.Xaml.Interactivity" + xmlns:core="using:Microsoft.Xaml.Interactions.Core" xmlns:userControls="using:ModernKeePass.Views.UserControls" x:Class="ModernKeePass.Views.OpenDatabasePage" mc:Ignorable="d"> @@ -24,11 +25,11 @@ - + - - - + + + diff --git a/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml.cs b/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml.cs index fee45d9..eb1b3ef 100644 --- a/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml.cs +++ b/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml.cs @@ -1,8 +1,9 @@ using System; -using Windows.Storage; +using Windows.Storage.AccessCache; using Windows.Storage.Pickers; using Windows.UI.Xaml; using Windows.UI.Xaml.Navigation; +using ModernKeePass.Domain.Dtos; using ModernKeePass.ViewModels; // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 @@ -21,13 +22,13 @@ namespace ModernKeePass.Views InitializeComponent(); } - protected override void OnNavigatedTo(NavigationEventArgs e) + protected override async void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); - var file = e.Parameter as StorageFile; + var file = e.Parameter as FileInfo; if (file != null) { - Model.OpenFile(file); + await Model.OpenFile(file); } } @@ -43,7 +44,15 @@ namespace ModernKeePass.Views // Application now has read/write access to the picked file var file = await picker.PickSingleFileAsync(); if (file == null) return; - Model.OpenFile(file); + + + var token = StorageApplicationPermissions.FutureAccessList.Add(file); + var fileInfo = new FileInfo + { + Path = token, + Name = file.DisplayName + }; + await Model.OpenFile(fileInfo); } } } diff --git a/ModernKeePass/Views/MainPageFrames/RecentDatabasesPage.xaml b/ModernKeePass/Views/MainPageFrames/RecentDatabasesPage.xaml index a12a46e..860da1c 100644 --- a/ModernKeePass/Views/MainPageFrames/RecentDatabasesPage.xaml +++ b/ModernKeePass/Views/MainPageFrames/RecentDatabasesPage.xaml @@ -45,7 +45,7 @@ - + diff --git a/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml b/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml index 947f470..866582a 100644 --- a/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml +++ b/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml @@ -11,7 +11,7 @@ mc:Ignorable="d" > - + @@ -42,7 +42,7 @@ diff --git a/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs b/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs index 96e6c83..92f1767 100644 --- a/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs +++ b/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs @@ -1,20 +1,20 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Windows.Storage; +using Windows.Storage.AccessCache; using Windows.Storage.Pickers; using Windows.System; using Windows.UI.Xaml; using Windows.UI.Xaml.Input; using MediatR; +using Microsoft.Extensions.DependencyInjection; using ModernKeePass.Application.Database.Commands.CloseDatabase; using ModernKeePass.Application.Database.Commands.SaveDatabase; using ModernKeePass.Application.Database.Queries.GetDatabase; using ModernKeePass.Common; +using ModernKeePass.Domain.Dtos; using ModernKeePass.Events; using ModernKeePass.Extensions; -using ModernKeePass.Interfaces; -using ModernKeePass.Services; using ModernKeePass.ViewModels; // Pour en savoir plus sur le modèle d'élément Contrôle utilisateur, consultez la page http://go.microsoft.com/fwlink/?LinkId=234236 @@ -24,6 +24,7 @@ namespace ModernKeePass.Views.UserControls public sealed partial class CompositeKeyUserControl { private readonly IMediator _mediator; + private readonly ResourceHelper _resource; public CompositeKeyVm Model => Grid.DataContext as CompositeKeyVm; public bool CreateNew @@ -62,26 +63,27 @@ namespace ModernKeePass.Views.UserControls typeof(CompositeKeyUserControl), new PropertyMetadata("OK", (o, args) => { })); - public StorageFile DatabaseFile + public string DatabaseFilePath { - get { return (StorageFile)GetValue(DatabaseFileProperty); } - set { SetValue(DatabaseFileProperty, value); } + get { return (string)GetValue(DatabaseFilePathProperty); } + set { SetValue(DatabaseFilePathProperty, value); } } - public static readonly DependencyProperty DatabaseFileProperty = + public static readonly DependencyProperty DatabaseFilePathProperty = DependencyProperty.Register( - "DatabaseFile", - typeof(StorageFile), + "DatabaseFilePath", + typeof(string), typeof(CompositeKeyUserControl), new PropertyMetadata(null, (o, args) => { })); public bool ShowComplexityIndicator => CreateNew || UpdateKey; - public CompositeKeyUserControl(): this(App.Mediator) + public CompositeKeyUserControl(): this(App.Services.GetService()) { } public CompositeKeyUserControl(IMediator mediator) { _mediator = mediator; + _resource = new ResourceHelper(); InitializeComponent(); } @@ -100,31 +102,30 @@ namespace ModernKeePass.Views.UserControls else { var database = await _mediator.Send(new GetDatabaseQuery()); - var resource = new ResourcesService(); if (database.IsOpen) { - await MessageDialogHelper.ShowActionDialog(resource.GetResourceValue("MessageDialogDBOpenTitle"), - string.Format(resource.GetResourceValue("MessageDialogDBOpenDesc"), database.Name), - resource.GetResourceValue("MessageDialogDBOpenButtonSave"), - resource.GetResourceValue("MessageDialogDBOpenButtonDiscard"), + await MessageDialogHelper.ShowActionDialog(_resource.GetResourceValue("MessageDialogDBOpenTitle"), + string.Format(_resource.GetResourceValue("MessageDialogDBOpenDesc"), database.Name), + _resource.GetResourceValue("MessageDialogDBOpenButtonSave"), + _resource.GetResourceValue("MessageDialogDBOpenButtonDiscard"), async command => { await _mediator.Send(new SaveDatabaseCommand()); ToastNotificationHelper.ShowGenericToast( database.Name, - resource.GetResourceValue("ToastSavedMessage")); + _resource.GetResourceValue("ToastSavedMessage")); await _mediator.Send(new CloseDatabaseCommand()); - await OpenDatabase(resource); + await OpenDatabase(); }, async command => { await _mediator.Send(new CloseDatabaseCommand()); - await OpenDatabase(resource); + await OpenDatabase(); }); } else { - await OpenDatabase(resource); + await OpenDatabase(); } } } @@ -151,7 +152,9 @@ namespace ModernKeePass.Views.UserControls // Application now has read/write access to the picked file var file = await picker.PickSingleFileAsync(); if (file == null) return; - Model.KeyFile = file; + + var token = StorageApplicationPermissions.FutureAccessList.Add(file); + Model.KeyFilePath = token; } private async void CreateKeyFileButton_Click(object sender, RoutedEventArgs e) @@ -166,14 +169,19 @@ namespace ModernKeePass.Views.UserControls var file = await savePicker.PickSaveFileAsync(); if (file == null) return; - await Model.CreateKeyFile(file); + var token = StorageApplicationPermissions.FutureAccessList.Add(file); + await Model.CreateKeyFile(new FileInfo + { + Path = token, + Name = file.DisplayName + }); } - private async Task OpenDatabase(IResourceService resource) + private async Task OpenDatabase() { var oldLabel = ButtonLabel; - ButtonLabel = resource.GetResourceValue("CompositeKeyOpening"); - if (await Dispatcher.RunTaskAsync(async () => await Model.OpenDatabase(DatabaseFile, CreateNew))) + ButtonLabel = _resource.GetResourceValue("CompositeKeyOpening"); + if (await Dispatcher.RunTaskAsync(async () => await Model.OpenDatabase(DatabaseFilePath, CreateNew))) { ValidationChecked?.Invoke(this, new PasswordEventArgs(Model.RootGroupId)); } diff --git a/ModernKeePass/Win81App.csproj b/ModernKeePass/Win81App.csproj index b3b4c35..8cba96b 100644 --- a/ModernKeePass/Win81App.csproj +++ b/ModernKeePass/Win81App.csproj @@ -117,32 +117,19 @@ App.xaml + - - - - - - - - DonatePage.xaml - - - - - - diff --git a/ModernKeePass10/.gitignore b/ModernKeePass10/.gitignore new file mode 100644 index 0000000..ef1d66c --- /dev/null +++ b/ModernKeePass10/.gitignore @@ -0,0 +1,37 @@ +################################################################################ +# This .gitignore file was automatically created by Microsoft(R) Visual Studio. +################################################################################ + +#ignore thumbnails created by windows +Thumbs.db +#Ignore files build by Visual Studio +*.obj +*.exe +*.pdb +*.user +*.aps +*.pch +*.vspscc +*_i.c +*_p.c +*.ncb +*.suo +*.tlb +*.tlh +*.bak +*.cache +*.ilk +*.log +[Bb]in +[Dd]ebug*/ +*.lib +*.sbr +obj/ +[Rr]elease*/ +_ReSharper*/ +[Tt]est[Rr]esult* +Translation/TrlUtil.vshost.exe.manifest +*.nupkg +.vs/ +/UpgradeLog.htm +ModernKeePass_StoreKey.pfx \ No newline at end of file diff --git a/ModernKeePass10/.sonarqube/conf/0/ProjectOutFolderPath.txt b/ModernKeePass10/.sonarqube/conf/0/ProjectOutFolderPath.txt new file mode 100644 index 0000000..737b5f1 --- /dev/null +++ b/ModernKeePass10/.sonarqube/conf/0/ProjectOutFolderPath.txt @@ -0,0 +1 @@ +C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\out\0 diff --git a/ModernKeePass10/.sonarqube/conf/SonarQubeAnalysisConfig.xml b/ModernKeePass10/.sonarqube/conf/SonarQubeAnalysisConfig.xml new file mode 100644 index 0000000..ea98012 --- /dev/null +++ b/ModernKeePass10/.sonarqube/conf/SonarQubeAnalysisConfig.xml @@ -0,0 +1,171 @@ + + + C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\conf + C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\out + C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\bin + C:\Sources\Other\ModernKeePass\ModernKeePass + true + https://sonarcloud.io + 7.2.0.12953 + ModernKeePass + + + + + + + 7.1.0.5212 + https://update.sonarsource.org/editions.json + true + true + .c,.h + .ts,.tsx + SonarQube + false + Unique + oracle.jdbc.OracleDriver + **/vendor/** + false + 60 + .cc,.cpp,.cxx,.c++,.hh,.hpp,.hxx,.h++,.ipp + SonarAnalyzer.CSharp + .html,.xhtml,.rhtml,.shtml + false + false + true + 100 + target/jacoco.exec, target/jacoco-it.exec + false + true + 30 + false + 30 + Unique + true + SonarAnalyzer.VisualBasic + true + true + 730 + 4 + https://secure.gravatar.com/avatar/{EMAIL_MD5}.jpg?s={SIZE}&d=identicon + 600 + amd, applescript, atomtest, browser, commonjs, couch, embertest, flow, greasemonkey, jasmine, jest, jquery, meteor, mocha, mongo, nashorn, node, phantomjs, prototypejs, protractor, qunit, rhino, serviceworker, shared-node-browser, shelljs, webextensions, worker, wsh, yui + false + **/node_modules/**,**/bower_components/** + .vb + .abap,.ab4,.flow,.asprog + true + 30 + py + .cs + sql,tab,pkb + SonarAnalyzer-7.1.0.5212.zip + .java,.jav + php,php3,php4,php5,phtml,inc + .xml,.xsd,.xsl + 480 + true + true + $, jQuery + 7.1.0.5212 + .go + 104 + .swift + https://api.github.com + false + as + https://api.github.com/ + true + xunit-reports/xunit-result-*.xml + angular,goog,google,OpenLayers,d3,dojo,dojox,dijit,Backbone,moment,casper + 24 + true + **/node_modules/**,**/bower_components/** + https://github.com/ + true + false + SonarAnalyzer.VisualBasic + noreply@sonarcloud.io + 7.1.0.5212 + node + 1 + SonarAnalyzer.VisualBasic + [SonarCloud] + c11 + csharp + true + (branch|release)-.* + .m + coverage.out + SonarAnalyzer-7.1.0.5212.zip + SonarAnalyzer.CSharp + https://api.bitbucket.org/ + false + false + coverage-reports/*coverage-*.xml + SonarAnalyzer.CSharp + true + 0.05,0.1,0.2,0.5 + true + devcockpit,pdfreport,governance,ldap,authaad,authgithub,authbitbucket,googleanalytics + 7.1.0.5212 + .js,.jsx,.vue + 20 + vbnet + true + https://update.sonarsource.org/update-center.properties + .tsql + c++11 + https://sonarcloud.io + https://about.sonarcloud.io/images/SonarCloud-white-210px.png + 105 + <div class="boxed-group" style="border: none; border-radius: 3px;"> + <div class="boxed-group-inner clearfix" style="padding: 30px; border-radius: 3px; border: #e6e6e6 1px solid; background: #f3f3f3;"> + <div style="overflow: hidden; line-height: 1.5; font-size: 16px;"> + <p> +Analyze your open source and private projects on SonarCloud. +Select your <a href="https://about.sonarcloud.io">plan</a> and start improving. + </p> + </div> + </div> +</div> + AWHW8ct9-T_TB3XqouNu + 07/06/2018 12:32:21 + + + geogeob + https://sonarcloud.io + + + + cs + C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\conf\SonarQubeRoslyn-cs.ruleset + + C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\0\Google.Protobuf.dll + C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\0\SonarAnalyzer.CSharp.dll + C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\0\SonarAnalyzer.dll + + + C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\conf\cs\SonarLint.xml + + + + vbnet + C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\conf\SonarQubeRoslyn-vbnet.ruleset + + C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\SonarAnalyzer.VisualBasic.nuspec + C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\[Content_Types].xml + C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\analyzers\Google.Protobuf.dll + C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\analyzers\SonarAnalyzer.dll + C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\analyzers\SonarAnalyzer.VisualBasic.dll + C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\package\services\metadata\core-properties\f124441cdae948bb922ac980ea59570c.psmdcp + C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\tools\install.ps1 + C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\tools\uninstall.ps1 + C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\_rels\.rels + + + C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\conf\vbnet\SonarLint.xml + + + + \ No newline at end of file diff --git a/ModernKeePass10/.sonarqube/conf/SonarQubeRoslyn-cs.ruleset b/ModernKeePass10/.sonarqube/conf/SonarQubeRoslyn-cs.ruleset new file mode 100644 index 0000000..c21b0af --- /dev/null +++ b/ModernKeePass10/.sonarqube/conf/SonarQubeRoslyn-cs.ruleset @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ModernKeePass10/.sonarqube/conf/SonarQubeRoslyn-vbnet.ruleset b/ModernKeePass10/.sonarqube/conf/SonarQubeRoslyn-vbnet.ruleset new file mode 100644 index 0000000..17328b3 --- /dev/null +++ b/ModernKeePass10/.sonarqube/conf/SonarQubeRoslyn-vbnet.ruleset @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ModernKeePass10/.sonarqube/conf/cs/SonarLint.xml b/ModernKeePass10/.sonarqube/conf/cs/SonarLint.xml new file mode 100644 index 0000000..8c2d373 --- /dev/null +++ b/ModernKeePass10/.sonarqube/conf/cs/SonarLint.xml @@ -0,0 +1,695 @@ + + + + + sonar.cs.ignoreHeaderComments + true + + + sonar.cs.file.suffixes + .cs + + + + + S2589 + + + S3433 + + + S4061 + + + S1121 + + + S1854 + + + S4457 + + + S4456 + + + S2278 + + + S4211 + + + S3923 + + + S4426 + + + S2486 + + + S4433 + + + S2758 + + + S1751 + + + S1871 + + + S4586 + + + S4581 + + + S2737 + + + S3400 + + + S3649 + + + S1144 + + + S1264 + + + S2201 + + + S1118 + + + S1006 + + + S4214 + + + S4210 + + + S3241 + + + S4428 + + + S1048 + + + S2183 + + + S3168 + + + S4220 + + + S3261 + + + S4260 + + + S4159 + + + S4277 + + + S2583 + + + S3440 + + + S3776 + + + threshold + 15 + + + propertyThreshold + 3 + + + + + S2326 + + + S1116 + + + S3358 + + + S4200 + + + S1172 + + + S1862 + + + S2275 + + + S3457 + + + S3459 + + + S3464 + + + S3343 + + + S818 + + + S1656 + + + S2184 + + + S1764 + + + S2971 + + + S3060 + + + S101 + + + S1066 + + + S107 + + + max + 7 + + + + + S1075 + + + S108 + + + S110 + + + max + 5 + + + + + S1104 + + + S1110 + + + S1117 + + + S112 + + + S1123 + + + S1125 + + + S1134 + + + S1135 + + + S1155 + + + S1163 + + + S1168 + + + S1185 + + + S1186 + + + S1206 + + + S1210 + + + S1215 + + + S125 + + + S1450 + + + S1479 + + + maximum + 30 + + + + + S1481 + + + S1607 + + + S1643 + + + S1699 + + + S1848 + + + S1905 + + + S1939 + + + S1940 + + + S1944 + + + S2068 + + + credentialWords + password, passwd, pwd + + + + + S2114 + + + S2123 + + + S2178 + + + S2187 + + + S2190 + + + S2219 + + + S2223 + + + S2225 + + + S2234 + + + S2259 + + + S2290 + + + S2291 + + + S2292 + + + S2306 + + + S2328 + + + S2342 + + + format + ^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$ + + + flagsAttributeFormat + ^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?s$ + + + + + S2344 + + + S2345 + + + S2346 + + + S2365 + + + S2368 + + + S2372 + + + S2376 + + + S2386 + + + S2436 + + + max + 2 + + + maxMethod + 3 + + + + + S2437 + + + S2681 + + + S2688 + + + S2692 + + + S2696 + + + S2743 + + + S2757 + + + S2761 + + + S2930 + + + S2933 + + + S2934 + + + S2953 + + + S2995 + + + S2996 + + + S2997 + + + S3005 + + + S3010 + + + S3169 + + + S3172 + + + S3217 + + + S3218 + + + S3220 + + + S3236 + + + S3237 + + + S3244 + + + S3246 + + + S3247 + + + S3249 + + + S3251 + + + S3256 + + + S3262 + + + S3263 + + + S3264 + + + S3265 + + + S3346 + + + S3376 + + + S3397 + + + S3415 + + + S3427 + + + S3442 + + + S3443 + + + S3444 + + + S3445 + + + S3447 + + + S3449 + + + S3450 + + + S3451 + + + S3453 + + + S3456 + + + S3458 + + + S3466 + + + S3597 + + + S3598 + + + S3600 + + + S3603 + + + S3604 + + + S3610 + + + S3626 + + + S3655 + + + S3693 + + + S3869 + + + S3871 + + + S3875 + + + S3877 + + + S3881 + + + S3884 + + + S3885 + + + S3887 + + + S3889 + + + S3897 + + + S3903 + + + S3904 + + + S3925 + + + S3926 + + + S3927 + + + S3928 + + + S3966 + + + S3971 + + + S3972 + + + S3981 + + + S3984 + + + S3998 + + + S4015 + + + S4016 + + + S4019 + + + S4035 + + + S4144 + + + S4158 + + + S907 + + + S927 + + + + + diff --git a/ModernKeePass10/.sonarqube/conf/vbnet/SonarLint.xml b/ModernKeePass10/.sonarqube/conf/vbnet/SonarLint.xml new file mode 100644 index 0000000..81fd3bf --- /dev/null +++ b/ModernKeePass10/.sonarqube/conf/vbnet/SonarLint.xml @@ -0,0 +1,186 @@ + + + + + sonar.vbnet.ignoreHeaderComments + true + + + sonar.vbnet.file.suffixes + .vb + + + + + S1751 + + + S1871 + + + S1656 + + + S1862 + + + S1764 + + + S2178 + + + S101 + + + format + ^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$ + + + + + S1075 + + + S112 + + + S114 + + + format + ^I([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$ + + + + + S117 + + + format + ^[a-z][a-z0-9]*([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$ + + + + + S1197 + + + S1542 + + + format + ^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$ + + + + + S1643 + + + S1645 + + + S1654 + + + format + ^[a-z][a-z0-9]*([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$ + + + + + S2304 + + + format + ^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?(\.([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?)*$ + + + + + S2340 + + + S2342 + + + format + ^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$ + + + flagsAttributeFormat + ^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?s$ + + + + + S2344 + + + S2345 + + + S2346 + + + S2347 + + + format + ^(([a-z][a-z0-9]*)?([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?_)?([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$ + + + + + S2349 + + + S2352 + + + S2355 + + + S2358 + + + S2359 + + + S2365 + + + S2368 + + + S2372 + + + S2375 + + + minimumSeriesLength + 6 + + + + + S2376 + + + S2951 + + + S3385 + + + S3981 + + + S4144 + + + + + diff --git a/ModernKeePass10/.sonarqube/out/.sonar/.sonar_lock b/ModernKeePass10/.sonarqube/out/.sonar/.sonar_lock new file mode 100644 index 0000000..e69de29 diff --git a/ModernKeePass10/.sonarqube/out/.sonar/report-task.txt b/ModernKeePass10/.sonarqube/out/.sonar/report-task.txt new file mode 100644 index 0000000..b51f880 --- /dev/null +++ b/ModernKeePass10/.sonarqube/out/.sonar/report-task.txt @@ -0,0 +1,7 @@ +organization=geogeob +projectKey=ModernKeePass +serverUrl=https://sonarcloud.io +serverVersion=7.2.0.12953 +dashboardUrl=https://sonarcloud.io/dashboard/index/ModernKeePass +ceTaskId=AWQER9hfTzX59Iu7A6N0 +ceTaskUrl=https://sonarcloud.io/api/ce/task?id=AWQER9hfTzX59Iu7A6N0 diff --git a/ModernKeePass10/.sonarqube/out/0/FilesToAnalyze.txt b/ModernKeePass10/.sonarqube/out/0/FilesToAnalyze.txt new file mode 100644 index 0000000000000000000000000000000000000000..3f47a3ebbd0fec8edb90ab92ae4397bb12577e5f GIT binary patch literal 32608 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 + + ModernKeePass.App + C# + Product + a0cfc681-769b-405a-8482-0cdee595a91f + C:\Sources\Other\ModernKeePass\ModernKeePass\ModernKeePass.App.csproj + false + + + + + C:\Sources\Other\ModernKeePass\ModernKeePass\bin\Debug\ModernKeePass.exe.RoslynCA.json + C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\out\0 + + Debug + AnyCPU + \ No newline at end of file diff --git a/ModernKeePass10/.sonarqube/out/0/output-cs/encoding.pb b/ModernKeePass10/.sonarqube/out/0/output-cs/encoding.pb new file mode 100644 index 0000000..d5c9f09 --- /dev/null +++ b/ModernKeePass10/.sonarqube/out/0/output-cs/encoding.pb @@ -0,0 +1,85 @@ +P +GC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\ClipboardAction.csutf-8T +KC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\NavigateToUrlAction.csutf-8Q +HC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\SetupFocusAction.csutf-8A +8C:\Sources\Other\ModernKeePass\ModernKeePass\App.xaml.csutf-8X +OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\IntToSymbolConverter.csutf-8[ +RC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\DatabaseOpenedException.csutf-8S +JC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ILicenseService.csutf-8[ +RC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IProxyInvocationHandler.csutf-8R +IC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentService.csutf-8O +FC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentItem.csutf-8T +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IResourceService.csutf-8V +MC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SingletonServiceBase.csutf-8i +`C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\SelectableDataTemplateSelector.csutf-8X +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsSaveVm.csutf-8] +TC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\DonatePage.xaml.csutf-8Q +HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\DatabaseService.csutf-8T +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISettingsService.csutf-8S +JC:\Sources\Other\ModernKeePass\ModernKeePass\Common\MessageDialogHelper.csutf-8P +GC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NavigationHelper.csutf-8Y +PC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NotifyPropertyChangedBase.csutf-8T +KC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ObservableDictionary.csutf-8L +CC:\Sources\Other\ModernKeePass\ModernKeePass\Common\RelayCommand.csutf-8Q +HC:\Sources\Other\ModernKeePass\ModernKeePass\Common\SuspensionManager.csutf-8P +GC:\Sources\Other\ModernKeePass\ModernKeePass\Services\LicenseService.csutf-8O +FC:\Sources\Other\ModernKeePass\ModernKeePass\Services\RecentService.csutf-8R +IC:\Sources\Other\ModernKeePass\ModernKeePass\Services\ResourcesService.csutf-8Q +HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SettingsService.csutf-8W +NC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ToastNotificationHelper.csutf-8i +`C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DiscreteIntToSolidColorBrushConverter.csutf-8d +[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\EmptyStringToVisibilityConverter.csutf-8Z +QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\NullToBooleanConverter.csutf-8Q +HC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\SaveException.csutf-8\ +SC:\Sources\Other\ModernKeePass\ModernKeePass\Extensions\DispatcherTaskExtensions.csutf-8T +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IDatabaseService.csutf-8X +OC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IHasSelectableObject.csutf-8T +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISelectableModel.csutf-8\ +SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\BasePages\LayoutAwarePageBase.csutf-8k +bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsDatabasePage.xaml.csutf-8n +eC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsNewDatabasePage.xaml.csutf-8g +^C:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSavePage.xaml.csutf-8k +bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSecurityPage.xaml.csutf-8j +aC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsWelcomePage.xaml.csutf-8h +_C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\FirstItemDataTemplateSelector.csutf-8U +LC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\ListViewWithDisable.csutf-8f +]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\BreadCrumbUserControl.xaml.csutf-8h +_C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\CompositeKeyUserControl.xaml.csutf-8S +JC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\TextBoxWithButton.csutf-8` +WC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\BooleanToVisibilityConverter.csutf-8Y +PC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ColorToBrushConverter.csutf-8d +[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DoubleToSolidColorBrushConverter.csutf-8g +^C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\InverseBooleanToVisibilityConverter.csutf-8Z +QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\PluralizationConverter.csutf-8c +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ProgressBarLegalValuesConverter.csutf-8X +OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\TextToWidthConverter.csutf-8Q +HC:\Sources\Other\ModernKeePass\ModernKeePass\Events\PasswordEventArgs.csutf-8N +EC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IIsEnabled.csutf-8M +DC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IPwEntity.csutf-8L +CC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPage.xaml.csutf-8\ +SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\AboutPage.xaml.csutf-8b +YC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\NewDatabasePage.xaml.csutf-8P +GC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPage.xaml.csutf-8^ +UC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\WelcomePage.xaml.csutf-8K +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\AboutVm.csutf-8R +IC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\CompositeKeyVm.csutf-8X +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\ListMenuItemVm.csutf-8X +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\MainMenuItemVm.csutf-8V +MC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\RecentItemVm.csutf-8S +JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\EntryDetailPage.xaml.csutf-8S +JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\GroupDetailPage.xaml.csutf-8c +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\OpenDatabasePage.xaml.csutf-8f +]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\RecentDatabasesPage.xaml.csutf-8c +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\SaveDatabasePage.xaml.csutf-8P +GC:\Sources\Other\ModernKeePass\ModernKeePass\Properties\AssemblyInfo.csutf-8K +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\EntryVm.csutf-8K +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\GroupVm.csutf-8W +NC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsNewVm.csutf-8N +EC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SettingsVm.csutf-8J +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\MainVm.csutf-8I +@C:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\NewVm.csutf-8J +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\OpenVm.csutf-8L +CC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\RecentVm.csutf-8J +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SaveVm.csutf-8\ +SC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsDatabaseVm.csutf-8i +`C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\HamburgerMenuUserControl.xaml.csutf-8 \ No newline at end of file diff --git a/ModernKeePass10/.sonarqube/out/0/output-cs/file-metadata.pb b/ModernKeePass10/.sonarqube/out/0/output-cs/file-metadata.pb new file mode 100644 index 0000000..14e6dbd --- /dev/null +++ b/ModernKeePass10/.sonarqube/out/0/output-cs/file-metadata.pb @@ -0,0 +1,139 @@ +I +GC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\ClipboardAction.csM +KC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\NavigateToUrlAction.csJ +HC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\SetupFocusAction.cs: +8C:\Sources\Other\ModernKeePass\ModernKeePass\App.xaml.csQ +OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\IntToSymbolConverter.csT +RC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\DatabaseOpenedException.csL +JC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ILicenseService.csT +RC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IProxyInvocationHandler.csK +IC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentService.csH +FC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentItem.csM +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IResourceService.csO +MC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SingletonServiceBase.csb +`C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\SelectableDataTemplateSelector.csQ +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsSaveVm.csV +TC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\DonatePage.xaml.csJ +HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\DatabaseService.csM +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISettingsService.csL +JC:\Sources\Other\ModernKeePass\ModernKeePass\Common\MessageDialogHelper.csI +GC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NavigationHelper.csR +PC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NotifyPropertyChangedBase.csM +KC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ObservableDictionary.csE +CC:\Sources\Other\ModernKeePass\ModernKeePass\Common\RelayCommand.csJ +HC:\Sources\Other\ModernKeePass\ModernKeePass\Common\SuspensionManager.csI +GC:\Sources\Other\ModernKeePass\ModernKeePass\Services\LicenseService.csH +FC:\Sources\Other\ModernKeePass\ModernKeePass\Services\RecentService.csK +IC:\Sources\Other\ModernKeePass\ModernKeePass\Services\ResourcesService.csJ +HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SettingsService.csP +NC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ToastNotificationHelper.csb +`C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DiscreteIntToSolidColorBrushConverter.cs] +[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\EmptyStringToVisibilityConverter.csS +QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\NullToBooleanConverter.csJ +HC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\SaveException.csU +SC:\Sources\Other\ModernKeePass\ModernKeePass\Extensions\DispatcherTaskExtensions.csM +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IDatabaseService.csQ +OC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IHasSelectableObject.csM +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISelectableModel.csU +SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\BasePages\LayoutAwarePageBase.csd +bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsDatabasePage.xaml.csg +eC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsNewDatabasePage.xaml.cs` +^C:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSavePage.xaml.csd +bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSecurityPage.xaml.csc +aC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsWelcomePage.xaml.csa +_C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\FirstItemDataTemplateSelector.csN +LC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\ListViewWithDisable.cs_ +]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\BreadCrumbUserControl.xaml.csa +_C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\CompositeKeyUserControl.xaml.csL +JC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\TextBoxWithButton.csY +WC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\BooleanToVisibilityConverter.csR +PC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ColorToBrushConverter.cs] +[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DoubleToSolidColorBrushConverter.cs` +^C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\InverseBooleanToVisibilityConverter.csS +QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\PluralizationConverter.cs\ +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ProgressBarLegalValuesConverter.csQ +OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\TextToWidthConverter.csJ +HC:\Sources\Other\ModernKeePass\ModernKeePass\Events\PasswordEventArgs.csG +EC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IIsEnabled.csF +DC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IPwEntity.csE +CC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPage.xaml.csU +SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\AboutPage.xaml.cs[ +YC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\NewDatabasePage.xaml.csI +GC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPage.xaml.csW +UC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\WelcomePage.xaml.csD +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\AboutVm.csK +IC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\CompositeKeyVm.csQ +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\ListMenuItemVm.csQ +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\MainMenuItemVm.csO +MC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\RecentItemVm.csL +JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\EntryDetailPage.xaml.csL +JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\GroupDetailPage.xaml.cs\ +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\OpenDatabasePage.xaml.cs_ +]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\RecentDatabasesPage.xaml.cs\ +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\SaveDatabasePage.xaml.csI +GC:\Sources\Other\ModernKeePass\ModernKeePass\Properties\AssemblyInfo.csD +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\EntryVm.csD +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\GroupVm.csP +NC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsNewVm.csG +EC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SettingsVm.csC +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\MainVm.csB +@C:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\NewVm.csC +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\OpenVm.csE +CC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\RecentVm.csC +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SaveVm.csU +SC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsDatabaseVm.csb +`C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\HamburgerMenuUserControl.xaml.csE +AC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\App.g.i.csC +?C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\App.g.csO +KC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\Colors.g.i.csM +IC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\Colors.g.csk +gC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsSavePage.g.i.csi +eC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsSavePage.g.csj +fC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\UserControls\BreadCrumbUserControl.g.i.csh +dC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\UserControls\BreadCrumbUserControl.g.csl +hC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\UserControls\CompositeKeyUserControl.g.i.csj +fC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\UserControls\CompositeKeyUserControl.g.csP +LC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPage.g.i.csN +JC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPage.g.cs` +\C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\AboutPage.g.i.cs^ +ZC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\AboutPage.g.csW +SC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\EntryDetailPage.g.i.csU +QC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\EntryDetailPage.g.csW +SC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\GroupDetailPage.g.i.csU +QC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\GroupDetailPage.g.csa +]C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\DonatePage.g.i.cs_ +[C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\DonatePage.g.csf +bC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\NewDatabasePage.g.i.csd +`C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\NewDatabasePage.g.csg +cC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\OpenDatabasePage.g.i.cse +aC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\OpenDatabasePage.g.csj +fC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\RecentDatabasesPage.g.i.csh +dC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\RecentDatabasesPage.g.csg +cC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\SaveDatabasePage.g.i.cse +aC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\SaveDatabasePage.g.csT +PC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPage.g.i.csR +NC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPage.g.csb +^C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\WelcomePage.g.i.cs` +\C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\WelcomePage.g.cso +kC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsDatabasePage.g.i.csm +iC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsDatabasePage.g.csr +nC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsNewDatabasePage.g.i.csp +lC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsNewDatabasePage.g.cso +kC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsSecurityPage.g.i.csm +iC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsSecurityPage.g.csn +jC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsWelcomePage.g.i.csl +hC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsWelcomePage.g.cs] +YC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\HamburgerButtonStyle.g.i.cs[ +WC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\HamburgerButtonStyle.g.csc +_C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\ListViewLeftIndicatorStyle.g.i.csa +]C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\ListViewLeftIndicatorStyle.g.cs\ +XC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\NoBorderButtonStyle.g.i.csZ +VC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\NoBorderButtonStyle.g.csO +KC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\Styles.g.i.csM +IC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\Styles.g.cs_ +[C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\TextBoxWithButtonStyle.g.i.cs] +YC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\TextBoxWithButtonStyle.g.csm +iC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\UserControls\HamburgerMenuUserControl.g.i.csk +gC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\UserControls\HamburgerMenuUserControl.g.csL +HC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\XamlTypeInfo.g.csQ +MC:\Users\GBE\AppData\Local\Temp\.NETCore,Version=v4.5.1.AssemblyAttributes.cs \ No newline at end of file diff --git a/ModernKeePass10/.sonarqube/out/0/output-cs/metrics.pb b/ModernKeePass10/.sonarqube/out/0/output-cs/metrics.pb new file mode 100644 index 0000000..1d889c5 --- /dev/null +++ b/ModernKeePass10/.sonarqube/out/0/output-cs/metrics.pb @@ -0,0 +1,180 @@ + +GC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\ClipboardAction.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=3;2=0;4=0;6=0;8=0;10=0;12=0r +   +KC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\NavigateToUrlAction.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=3;2=0;4=0;6=0;8=0;10=0;12=0r +  !x  +HC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\SetupFocusAction.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=2;2=1;4=0;6=0;8=0;10=0;12=0r +   +8C:\Sources\Other\ModernKeePass\ModernKeePass\App.xaml.cs7 8@HR 0=0;5=0;10=0;20=1;30=0;60=0;90=0Z1=5;2=1;4=2;6=1;8=0;10=0;12=0jH*>?@ABFTZ[^`fluvwz|}r +  !"#()+,-./023456789:;?ABCDEFGHINOPQRSUVWXYhix?  !"#$%&'()*-./12345679:;=>?ABCDEFGHINOPQXhi +RC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\DatabaseOpenedException.cs(0R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r  +JC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ILicenseService.cs(08@R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r  +  +RC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IProxyInvocationHandler.cs(0R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r  +IC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentService.cs(08@R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r +  +FC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentItem.cs(08@R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r + +  +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IResourceService.cs(0R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r +MC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SingletonServiceBase.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0r + +  + +`C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\SelectableDataTemplateSelector.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=4;2=1;4=0;6=0;8=0;10=0;12=0r + x +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsSaveVm.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=4;2=0;4=0;6=0;8=0;10=0;12=0r +  + +TC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\DonatePage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0jr + +   +HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\DatabaseService.csQ (082@2H2R 0=0;5=0;10=0;20=0;30=1;60=0;90=0Z1=25;2=5;4=0;6=2;8=0;10=0;12=0j$cdefghkyr +  !"#$%')*+,-/0123456789:<=>?@BCDEFHIJKLNOPQRTUVWYZ[]^_`ijlmnopqstuvwz{|}~x"#'+,1468>?DEJKPQTUY_npstuwz{| +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISettingsService.cs(0R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r +JC:\Sources\Other\ModernKeePass\ModernKeePass\Common\MessageDialogHelper.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=4;2=2;4=0;6=0;8=0;10=0;12=0j 9@ABEFHIKNQTVWXYx "$%+-.028:=BENQTV +GC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NavigationHelper.csD (8>@>H>R 0=0;5=0;10=0;20=0;30=0;60=1;90=0Z1=12;2=8;4=1;6=1;8=0;10=0;12=1j !"#&(*,-./02579:ABCDEFKLMSW`stuvxyzr + ;<=>?GHINOTUVXYZ[\^abfghiklpq{|}~x*?INTUXZ[afhi +PC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NotifyPropertyChangedBase.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=2;4=0;6=0;8=0;10=0;12=0r x  +KC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ObservableDictionary.cs( (08!@&H!R 0=0;5=0;10=0;20=0;30=1;60=0;90=0Z1=18;2=5;4=1;6=0;8=0;10=0;12=0j + r  !"#$&'()*,-./12345679:;<=>?@ACDEFGHIJKLMOPQRSTUVWXYZ\]^_`abcdfghiklmnpqrsuvwxz{|}x . "().35;=>@FGIJLSWX^_`bhmrw| +CC:\Sources\Other\ModernKeePass\ModernKeePass\Common\RelayCommand.cs (8@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=2;2=3;4=0;6=0;8=0;10=0;12=0j% + $%&'(1234567=>?@ABHIJKLr*  !")*+,-./89:;CDEFMNOPQRSTUVx+,-.:EPR +HC:\Sources\Other\ModernKeePass\ModernKeePass\Common\SuspensionManager.cs8 (08@HR 0=0;5=0;10=0;20=1;30=0;60=0;90=0Z1=5;2=3;4=3;6=0;8=0;10=0;12=0j~ !"#)*+,-3456789>HIN\]^_`abcdefmqvr + $%&'./01:;<=?@ABCDEFJKLOPQRSTUVWXYZghiklnoprstwxyz{|}~xS&0?BDLOPRSXinoswz|} +GC:\Sources\Other\ModernKeePass\ModernKeePass\Services\LicenseService.cs (08 @ H R 0=0;5=0;10=1;20=0;30=0;60=0;90=0Z1=5;2=0;4=0;6=1;8=0;10=0;12=0j*+r? + !"#$%&'(),-./012345678:;<=>@ABCEFGHIJx#$&'(),.012346<=BG +FC:\Sources\Other\ModernKeePass\ModernKeePass\Services\RecentService.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=4;2=1;4=0;6=0;8=0;10=0;12=0r, +  !#$%&()*+-./012x +  %*/ +IC:\Sources\Other\ModernKeePass\ModernKeePass\Services\ResourcesService.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0r   +HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SettingsService.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=1;4=0;6=0;8=0;10=0;12=0r + x + +NC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ToastNotificationHelper.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=2;2=1;4=0;6=0;8=0;10=0;12=0r0 +  !#$%&'(*+,-./123456x %&'(,.3 +`C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DiscreteIntToSolidColorBrushConverter.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=1;6=0;8=0;10=0;12=0r + x  +[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\EmptyStringToVisibilityConverter.cs 8@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=1;4=0;6=0;8=0;10=0;12=0r + x  +QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\NullToBooleanConverter.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=2;2=0;4=0;6=0;8=0;10=0;12=0r +  + +HC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\SaveException.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=2;2=0;4=0;6=0;8=0;10=0;12=0r  +   +SC:\Sources\Other\ModernKeePass\ModernKeePass\Extensions\DispatcherTaskExtensions.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=2;2=0;4=0;6=0;8=0;10=0;12=0jr +  x +  +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IDatabaseService.cs(08@R 0=0;5=0;10=0;20=1;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0jr  +  !"# +OC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IHasSelectableObject.cs(08@R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISelectableModel.cs(08@R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r +SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\BasePages\LayoutAwarePageBase.cs" (08#@#H#R 0=0;5=0;10=0;20=0;30=1;60=0;90=0Z1=13;2=4;4=1;6=1;8=0;10=0;12=0j\ "#*+,-.456789:;<=>ABFGOWXYZ[\]^ijlmnrstuv|}~r +  $%&()/012?@DEHIJKLMNPQRSTU_`abcdepwxyzx1 $%/01DHJPRacy +bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsDatabasePage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0jr + +   +eC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsNewDatabasePage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0jr + +   +^C:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSavePage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0jr + +   +bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSecurityPage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=2;2=0;4=0;6=0;8=0;10=0;12=0j +r  +aC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsWelcomePage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0jr + +   +_C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\FirstItemDataTemplateSelector.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=4;2=1;4=0;6=0;8=0;10=0;12=0r x  +LC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\ListViewWithDisable.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=1;4=0;6=0;8=0;10=0;12=0r + x  +]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\BreadCrumbUserControl.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=3;2=0;4=0;6=0;8=0;10=0;12=0jr +   +_C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\CompositeKeyUserControl.xaml.cs (08@HR 0=0;5=0;10=0;20=1;30=0;60=0;90=0Z1=8;2=4;4=0;6=1;8=0;10=0;12=0j `ort + !"#$%&'()*,-./01234569;<=>@ABCEFGIJKLMNOPQRSTUVWXY[\]^_abcefghijklmpqrsuvwxyz{|~x %"#&*./26=GIKLRSUW]_ajkmpqry|~ +JC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\TextBoxWithButton.cs ( +0 +8 @ H R 0=0;5=0;10=1;20=0;30=0;60=0;90=0Z1=8;2=1;4=0;6=0;8=0;10=0;12=0r@ +  !#$%&'()*+,-/0123456789;<=>?@ABCDEx !%&)-1259=>?A +WC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\BooleanToVisibilityConverter.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=0;2=1;4=1;6=0;8=0;10=0;12=0jr + x  +PC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ColorToBrushConverter.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=1;6=0;8=0;10=0;12=0r + x  +[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DoubleToSolidColorBrushConverter.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=2;2=0;4=0;6=0;8=0;10=0;12=0r + x +^C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\InverseBooleanToVisibilityConverter.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=0;2=1;4=1;6=0;8=0;10=0;12=0jr + x  +QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\PluralizationConverter.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=1;8=0;10=0;12=0jr + x  +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ProgressBarLegalValuesConverter.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=1;8=0;10=0;12=0r + x  +OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\TextToWidthConverter.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=1;4=0;6=0;8=0;10=0;12=0r +  +  +HC:\Sources\Other\ModernKeePass\ModernKeePass\Events\PasswordEventArgs.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=3;2=0;4=0;6=0;8=0;10=0;12=0r  +   +EC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IIsEnabled.cs(08@R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r +DC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IPwEntity.cs(08 @ R 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0j "#$r + !%&' +CC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPage.xaml.cs + (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=3;2=1;4=0;6=0;8=0;10=0;12=0j + r  !"#$%x !" +SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\AboutPage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0jr + +   +YC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\NewDatabasePage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=2;2=1;4=0;6=0;8=0;10=0;12=0j r + !"#$%x !" +GC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPage.xaml.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=2;2=1;4=0;6=0;8=0;10=0;12=0j + r x +UC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\WelcomePage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0jr + +   +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\AboutVm.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=4;2=0;4=0;6=0;8=0;10=0;12=0r   +IC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\CompositeKeyVm.cs: (08*@*H*R 0=0;5=0;10=0;20=0;30=1;60=0;90=0Z1=24;2=2;4=3;6=0;8=0;10=0;12=0jr +  !"$%&'()*+,./01234568:;<=>@ABCDFGHIJKLMNOPRSTUVWXYZ[]^_`aceghijklmnoprtuvwxy{|}~xK &)*034<=BCHKLMNTWXY_`ekrvwx +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\ListMenuItemVm.cs (08 @ H R 0=0;5=0;10=1;20=0;30=0;60=0;90=0Z1=13;2=0;4=0;6=0;8=0;10=0;12=0r +  +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\MainMenuItemVm.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=4;2=0;4=0;6=0;8=0;10=0;12=0r  + +MC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\RecentItemVm.cs ( 0 8 @ H R 0=0;5=0;10=1;20=0;30=0;60=0;90=0Z1=11;2=1;4=0;6=0;8=0;10=0;12=0r+ +  !"$%&')*+,./0123 +!&+0 +JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\EntryDetailPage.xaml.cs +(08@HR 0=0;5=0;10=1;20=0;30=0;60=0;90=0Z1=5;2=3;4=2;6=0;8=0;10=0;12=0j "#$%&'()*+,1245678rH  -:;<=>?ABCDHIJKLMNOPQRSTUVWYZ[\]^`abcefghijklmnoprstux<=>CKLMNOPQSTU\]bilnor +JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\GroupDetailPage.xaml.cs/ (08@HR 0=0;5=0;10=0;20=0;30=1;60=0;90=0Z1=9;2=6;4=2;6=0;8=0;10=0;12=0j %&'()*+,-./45789:;r +  !"#0=>?ABCDEGHIJPQRSTUVWXYZ[\]_`abcdefghijkmnopqrstuvwxyz{|~x = !"?ABCDITWYZ\beghjpqrstuvxyz +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\OpenDatabasePage.xaml.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=3;2=1;4=0;6=0;8=0;10=0;12=0j *r$ +  !"#$%&'(+,-./0x %&(+,- +]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\RecentDatabasesPage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0jr + +   +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\SaveDatabasePage.xaml.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=4;2=1;4=0;6=0;8=0;10=0;12=0j r*  !"#%&'()*+,./02345x !"),./02 +GC:\Sources\Other\ModernKeePass\ModernKeePass\Properties\AssemblyInfo.csR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0j r  +  +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\EntryVm.csX I(/0.8l@lHlR 0=0;5=0;10=0;20=0;30=0;60=0;90=1Z1=53;2=17;4=1;6=1;8=0;10=1;12=0j$%&r +  !"#')*+,-./0134567:;<=>@ABCDEFGHIKLMNOQRSTUWXYZ[\]^`abcdfghijlmnopqrstvwxyz{|}~x !"#+./56<=BEFGMNST[\bchinqrx{| +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\GroupVm.csR ((08E@EHER 0=0;5=0;10=0;20=0;30=0;60=1;90=0Z1=25;2=11;4=3;6=1;8=0;10=0;12=0j123r  !#$%')*+-/456789:;=>?@BCDEFHIJKLMNOPRSTUVXYZ[\^_`abcdefghjklnopqrsuwxy{|}~x #)*-/69>?DELMOTUZ[dfgjx}~ +NC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsNewVm.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=7;2=0;4=0;6=0;8=0;10=0;12=0r  !  +EC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SettingsVm.cs (08 @ H R 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=5;2=0;4=1;6=0;8=0;10=0;12=0rM +  "$%&'()+-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQSTUVx"$&+345;<=BCDFJKLNQS +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\MainVm.cs (08@HR 0=0;5=0;10=1;20=0;30=0;60=0;90=0Z1=6;2=0;4=1;6=0;8=1;10=0;12=0jvyr +  !"$&'()*+-/01345789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuwz{|}~x (!$&(05;?@DHLPVZ\]^beilpswz{} +@C:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\NewVm.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=2;2=0;4=0;6=0;8=0;10=0;12=0r +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\OpenVm.cs + (08 +@ +H +R 0=0;5=0;10=1;20=0;30=0;60=0;90=0Z1=5;2=2;4=0;6=0;8=0;10=0;12=0r# +  !"#$&'()*+x +  !"#( +CC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\RecentVm.cs (08 @ H R 0=0;5=0;10=1;20=0;30=0;60=0;90=0Z1=5;2=1;4=1;6=0;8=0;10=0;12=0r/ + !"#$&')*+,-./1234567x!"&+,-.34 +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SaveVm.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=3;2=1;4=0;6=0;8=0;10=0;12=0r + x  +SC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsDatabaseVm.cs ( 0 8@HR 0=0;5=0;10=0;20=1;30=0;60=0;90=0Z1=13;2=5;4=1;6=0;8=0;10=0;12=0jr] +  !"#$%')*+,-./012456789:;<=>?ACDEFGHJKLMNPQRSTUVWXY[]^_`abdfghijklx  #-/8:<>AEFHLMRUVX[]_dhi +`C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\HamburgerMenuUserControl.xaml.cs (08@HR 0=0;5=0;10=1;20=0;30=0;60=0;90=0Z1=15;2=2;4=0;6=0;8=0;10=0;12=0jrg +  !"#$%&')*+,-./012356789:;<=>?ABCDEFGHIJKMNOPQSTUVWXZ[\]^_`abcdfghijkmnopqrst #'+,/378;?CDGKOPTX\]`djq \ No newline at end of file diff --git a/ModernKeePass10/.sonarqube/out/0/output-cs/symrefs.pb b/ModernKeePass10/.sonarqube/out/0/output-cs/symrefs.pb new file mode 100644 index 0000000..1914fd4 --- /dev/null +++ b/ModernKeePass10/.sonarqube/out/0/output-cs/symrefs.pb @@ -0,0 +1,2912 @@ + +GC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\ClipboardAction.cs + G V +    $ +2 >  * 6   ' +     ) . + +  + +% + + +4 = +  ! , +KC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\NavigateToUrlAction.cs + $F Y + + + " % +2 =  * 5   & +     ( - + +  + +% + + +4 = + > A + 4 6 +HC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\SetupFocusAction.cs +   !P ` +   # & +2 F  + ? / + 1 6 + +  + +% + + +4 = +8C:\Sources\Other\ModernKeePass\ModernKeePass\App.xaml.cs + +  + +  + + '   & + + %!! " +(( )""" 6 + +((1 7( +((U p++ 744 +99 +2 +++ -- .. // 00 2 +,, 22 554 A77 "::8 E + +CC& 0 +CCJ KEE ! +NN (EE KK  + +II + +II@ DKK $( +NN= >dd pp rrI JF +XX \\ __ bb mm) 2ss xx  + + bb. @ +rr +xx9 P + +- 3 + +< = + +  + 0 + +  +  +  +9 A + +  +4 6 + +' - + +I J +9 : + +/ 5 + +K L +  + +  + $ + +  +N V +  + + & +7 @ + + /0 + +G K +! % +4 8 +1 5$ + +  +  +% . +OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\IntToSymbolConverter.cs + + % + + + +  + + +% *   % + + + +1 ; + + + +D M + + + +V ^ +       + +UU ! +UU) .WW" ' + +UU5 ? + +UUH Q + +UUZ b +WW XX ` +RC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\DatabaseOpenedException.cs + + (| +JC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ILicenseService.cs + + $ + +  4 < + + + +  + + + +" ' +RC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IProxyInvocationHandler.cs + + , + +  + + " + +/ 5 + +@ J +IC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentService.cs + + # + +    + + + + ' + + + +/ 4 + +  * 5 + +  ; N + +    + +   " + +  + 3 + +   x +FC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentItem.cs + +  + +  + +  + +   q +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IResourceService.cs + + % + +  + +' * +MC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SingletonServiceBase.cs + + .2 +/ 08 9% &  + +  +( 4 + +$ 0 + + + +  +`C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\SelectableDataTemplateSelector.cs + + / +   $M U + + + %X a + +  ( : +  B F# ' + +  Y b +  #/ ? +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsSaveVm.cs + + ( +* 3  "  + + + +  + +    +  / 7  + + ! + 6 ;n +TC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\DonatePage.xaml.cs + + * + + + +  +HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\DatabaseService.cs + 7 F +$ /## ++ $,, DD $EE JJ $KK PP $QQ TT )UU# .ww  +  +( 3 +Y d +  +  +% 0 +C N +  +  +  ++ 6 +  +  +  +  +B M +E P +@ K +E P +B M +  +B M +E P +@ K +E P + L +* 3__ zz !{{% . +  +  + " + - + % + *> + )11 &88 UU9 FVV - +( 5( + # $"" ##- 84 + *>> &?? ss  + $" +  +  + ". + ! +  +  +  +   "" # +''  +T Xf +// ''' *tt= I + & +  += I +  + " + ) +)) % +E V +,, ,,2 7 +TT 44  +  +WW 44 ( +22 88 % + +<< ( +?? ??" ' + +BB  +EE EE/ 4 + +HH& : +KK KK, 1 +NN * ) +QQ QQ. 3 + +UU  + +VV  + +YY  + +]]  +]]0 8__  +ii  + > +ii, /nn pp; >ss #ww2 5 +4 7 +ii6 ?uu  +tt ww$ 0 +& 2 + + %zz> N +{{ "|| & + + " + #$ + +  +  + 0 + +0 2 +4 6 +, . +8 : + +  + +  + +  +( ) + +% ) +  + +  + & + +  + +% 0 +  + + " + +* , +? A + + $ + +, 1 +/ 4 + +  +  +  +  +  +  ++ - +  +  +  +  +  +  ++ - +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISettingsService.cs + + %( +  ) *B C + + +  + + ' + ++ 7 + +  + , - + +" * + +. 3 +JC:\Sources\Other\ModernKeePass\ModernKeePass\Common\MessageDialogHelper.cs + + + + + +  ! 1 ++  +  9 >2 7 +  G R9 D +  [ k5 E +   t F V + +   G T + +   X e +   ( +HH% 6 1:: 1BB * + + * +9 B+ 4 +U ]  + 3%%" * + +i p + "" $$! + +$$ %% %%0 4 + +)) . + +))G P2 +))c k++< D-- .. 22  + +++  + +00  + +66! 0( +66; D88 ::2 ;::E N +:: ==  + +@@! 7 +@@? DBB+ 0 +@@M TBB2 9 +BB EE  +HH> CKK; @ +HHL SKK2 9 +HH\ mNN5 F + +HH NNH U2 +KK NN QQ TT VV  +GC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NavigationHelper.cs + +<< !F +>> ??0 4II NN TT UU aa  +??  +  +. 3 +  +. 3 +  ++ 0 +A F +  ++ 0 +D I +I N ++ 0 +) . +I N + +GG  +GG% )II  + +NN! ' + +NN) * + + ;YY >gg : + + .[[ 6ii 2 + +aa# ) + +aa+ ,8 +pp # " + " + % + . +qq & + % + % + (" +{{ ) + & +& 3 + + " +# ) + + % +# , + +  +! &$ + + , + ) +) 9 + + % +# , + + ( +# / + +K QH + +$ % +  +  +  +  + l + +  +  +2 < +  +/ 9 + $ +  + ) + 0 + +  + * +# - +! +T + +  +J S +X a +P Y +^ g +L U +Z c$ + +  +$ + + &$ + +  +0 : ++ 5$ + +  +? G +: B$ + +  +/ : +4 ?$ + +  +6 = +7 > + +: @$ + +  +  + H + +  +  +2 < +  + ) +" ,$ + +  +  + $ + +  + , + "= + +  +  +' / y  +  + + . + *< + ++ 4 + " + " + " + " + + . + *$ + ++ 4 +  +  + + !0 + +6 7 +  +@ A +@ A$ + +  + ! +i s$ + +  +) 4 + $ + + ! + ! +, 9$ + + ! +- ? +- ? + + # + +8 9 + +  + $ + +  +< E +# , + + ! +) ; + +6 < + + # +> P + +Q R + +6 < + + # +> P + +Q R + + ) + $ + +* 3 +  + +) < +' : + +Y b + & + +* 3 +  + += F + & +PC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NotifyPropertyChangedBase.cs + + * +  1 @    +   (  +  0 <  G S + + "( +# $* +6 7! " +, 43 ;  +8 == B  +Y e * + +KC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ObservableDictionary.cs + +   % + + : + 7""' K +I O( . +X [  +$ 4 % +   ++ 6(( ;; FF GG@ KSS 'WW ^^! ,__ hh )mm #rr #ww )|| # + ) + # + # +& 1 +< F )< + %)) !== %II %XX %bb % +7 =""L R +F I""T W +    ""  +&& ..  +&& "((! $))A D +&&+ 0((& + +,, 55  +,,5 9.. .. # + +11  +11G M33" ( +33 55  + +99  +99" %;;( +==D G + +CC 2 +CC8 <FF- 1GG "GGS WIID H +EE FF; GGG* 6 + +OO" % +UU WW( - + +\\  +^^ `` ) +`` bbD G + +ff# ' + +kk  +kk' *mm0 3 + +pp  +pp' *rr0 3 +pp7 <rr9 > + +uu# ) + +zz  +zz: >||- 1 + +  + +  + +9 F + +F S + + $ + +: ? + ! + $ + +E O +  +  + +  +" + + +  +& * +CC:\Sources\Other\ModernKeePass\ModernKeePass\Common\RelayCommand.cs + +  + (-- EE ( +$ /.. :: ::0 ; +" 3OO + + +  +# *    + +))  +))# *++ --  +))7 A.. $ + +88  + +88& / + +CC  + +CC# , + +MM * +OO PP RR  +HC:\Sources\Other\ModernKeePass\ModernKeePass\Common\SuspensionManager.cs/ + + +` q +e v q V +2 ?&& &LL4 Aii ss ! + & + % += J) +" -00 $KKs ~ rrw  + 1OO] qnnZ n +$$1 = +  + +..! + + +::! * +?? /BB *8 + +2 C??3 Dww3 D +  +  +AA BB< ADD1 6 + + 4DD 0( +JJ (LL' 2RR SS % +KK' 1LL  +OO PP1 5 +PP (SS2 < +VV XX5 6" + + )XX 4 + 4 + +gg! - +gg5 C zz}  +nn oo5 9 +oo$ ,ssV ^ +rr+ 5ss@ J +ww /zz *2 +yy zz< AzzN S|| }}4 9" + +* Ezz] x + :: + +* C||) B + 8 +H a + 8" + + 7}} 3 + ' + +  +5 6< + +* F + ; + 7 +7 S += Y + + (T + +/ 4 +  +  +  +  +; @ +( -0 + += L +  +9 H +9 H0 + +U c +& 4 +< J +" 0 + + *$ + +1 6 +( - +W \ + +) ; + *$ + +  +< E +J S$ + +1 E + 1 + 10 + +L Q +9 > +. 3 + H + +  +  +  +  +: D + < + + # + # +3 B +& 5 +K Z$ + +> C +2 7 + $ + +  +  +1 ;$ + +; @ +2 7 +' , + +  +  + + + + + ) + +4 5 +/ 0 +GC:\Sources\Other\ModernKeePass\ModernKeePass\Services\LicenseService.cs +     7 E2 +   "22! /44! /:: )== " + +    + +  + +  + +  + +  + 220 < + 440 @ +; C  +' >BB #GG * + +  +   + +!! '( +!!/ 4##O T((] b00] bF +## $$ #''( 7((> M,,, ;.., ;00> M +@@ ('' '.. + +::+ A((' =00' = +EE ',, + +::G T<<X e +::] h<<K V +<< ==$ * +@@. ;BB( 5 +EE- :GG4 A +FC:\Sources\Other\ModernKeePass\ModernKeePass\Services\RecentService.cs +     6 CP +  9 =! %" & #- 1%% ** //  + +  + +1 < +B U + +     2 + 1 60 5= B9 > + M Q + +##  +##% )%%  +##2 :%% # + +((  + +--( 4 +--< A//+ 0 +IC:\Sources\Other\ModernKeePass\ModernKeePass\Services\ResourcesService.cs + + ! + -  9 I +  ( 7   * + +   & +  . 1  L O +     +HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SettingsService.cs + 8 G2 + + +& -- 4   < +        0 1  I J G H + +    +  & .5 = +  2 > # + +  + 3 4( +) 1$ ,  % +5 :$ )' , +NC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ToastNotificationHelper.cs + + + + / + +   )( +  4 : #a g9 ? +  C IK Q +  R VH L + T ^; E< +  /) 8) 8 +. = +    +  " + < B +   @ E +## +33  +##3 8''H M +##A E((H L2 +%% && /'') 8(() 8**. = +&& '' ((  +** ..@ E + +11 ) +114 =33 &33/ 8 +`C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DiscreteIntToSolidColorBrushConverter.cs + + 6 + + + +  + + +% *  0 5 + + + +1 ; + + + +D M + + + +V ^ +       + + ! + +) . + +5 ? + +H Q + +Z b +[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\EmptyStringToVisibilityConverter.cs + + + * + +    +  % *     ) . + +  1 ; + +  D M + +  V ^ +     ( , + + ! + +) . + +5 ? + +H Q + +Z b +QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\NullToBooleanConverter.cs + + ' + +  +% * + +  + +1 ; + +D M + +V ^ + +   ! + +  ) . + +  5 ? + +  H Q + +  Z b +HC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\SaveException.cs + +  + +    + +    +  ' 0   & +SC:\Sources\Other\ModernKeePass\ModernKeePass\Extensions\DispatcherTaskExtensions.cs + + 0( +  1 2  ! " + +   @ A + +  $ 0 +  H R    + + + 9 = + + +7 ?  & .( +   $ ( ( - +! #6 8 + +! - +B L ) + ? C +4 <X ` +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IDatabaseService.cs + + + + % + +    + +    + +  + +  + +  + + ! + +  + + 3 + + # + +  + +  + +  + +  + +  + + " + +) 2 + +  + +  + +  + + " + +  + +% * + +    + +  # % + +!!  + +!! #i +OC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IHasSelectableObject.cs + + ) + + %e +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISelectableModel.cs + + % + +  +SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\BasePages\LayoutAwarePageBase.cs + +   $x + 0      00  + # +  +  +  + : + ( +0 8 +0 8 +  +B J( +, :JJ "RR "aa  +, 1cc. 3 + + " +?? 1* D +__ 1* D + +   D J + +   T ] + + )$$* <, + + ,%% !11 ! + ! + +(( 0 + +((8 > + +((Z [N +ww 1// +HH / + * + * + + +" < + +??9 ?( +??T UDD PP RR7 8 + +__9 ? +__T Ucc  +pp =yy1 R + +1 7 + +d e + +  +/ : + + - + 2 + +  + " + + - + +B C ++ , + + / + +D E +- .| +bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsDatabasePage.xaml.cs + + 4 + + + + # +eC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsNewDatabasePage.xaml.cs + + 7 + + + + &x +^C:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSavePage.xaml.cs + + 0 + + + +  +bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSecurityPage.xaml.cs + +   4 + +   # + + @ + +H N + +b c{ +aC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsWelcomePage.xaml.cs + + 3 + + + + " +_C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\FirstItemDataTemplateSelector.cs + + . + %T ] +   %` i + +  ( : + +  B F +  Y b  J SB K +   ! - +  ! +LC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\ListViewWithDisable.cs + + $ + +   ? +  Q X  1 8   # +  a e  : > !( +      ( + % /" ,) 3 +]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\BreadCrumbUserControl.xaml.cs +   5 , + +   $ + +& 1 +2 E: M . + 0 5 + +> ? + +A E +_C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\CompositeKeyUserControl.xaml.cs( + 7 .)) .55 .R + #KK LLF KSSD IUUJ O]]- 2rr  +  + 99/ 8SSW ` +2 C( 9 , + . 3 + +- . + +0 4 +   99< EII  +%%2 C""( 9## , +## ##. 3 + +**- . + +**0 4( +,, !QQ *RR WW  +112 E..* =// . +// //0 5 + +66, - + +66/ 3 + +99 + + +;; & +AA 9@@ 1 +@@2 DGG  + +AAA G + +AAS T +CC 8BB 0 +BB1 BLL !UU % + +CC@ F + +CCZ [ +EE -__ " + +EE5 ; + +EEM N +PP RR & +QQ WW & + +[[ ( +[[0 6__# )( +[[K L]] __+ ,aa  + +ee . + +ee6 < + +eeN O +gg mm pp # +pp qq rr  + +uu 4 + +uu< B + +uuT U +ww || ~~ ' +~~   + $ +JC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\TextBoxWithButton.cs2 + " (   (,, (88 ( + + + + " +2 F  * >   / +     1 6 + +2 3 + +5 9 +3 >AA5 @ + + # +2 G* ? 0 + 2 7 + +!!4 5 + +!!7 ; + +## # +((2 I%%( ?&& 2 +&& &&4 9 + +--, - + +--/ 3 + +// & +442 F11. B22 / +22 221 6 + +99, - + +99/ 3 + +;; / +>> ?? AA  +AA' -AAI O +AA/ 0AAQ R +WC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\BooleanToVisibilityConverter.cs + + - + +    +  % *     1 6 + +  1 ; + +  D M + +  V ^ +       + + ! +) . "@ E + +5 ? + +H Q + +Z b +   +PC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ColorToBrushConverter.cs + + & + + + +  + + +% *     2 7 + + + +1 ; + + +D M  ( 1  _ h + + + +V ^< +           + + ! + +) . + +5 ? + +H Q + +Z b +[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DoubleToSolidColorBrushConverter.cs + + 1 + + + +  + + +% *, 1 + + + +1 ; + + +D M, 5 + + + +V ^ + 2 > + A I + 2 7D I + ? B + + ! + +) . + +5 ? + +H Q + +Z b +^C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\InverseBooleanToVisibilityConverter.cs + + 4 + +    +  % *     0 5 + +  1 ; + +  D M + +  V ^ +       + + ! +) . "? D + +5 ? + +H Q + +Z b +   +QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\PluralizationConverter.cs + + ' + +  +% *     - 2 + +1 ; +D M + +, 5 + +V ^ + + + )  ' @2 +   $   $  0 D$ 8> R +      +  " + + ! + +) . + +5 ? + +H Q + +Z b +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ProgressBarLegalValuesConverter.cs + + 0 + +  +% * 2 7 + +1 ; +D M + +* 3 + +V ^ + + + '  % <2 +   "   "  . @( :( : +  ) 1 +  ) 1( +     + + ! + +) . + +5 ? + +H Q + +Z b +OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\TextToWidthConverter.cs + + % + +  +% *    + +1 ; +D M + +( 1 + +V ^ + + +   " * +       + + ! + +) . + +5 ? + +H Q + +Z b +HC:\Sources\Other\ModernKeePass\ModernKeePass\Events\PasswordEventArgs.cs + + " +     + + + +  + + +) 0   _ +EC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IIsEnabled.cs + +  + +  +DC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IPwEntity.cs +     + +  + +    + + + +  + +    + +    + +   ) + +  + +  + +  + + % + +  + +  + +!!  + +%%  + +%%" 1 +CC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPage.xaml.cs + +   ( +  $ + +  + + 2 +: @+ 1 +\ ]3 42 +   3 ?J V + + - +B C!! m +SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\AboutPage.xaml.cs + + ) + + + +  +YC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\NewDatabasePage.xaml.cs + + / + ""  + +  + + - + +5 ; + +M N +     ' +   !! ""  +GC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPage.xaml.cs + +   , + # $ + +  + + 2 +: @+ 1 +\ ]3 4 +  ,U ao +UC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\WelcomePage.xaml.cs + + + + + + +  +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\AboutVm.cs + + ( +! )   & &  + +    + +    +  !* 1 + +  + +  + &  +IC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\CompositeKeyVm.cs + + X + CC0 ;MM" -mm  +6 A +$ / +L W +/ : + MM. 4" +  +B G +0 5 + +  +  +X _8 + (xx  +  +1 9 + , + 88/ : +  +  +gg ! % , + . 3, +$$ 88> H +  +  +hh && $)) + +'' ))- 2, +.. "88_ m + " +  +ii $00 (33 / +11 331 6 + +88 * +jj 88 *  + 8 +RR "88L S +  + % +p w +:: NN  +  +ll << ==" ) +== ==+ 0 +@@ MM  +  +mm 'BB )CC" - +CC CC< A +FF ee\ d +E M +kk HH "KK  +II KK ! +nn $TT !WW  +UU WW XX # +]] !XX ( +oo #__ %``" .ww  +`` ``0 5 +cc  +% . + +ee 1f +pp* 3vv ww $ +8 A +9 B +8 A +< E + ( + " + +rr  + +tt  +tt/ 7xx  +ttJ Rvv  + +{{ , +{{2 ; +: C$ + + / +$ 6 +$ 6< + +  +! - + , +$ 0 + )0 + + ! +  +  +  + +  +T U + +  + " + +  + + !$ + +. 2 + " +  + +) - +  + +; ? + "< + +  + ) +/ ; + , +  +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\ListMenuItemVm.cs + +  + + +  $" - +     + +  + +  + +  + +  + +  + / 4 + + 'u +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\MainMenuItemVm.cs + +  + +  + +  +MC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\RecentItemVm.cs + +  + + +  $" -( +   ' * &&$ 0 +    00& + +   + +  + +  + / 4 + +  + +  +# (  +1 9  +H L  + + $ +$$ $!!  +$$6 >&&  + +)) $ +.. *++  +..: @00  +JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\EntryDetailPage.xaml.cs + + /< + KK NN SS7 <TT \\3 82 + 0  << CC  + +  +-- /* D + +--7 = + +--R S + +:: -( +::B C<<+ ,== >># $ + +AA / +AAD ECC- . + +HH ' + +HH/ 5 + +HHG Hd +JJ LL MM NN1 9NN^ fOO1 9PP QQ SS> FTT$ , +KK OOa h +NN SSk o + +QQG H + +YY ( + +YY0 6 + +YYH I +[[ \\: B\\l t + +`` 2 + +``: @ +``W Xbb/ 0 + +ee @ +eeH Ngg ! + +eej k +gg ii nn $ +hh nn rr% * +JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\GroupDetailPage.xaml.cs + /\\" 1 +" 12 + 0!! "" ?? II z + pp ss xx; @yy  +3 8 +4 9 +4 9 +  +  +  + +  +00 /""* D + +007 = + +00R S + +== -< +==B C??+ ,AA BB3 4CC DD( ) + +GG / +GGD EII- . + +PP , +PP4 :RR ! + +PPV W +RR TT YY $ +SS YY \\4 9 + +__ - + +__5 ; + +__W X +aa gg jj4 9 + +mm ' + +mm/ 5 + +mmG Hd +oo qq rr ss1 9ss^ ftt1 9uu vv xxB Jyy( 0 +pp tta h +ss xxo s + +vvG H + +~~ ( + +~~0 6 + +~~H I$ + +  +: B +  + + 3 + +; A0 + +d e +  +  +) * + + , + +4 : + +L M + + , + +4 : + +L M + + / + +7 =$ + +Z [ +  +  + + 5 + +@ F$ + +o s +E I +  + +    + +  +# * + +1 2 +6 70 + +  +O U +\ b +u { + + 7 + +B H + +s w +E I + +  +4 9 + +8 9 += > + + 2 + +: @ + +W X +/ 0 +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\OpenDatabasePage.xaml.cs + + 0 +   + --  + +  + + - +B C   + +   - + +  5 ; + +  M N +"" (( ++ # +++ ,, -- w +]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\RecentDatabasesPage.xaml.cs + + 3 + + + + " +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\SaveDatabasePage.xaml.cs + + 0( +  "" 22  + !! 00  + +  + + - +B C   + + - + +5 ; + +M N + +%% / + +%%7 = + +%%O P +'' ,, .. ' +.. // 00 I +GC:\Sources\Other\ModernKeePass\ModernKeePass\Properties\AssemblyInfo.cs +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\EntryVm.cs +  +' .p + """I T##H S##a l +: E +  +1 < + ' +  + : + $ +  +  +  +0 = + +% 4 + +! )8 @8 @7 ?   (!! $[[ [[; Cbb, 4cc) 1hh !ii) 1ii? G + ! +  +- 5 +  +  +  +  +  +0 8 +  +M U + +% 4 + + + +@@ E M\ d + + * + + %" 3cc 'ii ' + + 1 + , + ( + , + ( + ) + % + ( + $ + - + ) + ( + $ + * + & + + + ' + ! +" -" +    +) / +c i + +!!  + +"" % + +* 3"") 2 +  +  +/ 8 +  +  +J S +  +  +J S +  + +##& 0, +'' nn # +H R +  +)) $ + - + + &++ (..  +,, .." 'z + + *// %FF %GG %rr %|| % + % + % + ! + ! + ! + +33 > + + $55 &<< &BB &MM &SS &> + + "66 == EE NN TT  +66 663 8 + +::  +== ==6 ; +CC EE4 9 + +KK  +NN NN1 6 + +QQ  +TT TT3 8 + +WW  + +`` ( +cc cc? D + +ff " +ii ii\ a + +ll  + + nn' 2qq  +oo qq # + +vv  + + xx #{{  +yy {{ " + + $$ + + & + * + ! + +  +$ ) + +  +# ( + +& -$ + +  +  +  + + ) +, 8 + +  +$ + + +1 @ + $ + +* 3 +  + ) + +2 > +G S + +  + +! & +? D + +0 6 +F L + +  + + $ +  + +. 4 +  + +G O +  + +b j +  + + $ + +  +* 3 +* 3 +' 0 +( 1 +& / ++ 4 +& / +) 2 +  +/ 8$ + + $ +% - +8 @ + +, / +- 0 + +* - +" % + +6 > +A I + + ! + +) 8 ++ :$ + +  +  +  + + $ + +! , +  + % + +  + +  + + ! + + ' +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\GroupVm.cs +      ''$ +''] dbb' .cc ww* 1{{( / +. 5 +  +  +  +2 9v + "++! ,--0 ;//X cdd (ff" -  + ' +  +  + F + $ +  +  +  +  +0 =Z +- 4$ +==Z a +  +  +  +  +< C +rr. 6 !* 2 + 4 9 +$ .  . 8( +     ## ! + "  ( -\ +''- 3& , +  +  +  +  +  +; A8 +)) ** " +E K +) / +* 0 +nn! ))) (99 %DD !DD; CEE LL LL; COO }}  +( 0 +' / +  +1 9 + ! +  + " +1 9 +  +* 2 +  +/ 7 +_ g +q y +  +  +e m +** 66c e66i k +++ --# , + +-- @ +44 --< F//I S//d n +1 ; +> H + +// % +oo* 3//) 266 "66. 766M V99/ 8~~  +L U +  +/ 8 +  +  +> G +  +  +J S +  +  +77 99  + +==< L. +BB  +7 ; +Q U +  +EE EE" ' + +HH  +OO OO, 1 +RR  +D N +pp TT $UU" - +UU UU/ 4 + +XX  +ss "ZZ &[[" / +[[ [[1 6 + +^^& 0 +bb gg jj 2 +cc dd ff ff !gg %. +qq ' + $ + ' +K Z + +uu " +ww  +V ] + & +ww! (ww] d +ww2 8wwf l +wwA Mxx& 2 + +{{ , +{{ &}}  +8 ? +7 > +{{0 6  +{{I Q~~ . +{{Z f +  += I +g s + +O P +` a + + . +) B + +M N +^ _ + +6 << + +_ ` +  +* + +N O +7 8$ + +  +> F +. 6 + + "0 + +* . +2 6 +> B +f j$ + +  + % +' .$ + +  +  +  + + " + +  +' .0 + +  +  +  +  + + ! + +) 8 ++ :$ + +  +  +  + + $ + +! , +  + % + +  + +  + +  + +  +& . + +L M +Q R + +  +4 5 + +  + +J K +O P + +^ _ +c d + +  +4 5 + + ' +NC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsNewVm.cs + + < +  * 3  "  "  + +    + +  +. 6  + + " + 1 6 + +# . + + ' + < A +EC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SettingsVm.cs + +   P +   , & ! ! !"" -$$ !&& ! +F P #" , +E NSS  + . 3 + ,QQ  + % *""? D + +++  + +--  +--+ 3FF (NN (Z +--F N33 $44 $;; $<< $BB $CC $JJ $KK $ +// QQ $SS% . +QQ4 5QQ9 : +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\MainVm.cs + +    +F T '" 0P + , & ! !!! !$$ -&& !(( ! + +  +E R +  + 2 7 + ,ww  + % *$$? D + +--  + +//  +// ,//M [ +//4 D//] m + +33 F +33 *>> .GG .OO .YY .dd" 0" 0F +332 B==" 2FF" 2NN" 2XX" 2kk" 2rr" 2z +33U ]55! )555 =@@! )@@5 =@@M U\\ !\\- 5zz zz$ ,}} $ + (P +33p x;; $DD $LL $VV $bb $ii $pp $ + +33 ]] ^^ & +55 QQ! /RR .* +77 ww ({{  +) 6 +ww8 9ww= >Z +@C:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\NewVm.cs + +  + +  +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\OpenVm.cs + +  + + + + #2 +* 3 + +' 0   '     + +    + +  + + 2 +' /  % -  +   +) -  +   +) -  % )##  +> D##" ( +&& $##  +&&1 5(( (( ! +&&F L((  +CC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\RecentVm.cs + + ( + + +( /++ ,, !33 P +  ! . & ! ! ! -!! !""  +  2 > %" .2 +1 <,, -- .. *44  + 0 5 + ,..  + % */ 4 + +&&  + +))  +))' -++  + +11  +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SaveVm.cs + + 2 + + +* 3     + +    + +    +  ' /  + +  +$ )  + +  +% )  +SC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsDatabaseVm.cs + + # +* 3 "    "## $::E N>> EEF OFF LL% .MM hh ii F + %UU !VV !XX ![[ -]] !__ ! + + ! + . 3 + #UU. = +!! ##  +''- 3RR ii  + +))# *( +-- --" %--K N//7 : + +44 2 +88 88" %88M P::. 1::c f +>> >>? D + +AA# / + +CC % +FF FFv { + +HH# 1 +HHL MHHQ R + +JJ ' +MMK LMMP Q +MM MMZ _ + +PP , +RR/ 0RR4 5 +SS UU% *[[8 = + +dd ! + +ff ! +ff3 ;hh  +`C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\HamburgerMenuUserControl.xaml.csP + + + 8 /&& /22 />> /JJ /WW /cc / + +   ' + + ! +2 E* = . + 0 5 + +0 1 + +3 7 + + ! +""2 E* =   . +     0 5 + +''0 1 + +''3 7 + +)) ' +..2 K++* C,, 4 +,, ,,6 ; + +33/ 0 + +332 6 + +55 " +::2 F77" 688 / +88 881 6 + +??, - + +??/ 3 + +AA ) +FF2 ICC. EDD 2 +DD DD4 9 + +KK< = + +KK? C + +MM& 1 +SS2 EOO: MPP . +PP PP0 5 + +XX= > + +XX@ D + +ZZ " +__2 F\\" 6]] / +]] ]]1 6 + +dd, - + +dd/ 3 +gg 9ff 1 +ff2 Bjj  + +ggA G + +ggc d + +hh 0 +hh8 >jj% + +hhZ [jj- . +nn 6mm . +mm/ <qq  + +nn> D + +nnV W + +oo ' +oo/ 5qq" ( +ooG Hqq* + \ No newline at end of file diff --git a/ModernKeePass10/.sonarqube/out/0/output-cs/token-cpd.pb b/ModernKeePass10/.sonarqube/out/0/output-cs/token-cpd.pb new file mode 100644 index 0000000..b50b350 --- /dev/null +++ b/ModernKeePass10/.sonarqube/out/0/output-cs/token-cpd.pb @@ -0,0 +1,24951 @@ + +GC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\ClipboardAction.cs + namespace  + ModernKeePass +  +.  +Actions  +{  +public + +class  +ClipboardAction  +:! " +DependencyObject# 3 +,3 4 +IAction5 < +{  +public    +string    +Text    +{ + +  +get    +{    +return    +(    +string    +)   ! +GetValue  ! ) +(  ) * + TextProperty  * 6 +)  6 7 +;  7 8 +}  9 : +set    +{    +SetValue    +(    + TextProperty   ' +,  ' ( +value  ) . +)  . / +;  / 0 +}  1 2 +}    +public  +static  +readonly  +DependencyProperty 1 + TextProperty2 > +=? @ +DependencyProperty  +.  +Register ' +(' ( +$str( . +,. / +typeof0 6 +(6 7 +string7 = +)= > +,> ? +typeof@ F +(F G +ClipboardActionG V +)V W +,W X +newY \ +PropertyMetadata] m +(m n +stringn t +.t u +Emptyu z +)z { +){ | +;| } +public  +object  +Execute  +(  +object $ +sender% + +,+ , +object- 3 + parameter4 = +)= > +{  +var  + dataPackage  +=  +new ! + DataPackage" - +{. / +RequestedOperation0 B +=C D +DataPackageOperationE Y +.Y Z +CopyZ ^ +}_ ` +;` a + dataPackage  +.  +SetText  +(  +Text $ +)$ % +;% & + Clipboard  +.  + +SetContent  +( ! + dataPackage! , +), - +;- . +return  +null  +;  +}  +}  +}  +KC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\NavigateToUrlAction.cs + namespace  + ModernKeePass +  +.  +Actions  +{  +public + +class  +NavigateToUrlAction $ +:% & +DependencyObject' 7 +,7 8 +IAction9 @ +{    +public + +  +string + +  +Url + +  +{    +get    +{    +return    +(    +string    +)   ! +GetValue  ! ) +(  ) * + UrlProperty  * 5 +)  5 6 +;  6 7 +}  8 9 +set    +{    +SetValue    +(    + UrlProperty   & +,  & ' +value  ( - +)  - . +;  . / +}  0 1 +}  +public  +static  +readonly  +DependencyProperty 1 + UrlProperty2 = +=> ? +DependencyProperty  +.  +Register ' +(' ( +$str( - +,- . +typeof/ 5 +(5 6 +string6 < +)< = +,= > +typeof? E +(E F +NavigateToUrlActionF Y +)Y Z +,Z [ +new\ _ +PropertyMetadata` p +(p q +stringq w +.w x +Emptyx } +)} ~ +)~  +;   +public  +object  +Execute  +(  +object $ +sender% + +,+ , +object- 3 + parameter4 = +)= > +{  +try  +{  +var  +uri  +=  +new  +Uri ! +(! " +Url" % +)% & +;& ' +return  +Windows  +.  +System % +.% & +Launcher& . +.. / +LaunchUriAsync/ = +(= > +uri> A +)A B +.B C + +GetAwaiterC M +(M N +)N O +.O P + GetResultP Y +(Y Z +)Z [ +;[ \ +}  +catch  +(  + Exception  +ex  +)  +{  +MessageDialogHelper # +.# $ +ShowErrorDialog$ 3 +(3 4 +ex4 6 +)6 7 +;7 8 +return  +false  +;  +}  +}  +}    +}!!  +HC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\SetupFocusAction.cs + namespace  + ModernKeePass +  +.  +Actions  +{  +public   + +class    +SetupFocusAction   ! +:  " # +DependencyObject  $ 4 +,  4 5 +IAction  6 = +{ + +  +public    +Control    + TargetObject   # +{    +get    +{    +return    +(    +Control   ! +)  ! " +GetValue  " * +(  * + +TargetObjectProperty  + ? +)  ? @ +;  @ A +}  B C +set  +{  +SetValue  +(  +TargetObjectProperty / +,/ 0 +value1 6 +)6 7 +;7 8 +}9 : +}  +public  +static  +readonly  +DependencyProperty 1 +TargetObjectProperty2 F +=G H +DependencyProperty  +.  +Register ' +(' ( +$str( 6 +,6 7 +typeof8 > +(> ? +Control? F +)F G +,G H +typeofI O +(O P +SetupFocusActionP ` +)` a +,a b +newc f +PropertyMetadatag w +(w x +nullx | +)| } +)} ~ +;~  +public  +object  +Execute  +(  +object $ +sender% + +,+ , +object- 3 + parameter4 = +)= > +{  +return  +Task  +.  +Factory  +.  +StartNew ( +(( ) +(  +)  +=>  + +Dispatcher  +. ! +RunAsync! ) +() *" +CoreDispatcherPriority* @ +.@ A +LowA D +,D E +(  +)  +=>  + TargetObject & +?& ' +.' ( +Focus( - +(- . + +FocusState. 8 +.8 9 + Programmatic9 E +)E F +)F G +)G H +;H I +}  +}  +} \ +8C:\Sources\Other\ModernKeePass\ModernKeePass\App.xaml.cs + namespace  + ModernKeePass +  +{  +sealed + +partial  +class  +App  +{  +public  +App  +(  +)  +{  + HockeyClient  +.  +Current  +. ! + Configure! * +(* + +$str+ M +)M N +;N O +InitializeComponent  +(  +) ! +;! " + +Suspending    ++=    + OnSuspending   & +;  & ' +Resuming!!  ++=!!  + +OnResuming!! " +;!!" # +UnhandledException""  ++="" ! +OnUnhandledException""" 6 +;""6 7 +}##  +private((  +void((  +OnUnhandledException(( ) +((() * +object((* 0 +sender((1 7 +,((7 8' +UnhandledExceptionEventArgs((9 T' +unhandledExceptionEventArgs((U p +)((p q +{))  +var++  + exception++  +=++ ' +unhandledExceptionEventArgs++ 7 +.++7 8 + Exception++8 A +;++A B +var,,  + realException,,  +=,,  + exception--  +is-- % +TargetInvocationException-- 6 +&&--7 9 + exception..  +...  +InnerException.. ( +!=..) + +null.., 0 +?//  + exception//  +.//  +InnerException// . +:00  + exception00  +;00  +if22  +(22  + realException22  +is22  + SaveException22! . +)22. / +{33 ' +unhandledExceptionEventArgs44 + +.44+ , +Handled44, 3 +=444 5 +true446 : +;44: ; +MessageDialogHelper55 # +.55# $ +SaveErrorDialog55$ 3 +(553 4 + realException554 A +as55B D + SaveException55E R +,55R S +DatabaseService55T c +.55c d +Instance55d l +)55l m +;55m n +}66  +else77  +if77  +(77  + realException77 " +is77# %# +DatabaseOpenedException77& = +)77= > +{88 ' +unhandledExceptionEventArgs99 + +.99+ , +Handled99, 3 +=994 5 +true996 : +;99: ; +MessageDialogHelper:: # +.::# $ +SaveUnchangedDialog::$ 7 +(::7 8 + realException::8 E +as::F H# +DatabaseOpenedException::I ` +,::` a +DatabaseService::b q +.::q r +Instance::r z +)::z { +;::{ | +};;  +}<<  + protectedCC  +overrideCC  +asyncCC  +voidCC! % + +OnLaunchedCC& 0 +(CC0 1$ +LaunchActivatedEventArgsCC1 I +eCCJ K +)CCK L +{DD  +OnLaunchOrActivatedEE  +(EE  +eEE ! +)EE! " +;EE" # +awaitFF  + HockeyClientFF  +.FF  +CurrentFF & +.FF& ' +SendCrashesAsyncFF' 7 +(FF7 8 +)FFU V +;FFV W +}GG  + protectedII  +overrideII  +voidII  + OnActivatedII + +(II+ , +IActivatedEventArgsII, ? +argsII@ D +)IID E +{JJ  +OnLaunchOrActivatedKK  +(KK  +argsKK $ +)KK$ % +;KK% & +}LL  +privateNN  +voidNN  +OnLaunchOrActivatedNN ( +(NN( ) +IActivatedEventArgsNN) < +eNN= > +)NN> ? +{OO  +ifRR  +(RR  +SystemRR  +.RR  + DiagnosticsRR " +.RR" # +DebuggerRR# + +.RR+ , + +IsAttachedRR, 6 +)RR6 7 +{SS  +}UU  +varXX  + rootFrameXX  +=XX  +WindowXX " +.XX" # +CurrentXX# * +.XX* + +ContentXX+ 2 +asXX3 5 +FrameXX6 ; +;XX; < +if\\  +(\\  + rootFrame\\  +==\\  +null\\ ! +)\\! " +{]]  + rootFrame__  +=__  +new__  +Frame__ % +{__& ' +Language__' / +=__0 1 +Windows__2 9 +.__9 : + Globalization__: G +.__G H +ApplicationLanguages__H \ +.__\ ] + Languages__] f +[__f g +$num__g h +]__h i +}__i j +;__j k + rootFramebb  +.bb  +NavigationFailedbb * ++=bb+ - +OnNavigationFailedbb. @ +;bb@ A +ifdd  +(dd  +edd  +.dd " +PreviousExecutionStatedd , +==dd- /% +ApplicationExecutionStatedd0 I +.ddI J + +TerminatedddJ T +)ddT U +{ee  +MessageDialogHelperhh ' +.hh' (" +ShowNotificationDialoghh( > +(hh> ? +$strhh? O +,hhO P +$strhhQ } +)hh} ~ +;hh~  +}jj  +Windowmm  +.mm  +Currentmm  +.mm  +Contentmm & +=mm' ( + rootFramemm) 2 +;mm2 3 +}nn  +ifpp  +(pp  +epp  +ispp $ +LaunchActivatedEventArgspp - +)pp- . +{qq  +varrr # +lauchActivatedEventArgsrr + +=rr, - +(rr. /$ +LaunchActivatedEventArgsrr/ G +)rrG H +errI J +;rrJ K +ifss  +(ss  + rootFramess  +.ss  +Contentss % +==ss& ( +nullss) - +)ss- . +{tt  + rootFramexx  +.xx  +Navigatexx & +(xx& ' +typeofxx' - +(xx- . +MainPagexx. 6 +)xx6 7 +,xx7 8# +lauchActivatedEventArgsxx9 P +.xxP Q + ArgumentsxxQ Z +)xxZ [ +;xx[ \ +}yy  +}  +Window +  +. +  +Current +  +. +  +Activate + # +( +# $ +) +$ % +; +% & +} +  +private +  +async +  +void +  + +OnResuming + % +( +% & +object +& , +sender +- 3 +, +3 4 +object +5 ; +e +< = +) += > +{ +  +var +  + currentFrame +  += +  +Window + % +. +% & +Current +& - +. +- . +Content +. 5 +as +6 8 +Frame +9 > +; +> ? +var +  +database +  += +  +DatabaseService + * +. +* + +Instance ++ 3 +; +3 4 +if +  +( +  +database +  +. +  + DatabaseFile + % +== +& ( +null +) - +) +- . +{ + % +ToastNotificationHelper + ' +. +' ( +ShowGenericToast +( 8 +( +8 9 +$str +9 H +, +H I +$str +J v +) +v w +; +w x +return +  +; +  +} +  +try +  +{ +  +if +  +( +  +database +  +. +  + CompositeKey + ) +!= +* , +null +- 1 +) +1 2 +await +3 8 +database +9 A +. +A B +ReOpen +B H +( +H I +) +I J +; +J K +} +  +catch +  +( +  + Exception +  +ex +  +) +  +{ +  + currentFrame +  +? +  +. +  +Navigate + & +( +& ' +typeof +' - +( +- . +MainPage +. 6 +) +6 7 +) +7 8 +; +8 9! +MessageDialogHelper + # +. +# $ +ShowErrorDialog +$ 3 +( +3 4 +ex +4 6 +) +6 7 +; +7 8% +ToastNotificationHelper + ' +. +' ( +ShowGenericToast +( 8 +( +8 9 +$str +9 H +, +H I +$str +J t +) +t u +; +u v +} +  +} +  +void +  +OnNavigationFailed +  +( +  +object + & +sender +' - +, +- .' +NavigationFailedEventArgs +/ H +e +I J +) +J K +{ +  +throw +  +new +  + Exception +  +( +  +$str + 6 ++ +7 8 +e +9 : +. +: ; +SourcePageType +; I +. +I J +FullName +J R +) +R S +; +S T +} +  +private +  +async +  +void +  + OnSuspending + ' +( +' ( +object +( . +sender +/ 5 +, +5 6! +SuspendingEventArgs +7 J +e +K L +) +L M +{ +  +var +  +deferral +  += +  +e +  +. + ! +SuspendingOperation + 0 +. +0 1 + GetDeferral +1 < +( +< = +) += > +; +> ? +var +  +database +  += +  +DatabaseService + * +. +* + +Instance ++ 3 +; +3 4 +try +  +{ +  +if +  +( +  +SettingsService + # +. +# $ +Instance +$ , +. +, - + +GetSetting +- 7 +( +7 8 +$str +8 E +, +E F +true +G K +) +K L +) +L M +database +N V +. +V W +Save +W [ +( +[ \ +) +\ ] +; +] ^ +await +  +database +  +. +  +Close + $ +( +$ % +false +% * +) +* + +; ++ , +} +  +catch +  +( +  + Exception +  + exception + & +) +& ' +{ + % +ToastNotificationHelper + ' +. +' ( +ShowErrorToast +( 6 +( +6 7 + exception +7 @ +) +@ A +; +A B +} +  +deferral +  +. +  +Complete +  +( +  +) +  +; +  +} +  + protected +  +override +  +void +  +OnFileActivated + / +( +/ 0$ +FileActivatedEventArgs +0 F +args +G K +) +K L +{ +  +base +  +. +  +OnFileActivated +  +( + ! +args +! % +) +% & +; +& ' +var +  + rootFrame +  += +  +new +  +Frame + % +( +% & +) +& ' +; +' ( +DatabaseService +  +. +  +Instance + $ +. +$ % + DatabaseFile +% 1 += +2 3 +args +4 8 +. +8 9 +Files +9 > +[ +> ? +$num +? @ +] +@ A +as +B D + StorageFile +E P +; +P Q + rootFrame +  +. +  +Navigate +  +( +  +typeof + % +( +% & +MainPage +& . +) +. / +, +/ 0 +args +1 5 +) +5 6 +; +6 7 +Window +  +. +  +Current +  +. +  +Content + " += +# $ + rootFrame +% . +; +. / +Window +  +. +  +Current +  +. +  +Activate + # +( +# $ +) +$ % +; +% & +} +  +} +  +} X +OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\IntToSymbolConverter.cs + namespace  + ModernKeePass +  +.  + +Converters " +{  +public + +class  +IntToSymbolConverter % +:& ' +IValueConverter( 7 +{    +public + +  +object + +  +Convert + +  +( + +  +object + + $ +value + +% * +, + +* + +Type + +, 0 + +targetType + +1 ; +, + +; < +object + += C + parameter + +D M +, + +M N +string + +O U +language + +V ^ +) + +^ _ +{    +var    +icon    +=    +(    +PwIcon    +)    +value   % +;  % & +switch    +(    +icon    +)    +{  +case  +PwIcon  +.  +Key  +:  +return! ' +Symbol( . +.. / + Permissions/ : +;: ; +case  +PwIcon  +.  + WorldSocket ' +:' ( +case  +PwIcon  +.  +World ! +:! " +return# ) +Symbol* 0 +.0 1 +World1 6 +;6 7 +case  +PwIcon  +.  +Warning # +:# $ +return% + +Symbol, 2 +.2 3 + Important3 < +;< = +case  +PwIcon  +.  + WorldComputer ) +:) * +case  +PwIcon  +.  +Drive ! +:! " +case  +PwIcon  +.  + DriveWindows ( +:( ) +case  +PwIcon  +.  + NetworkServer ) +:) * +return+ 1 +Symbol2 8 +.8 9 +MapDrive9 A +;A B +case  +PwIcon  +.  +MarkedDirectory + +:+ , +return- 3 +Symbol4 : +.: ; +Map; > +;> ? +case  +PwIcon  +.  +UserCommunication - +:- . +return/ 5 +Symbol6 < +.< = + ContactInfo= H +;H I +case  +PwIcon  +.  +Parts ! +:! " +return# ) +Symbol* 0 +.0 1 +ViewAll1 8 +;8 9 +case  +PwIcon  +.  +Notepad # +:# $ +return% + +Symbol, 2 +.2 3 +Document3 ; +;; < +case  +PwIcon  +.  +Identity $ +:$ % +return& , +Symbol- 3 +.3 4 +Contact24 < +;< = +case  +PwIcon  +.  + +PaperReady & +:& ' +return( . +Symbol/ 5 +.5 6 + +SyncFolder6 @ +;@ A +case  +PwIcon  +.  +Digicam # +:# $ +return% + +Symbol, 2 +.2 3 +Camera3 9 +;9 : +case  +PwIcon  +.  +IRCommunication + +:+ , +return- 3 +Symbol4 : +.: ; +View; ? +;? @ +case  +PwIcon  +.  +Energy " +:" # +return$ * +Symbol+ 1 +.1 2 +ZeroBars2 : +;: ; +case    +PwIcon    +.    +Scanner   # +:  # $ +return  % + +Symbol  , 2 +.  2 3 +Scan  3 7 +;  7 8 +case!!  +PwIcon!!  +.!!  +CDRom!! ! +:!!! " +return!!# ) +Symbol!!* 0 +.!!0 1 +Rotate!!1 7 +;!!7 8 +case""  +PwIcon""  +.""  +Monitor"" # +:""# $ +return""% + +Symbol"", 2 +.""2 3 +Caption""3 : +;"": ; +case##  +PwIcon##  +.##  +EMailBox## $ +:##$ % +case$$  +PwIcon$$  +.$$  +EMail$$ ! +:$$! " +return$$# ) +Symbol$$* 0 +.$$0 1 +Mail$$1 5 +;$$5 6 +case%%  +PwIcon%%  +.%%  + Configuration%% ) +:%%) * +return%%+ 1 +Symbol%%2 8 +.%%8 9 +Setting%%9 @ +;%%@ A +case&&  +PwIcon&&  +.&&  +ClipboardReady&& * +:&&* + +return&&, 2 +Symbol&&3 9 +.&&9 : +Paste&&: ? +;&&? @ +case''  +PwIcon''  +.''  +PaperNew'' $ +:''$ % +return''& , +Symbol''- 3 +.''3 4 +Page2''4 9 +;''9 : +case((  +PwIcon((  +.((  +Screen(( " +:((" # +return(($ * +Symbol((+ 1 +.((1 2 + GoToStart((2 ; +;((; < +case))  +PwIcon))  +.))  + EnergyCareful)) ) +:))) * +return))+ 1 +Symbol))2 8 +.))8 9 +FourBars))9 A +;))A B +case**  +PwIcon**  +.**  +Disk**  +:** ! +return**" ( +Symbol**) / +.**/ 0 +Save**0 4 +;**4 5 +case--  +PwIcon--  +.--  +Console-- # +:--# $ +return--% + +Symbol--, 2 +.--2 3 + SlideShow--3 < +;--< = +case..  +PwIcon..  +...  +Printer.. # +:..# $ +return..% + +Symbol.., 2 +...2 3 +Scan..3 7 +;..7 8 +case//  +PwIcon//  +.//  + ProgramIcons// ( +://( ) +return//* 0 +Symbol//1 7 +.//7 8 + GoToStart//8 A +;//A B +case11  +PwIcon11  +.11  +Settings11 $ +:11$ % +case22  +PwIcon22  +.22  +Tool22  +:22 ! +return22" ( +Symbol22) / +.22/ 0 +Repair220 6 +;226 7 +case33  +PwIcon33  +.33  +Archive33 # +:33# $ +return33% + +Symbol33, 2 +.332 3 +Crop333 7 +;337 8 +case44  +PwIcon44  +.44  +Count44 ! +:44! " +return44# ) +Symbol44* 0 +.440 1 + +Calculator441 ; +;44; < +case55  +PwIcon55  +.55  +Clock55 ! +:55! " +return55# ) +Symbol55* 0 +.550 1 +Clock551 6 +;556 7 +case66  +PwIcon66  +.66  + EMailSearch66 ' +:66' ( +return66) / +Symbol660 6 +.666 7 +Find667 ; +;66; < +case77  +PwIcon77  +.77  + PaperFlag77 % +:77% & +return77' - +Symbol77. 4 +.774 5 +Flag775 9 +;779 : +case99  +PwIcon99  +.99  +TrashBin99 $ +:99$ % +return99& , +Symbol99- 3 +.993 4 +Delete994 : +;99: ; +case::  +PwIcon::  +.::  +Expired:: # +:::# $ +return::% + +Symbol::, 2 +.::2 3 +Cancel::3 9 +;::9 : +case;;  +PwIcon;;  +.;;  +Info;;  +:;; ! +return;;" ( +Symbol;;) / +.;;/ 0 +Help;;0 4 +;;;4 5 +case==  +PwIcon==  +.==  +Folder== " +:==" # +case>>  +PwIcon>>  +.>>  + +FolderOpen>> & +:>>& ' +case??  +PwIcon??  +.??  + FolderPackage?? ) +:??) * +return??+ 1 +Symbol??2 8 +.??8 9 +Folder??9 ? +;??? @ +caseAA  +PwIconAA  +.AA  + PaperLockedAA ' +:AA' ( +returnAA) / +SymbolAA0 6 +.AA6 7 +ProtectedDocumentAA7 H +;AAH I +caseBB  +PwIconBB  +.BB  +CheckedBB # +:BB# $ +returnBB% + +SymbolBB, 2 +.BB2 3 +AcceptBB3 9 +;BB9 : +caseCC  +PwIconCC  +.CC  +PenCC  +:CC  +returnCC! ' +SymbolCC( . +.CC. / +EditCC/ 3 +;CC3 4 +caseDD  +PwIconDD  +.DD  + ThumbnailDD % +:DD% & +returnDD' - +SymbolDD. 4 +.DD4 5 + BrowsePhotosDD5 A +;DDA B +caseEE  +PwIconEE  +.EE  +BookEE  +:EE ! +returnEE" ( +SymbolEE) / +.EE/ 0 +LibraryEE0 7 +;EE7 8 +caseFF  +PwIconFF  +.FF  +ListFF  +:FF ! +returnFF" ( +SymbolFF) / +.FF/ 0 +ListFF0 4 +;FF4 5 +caseGG  +PwIconGG  +.GG  +UserKeyGG # +:GG# $ +returnGG% + +SymbolGG, 2 +.GG2 3 +ContactPresenceGG3 B +;GGB C +caseHH  +PwIconHH  +.HH  +HomeHH  +:HH ! +returnHH" ( +SymbolHH) / +.HH/ 0 +HomeHH0 4 +;HH4 5 +caseII  +PwIconII  +.II  +StarII  +:II ! +returnII" ( +SymbolII) / +.II/ 0 + OutlineStarII0 ; +;II; < +caseNN  +PwIconNN  +.NN  +MoneyNN ! +:NN! " +returnNN# ) +SymbolNN* 0 +.NN0 1 +ShopNN1 5 +;NN5 6 +caseOO  +PwIconOO  +.OO  + CertificateOO ' +:OO' ( +returnOO) / +SymbolOO0 6 +.OO6 7 + PreviewLinkOO7 B +;OOB C +casePP  +PwIconPP  +.PP  + +BlackBerryPP & +:PP& ' +returnPP( . +SymbolPP/ 5 +.PP5 6 + CellPhonePP6 ? +;PP? @ +defaultQQ  +:QQ  +returnQQ  +SymbolQQ & +.QQ& ' +StopQQ' + +;QQ+ , +}RR  +}SS  +publicUU  +objectUU  + ConvertBackUU ! +(UU! " +objectUU" ( +valueUU) . +,UU. / +TypeUU0 4 + +targetTypeUU5 ? +,UU? @ +objectUUA G + parameterUUH Q +,UUQ R +stringUUS Y +languageUUZ b +)UUb c +{VV  +varWW  +symbolWW  +=WW  +(WW  +SymbolWW  +)WW ! +valueWW" ' +;WW' ( +switchXX  +(XX  +symbolXX  +)XX  +{YY  +casehh  +Symbolhh  +.hh  +Deletehh " +:hh" # +returnii  +PwIconii ! +.ii! " +TrashBinii" * +;ii* + +default +  +: +  +return +  +PwIcon + ! +. +! " +Folder +" ( +; +( ) +} +  +} +  +} +  +}  +RC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\DatabaseOpenedException.cs + namespace  + ModernKeePass +  +.  + +Exceptions " +{  +public + +class # +DatabaseOpenedException ( +:( ) + Exception* 3 +{  +}  +}   +JC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ILicenseService.cs + namespace  + ModernKeePass +  +.  + +Interfaces " +{  +public + + interface  +ILicenseService $ +{  +IReadOnlyDictionary    +<    +string   " +,  " # +ProductListing  $ 2 +>  2 3 +Products  4 < +{  = > +get  ? B +;  B C +}  D E +Task + +  +< + +  +int + +  +> + +  +Purchase + +  +( + +  +string + + ! +addOn + +" ' +) + +' ( +; + +( ) +}    +}   +RC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IProxyInvocationHandler.cs + namespace  + ModernKeePass +  +.  + +Interfaces " +{  +public + + interface # +IProxyInvocationHandler , +{  +object  +Invoke  +(  +object  +proxy " +," # + +MethodInfo$ . +method/ 5 +,5 6 +object7 = +[= > +]> ? + +parameters@ J +)J K +;K L +}  +}   +IC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentService.cs + namespace  + ModernKeePass +  +.  + +Interfaces " +{  +public + + interface  +IRecentService # +{  +int    + +EntryCount    +{    +get    +;    +}    +Task + +  +< + +  + IStorageItem + +  +> + +  + GetFileAsync + + ' +( + +' ( +string + +( . +token + +/ 4 +) + +4 5 +; + +5 6 +ObservableCollection    +<    + IRecentItem   ( +>  ( ) + GetAllFiles  * 5 +(  5 6 +bool  6 : +removeIfNonExistant  ; N +=  O P +true  Q U +)  U V +;  V W +void    +Add    +(    + IStorageItem    +file   " +,  " # +string  $ * +metadata  + 3 +)  3 4 +;  4 5 +void    +ClearAll    +(    +)    +;    +}  +}  +FC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentItem.cs + namespace  + ModernKeePass +  +.  + +Interfaces " +{  +public + + interface  + IRecentItem  +{  + StorageFile  + DatabaseFile  +{! " +get# & +;& ' +}( ) +string  +Token  +{  +get  +;  +}  +string    +Name    +{    +get    +;    +}    +} + +  +}   +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IResourceService.cs + namespace  + ModernKeePass +  +.  + +Interfaces " +{  +public + + interface  +IResourceService % +{  +string  +GetResourceValue  +(  +string & +key' * +)* + +;+ , +}  +}  +MC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SingletonServiceBase.cs + namespace  + ModernKeePass +  +.  +Services  +{  +public + +abstract  +class  +SingletonServiceBase . +<. / +T/ 0 +>0 1 +where2 7 +T8 9 +:: ; +new< ? +(? @ +)@ A +{  +private  +static  +readonly  +Lazy $ +<$ % +T% & +>& ' + LazyInstance( 4 +=5 6 +new  +Lazy  +<  +T  +>  +(  +(  +)  +=>  +new ! +T" # +(# $ +)$ % +)% & +;& ' +public + +  +static + +  +T + +  +Instance + +  +=> + +! # + LazyInstance + +$ 0 +. + +0 1 +Value + +1 6 +; + +6 7 +}    +}   + +`C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\SelectableDataTemplateSelector.cs + namespace  + ModernKeePass +  +.  +TemplateSelectors ) +{  +public + +class * +SelectableDataTemplateSelector / +:/ 0 +DataTemplateSelector1 E +{  +public    + DataTemplate    +TrueItem   $ +{  % & +get  ' * +;  * + +set  , / +;  / 0 +}  1 2 +public + +  + DataTemplate + +  + FalseItem + + % +{ + +& ' +get + +( + +; + ++ , +set + +- 0 +; + +0 1 +} + +2 3 + protected    +override    + DataTemplate   ' +SelectTemplateCore  ( : +(  : ; +object  ; A +item  B F +,  F G +DependencyObject  H X + container  Y b +)  b c +{    +var  +isSelectableItem  +=! " +item# ' +as( * +ISelectableModel+ ; +;; < +return  +isSelectableItem # +!=$ & +null' + +&&, . +isSelectableItem/ ? +.? @ + +IsSelected@ J +?K L +TrueItemM U +:V W + FalseItemX a +;a b +}  +}  +}  + +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsSaveVm.cs + namespace  + ModernKeePass +  +.  + +ViewModels " +{  +public + +class  +SettingsSaveVm  +{  +private  +readonly  +ISettingsService ) + _settings* 3 +;3 4 +public + +  +SettingsSaveVm + +  +( + +  +) + +  +: + + ! +this + +" & +( + +& ' +SettingsService + +' 6 +. + +6 7 +Instance + +7 ? +) + +? @ +{    +}   +  +public    +SettingsSaveVm    +(    +ISettingsService   . +settings  / 7 +)  7 8 +{  + _settings  +=  +settings  +; ! +}  +public  +bool  + IsSaveSuspend ! +{  +get  +{  +return  + _settings " +." # + +GetSetting# - +(- . +$str. ; +,; < +true= A +)A B +;B C +}D E +set  +{  + _settings  +.  + +PutSetting & +(& ' +$str' 4 +,4 5 +value6 ; +); < +;< = +}> ? +}  +}  +}  +TC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\DonatePage.xaml.cs + namespace  + ModernKeePass +  +.  +Views  +{  +public + +sealed  +partial  +class  + +DonatePage * +{    +public + +  + +DonatePage + +  +( + +  +) + +  +{    +InitializeComponent    +(    +)   ! +;  ! " +}    +}  +}  +HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\DatabaseService.cs + namespace  + ModernKeePass +  +.  +Services  +{  +public + +class  +DatabaseService  +: ! +SingletonServiceBase" 6 +<6 7 +DatabaseService7 F +>F G +,G H +IDatabaseServiceI Y +{  +private  +readonly  + +PwDatabase # + _pwDatabase$ / +=0 1 +new2 5 + +PwDatabase6 @ +(@ A +)A B +;B C +private  +readonly  +ISettingsService ) + _settings* 3 +;3 4 +private  + StorageFile  +_realDatabaseFile - +;- . +private  + StorageFile  + _databaseFile ) +;) * +private  +GroupVm  + _recycleBin # +;# $ +private  + CompositeKey  + _compositeKey * +;* + +public  +GroupVm  + RootGroup  +{! " +get# & +;& ' +set( + +;+ , +}- . +public  +GroupVm  + +RecycleBin ! +{  +get  +{  +return  + _recycleBin $ +;$ % +}& ' +set    +{!!  + _recycleBin""  +=""  +value"" # +;""# $ + _pwDatabase##  +.##  +RecycleBinUuid## * +=##+ , + _recycleBin##- 8 +?##8 9 +.##9 : +IdUuid##: @ +;##@ A +}$$  +}%%  +public''  +string''  +Name''  +=>''  + DatabaseFile'' * +?''* + +.''+ , +Name'', 0 +;''0 1 +public))  +bool))  +RecycleBinEnabled)) % +{**  +get++  +{++  +return++  + _pwDatabase++ $ +.++$ % +RecycleBinEnabled++% 6 +;++6 7 +}++8 9 +set,,  +{,,  + _pwDatabase,,  +.,,  +RecycleBinEnabled,, / +=,,0 1 +value,,2 7 +;,,7 8 +},,9 : +}--  +public//  + StorageFile//  + DatabaseFile// ' +{00  +get11  +{11  +return11  + _databaseFile11 & +;11& ' +}11( ) +set22  +{33  +if44  +(44  +IsOpen44  +&&44  + +HasChanged44 ( +)44( ) +{55  +throw66  +new66 # +DatabaseOpenedException66 5 +(665 6 +)666 7 +;667 8 +}77  + _databaseFile88  +=88  +value88 % +;88% & +}99  +}::  +public<<  + CompositeKey<<  + CompositeKey<< ( +{==  +get>>  +{>>  +return>>  + _compositeKey>> & +;>>& ' +}>>( ) +set??  +{??  + _compositeKey??  +=?? ! +value??" ' +;??' ( +}??) * +}@@  +publicBB  +PwUuidBB  + +DataCipherBB  +{CC  +getDD  +{DD  +returnDD  + _pwDatabaseDD $ +.DD$ % +DataCipherUuidDD% 3 +;DD3 4 +}DD5 6 +setEE  +{EE  + _pwDatabaseEE  +.EE  +DataCipherUuidEE , +=EE- . +valueEE/ 4 +;EE4 5 +}EE6 7 +}FF  +publicHH " +PwCompressionAlgorithmHH % +CompressionAlgorithmHH& : +{II  +getJJ  +{JJ  +returnJJ  + _pwDatabaseJJ $ +.JJ$ % + CompressionJJ% 0 +;JJ0 1 +}JJ2 3 +setKK  +{KK  + _pwDatabaseKK  +.KK  + CompressionKK ) +=KK* + +valueKK, 1 +;KK1 2 +}KK3 4 +}LL  +publicNN  + KdfParametersNN  + KeyDerivationNN * +{OO  +getPP  +{PP  +returnPP  + _pwDatabasePP $ +.PP$ % + KdfParametersPP% 2 +;PP2 3 +}PP4 5 +setQQ  +{QQ  + _pwDatabaseQQ  +.QQ  + KdfParametersQQ + +=QQ, - +valueQQ. 3 +;QQ3 4 +}QQ5 6 +}RR  +publicTT  +boolTT  +IsOpenTT  +=>TT  + _pwDatabaseTT ) +.TT) * +IsOpenTT* 0 +;TT0 1 +publicUU  +boolUU  + +IsFileOpenUU  +=>UU ! +!UU" # + _pwDatabaseUU# . +.UU. / +IsOpenUU/ 5 +&&UU6 8 + _databaseFileUU9 F +!=UUG I +nullUUJ N +;UUN O +publicVV  +boolVV  +IsClosedVV  +=>VV  + _databaseFileVV - +==VV. 0 +nullVV1 5 +;VV5 6 +publicWW  +boolWW  + +HasChangedWW  +{WW  +getWW! $ +;WW$ % +setWW& ) +;WW) * +}WW+ , +publicYY  +DatabaseServiceYY  +(YY  +)YY  +:YY! " +thisYY# ' +(YY' ( +SettingsServiceYY( 7 +.YY7 8 +InstanceYY8 @ +)YY@ A +{ZZ  +}[[  +public]]  +DatabaseService]]  +(]]  +ISettingsService]] / +settings]]0 8 +)]]8 9 +{^^  + _settings__  +=__  +settings__  +;__ ! +}``  +publicii  +asyncii  +Taskii  +Openii  +(ii  + CompositeKeyii + +keyii, / +,ii/ 0 +boolii1 5 + createNewii6 ? +=ii@ A +falseiiB G +)iiG H +{jj  +tryll  +{mm  +ifnn  +(nn  +keynn  +==nn  +nullnn  +)nn  +{oo  +throwpp  +newpp ! +ArgumentNullExceptionpp 3 +(pp3 4 +nameofpp4 : +(pp: ; +keypp; > +)pp> ? +)pp? @ +;pp@ A +}qq  + _compositeKeyss  +=ss  +keyss # +;ss# $ +vartt  + ioConnectiontt  +=tt! " +IOConnectionInfott# 3 +.tt3 4 +FromFilett4 < +(tt< = + DatabaseFilett= I +)ttI J +;ttJ K +ifuu  +(uu  + createNewuu  +)uu  +{vv  + _pwDatabaseww  +.ww  +Newww # +(ww# $ + ioConnectionww$ 0 +,ww0 1 +keyww2 5 +)ww5 6 +;ww6 7 +ifzz  +(zz  + _settingszz ! +.zz! " + +GetSettingzz" , +<zz, - +boolzz- 1 +>zz1 2 +(zz2 3 +$strzz3 ; +)zz; < +)zz< = +CreateSampleDatazz> N +(zzN O +)zzO P +;zzP Q +var{{  + +fileFormat{{ " +={{# $ + _settings{{% . +.{{. / + +GetSetting{{/ 9 +<{{9 : +string{{: @ +>{{@ A +({{A B +$str{{B U +){{U V +;{{V W +switch||  +(||  + +fileFormat|| & +)||& ' +{}}  +case~~  +$str~~  +:~~ ! + KeyDerivation ) +=* + +KdfPool, 3 +.3 4 +Get4 7 +(7 8 +$str8 @ +)@ A +.A B +GetDefaultParametersB V +(V W +)W X +;X Y +break + ! +; +! " +} +  +} +  +else +  + _pwDatabase +  +. + ! +Open +! % +( +% & + ioConnection +& 2 +, +2 3 +key +4 7 +, +7 8 +new +9 < +NullStatusLogger += M +( +M N +) +N O +) +O P +; +P Q +if +  +( +  + _settings +  +. +  + +GetSetting + ( +< +( ) +bool +) - +> +- . +( +. / +$str +/ ? +) +? @ +) +@ A +{ +  +_realDatabaseFile + % += +& ' + _databaseFile +( 5 +; +5 6 +var +  + +backupFile + " += +# $ +await +  +ApplicationData + - +. +- . +Current +. 5 +. +5 6 + RoamingFolder +6 C +. +C D +CreateFileAsync +D S +( +S T +Name +T X +, +X Y% +CreationCollisionOption + 3 +. +3 4 + FailIfExists +4 @ +) +@ A +; +A B +Save +  +( +  + +backupFile + # +) +# $ +; +$ % +} +  + RootGroup +  += +  +new +  +GroupVm + ' +( +' ( + _pwDatabase +( 3 +. +3 4 + RootGroup +4 = +, += > +null +? C +, +C D +RecycleBinEnabled +E V +? +W X + _pwDatabase +Y d +. +d e +RecycleBinUuid +e s +: +t u +null +v z +) +z { +; +{ | +} +  +catch +  +( + * +InvalidCompositeKeyException + / +ex +0 2 +) +2 3 +{ +  + HockeyClient +  +. +  +Current + $ +. +$ % +TrackException +% 3 +( +3 4 +ex +4 6 +) +6 7 +; +7 8 +throw +  +new +  +ArgumentException + + +( ++ , +ex +, . +. +. / +Message +/ 6 +, +6 7 +ex +8 : +) +: ; +; +; < +} +  +} +  +public +  +async +  +Task +  +ReOpen +  +( + ! +) +! " +{ +  +await +  +Open +  +( +  + _compositeKey + $ +) +$ % +; +% & +} +  +public +  +void +  +Save +  +( +  +) +  +{ +  +if +  +( +  +! +  +IsOpen +  +) +  +return +  +; +  +try +  +{ +  + _pwDatabase +  +. +  +Save +  +( + ! +new +! $ +NullStatusLogger +% 5 +( +5 6 +) +6 7 +) +7 8 +; +8 9 +if +  +( +  + _settings +  +. +  + +GetSetting + ( +< +( ) +bool +) - +> +- . +( +. / +$str +/ ? +) +? @ +) +@ A +{ +  + _pwDatabase +  +. +  +Open + $ +( +$ % + _pwDatabase +% 0 +. +0 1 +IOConnectionInfo +1 A +, +A B + _pwDatabase +C N +. +N O + MasterKey +O X +, +X Y +new +Z ] +NullStatusLogger +^ n +( +n o +) +o p +) +p q +; +q r +} +  +} +  +catch +  +( +  + Exception +  +e +  +) +  +{ +  +throw +  +new +  + SaveException + ' +( +' ( +e +( ) +) +) * +; +* + +} +  +} +  +public +  +void +  +Save +  +( +  + StorageFile + $ +file +% ) +) +) * +{ +  +var +  +oldFile +  += +  + DatabaseFile + & +; +& ' + DatabaseFile +  += +  +file +  +; +  +try +  +{ +  + _pwDatabase +  +. +  +SaveAs + " +( +" # +IOConnectionInfo +# 3 +. +3 4 +FromFile +4 < +( +< = + DatabaseFile += I +) +I J +, +J K +true +L P +, +P Q +new +R U +NullStatusLogger +V f +( +f g +) +g h +) +h i +; +i j +} +  +catch +  +{ +  + DatabaseFile +  += +  +oldFile + & +; +& ' +throw +  +; +  +} +  +} +  +public +  +async +  +Task +  +Close +  +( +  +bool + $ + releaseFile +% 0 += +1 2 +true +3 7 +) +7 8 +{ +  + _pwDatabase +  +? +  +. +  +Close +  +( +  +) +  +; + ! +if +  +( +  + _settings +  +. +  + +GetSetting + $ +< +$ % +bool +% ) +> +) * +( +* + +$str ++ ; +) +; < +) +< = +{ +  +if +  +( +  + _pwDatabase +  +!= + " +null +# ' +&& +( * + _pwDatabase ++ 6 +. +6 7 +Modified +7 ? +) +? @ +Save +  +( +  +_realDatabaseFile + * +) +* + +; ++ , +await +  + DatabaseFile + " +. +" # + DeleteAsync +# . +( +. / +) +/ 0 +; +0 1 +} +  +if +  +( +  + releaseFile +  +) +  + DatabaseFile + ) += +* + +null +, 0 +; +0 1 +} +  +public +  +void +  +AddDeletedItem + " +( +" # +PwUuid +# ) +id +* , +) +, - +{ +  + _pwDatabase +  +. +  +DeletedObjects + & +. +& ' +Add +' * +( +* + +new ++ . +PwDeletedObject +/ > +( +> ? +id +? A +, +A B +DateTime +C K +. +K L +UtcNow +L R +) +R S +) +S T +; +T U +} +  +public +  +void +  +CreateRecycleBin + $ +( +$ % +string +% + +title +, 1 +) +1 2 +{ +  + +RecycleBin +  += +  + RootGroup + " +. +" # + AddNewGroup +# . +( +. / +title +/ 4 +) +4 5 +; +5 6 + +RecycleBin +  +. +  + +IsSelected + ! += +" # +true +$ ( +; +( ) + +RecycleBin +  +. +  +IconId +  += +  +( + ! +int +! $ +) +$ % +PwIcon +% + +. ++ , +TrashBin +, 4 +; +4 5 +} +  +private +  +void +  +CreateSampleData + % +( +% & +) +& ' +{ +  + _pwDatabase +  +. +  + RootGroup + ! +. +! " +AddGroup +" * +( +* + +new ++ . +PwGroup +/ 6 +( +6 7 +true +7 ; +, +; < +true += A +, +A B +$str +C L +, +L M +PwIcon +N T +. +T U +Count +U Z +) +Z [ +, +[ \ +true +] a +) +a b +; +b c + _pwDatabase +  +. +  + RootGroup + ! +. +! " +AddGroup +" * +( +* + +new ++ . +PwGroup +/ 6 +( +6 7 +true +7 ; +, +; < +true += A +, +A B +$str +C J +, +J K +PwIcon +L R +. +R S +EMail +S X +) +X Y +, +Y Z +true +[ _ +) +_ ` +; +` a + _pwDatabase +  +. +  + RootGroup + ! +. +! " +AddGroup +" * +( +* + +new ++ . +PwGroup +/ 6 +( +6 7 +true +7 ; +, +; < +true += A +, +A B +$str +C M +, +M N +PwIcon +O U +. +U V +World +V [ +) +[ \ +, +\ ] +true +^ b +) +b c +; +c d +var +  +pe +  += +  +new +  +PwEntry +  +( + ! +true +! % +, +% & +true +' + +) ++ , +; +, - +pe +  +. +  +Strings +  +. +  +Set +  +( +  +PwDefs + ! +. +! " + +TitleField +" , +, +, - +new +. 1 +ProtectedString +2 A +( +A B + _pwDatabase +B M +. +M N +MemoryProtection +N ^ +. +^ _ + ProtectTitle +_ k +, +k l +$str +  +) +  +) +  +; + ! +pe +  +. +  +Strings +  +. +  +Set +  +( +  +PwDefs + ! +. +! " + UserNameField +" / +, +/ 0 +new +1 4 +ProtectedString +5 D +( +D E + _pwDatabase +E P +. +P Q +MemoryProtection +Q a +. +a b +ProtectUserName +b q +, +q r +$str +  +) +  +) +  +; +  +pe +  +. +  +Strings +  +. +  +Set +  +( +  +PwDefs + ! +. +! " +UrlField +" * +, +* + +new +, / +ProtectedString +0 ? +( +? @ + _pwDatabase +@ K +. +K L +MemoryProtection +L \ +. +\ ] + +ProtectUrl +] g +, +g h +PwDefs +  +. +  + HomepageUrl + " +) +" # +) +# $ +; +$ % +pe +  +. +  +Strings +  +. +  +Set +  +( +  +PwDefs + ! +. +! " + PasswordField +" / +, +/ 0 +new +1 4 +ProtectedString +5 D +( +D E + _pwDatabase +E P +. +P Q +MemoryProtection +Q a +. +a b +ProtectPassword +b q +, +q r +$str +  +) +  +) +  +; +  +pe +  +. +  +Strings +  +. +  +Set +  +( +  +PwDefs + ! +. +! " + +NotesField +" , +, +, - +new +. 1 +ProtectedString +2 A +( +A B + _pwDatabase +B M +. +M N +MemoryProtection +N ^ +. +^ _ + ProtectNotes +_ k +, +k l +$str + 3 +) +3 4 +) +4 5 +; +5 6 + _pwDatabase +  +. +  + RootGroup + ! +. +! " +AddEntry +" * +( +* + +pe ++ - +, +- . +true +/ 3 +) +3 4 +; +4 5 +pe +  += +  +new +  +PwEntry +  +( +  +true + ! +, +! " +true +# ' +) +' ( +; +( ) +pe +  +. +  +Strings +  +. +  +Set +  +( +  +PwDefs + ! +. +! " + +TitleField +" , +, +, - +new +. 1 +ProtectedString +2 A +( +A B + _pwDatabase +B M +. +M N +MemoryProtection +N ^ +. +^ _ + ProtectTitle +_ k +, +k l +$str + ! +) +! " +) +" # +; +# $ +pe +  +. +  +Strings +  +. +  +Set +  +( +  +PwDefs + ! +. +! " + UserNameField +" / +, +/ 0 +new +1 4 +ProtectedString +5 D +( +D E + _pwDatabase +E P +. +P Q +MemoryProtection +Q a +. +a b +ProtectUserName +b q +, +q r +$str +  +) +  +) +  +; +  +pe +  +. +  +Strings +  +. +  +Set +  +( +  +PwDefs + ! +. +! " +UrlField +" * +, +* + +new +, / +ProtectedString +0 ? +( +? @ + _pwDatabase +@ K +. +K L +MemoryProtection +L \ +. +\ ] + +ProtectUrl +] g +, +g h +PwDefs +  +. +  +HelpUrl +  ++ +  +$str +! 3 +) +3 4 +) +4 5 +; +5 6 +pe +  +. +  +Strings +  +. +  +Set +  +( +  +PwDefs + ! +. +! " + PasswordField +" / +, +/ 0 +new +1 4 +ProtectedString +5 D +( +D E + _pwDatabase +E P +. +P Q +MemoryProtection +Q a +. +a b +ProtectPassword +b q +, +q r +$str +  +) +  +) +  +; +  +pe +  +. +  +AutoType +  +. +  +Add +  +( +  +new + ! +AutoTypeAssociation + 3 +( +3 4 +$str +4 K +, +K L +string +M S +. +S T +Empty +T Y +) +Y Z +) +Z [ +; +[ \ + _pwDatabase +  +. +  + RootGroup + ! +. +! " +AddEntry +" * +( +* + +pe ++ - +, +- . +true +/ 3 +) +3 4 +; +4 5 +} +  +} +  +}  +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISettingsService.cs + namespace  + ModernKeePass +  +.  + +Interfaces " +{  +public + + interface  +ISettingsService % +{  +T  + +GetSetting +  +<  +T  +>  +(  +string  +property ' +,' ( +T) * + defaultValue+ 7 +=8 9 +default: A +(A B +TB C +)C D +)D E +;E F +void  + +PutSetting  +<  +T  +>  +(  +string ! +property" * +,* + +T, - +value. 3 +)3 4 +;4 5 +}  +} 8 +JC:\Sources\Other\ModernKeePass\ModernKeePass\Common\MessageDialogHelper.cs + namespace  + ModernKeePass +  +.  +Common  +{   +public + + + +static + +  +class + +  +MessageDialogHelper + + + +{    +public    +static    +async    +void    +ShowActionDialog  ! 1 +(  1 2 +string  2 8 +title  9 > +,  > ? +string  @ F + contentText  G R +,  R S +string  T Z +actionButtonText  [ k +,  k l +string  m s +cancelButtonText   t  +, +   % +UICommandInvokedHandler +    + actionCommand +    +, +   % +UICommandInvokedHandler +    + cancelCommand +    +) +    +{  +var  + messageDialog  +=  +CreateBasicDialog 1 +(1 2 +title2 7 +,7 8 + contentText9 D +,D E +cancelButtonTextF V +,V W + cancelCommandX e +)e f +;f g + messageDialog  +.  +Commands " +." # +Add# & +(& ' +new' * + UICommand+ 4 +(4 5 +actionButtonText5 E +,E F + actionCommandG T +)T U +)U V +;V W +await  + messageDialog  +.  + ShowAsync ) +() * +)* + +;+ , +}  +public  +static  +void  +SaveErrorDialog * +(* + + SaveException+ 8 + exception9 B +,B C +IDatabaseServiceD T +databaseU ] +)] ^ +{  +ShowActionDialog  +(  +$str ) +,) * + exception+ 4 +.4 5 +InnerException5 C +.C D +MessageD K +,K L +$strM V +,V W +$strX a +,a b +asyncc h +commandi p +=>q s +{  +var  + +savePicker  +=  +new! $ +FileSavePicker% 3 +{ " +SuggestedStartLocation * +=+ , +PickerLocationId- = +.= > +DocumentsLibrary> N +,N O +SuggestedFileName   % +=  & ' +$"  ( * +{  * + +database  + 3 +.  3 4 + DatabaseFile  4 @ +.  @ A + DisplayName  A L +}  L M + - copy  M T +"  T U +}!!  +;!!  + +savePicker""  +.""  +FileTypeChoices"" * +.""* + +Add""+ . +("". / +$str""/ E +,""E F +new""G J +List""K O +<""O P +string""P V +>""V W +{""X Y +$str""Z a +}""b c +)""c d +;""d e +var$$  +file$$  +=$$  +await$$  + +savePicker$$! + +.$$+ , +PickSaveFileAsync$$, = +($$= > +)$$> ? +;$$? @ +if%%  +(%%  +file%%  +!=%%  +null%%  +)%% ! +database%%" * +.%%* + +Save%%+ / +(%%/ 0 +file%%0 4 +)%%4 5 +;%%5 6 +}&&  +,&&  +null&&  +)&&  +;&&  +}''  +public))  +static))  +void))  +SaveUnchangedDialog)) . +()). /# +DatabaseOpenedException))/ F + exception))G P +,))P Q +IDatabaseService))R b +database))c k +)))k l +{**  +ShowActionDialog++  +(++  +$str++ . +,++. / +$"++0 2 + Database ++2 ; +{++; < +database++< D +.++D E +Name++E I +}++I J9 +- is currently opened. What to you wish to do?++J w +"++w x +,++x y +$str ++z  +, +++  +$str +++  +, +++  +command +++  +=> +++  +{,,  +database--  +.--  +Save--  +(--  +)--  +;--  +database..  +...  +Close..  +(..  +)..  +;.. ! +}//  +,//  +command00  +=>00  +{11  +database22  +.22  +Close22  +(22  +)22  +;22 ! +}33  +)33  +;33  +}44  +public66  +static66  +async66  +void66  +ShowErrorDialog66! 0 +(660 1 + Exception661 : + exception66; D +)66D E +{77  +if88  +(88  + exception88  +==88  +null88 ! +)88! " +return88# ) +;88) * +var::  + messageDialog::  +=::  +CreateBasicDialog:: 1 +(::1 2 + exception::2 ; +.::; < +Message::< C +,::C D + exception::E N +.::N O + +StackTrace::O Y +,::Y Z +$str::[ _ +)::_ ` +;::` a +await==  + messageDialog==  +.==  + ShowAsync== ) +(==) * +)==* + +;==+ , +}>>  +public@@  +static@@  +async@@  +void@@ " +ShowNotificationDialog@@! 7 +(@@7 8 +string@@8 > +title@@? D +,@@D E +string@@F L +message@@M T +)@@T U +{AA  +varBB  +dialogBB  +=BB  +CreateBasicDialogBB * +(BB* + +titleBB+ 0 +,BB0 1 +messageBB2 9 +,BB9 : +$strBB; ? +)BB? @ +;BB@ A +awaitEE  +dialogEE  +.EE  + ShowAsyncEE " +(EE" # +)EE# $ +;EE$ % +}FF  +privateHH  +staticHH  + MessageDialogHH $ +CreateBasicDialogHH% 6 +(HH6 7 +stringHH7 = +titleHH> C +,HHC D +stringHHE K +messageHHL S +,HHS T +stringHHU [ +dismissActionTextHH\ m +,HHm n$ +UICommandInvokedHandler HHo  + cancelCommand +HH  += +HH  +null +HH  +) +HH  +{II  +varKK  + messageDialogKK  +=KK  +newKK # + MessageDialogKK$ 1 +(KK1 2 +messageKK2 9 +,KK9 : +titleKK; @ +)KK@ A +;KKA B + messageDialogNN  +.NN  +CommandsNN " +.NN" # +AddNN# & +(NN& ' +newNN' * + UICommandNN+ 4 +(NN4 5 +dismissActionTextNN5 F +,NNF G + cancelCommandNNH U +)NNU V +)NNV W +;NNW X + messageDialogQQ  +.QQ  +DefaultCommandIndexQQ - +=QQ. / +$numQQ0 1 +;QQ1 2 + messageDialogTT  +.TT  +CancelCommandIndexTT , +=TT- . +$numTT/ 0 +;TT0 1 +returnVV  + messageDialogVV  +;VV ! +}WW  +}XX  +}YY  +GC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NavigationHelper.cs + namespace   + ModernKeePass   +  +.    +Common    +{  +[;;  +Windows;;  +.;;  + +Foundation;;  +.;;  +Metadata;;  +.;; ! + WebHostHidden;;! . +];;. / +public<< + +class<<  +NavigationHelper<< ! +:<<" # +DependencyObject<<$ 4 +{==  +private>>  +Page>>  +Page>>  +{>>  +get>>  +;>>  +set>>! $ +;>>$ % +}>>& ' +private??  +Frame??  +Frame??  +{??  +get?? ! +{??" # +return??$ * +this??+ / +.??/ 0 +Page??0 4 +.??4 5 +Frame??5 : +;??: ; +}??< = +}??> ? +publicGG  +NavigationHelperGG  +(GG  +PageGG $ +pageGG% ) +)GG) * +{HH  +thisII  +.II  +PageII  +=II  +pageII  +;II  +thisNN  +.NN  +PageNN  +.NN  +LoadedNN  ++=NN  +(NN ! +senderNN! ' +,NN' ( +eNN) * +)NN* + +=>NN, . +{OO  +ifTT  +(TT  +thisTT  +.TT  +PageTT  +.TT  + ActualHeightTT * +==TT+ - +WindowTT. 4 +.TT4 5 +CurrentTT5 < +.TT< = +BoundsTT= C +.TTC D +HeightTTD J +&&TTK M +thisUU  +.UU  +PageUU  +.UU  + ActualWidthUU ) +==UU* , +WindowUU- 3 +.UU3 4 +CurrentUU4 ; +.UU; < +BoundsUU< B +.UUB C +WidthUUC H +)UUH I +{VV  +WindowXX  +.XX  +CurrentXX " +.XX" # + +CoreWindowXX# - +.XX- . + +DispatcherXX. 8 +.XX8 9# +AcceleratorKeyActivatedXX9 P ++=XXQ S2 +&CoreDispatcher_AcceleratorKeyActivatedYY > +;YY> ? +WindowZZ  +.ZZ  +CurrentZZ " +.ZZ" # + +CoreWindowZZ# - +.ZZ- . +PointerPressedZZ. < ++=ZZ= ? +this[[  +.[[ % +CoreWindow_PointerPressed[[ 6 +;[[6 7 +}\\  +}^^  +;^^  +thisaa  +.aa  +Pageaa  +.aa  +Unloadedaa  ++=aa ! +(aa" # +senderaa# ) +,aa) * +eaa+ , +)aa, - +=>aa. 0 +{bb  +Windowff  +.ff  +Currentff  +.ff  + +CoreWindowff ) +.ff) * + +Dispatcherff* 4 +.ff4 5# +AcceleratorKeyActivatedff5 L +-=ffM O2 +&CoreDispatcher_AcceleratorKeyActivatedgg : +;gg: ; +Windowhh  +.hh  +Currenthh  +.hh  + +CoreWindowhh ) +.hh) * +PointerPressedhh* 8 +-=hh9 ; +thisii  +.ii % +CoreWindow_PointerPressedii 2 +;ii2 3 +}kk  +;kk  +}ll  + RelayCommandpp  +_goBackCommandpp # +;pp# $ + RelayCommandqq  +_goForwardCommandqq & +;qq& ' +public{{  + RelayCommand{{  + GoBackCommand{{ ) +{||  +get}}  +{~~  +if  +(  +_goBackCommand " +==# % +null& * +)* + +{ +  +_goBackCommand + " += +# $ +new +% ( + RelayCommand +) 5 +( +5 6 +( +  +) +  +=> +  +this + " +. +" # +GoBack +# ) +( +) * +) +* + +, ++ , +( +  +) +  +=> +  +this + " +. +" # + CanGoBack +# , +( +, - +) +- . +) +. / +; +/ 0 +} +  +return +  +_goBackCommand + % +; +% & +} +  +set +  +{ +  +_goBackCommand +  += +  +value +! & +; +& ' +} +  +} +  +public +  + RelayCommand +  +GoForwardCommand + , +{ +  +get +  +{ +  +if +  +( +  +_goForwardCommand + % +== +& ( +null +) - +) +- . +{ +  +_goForwardCommand + % += +& ' +new +( + + RelayCommand +, 8 +( +8 9 +( +  +) +  +=> +  +this + " +. +" # + GoForward +# , +( +, - +) +- . +, +. / +( +  +) +  +=> +  +this + " +. +" # + CanGoForward +# / +( +/ 0 +) +0 1 +) +1 2 +; +2 3 +} +  +return +  +_goForwardCommand + ( +; +( ) +} +  +} +  +public +  +virtual +  +bool +  + CanGoBack + % +( +% & +) +& ' +{ +  +return +  +this +  +. +  +Frame +  +!= +  +null +! % +&& +& ( +this +) - +. +- . +Frame +. 3 +. +3 4 + CanGoBack +4 = +; += > +} +  +public +  +virtual +  +bool +  + CanGoForward + ( +( +( ) +) +) * +{ +  +return +  +this +  +. +  +Frame +  +!= +  +null +! % +&& +& ( +this +) - +. +- . +Frame +. 3 +. +3 4 + CanGoForward +4 @ +; +@ A +} +  +public +  +virtual +  +void +  +GoBack + " +( +" # +) +# $ +{ +  +if +  +( +  +this +  +. +  +Frame +  +!= +  +null + " +&& +# % +this +& * +. +* + +Frame ++ 0 +. +0 1 + CanGoBack +1 : +) +: ; +this +< @ +. +@ A +Frame +A F +. +F G +GoBack +G M +( +M N +) +N O +; +O P +} +  +public +  +virtual +  +void +  + GoForward + % +( +% & +) +& ' +{ +  +if +  +( +  +this +  +. +  +Frame +  +!= +  +null + " +&& +# % +this +& * +. +* + +Frame ++ 0 +. +0 1 + CanGoForward +1 = +) += > +this +? C +. +C D +Frame +D I +. +I J + GoForward +J S +( +S T +) +T U +; +U V +} +  +private +  +void + 4 +&CoreDispatcher_AcceleratorKeyActivated + ; +( +; < +CoreDispatcher +< J +sender +K Q +, +Q R% +AcceleratorKeyEventArgs + # +e +$ % +) +% & +{ +  +var +  + +virtualKey +  += +  +e +  +. +  + +VirtualKey + ) +; +) * +if +  +( +  +( +  +e +  +. +  + EventType +  +== + ) +CoreAcceleratorKeyEventType + ; +. +; < + SystemKeyDown +< I +|| +J L +e +  +. +  + EventType +  +== + ) +CoreAcceleratorKeyEventType + : +. +: ; +KeyDown +; B +) +B C +&& +D F +( +  + +virtualKey +  +== +  + +VirtualKey + ) +. +) * +Left +* . +|| +/ 1 + +virtualKey +2 < +== += ? + +VirtualKey +@ J +. +J K +Right +K P +|| +Q S +( +  +int +  +) +  + +virtualKey +  +== + " +$num +# & +|| +' ) +( +* + +int ++ . +) +. / + +virtualKey +/ 9 +== +: < +$num += @ +) +@ A +) +A B +{ +  +var +  + +coreWindow +  += +  +Window +! ' +. +' ( +Current +( / +. +/ 0 + +CoreWindow +0 : +; +: ; +var +  + downState +  += + " +CoreVirtualKeyStates + 4 +. +4 5 +Down +5 9 +; +9 : +bool +  +menuKey +  += +  +( +  + +coreWindow + * +. +* + + GetKeyState ++ 6 +( +6 7 + +VirtualKey +7 A +. +A B +Menu +B F +) +F G +& +H I + downState +J S +) +S T +== +U W + downState +X a +; +a b +bool +  + +controlKey +  += + ! +( +" # + +coreWindow +# - +. +- . + GetKeyState +. 9 +( +9 : + +VirtualKey +: D +. +D E +Control +E L +) +L M +& +N O + downState +P Y +) +Y Z +== +[ ] + downState +^ g +; +g h +bool +  +shiftKey +  += +  +( + ! + +coreWindow +! + +. ++ , + GetKeyState +, 7 +( +7 8 + +VirtualKey +8 B +. +B C +Shift +C H +) +H I +& +J K + downState +L U +) +U V +== +W Y + downState +Z c +; +c d +bool +  + noModifiers +  += +! " +! +# $ +menuKey +$ + +&& +, . +! +/ 0 + +controlKey +0 : +&& +; = +! +> ? +shiftKey +? G +; +G H +bool +  +onlyAlt +  += +  +menuKey + & +&& +' ) +! +* + + +controlKey ++ 5 +&& +6 8 +! +9 : +shiftKey +: B +; +B C +if +  +( +  +( +  +( +  +int +  +) +  + +virtualKey + $ +== +% ' +$num +( + +&& +, . + noModifiers +/ : +) +: ; +|| +< > +( +  + +virtualKey +  +== + " + +VirtualKey +# - +. +- . +Left +. 2 +&& +3 5 +onlyAlt +6 = +) += > +) +> ? +{ +  +e +  +. +  +Handled +  += +  +true + $ +; +$ % +this +  +. +  + GoBackCommand + & +. +& ' +Execute +' . +( +. / +null +/ 3 +) +3 4 +; +4 5 +} +  +else +  +if +  +( +  +( +  +( +  +int +  +) +  + +virtualKey + ) +== +* , +$num +- 0 +&& +1 3 + noModifiers +4 ? +) +? @ +|| +A C +( +  + +virtualKey +  +== + " + +VirtualKey +# - +. +- . +Right +. 3 +&& +4 6 +onlyAlt +7 > +) +> ? +) +? @ +{ +  +e +  +. +  +Handled +  += +  +true + $ +; +$ % +this +  +. +  +GoForwardCommand + ) +. +) * +Execute +* 1 +( +1 2 +null +2 6 +) +6 7 +; +7 8 +} +  +} +  +} +  +private +  +void + ' +CoreWindow_PointerPressed + . +( +. / + +CoreWindow +/ 9 +sender +: @ +, +@ A +PointerEventArgs +  +e +  +) +  +{ +  +var +  + +properties +  += +  +e +  +. +  + CurrentPoint + + +. ++ , + +Properties +, 6 +; +6 7 +if +  +( +  + +properties +  +. + ! +IsLeftButtonPressed + . +|| +/ 1 + +properties +2 < +. +< =" +IsRightButtonPressed += Q +|| +R T + +properties +  +. + # +IsMiddleButtonPressed + 0 +) +0 1 +return +2 8 +; +8 9 +bool +  + backPressed +  += +  + +properties + ) +. +) * +IsXButton1Pressed +* ; +; +; < +bool +  +forwardPressed +  += + ! + +properties +" , +. +, - +IsXButton2Pressed +- > +; +> ? +if +  +( +  + backPressed +  +^ +  +forwardPressed + , +) +, - +{ +  +e +  +. +  +Handled +  += +  +true +  +; + ! +if +  +( +  + backPressed +  +) +  +this +! % +. +% & + GoBackCommand +& 3 +. +3 4 +Execute +4 ; +( +; < +null +< @ +) +@ A +; +A B +if +  +( +  +forwardPressed + " +) +" # +this +$ ( +. +( ) +GoForwardCommand +) 9 +. +9 : +Execute +: A +( +A B +null +B F +) +F G +; +G H +} +  +} +  +private +  +String +  +_pageKey +  +; +  +public +  +event + # +LoadStateEventHandler + * + LoadState ++ 4 +; +4 5 +public +  +event + # +SaveStateEventHandler + * + SaveState ++ 4 +; +4 5 +public +  +void +  + OnNavigatedTo + ! +( +! "! +NavigationEventArgs +" 5 +e +6 7 +) +7 8 +{ +  +var +  + +frameState +  += +  +SuspensionManager + . +. +. /" +SessionStateForFrame +/ C +( +C D +this +D H +. +H I +Frame +I N +) +N O +; +O P +this +  +. +  +_pageKey +  += +  +$str + # ++ +$ % +this +& * +. +* + +Frame ++ 0 +. +0 1 +BackStackDepth +1 ? +; +? @ +if +  +( +  +e +  +. +  +NavigationMode +  +== +! # +NavigationMode +$ 2 +. +2 3 +New +3 6 +) +6 7 +{ +  +var +  + nextPageKey +  += + ! +this +" & +. +& ' +_pageKey +' / +; +/ 0 +int +  + nextPageIndex + ! += +" # +this +$ ( +. +( ) +Frame +) . +. +. / +BackStackDepth +/ = +; += > +while +  +( +  + +frameState + ! +. +! " +Remove +" ( +( +( ) + nextPageKey +) 4 +) +4 5 +) +5 6 +{ +  + nextPageIndex + ! +++ +! # +; +# $ + nextPageKey +  += + ! +$str +" ) ++ +* + + nextPageIndex +, 9 +; +9 : +} +  +if +  +( +  +this +  +. +  + LoadState + " +!= +# % +null +& * +) +* + +{ +  +this +  +. +  + LoadState + " +( +" # +this +# ' +, +' ( +new +) , +LoadStateEventArgs +- ? +( +? @ +e +@ A +. +A B + Parameter +B K +, +K L +null +M Q +) +Q R +) +R S +; +S T +} +  +} +  +else +  +{ +  +if +  +( +  +this +  +. +  + LoadState + " +!= +# % +null +& * +) +* + +{ +  +this +  +. +  + LoadState + " +( +" # +this +# ' +, +' ( +new +) , +LoadStateEventArgs +- ? +( +? @ +e +@ A +. +A B + Parameter +B K +, +K L +( +M N + +Dictionary +N X +< +X Y +String +Y _ +, +_ ` +Object +a g +> +g h +) +h i + +frameState +i s +[ +s t +this +t x +. +x y +_pageKey y  +]   +)   +)   +;   +} +  +} +  +} +  +public +  +void +  +OnNavigatedFrom + # +( +# $! +NavigationEventArgs +$ 7 +e +8 9 +) +9 : +{ +  +var +  + +frameState +  += +  +SuspensionManager + . +. +. /" +SessionStateForFrame +/ C +( +C D +this +D H +. +H I +Frame +I N +) +N O +; +O P +var +  + pageState +  += +  +new +  + +Dictionary + * +< +* + +String ++ 1 +, +1 2 +Object +3 9 +> +9 : +( +: ; +) +; < +; +< = +if +  +( +  +this +  +. +  + SaveState +  +!= + ! +null +" & +) +& ' +{ +  +this +  +. +  + SaveState +  +( +  +this + # +, +# $ +new +% ( +SaveStateEventArgs +) ; +( +; < + pageState +< E +) +E F +) +F G +; +G H +} +  + +frameState +  +[ +  +_pageKey +  +] +  += +! " + pageState +# , +; +, - +} +  +} +  +public + + +delegate +  +void + # +LoadStateEventHandler + . +( +. / +object +/ 5 +sender +6 < +, +< = +LoadStateEventArgs +> P +e +Q R +) +R S +; +S T +public + + +delegate +  +void + # +SaveStateEventHandler + . +( +. / +object +/ 5 +sender +6 < +, +< = +SaveStateEventArgs +> P +e +Q R +) +R S +; +S T +public + + +class +  +LoadStateEventArgs + # +: +$ % + EventArgs +& / +{ +  +public +  +Object + ! +NavigationParameter + ) +{ +* + +get +, / +; +/ 0 +private +1 8 +set +9 < +; +< = +} +> ? +public +  + +Dictionary +  +< +  +string +  +, + ! +Object +" ( +> +( ) + PageState +* 3 +{ +4 5 +get +6 9 +; +9 : +private +; B +set +C F +; +F G +} +H I +public +  +LoadStateEventArgs + ! +( +! " +Object +" (! +navigationParameter +) < +, +< = + +Dictionary +> H +< +H I +string +I O +, +O P +Object +Q W +> +W X + pageState +Y b +) +b c +: +  +base +  +( +  +) +  +{ +  +this +  +. + ! +NavigationParameter + $ += +% &! +navigationParameter +' : +; +: ; +this +  +. +  + PageState +  += +  + pageState + & +; +& ' +} +  +} +  +public + + +class +  +SaveStateEventArgs + # +: +$ % + EventArgs +& / +{ +  +public +  + +Dictionary +  +< +  +string +  +, + ! +Object +" ( +> +( ) + PageState +* 3 +{ +4 5 +get +6 9 +; +9 : +private +; B +set +C F +; +F G +} +H I +public +  +SaveStateEventArgs + ! +( +! " + +Dictionary +" , +< +, - +string +- 3 +, +3 4 +Object +5 ; +> +; < + pageState += F +) +F G +: +  +base +  +( +  +) +  +{ +  +this +  +. +  + PageState +  += +  + pageState + & +; +& ' +} +  +} +  +}  +PC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NotifyPropertyChangedBase.cs + namespace  + ModernKeePass +  +.  +Common  +{  +public + +class % +NotifyPropertyChangedBase * +:+ ," +INotifyPropertyChanged- C +{  +public    +event   ' +PropertyChangedEventHandler   0 +PropertyChanged  1 @ +;  @ A + protected    +void    +OnPropertyChanged   ( +(  ( ) +string  ) / + propertyName  0 < +=  = > +$str  ? A +)  A B +{    +PropertyChanged    +?    +.    +Invoke   # +(  # $ +this  $ ( +,  ( ) +new  * -$ +PropertyChangedEventArgs  . F +(  F G + propertyName  G S +)  S T +)  T U +;  U V +}  + protected  +bool  + SetProperty " +<" # +T# $ +>$ % +(% & +ref& ) +T* + +property, 4 +,4 5 +T6 7 +value8 = +,= > +[? @ +CallerMemberName@ P +]P Q +stringR X + propertyNameY e +=f g +$strh j +)j k +{  +if  +(  +EqualityComparer  +< ! +T! " +>" # +.# $ +Default$ + +.+ , +Equals, 2 +(2 3 +property3 ; +,; < +value= B +)B C +)C D +{  +return  +false  +;  +}  +property  +=  +value  +;  +OnPropertyChanged  +(  + propertyName * +)* + +;+ , +return  +true  +;  +}  +}  +} ` +KC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ObservableDictionary.cs + namespace  + ModernKeePass +  +.  +Common  +{  +public   + +class    +ObservableDictionary   % +:  & ' +IObservableMap  ( 6 +<  6 7 +string  7 = +,  = > +object  ? E +>  E F +{    +private  +class 0 +$ObservableDictionaryChangedEventArgs : +:; < +IMapChangedEventArgs= Q +<Q R +stringR X +>X Y +{  +public 0 +$ObservableDictionaryChangedEventArgs 7 +(7 8 +CollectionChange8 H +changeI O +,O P +stringQ W +keyX [ +)[ \ +{  +this  +.  +CollectionChange % +=& ' +change( . +;. / +this  +.  +Key  +=  +key  +;  +}  +public  +CollectionChange # +CollectionChange$ 4 +{5 6 +get7 : +;: ; +private< C +setD G +;G H +}I J +public  +string  +Key  +{  +get # +;# $ +private% , +set- 0 +;0 1 +}2 3 +}  +private  + +Dictionary  +<  +string ! +,! " +object# ) +>) * + _dictionary+ 6 +=7 8 +new9 < + +Dictionary= G +<G H +stringH N +,N O +objectP V +>V W +(W X +)X Y +;Y Z +public  +event " +MapChangedEventHandler + +<+ , +string, 2 +,2 3 +object4 : +>: ; + +MapChanged< F +;F G +private  +void  +InvokeMapChanged % +(% & +CollectionChange& 6 +change7 = +,= > +string? E +keyF I +)I J +{  +var  + eventHandler  +=  + +MapChanged ) +;) * +if    +(    + eventHandler    +!=    +null   $ +)  $ % +{!!  + eventHandler""  +(""  +this"" ! +,""! " +new""# &0 +$ObservableDictionaryChangedEventArgs""' K +(""K L +change""L R +,""R S +key""T W +)""W X +)""X Y +;""Y Z +}##  +}$$  +public&&  +void&&  +Add&&  +(&&  +string&&  +key&& " +,&&" # +object&&$ * +value&&+ 0 +)&&0 1 +{''  +this((  +.((  + _dictionary((  +.((  +Add((  +((( ! +key((! $ +,(($ % +value((& + +)((+ , +;((, - +this))  +.))  +InvokeMapChanged)) ! +())! " +CollectionChange))" 2 +.))2 3 + ItemInserted))3 ? +,))? @ +key))A D +)))D E +;))E F +}**  +public,,  +void,,  +Add,,  +(,,  + KeyValuePair,, $ +<,,$ % +string,,% + +,,,+ , +object,,- 3 +>,,3 4 +item,,5 9 +),,9 : +{--  +this..  +...  +Add..  +(..  +item..  +...  +Key..  +,..  +item.. # +...# $ +Value..$ ) +)..) * +;..* + +}//  +public11  +void11  +AddRange11  +(11  + IEnumerable11 ( +<11( ) + KeyValuePair11) 5 +<115 6 +string116 < +,11< = +object11> D +>11D E +>11E F +values11G M +)11M N +{22  +foreach33  +(33  +var33  +value33  +in33 ! +values33" ( +)33( ) +{44  +Add55  +(55  +value55  +)55  +;55  +}66  +}77  +public99  +bool99  +Remove99  +(99  +string99 ! +key99" % +)99% & +{::  +if;;  +(;;  +this;;  +.;;  + _dictionary;;  +.;; ! +Remove;;! ' +(;;' ( +key;;( + +);;+ , +);;, - +{<<  +this==  +.==  +InvokeMapChanged== % +(==% & +CollectionChange==& 6 +.==6 7 + ItemRemoved==7 B +,==B C +key==D G +)==G H +;==H I +return>>  +true>>  +;>>  +}??  +return@@  +false@@  +;@@  +}AA  +publicCC  +boolCC  +RemoveCC  +(CC  + KeyValuePairCC ' +<CC' ( +stringCC( . +,CC. / +objectCC0 6 +>CC6 7 +itemCC8 < +)CC< = +{DD  +objectEE  + currentValueEE  +;EE  +ifFF  +(FF  +thisFF  +.FF  + _dictionaryFF  +.FF ! + TryGetValueFF! , +(FF, - +itemFF- 1 +.FF1 2 +KeyFF2 5 +,FF5 6 +outFF7 : + currentValueFF; G +)FFG H +&&FFI K +ObjectGG  +.GG  +EqualsGG  +(GG  +itemGG " +.GG" # +ValueGG# ( +,GG( ) + currentValueGG* 6 +)GG6 7 +&&GG8 : +thisGG; ? +.GG? @ + _dictionaryGG@ K +.GGK L +RemoveGGL R +(GGR S +itemGGS W +.GGW X +KeyGGX [ +)GG[ \ +)GG\ ] +{HH  +thisII  +.II  +InvokeMapChangedII % +(II% & +CollectionChangeII& 6 +.II6 7 + ItemRemovedII7 B +,IIB C +itemIID H +.IIH I +KeyIII L +)IIL M +;IIM N +returnJJ  +trueJJ  +;JJ  +}KK  +returnLL  +falseLL  +;LL  +}MM  +publicOO  +objectOO  +thisOO  +[OO  +stringOO ! +keyOO" % +]OO% & +{PP  +getQQ  +{RR  +returnSS  +thisSS  +.SS  + _dictionarySS ' +[SS' ( +keySS( + +]SS+ , +;SS, - +}TT  +setUU  +{VV  +thisWW  +.WW  + _dictionaryWW  +[WW ! +keyWW! $ +]WW$ % +=WW& ' +valueWW( - +;WW- . +thisXX  +.XX  +InvokeMapChangedXX % +(XX% & +CollectionChangeXX& 6 +.XX6 7 + ItemChangedXX7 B +,XXB C +keyXXD G +)XXG H +;XXH I +}YY  +}ZZ  +public\\  +void\\  +Clear\\  +(\\  +)\\  +{]]  +var^^  + priorKeys^^  +=^^  +this^^  +.^^ ! + _dictionary^^! , +.^^, - +Keys^^- 1 +.^^1 2 +ToArray^^2 9 +(^^9 : +)^^: ; +;^^; < +this__  +.__  + _dictionary__  +.__  +Clear__ " +(__" # +)__# $ +;__$ % +foreach``  +(``  +var``  +key``  +in``  + priorKeys`` ) +)``) * +{aa  +thisbb  +.bb  +InvokeMapChangedbb % +(bb% & +CollectionChangebb& 6 +.bb6 7 + ItemRemovedbb7 B +,bbB C +keybbD G +)bbG H +;bbH I +}cc  +}dd  +publicff  + ICollectionff  +<ff  +stringff ! +>ff! " +Keysff# ' +{gg  +gethh  +{hh  +returnhh  +thishh  +.hh  + _dictionaryhh ) +.hh) * +Keyshh* . +;hh. / +}hh0 1 +}ii  +publickk  +boolkk  + ContainsKeykk  +(kk  +stringkk & +keykk' * +)kk* + +{ll  +returnmm  +thismm  +.mm  + _dictionarymm # +.mm# $ + ContainsKeymm$ / +(mm/ 0 +keymm0 3 +)mm3 4 +;mm4 5 +}nn  +publicpp  +boolpp  + TryGetValuepp  +(pp  +stringpp & +keypp' * +,pp* + +outpp, / +objectpp0 6 +valuepp7 < +)pp< = +{qq  +returnrr  +thisrr  +.rr  + _dictionaryrr # +.rr# $ + TryGetValuerr$ / +(rr/ 0 +keyrr0 3 +,rr3 4 +outrr5 8 +valuerr9 > +)rr> ? +;rr? @ +}ss  +publicuu  + ICollectionuu  +<uu  +objectuu ! +>uu! " +Valuesuu# ) +{vv  +getww  +{ww  +returnww  +thisww  +.ww  + _dictionaryww ) +.ww) * +Valuesww* 0 +;ww0 1 +}ww2 3 +}xx  +publiczz  +boolzz  +Containszz  +(zz  + KeyValuePairzz ) +<zz) * +stringzz* 0 +,zz0 1 +objectzz2 8 +>zz8 9 +itemzz: > +)zz> ? +{{{  +return||  +this||  +.||  + _dictionary|| # +.||# $ +Contains||$ , +(||, - +item||- 1 +)||1 2 +;||2 3 +}}}  +public  +int  +Count  +{ +  +get +  +{ +  +return +  +this +  +. +  + _dictionary + ) +. +) * +Count +* / +; +/ 0 +} +1 2 +} +  +public +  +bool +  + +IsReadOnly +  +{ +  +get +  +{ +  +return +  +false +  +; +  +} + ! +} +  +public +  + IEnumerator +  +< +  + KeyValuePair + ' +< +' ( +string +( . +, +. / +object +0 6 +> +6 7 +> +7 8 + GetEnumerator +9 F +( +F G +) +G H +{ +  +return +  +this +  +. +  + _dictionary + # +. +# $ + GetEnumerator +$ 1 +( +1 2 +) +2 3 +; +3 4 +} +  +System +  +. +  + Collections +  +. +  + IEnumerator + & +System +' - +. +- . + Collections +. 9 +. +9 : + IEnumerable +: E +. +E F + GetEnumerator +F S +( +S T +) +T U +{ +  +return +  +this +  +. +  + _dictionary + # +. +# $ + GetEnumerator +$ 1 +( +1 2 +) +2 3 +; +3 4 +} +  +public +  +void +  +CopyTo +  +( +  + KeyValuePair + ' +< +' ( +string +( . +, +. / +object +0 6 +> +6 7 +[ +7 8 +] +8 9 +array +: ? +, +? @ +int +A D + +arrayIndex +E O +) +O P +{ +  +int +  + arraySize +  += +  +array + ! +. +! " +Length +" ( +; +( ) +foreach +  +( +  +var +  +pair +  +in +  +this +! % +. +% & + _dictionary +& 1 +) +1 2 +{ +  +if +  +( +  + +arrayIndex +  +>= + ! + arraySize +" + +) ++ , +break +- 2 +; +2 3 +array +  +[ +  + +arrayIndex +  +++ + " +] +" # += +$ % +pair +& * +; +* + +} +  +} +  +} +  +}  +CC:\Sources\Other\ModernKeePass\ModernKeePass\Common\RelayCommand.cs + namespace  + ModernKeePass +  +.  +Common  +{   +public + +class  + RelayCommand  +:  +ICommand ( +{  +private  +readonly  +Action  +_execute ( +;( ) +private  +readonly  +Func  +<  +bool " +>" # + _canExecute$ / +;/ 0 +public  +event  + EventHandler ! +CanExecuteChanged" 3 +;3 4 +public  + RelayCommand  +(  +Action " +execute# * +)* + +:    +this    +(    +execute    +,    +null    +)   ! +{!!  +}""  +public))  + RelayCommand))  +())  +Action)) " +execute))# * +,))* + +Func)), 0 +<))0 1 +bool))1 5 +>))5 6 + +canExecute))7 A +)))A B +{**  +if++  +(++  +execute++  +==++  +null++  +)++  +throw,,  +new,, ! +ArgumentNullException,, / +(,,/ 0 +$str,,0 9 +),,9 : +;,,: ; +_execute--  +=--  +execute--  +;--  + _canExecute..  +=..  + +canExecute.. $ +;..$ % +}//  +public88  +bool88  + +CanExecute88  +(88  +object88 % + parameter88& / +)88/ 0 +{99  +return::  + _canExecute::  +==:: ! +null::" & +?::' ( +true::) - +:::. / + _canExecute::0 ; +(::; < +)::< = +;::= > +};;  +publicCC  +voidCC  +ExecuteCC  +(CC  +objectCC " + parameterCC# , +)CC, - +{DD  +_executeEE  +(EE  +)EE  +;EE  +}FF  +publicMM  +voidMM " +RaiseCanExecuteChangedMM * +(MM* + +)MM+ , +{NN  +varOO  +handlerOO  +=OO  +CanExecuteChangedOO + +;OO+ , +ifPP  +(PP  +handlerPP  +!=PP  +nullPP  +)PP  +{QQ  +handlerRR  +(RR  +thisRR  +,RR  + EventArgsRR ' +.RR' ( +EmptyRR( - +)RR- . +;RR. / +}SS  +}TT  +}UU  +}VV ‹ +HC:\Sources\Other\ModernKeePass\ModernKeePass\Common\SuspensionManager.cs + namespace  + ModernKeePass +  +.  +Common  +{  +internal  +sealed  +class  +SuspensionManager + +{  +private  +static  + +Dictionary ! +<! " +string" ( +,( ) +object* 0 +>0 1 + _sessionState2 ? +=@ A +newB E + +DictionaryF P +<P Q +stringQ W +,W X +objectY _ +>_ ` +(` a +)a b +;b c +private  +static  +List  +<  +Type  +> ! + _knownTypes" - +=. / +new0 3 +List4 8 +<8 9 +Type9 = +>= > +(> ? +)? @ +;@ A +private  +const  +string  +sessionStateFilename 1 +=2 3 +$str4 G +;G H +public$$  +static$$  + +Dictionary$$  +<$$ ! +string$$! ' +,$$' ( +object$$) / +>$$/ 0 + SessionState$$1 = +{%%  +get&&  +{&&  +return&&  + _sessionState&& & +;&&& ' +}&&( ) +}''  +public..  +static..  +List..  +<..  +Type..  +>..  + +KnownTypes..! + +{//  +get00  +{00  +return00  + _knownTypes00 $ +;00$ % +}00& ' +}11  +public::  +static::  +async::  +Task::  + SaveAsync::! * +(::* + +)::+ , +{;;  +try<<  +{==  +foreach??  +(??  +var??  +weakFrameReference?? / +in??0 2 +_registeredFrames??3 D +)??D E +{@@  +FrameAA  +frameAA  +;AA  +ifBB  +(BB  +weakFrameReferenceBB * +.BB* + + TryGetTargetBB+ 7 +(BB7 8 +outBB8 ; +frameBB< A +)BBA B +)BBB C +{CC $ +SaveFrameNavigationStateDD 0 +(DD0 1 +frameDD1 6 +)DD6 7 +;DD7 8 +}EE  +}FF  + MemoryStreamJJ  + sessionDataJJ ( +=JJ) * +newJJ+ . + MemoryStreamJJ/ ; +(JJ; < +)JJ< = +;JJ= >" +DataContractSerializerKK & + +serializerKK' 1 +=KK2 3 +newKK4 7" +DataContractSerializerKK8 N +(KKN O +typeofKKO U +(KKU V + +DictionaryKKV ` +<KK` a +stringKKa g +,KKg h +objectKKi o +>KKo p +)KKp q +,KKq r + _knownTypesKKs ~ +)KK~  +; KK  + +serializerLL  +.LL  + WriteObjectLL & +(LL& ' + sessionDataLL' 2 +,LL2 3 + _sessionStateLL4 A +)LLA B +;LLB C + StorageFileOO  +fileOO  +=OO! " +awaitOO# ( +ApplicationDataOO) 8 +.OO8 9 +CurrentOO9 @ +.OO@ A + LocalFolderOOA L +.OOL M +CreateFileAsyncOOM \ +(OO\ ] +sessionStateFilenameOO] q +,OOq r$ +CreationCollisionOption OOs  +. +OO  +ReplaceExisting +OO  +) +OO  +; +OO  +usingPP  +(PP  +StreamPP  + +fileStreamPP ( +=PP) * +awaitPP+ 0 +filePP1 5 +.PP5 6# +OpenStreamForWriteAsyncPP6 M +(PPM N +)PPN O +)PPO P +{QQ  + sessionDataRR  +.RR  +SeekRR $ +(RR$ % +$numRR% & +,RR& ' + +SeekOriginRR( 2 +.RR2 3 +BeginRR3 8 +)RR8 9 +;RR9 : +awaitSS  + sessionDataSS % +.SS% & + CopyToAsyncSS& 1 +(SS1 2 + +fileStreamSS2 < +)SS< = +;SS= > +}TT  +}UU  +catchVV  +(VV  + ExceptionVV  +eVV  +)VV  +{WW  +throwXX  +newXX & +SuspensionManagerExceptionXX 4 +(XX4 5 +eXX5 6 +)XX6 7 +;XX7 8 +}YY  +}ZZ  +publicgg  +staticgg  +asyncgg  +Taskgg  + RestoreAsyncgg! - +(gg- . +Stringgg. 4 +sessionBaseKeygg5 C +=ggD E +nullggF J +)ggJ K +{hh  + _sessionStateii  +=ii  +newii  + +Dictionaryii * +<ii* + +Stringii+ 1 +,ii1 2 +Objectii3 9 +>ii9 : +(ii: ; +)ii; < +;ii< = +trykk  +{ll  + StorageFilenn  +filenn  +=nn! " +awaitnn# ( +ApplicationDatann) 8 +.nn8 9 +Currentnn9 @ +.nn@ A + LocalFoldernnA L +.nnL M + GetFileAsyncnnM Y +(nnY Z +sessionStateFilenamennZ n +)nnn o +;nno p +usingoo  +(oo  + IInputStreamoo # +inStreamoo$ , +=oo- . +awaitoo/ 4 +fileoo5 9 +.oo9 :# +OpenSequentialReadAsyncoo: Q +(ooQ R +)ooR S +)ooS T +{pp " +DataContractSerializerrr * + +serializerrr+ 5 +=rr6 7 +newrr8 ;" +DataContractSerializerrr< R +(rrR S +typeofrrS Y +(rrY Z + +DictionaryrrZ d +<rrd e +stringrre k +,rrk l +objectrrm s +>rrs t +)rrt u +,rru v + _knownTypes rrw  +) +rr  +; +rr  + _sessionStatess ! +=ss" # +(ss$ % + +Dictionaryss% / +<ss/ 0 +stringss0 6 +,ss6 7 +objectss8 > +>ss> ? +)ss? @ + +serializerss@ J +.ssJ K + +ReadObjectssK U +(ssU V +inStreamssV ^ +.ss^ _ +AsStreamForReadss_ n +(ssn o +)sso p +)ssp q +;ssq r +}tt  +foreachww  +(ww  +varww  +weakFrameReferenceww / +inww0 2 +_registeredFramesww3 D +)wwD E +{xx  +Frameyy  +frameyy  +;yy  +ifzz  +(zz  +weakFrameReferencezz * +.zz* + + TryGetTargetzz+ 7 +(zz7 8 +outzz8 ; +framezz< A +)zzA B +&&zzC E +(zzF G +stringzzG M +)zzM N +framezzN S +.zzS T +GetValuezzT \ +(zz\ ]' +FrameSessionBaseKeyPropertyzz] x +)zzx y +==zzz | +sessionBaseKey zz}  +) +zz  +{{{  +frame||  +.||  + +ClearValue|| ( +(||( )% +FrameSessionStateProperty||) B +)||B C +;||C D' +RestoreFrameNavigationState}} 3 +(}}3 4 +frame}}4 9 +)}}9 : +;}}: ; +}~~  +}  +} +  +catch +  +( +  + Exception +  +e +  +) +  +{ +  +throw +  +new + ( +SuspensionManagerException + 4 +( +4 5 +e +5 6 +) +6 7 +; +7 8 +} +  +} +  +private +  +static +  +DependencyProperty + )* +FrameSessionStateKeyProperty +* F += +G H +DependencyProperty +  +. +  +RegisterAttached + / +( +/ 0 +$str +0 G +, +G H +typeof +I O +( +O P +String +P V +) +V W +, +W X +typeof +Y _ +( +_ ` +SuspensionManager +` q +) +q r +, +r s +null +t x +) +x y +; +y z +private +  +static +  +DependencyProperty + )) +FrameSessionBaseKeyProperty +* E += +F G +DependencyProperty +  +. +  +RegisterAttached + / +( +/ 0 +$str +0 L +, +L M +typeof +N T +( +T U +String +U [ +) +[ \ +, +\ ] +typeof +^ d +( +d e +SuspensionManager +e v +) +v w +, +w x +null +y } +) +} ~ +; +~  +private +  +static +  +DependencyProperty + )' +FrameSessionStateProperty +* C += +D E +DependencyProperty +  +. +  +RegisterAttached + / +( +/ 0 +$str +0 D +, +D E +typeof +F L +( +L M + +Dictionary +M W +< +W X +String +X ^ +, +^ _ +Object +` f +> +f g +) +g h +, +h i +typeof +j p +( +p q +SuspensionManager q  +)   +,   +null   +)   +;   +private +  +static +  +List +  +< +  + WeakReference + ) +< +) * +Frame +* / +> +/ 0 +> +0 1 +_registeredFrames +2 C += +D E +new +F I +List +J N +< +N O + WeakReference +O \ +< +\ ] +Frame +] b +> +b c +> +c d +( +d e +) +e f +; +f g +public +  +static +  +void +  + RegisterFrame + ( +( +( ) +Frame +) . +frame +/ 4 +, +4 5 +String +6 < +sessionStateKey += L +, +L M +String +N T +sessionBaseKey +U c += +d e +null +f j +) +j k +{ +  +if +  +( +  +frame +  +. +  +GetValue +  +( + * +FrameSessionStateKeyProperty + ; +) +; < +!= += ? +null +@ D +) +D E +{ +  +throw +  +new + ' +InvalidOperationException + 3 +( +3 4 +$str +4 l +) +l m +; +m n +} +  +if +  +( +  +frame +  +. +  +GetValue +  +( + ' +FrameSessionStateProperty + 8 +) +8 9 +!= +: < +null += A +) +A B +{ +  +throw +  +new + ' +InvalidOperationException + 3 +( +3 4 +$str 4  +)   +;   +} +  +if +  +( +  +! +  +string +  +. +  + IsNullOrEmpty + % +( +% & +sessionBaseKey +& 4 +) +4 5 +) +5 6 +{ +  +frame +  +. +  +SetValue +  +( + ) +FrameSessionBaseKeyProperty + : +, +: ; +sessionBaseKey +< J +) +J K +; +K L +sessionStateKey +  += + ! +sessionBaseKey +" 0 ++ +1 2 +$str +3 6 ++ +7 8 +sessionStateKey +9 H +; +H I +} +  +frame +  +. +  +SetValue +  +( + * +FrameSessionStateKeyProperty + 7 +, +7 8 +sessionStateKey +9 H +) +H I +; +I J +_registeredFrames +  +. +  +Add + ! +( +! " +new +" % + WeakReference +& 3 +< +3 4 +Frame +4 9 +> +9 : +( +: ; +frame +; @ +) +@ A +) +A B +; +B C) +RestoreFrameNavigationState + ' +( +' ( +frame +( - +) +- . +; +. / +} +  +public +  +static +  +void +  +UnregisterFrame + * +( +* + +Frame ++ 0 +frame +1 6 +) +6 7 +{ +  + SessionState +  +. +  +Remove +  +( +  +( + ! +String +! ' +) +' ( +frame +( - +. +- . +GetValue +. 6 +( +6 7* +FrameSessionStateKeyProperty +7 S +) +S T +) +T U +; +U V +_registeredFrames +  +. +  + RemoveAll + ' +( +' ( +( +( ) +weakFrameReference +) ; +) +; < +=> += ? +{ +  +Frame +  + testFrame +  +; +  +return +  +! +  +weakFrameReference + * +. +* + + TryGetTarget ++ 7 +( +7 8 +out +8 ; + testFrame +< E +) +E F +|| +G I + testFrame +J S +== +T V +frame +W \ +; +\ ] +} +  +) +  +; +  +} +  +public +  +static +  + +Dictionary +  +< + ! +String +! ' +, +' ( +Object +) / +> +/ 0" +SessionStateForFrame +1 E +( +E F +Frame +F K +frame +L Q +) +Q R +{ +  +var +  + +frameState +  += +  +( +  + +Dictionary + ( +< +( ) +String +) / +, +/ 0 +Object +1 7 +> +7 8 +) +8 9 +frame +9 > +. +> ? +GetValue +? G +( +G H' +FrameSessionStateProperty +H a +) +a b +; +b c +if +  +( +  + +frameState +  +== +  +null + " +) +" # +{ +  +var +  +frameSessionKey + # += +$ % +( +& ' +String +' - +) +- . +frame +. 3 +. +3 4 +GetValue +4 < +( +< =* +FrameSessionStateKeyProperty += Y +) +Y Z +; +Z [ +if +  +( +  +frameSessionKey + # +!= +$ & +null +' + +) ++ , +{ +  +if +  +( +  +! +  + _sessionState + & +. +& ' + ContainsKey +' 2 +( +2 3 +frameSessionKey +3 B +) +B C +) +C D +{ +  + _sessionState + % +[ +% & +frameSessionKey +& 5 +] +5 6 += +7 8 +new +9 < + +Dictionary += G +< +G H +String +H N +, +N O +Object +P V +> +V W +( +W X +) +X Y +; +Y Z +} +  + +frameState +  += +  +( +! " + +Dictionary +" , +< +, - +String +- 3 +, +3 4 +Object +5 ; +> +; < +) +< = + _sessionState += J +[ +J K +frameSessionKey +K Z +] +Z [ +; +[ \ +} +  +else +  +{ +  + +frameState +  += +  +new +! $ + +Dictionary +% / +< +/ 0 +String +0 6 +, +6 7 +Object +8 > +> +> ? +( +? @ +) +@ A +; +A B +} +  +frame +  +. +  +SetValue +  +( + ' +FrameSessionStateProperty + 8 +, +8 9 + +frameState +: D +) +D E +; +E F +} +  +return +  + +frameState +  +; +  +} +  +private +  +static +  +void + ) +RestoreFrameNavigationState + 7 +( +7 8 +Frame +8 = +frame +> C +) +C D +{ +  +var +  + +frameState +  += + " +SessionStateForFrame + 1 +( +1 2 +frame +2 7 +) +7 8 +; +8 9 +if +  +( +  + +frameState +  +. +  + ContainsKey + & +( +& ' +$str +' 3 +) +3 4 +) +4 5 +{ +  +frame +  +. +  +SetNavigationState + ( +( +( ) +( +) * +String +* 0 +) +0 1 + +frameState +1 ; +[ +; < +$str +< H +] +H I +) +I J +; +J K +} +  +} +  +private +  +static +  +void + & +SaveFrameNavigationState + 4 +( +4 5 +Frame +5 : +frame +; @ +) +@ A +{ +  +var +  + +frameState +  += + " +SessionStateForFrame + 1 +( +1 2 +frame +2 7 +) +7 8 +; +8 9 + +frameState +  +[ +  +$str + # +] +# $ += +% & +frame +' , +. +, - +GetNavigationState +- ? +( +? @ +) +@ A +; +A B +} +  +} +  +public + + +class + ( +SuspensionManagerException + + +: +, - + Exception +. 7 +{ +  +public + ( +SuspensionManagerException + ) +( +) * +) +* + +{ +  +} +  +public + ( +SuspensionManagerException + ) +( +) * + Exception +* 3 +e +4 5 +) +5 6 +: +  +base +  +( +  +$str + - +, +- . +e +/ 0 +) +0 1 +{ +  +} +  +} +  +} - +GC:\Sources\Other\ModernKeePass\ModernKeePass\Services\LicenseService.cs + namespace  + ModernKeePass +  +.  +Services  +{  +public   + +class    +LicenseService    +:   ! +SingletonServiceBase  " 6 +<  6 7 +LicenseService  7 E +>  E F +,  F G +ILicenseService  H W +{ + +  +public    +enum    +PurchaseResult   " +{    + Succeeded    +,    +NothingToFulfill  +,  +PurchasePending  +,  +PurchaseReverted  +,  + ServerError  +,  + NotPurchased  +,  +AlreadyPurchased  +}  +public  +IReadOnlyDictionary " +<" # +string# ) +,) * +ProductListing+ 9 +>9 : +Products; C +{D E +getF I +;I J +}K L +private  +readonly  +HashSet  +< ! +Guid! % +>% &# +_consumedTransactionIds' > +=? @ +newA D +HashSetE L +<L M +GuidM Q +>Q R +(R S +)S T +;T U +public  +LicenseService  +(  +)  +{  +var  +listing  +=  + +CurrentApp $ +.$ %' +LoadListingInformationAsync% @ +(@ A +)A B +.B C + +GetAwaiterC M +(M N +)N O +.O P + GetResultP Y +(Y Z +)Z [ +;[ \ +Products  +=  +listing  +.  +ProductListings . +;. / +}  +public!!  +async!!  +Task!!  +<!!  +int!!  +>!!  +Purchase!! ' +(!!' ( +string!!( . +addOn!!/ 4 +)!!4 5 +{""  +var##  +purchaseResults##  +=## ! +await##" ' + +CurrentApp##( 2 +.##2 3' +RequestProductPurchaseAsync##3 N +(##N O +addOn##O T +)##T U +;##U V +switch$$  +($$  +purchaseResults$$ # +.$$# $ +Status$$$ * +)$$* + +{%%  +case&& ! +ProductPurchaseStatus&& * +.&&* + + Succeeded&&+ 4 +:&&4 5 +GrantFeatureLocally'' ' +(''' ( +purchaseResults''( 7 +.''7 8 + TransactionId''8 E +)''E F +;''F G +return((  +(((  +int((  +)((  +await((! &" +ReportFulfillmentAsync((' = +(((= > +purchaseResults((> M +.((M N + TransactionId((N [ +,(([ \ +addOn((] b +)((b c +;((c d +case)) ! +ProductPurchaseStatus)) * +.))* + + NotFulfilled))+ 7 +:))7 8 +if,,  +(,,  +!,,  +IsLocallyFulfilled,, + +(,,+ , +purchaseResults,,, ; +.,,; < + TransactionId,,< I +),,I J +),,J K +{--  +GrantFeatureLocally.. + +(..+ , +purchaseResults.., ; +...; < + TransactionId..< I +)..I J +;..J K +}//  +return00  +(00  +int00  +)00  +await00! &" +ReportFulfillmentAsync00' = +(00= > +purchaseResults00> M +.00M N + TransactionId00N [ +,00[ \ +addOn00] b +)00b c +;00c d +case11 ! +ProductPurchaseStatus11 * +.11* + + NotPurchased11+ 7 +:117 8 +return22  +(22  +int22  +)22  +PurchaseResult22! / +.22/ 0 + NotPurchased220 < +;22< = +case33 ! +ProductPurchaseStatus33 * +.33* + +AlreadyPurchased33+ ; +:33; < +return44  +(44  +int44  +)44  +PurchaseResult44! / +.44/ 0 +AlreadyPurchased440 @ +;44@ A +default55  +:55  +throw66  +new66 ' +ArgumentOutOfRangeException66 9 +(669 : +)66: ; +;66; < +}77  +}88  +private::  +async::  +Task::  +<::  +PurchaseResult:: ) +>::) *" +ReportFulfillmentAsync::+ A +(::A B +Guid::B F + transactionId::G T +,::T U +string::V \ + productName::] h +)::h i +{;;  +var<<  +result<<  +=<<  +await<<  + +CurrentApp<< ) +.<<) *, + ReportConsumableFulfillmentAsync<<* J +(<<J K + productName<<K V +,<<V W + transactionId<<X e +)<<e f +;<<f g +return==  +(==  +PurchaseResult== " +)==" # +result==$ * +;==* + +}>>  +private@@  +void@@  +GrantFeatureLocally@@ ( +(@@( ) +Guid@@) - + transactionId@@. ; +)@@; < +{AA # +_consumedTransactionIdsBB # +.BB# $ +AddBB$ ' +(BB' ( + transactionIdBB( 5 +)BB5 6 +;BB6 7 +}CC  +privateEE  +boolEE  +IsLocallyFulfilledEE ' +(EE' ( +GuidEE( , + transactionIdEE- : +)EE: ; +{FF  +returnGG # +_consumedTransactionIdsGG * +.GG* + +ContainsGG+ 3 +(GG3 4 + transactionIdGG4 A +)GGA B +;GGB C +}HH  +}II  +}JJ  +FC:\Sources\Other\ModernKeePass\ModernKeePass\Services\RecentService.cs + namespace   + ModernKeePass   +  +.    +Services    +{ + +  +public   + +class    + RecentService    +:    +SingletonServiceBase  ! 5 +<  5 6 + RecentService  6 C +>  C D +,  D E +IRecentService  F T +{    +private    +readonly   + +StorageItemMostRecentlyUsedList   8 +_mru  9 = +=  > ?) +StorageApplicationPermissions  @ ] +.  ] ^ +MostRecentlyUsedList  ^ r +;  r s +public  +int  + +EntryCount  +=>  +_mru! % +.% & +Entries& - +.- . +Count. 3 +;3 4 +public  +ObservableCollection # +<# $ + IRecentItem$ / +>/ 0 + GetAllFiles1 < +(< = +bool= A +removeIfNonExistantB U +=V W +trueX \ +)\ ] +{  +var  +result  +=  +new  +ObservableCollection 1 +<1 2 + IRecentItem2 = +>= > +(> ? +)? @ +;@ A +foreach  +(  +var  +entry  +in ! +_mru" & +.& ' +Entries' . +). / +{  +try  +{  +var  +file  +=  +_mru # +.# $ + GetFileAsync$ 0 +(0 1 +entry1 6 +.6 7 +Token7 < +,< = +AccessCacheOptions> P +.P Q$ +SuppressAccessTimeUpdateQ i +)i j +.j k + +GetAwaiterk u +(u v +)v w +.w x + GetResult x  +( +  +) +  +; +  +result  +.  +Add  +(  +new " + RecentItemVm# / +(/ 0 +entry0 5 +.5 6 +Token6 ; +,; < +entry= B +.B C +MetadataC K +,K L +fileM Q +)Q R +)R S +;S T +}  +catch  +(  + Exception  +) ! +{  +if  +(  +removeIfNonExistant + +)+ , +_mru- 1 +.1 2 +Remove2 8 +(8 9 +entry9 > +.> ? +Token? D +)D E +;E F +}  +}  +return    +result    +;    +}!!  +public##  +void##  +Add##  +(##  + IStorageItem## $ +file##% ) +,##) * +string##+ 1 +metadata##2 : +)##: ; +{$$  +_mru%%  +.%%  +Add%%  +(%%  +file%%  +,%%  +metadata%% # +)%%# $ +;%%$ % +}&&  +public((  +void((  +ClearAll((  +(((  +)((  +{))  +_mru**  +.**  +Clear**  +(**  +)**  +;**  +}++  +public--  +async--  +Task--  +<--  + IStorageItem-- & +>--& ' + GetFileAsync--( 4 +(--4 5 +string--5 ; +token--< A +)--A B +{..  +return//  +await//  +_mru//  +.//  + GetFileAsync// * +(//* + +token//+ 0 +)//0 1 +;//1 2 +}00  +}11  +}22  +IC:\Sources\Other\ModernKeePass\ModernKeePass\Services\ResourcesService.cs + namespace  + ModernKeePass +  +.  +Services  +{  +public + +class  +ResourcesService ! +:! " +IResourceService# 3 +{  +private  +const  +string  +ResourceFileName - +=. / +$str0 < +;< = +private    +readonly    +ResourceLoader   ' +_resourceLoader  ( 7 +=  8 9 +ResourceLoader  : H +.  H I +GetForCurrentView  I Z +(  Z [ +)  [ \ +;  \ ] +public    +string    +GetResourceValue   & +(  & ' +string  ' - +key  . 1 +)  1 2 +{    +var    +resource    +=    +_resourceLoader   * +.  * + + GetString  + 4 +(  4 5 +$"  5 7 +/  7 8 +{  8 9 +ResourceFileName  9 I +}  I J +/  J K +{  K L +key  L O +}  O P +"  P Q +)  Q R +;  R S +return  +resource  +;  +}  +}  +}  +HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SettingsService.cs + namespace  + ModernKeePass +  +.  +Services  +{  +public + +class  +SettingsService  +:! " +SingletonServiceBase# 7 +<7 8 +SettingsService8 G +>G H +,H I +ISettingsServiceJ Z +{    +private + +  +readonly + +  + IPropertySet + + % +_values + +& - += + +. / +ApplicationData + +0 ? +. + +? @ +Current + +@ G +. + +G H + LocalSettings + +H U +. + +U V +Values + +V \ +; + +\ ] +public    +T    + +GetSetting    +<    +T    +>    +(    +string   % +property  & . +,  . / +T  0 1 + defaultValue  2 > +=  ? @ +default  A H +(  H I +T  I J +)  J K +)  K L +{    +try  +{  +return  +(  +T  +)  +Convert ! +.! " + +ChangeType" , +(, - +_values- 4 +[4 5 +property5 = +]= > +,> ? +typeof@ F +(F G +TG H +)H I +)I J +;J K +}  +catch  +(  +InvalidCastException ' +)' ( +{  +return  + defaultValue # +;# $ +}  +}  +public  +void  + +PutSetting  +<  +T  +> ! +(! " +string" ( +property) 1 +,1 2 +T3 4 +value5 : +): ; +{  +if  +(  +_values  +.  + ContainsKey # +(# $ +property$ , +), - +)- . +_values  +[  +property  +] ! +=" # +value$ ) +;) * +else  +_values  +.  +Add  +(  +property % +,% & +value' , +), - +;- . +}  +}  +} . +NC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ToastNotificationHelper.cs + namespace  + ModernKeePass +  +.  +Common  +{   +public + + + +static + +  +class + + # +ToastNotificationHelper + + / +{    +public    +static    +void    +ShowMovedToast   ) +(  ) * + IPwEntity  * 3 +entity  4 : +,  : ; +string  < B +action  C I +,  I J +string  K Q +text  R V +)  V W +{    +var  + +entityType  +=  +entity # +is$ & +GroupVm' . +?/ 0 +$str1 8 +:9 : +$str; B +;B C +var  +notificationXml  += !$ +ToastNotificationManager" : +.: ; +GetTemplateContent; M +(M N +ToastTemplateTypeN _ +._ ` + ToastText02` k +)k l +;l m +var  + toastElements  +=  +notificationXml / +./ 0 +GetElementsByTagName0 D +(D E +$strE K +)K L +;L M + toastElements  +[  +$num  +]  +.  + AppendChild ( +(( ) +notificationXml) 8 +.8 9 +CreateTextNode9 G +(G H +$"H J +{J K +actionK Q +}Q R +{S T + +entityTypeT ^ +}^ _ +{` a +entitya g +.g h +Nameh l +}l m +"m n +)n o +)o p +;p q + toastElements  +[  +$num  +]  +.  + AppendChild ( +(( ) +notificationXml) 8 +.8 9 +CreateTextNode9 G +(G H +textH L +)L M +)M N +;N O +var  + toastNode  +=  +notificationXml + +.+ , +SelectSingleNode, < +(< = +$str= E +)E F +;F G +var  +launch  +=  +new  + +JsonObject ' +{  +{  +$str  +,  + JsonValue ( +.( ) +CreateStringValue) : +(: ; + +entityType; E +)E F +}F G +,G H +{  +$str  +,  + JsonValue & +.& ' +CreateStringValue' 8 +(8 9 +entity9 ? +.? @ +Id@ B +)B C +}C D +}  +;  +(  +(  + +XmlElement  +)  + toastNode " +)" # +?# $ +.$ % + SetAttribute% 1 +(1 2 +$str2 : +,: ; +launch< B +.B C + StringifyC L +(L M +)M N +)N O +;O P +var  +toast  +=  +new  +ToastNotification - +(- . +notificationXml. = +)= > +{  +ExpirationTime  +=  +DateTime! ) +.) * +Now* - +.- . + +AddSeconds. 8 +(8 9 +$num9 : +): ; +}  +; $ +ToastNotificationManager   $ +.  $ % +CreateToastNotifier  % 8 +(  8 9 +)  9 : +.  : ; +Show  ; ? +(  ? @ +toast  @ E +)  E F +;  F G +}!!  +public##  +static##  +void##  +ShowGenericToast## + +(##+ , +string##, 2 +title##3 8 +,##8 9 +string##: @ +text##A E +)##E F +{$$  +var%%  +notificationXml%%  +=%% !$ +ToastNotificationManager%%" : +.%%: ; +GetTemplateContent%%; M +(%%M N +ToastTemplateType%%N _ +.%%_ ` + ToastText02%%` k +)%%k l +;%%l m +var&&  + toastElements&&  +=&&  +notificationXml&& / +.&&/ 0 +GetElementsByTagName&&0 D +(&&D E +$str&&E K +)&&K L +;&&L M + toastElements''  +[''  +$num''  +]''  +.''  + AppendChild'' ( +(''( ) +notificationXml'') 8 +.''8 9 +CreateTextNode''9 G +(''G H +title''H M +)''M N +)''N O +;''O P + toastElements((  +[((  +$num((  +]((  +.((  + AppendChild(( ( +(((( ) +notificationXml(() 8 +.((8 9 +CreateTextNode((9 G +(((G H +text((H L +)((L M +)((M N +;((N O +var**  +toast**  +=**  +new**  +ToastNotification** - +(**- . +notificationXml**. = +)**= > +{++  +ExpirationTime,,  +=,,  +DateTime,,! ) +.,,) * +Now,,* - +.,,- . + +AddSeconds,,. 8 +(,,8 9 +$num,,9 : +),,: ; +}--  +;-- $ +ToastNotificationManager.. $ +...$ % +CreateToastNotifier..% 8 +(..8 9 +)..9 : +...: ; +Show..; ? +(..? @ +toast..@ E +)..E F +;..F G +}//  +public11  +static11  +void11  +ShowErrorToast11 ) +(11) * + Exception11* 3 + exception114 = +)11= > +{22  +ShowGenericToast33  +(33  + exception33 & +.33& ' +Source33' - +,33- . + exception33/ 8 +.338 9 +Message339 @ +)33@ A +;33A B +}44  +}55  +}66  +`C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DiscreteIntToSolidColorBrushConverter.cs + namespace  + ModernKeePass +  +.  + +Converters " +{  +public + +class 1 +%DiscreteIntToSolidColorBrushConverter 6 +:7 8 +IValueConverter9 H +{    +public + +  +object + +  +Convert + +  +( + +  +object + + $ +value + +% * +, + +* + +Type + +, 0 + +targetType + +1 ; +, + +; < +object + += C + parameter + +D M +, + +M N +string + +O U +language + +V ^ +) + +^ _ +{    +var    +status    +=    +System    +.    +Convert   ' +.  ' ( +ToInt32  ( / +(  / 0 +value  0 5 +)  5 6 +;  6 7 +switch    +(    +status    +)    +{  +case  +$num  +:  +return  +new " +SolidColorBrush# 2 +(2 3 +Colors3 9 +.9 : +Red: = +)= > +;> ? +case  +$num  +:  +return  +new " +SolidColorBrush# 2 +(2 3 +Colors3 9 +.9 : +Yellow: @ +)@ A +;A B +case  +$num  +:  +return  +new " +SolidColorBrush# 2 +(2 3 +Colors3 9 +.9 : +Green: ? +)? @ +;@ A +default  +:  +return  +new # +SolidColorBrush$ 3 +(3 4 +Colors4 : +.: ; +Black; @ +)@ A +;A B +}  +}  +public  +object  + ConvertBack ! +(! " +object" ( +value) . +,. / +Type0 4 + +targetType5 ? +,? @ +objectA G + parameterH Q +,Q R +stringS Y +languageZ b +)b c +{  +throw  +new # +NotImplementedException - +(- . +). / +;/ 0 +}  +}  +}  +[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\EmptyStringToVisibilityConverter.cs + namespace  + ModernKeePass +  +.  + +Converters " +{  +class , + EmptyStringToVisibilityConverter + * +:* + +IValueConverter, ; +{  +public    +object    +Convert    +(    +object   $ +value  % * +,  * + +Type  , 0 + +targetType  1 ; +,  ; < +object  = C + parameter  D M +,  M N +string  O U +language  V ^ +)  ^ _ +{ + +  +var    +text    +=    +value    +is    +string   & +?  ' ( +value  ) . +.  . / +ToString  / 7 +(  7 8 +)  8 9 +:  : ; +string  < B +.  B C +Empty  C H +;  H I +return    +string    +.    + IsNullOrEmpty   ' +(  ' ( +text  ( , +)  , - +?  . / + +Visibility  0 : +.  : ; + Collapsed  ; D +:  E F + +Visibility  G Q +.  Q R +Visible  R Y +;  Y Z +}    +public  +object  + ConvertBack ! +(! " +object" ( +value) . +,. / +Type0 4 + +targetType5 ? +,? @ +objectA G + parameterH Q +,Q R +stringS Y +languageZ b +)b c +{  +throw  +new # +NotImplementedException - +(- . +). / +;/ 0 +}  +}  +}  +QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\NullToBooleanConverter.cs + namespace  + ModernKeePass +  +.  + +Converters " +{  +public + +class " +NullToBooleanConverter ' +:( ) +IValueConverter* 9 +{  +public  +object  +Convert  +(  +object $ +value% * +,* + +Type, 0 + +targetType1 ; +,; < +object= C + parameterD M +,M N +stringO U +languageV ^ +)^ _ +{    +return + +  +value + +  +!= + +  +null + +  +; + + ! +}    +public    +object    + ConvertBack   ! +(  ! " +object  " ( +value  ) . +,  . / +Type  0 4 + +targetType  5 ? +,  ? @ +object  A G + parameter  H Q +,  Q R +string  S Y +language  Z b +)  b c +{  +throw  +new # +NotImplementedException - +(- . +). / +;/ 0 +}  +}  +}  +HC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\SaveException.cs + namespace  + ModernKeePass +  +.  + +Exceptions " +{  +public + +class  + SaveException  +:  + Exception! * +{  +public  +new  + Exception  +InnerException + +{, - +get. 1 +;1 2 +}3 4 +public    + SaveException    +(    + Exception   & + exception  ' 0 +)  0 1 +{ + +  +InnerException    +=    + exception   & +;  & ' +}    +}    +}  +SC:\Sources\Other\ModernKeePass\ModernKeePass\Extensions\DispatcherTaskExtensions.cs + namespace  + ModernKeePass +  +.  + +Extensions " +{  +public + +static  +class $ +DispatcherTaskExtensions 0 +{  +public    +static    +async    +Task    +<   ! +T  ! " +>  " # + RunTaskAsync  $ 0 +<  0 1 +T  1 2 +>  2 3 +(  3 4 +this  4 8 +CoreDispatcher  9 G + +dispatcher  H R +,  R S +Func + +  +< + +  +Task + +  +< + +  +T + +  +> + +  +> + +  +func + +  +, + + " +CoreDispatcherPriority + + 6 +priority + +7 ? += + +@ A" +CoreDispatcherPriority + +B X +. + +X Y +Normal + +Y _ +) + +_ ` +{    +var    +taskCompletionSource   $ +=  % & +new  ' * +TaskCompletionSource  + ? +<  ? @ +T  @ A +>  A B +(  B C +)  C D +;  D E +await    + +dispatcher    +.    +RunAsync   % +(  % & +priority  & . +,  . / +async  0 5 +(  6 7 +)  7 8 +=>  9 ; +{  +try  +{  +taskCompletionSource ( +.( ) + SetResult) 2 +(2 3 +await3 8 +func9 = +(= > +)> ? +)? @ +;@ A +}  +catch  +(  + Exception  +ex! # +)# $ +{  +taskCompletionSource ( +.( ) + SetException) 5 +(5 6 +ex6 8 +)8 9 +;9 : +}  +}  +)  +;  +return  +await  +taskCompletionSource - +.- . +Task. 2 +;2 3 +}  +public  +static  +async  +Task  + RunTaskAsync! - +(- . +this. 2 +CoreDispatcher3 A + +dispatcherB L +,L M +Func  +<  +Task  +>  +func  +, " +CoreDispatcherPriority 3 +priority4 < +== >" +CoreDispatcherPriority? U +.U V +NormalV \ +)\ ] +=>^ ` +await  + RunTaskAsync  +(  + +dispatcher ) +,) * +async+ 0 +(1 2 +)2 3 +=>4 6 +{7 8 +await9 > +func? C +(C D +)D E +;E F +returnG M +falseN S +;S T +}U V +,V W +priorityX ` +)` a +;a b +}  +}   +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IDatabaseService.cs + namespace  + ModernKeePass +  +.  + +Interfaces " +{   +public + + + + interface + +  +IDatabaseService + + % +{    +string    +Name    +{    +get    +;    +}    +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 3 +{4 5 +get6 9 +;9 : +set; > +;> ? +}@ A + KdfParameters  + KeyDerivation # +{$ % +get& ) +;) * +set+ . +;. / +}0 1 +bool  +IsOpen  +{  +get  +;  +}  +bool  + +IsFileOpen  +{  +get  +;  +}  +bool  +IsClosed  +{  +get  +;  +}  +bool  + +HasChanged  +{  +get  +;  +set " +;" # +}$ % +Task  +Open  +(  + CompositeKey  +key " +," # +bool$ ( + createNew) 2 +=3 4 +false5 : +): ; +;; < +Task  +ReOpen  +(  +)  +;  +void  +Save  +(  +)  +;  +void  +Save  +(  + StorageFile  +file " +)" # +;# $ +void  +CreateRecycleBin  +(  +string $ +title% * +)* + +;+ , +void    +AddDeletedItem    +(    +PwUuid   " +id  # % +)  % & +;  & ' +Task!!  +Close!!  +(!!  +bool!!  + releaseFile!! # +=!!$ % +true!!& * +)!!* + +;!!+ , +}""  +}##  +OC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IHasSelectableObject.cs + namespace  + ModernKeePass +  +.  + +Interfaces " +{  +public + + interface  +IHasSelectableObject ) +{  +ISelectableModel  + SelectedItem % +{& ' +get( + +;+ , +set- 0 +;0 1 +}2 3 +}  +}  +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISelectableModel.cs + namespace  + ModernKeePass +  +.  + +Interfaces " +{  +public + + interface  +ISelectableModel % +{  +bool  + +IsSelected  +{  +get  +;  +set " +;" # +}$ % +}  +} I +SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\BasePages\LayoutAwarePageBase.cs + namespace   + ModernKeePass   +  +.    +Views    +.    + BasePages   ' +{ + +  +public   + +class    +LayoutAwarePageBase   $ +:  $ % +Page  & * +{    +public  +NavigationHelper  +NavigationHelper 0 +{1 2 +get3 6 +;6 7 +}8 9 +public  +virtual  +ListView  +ListView ( +{) * +get+ . +;. / +set0 3 +;3 4 +}5 6 +public  +virtual  +CollectionViewSource + +ListViewSource, : +{; < +get= @ +;@ A +setB E +;E F +}G H +public  +virtual  +IHasSelectableObject + +Model, 1 +{2 3 +get4 7 +;7 8 +set9 < +;< = +}> ? +public  +LayoutAwarePageBase " +(" # +)# $ +{  +NavigationHelper  +=  +new " +NavigationHelper# 3 +(3 4 +this4 8 +)8 9 +;9 : +NavigationHelper  +.  + LoadState & ++=' )& +navigationHelper_LoadState* D +;D E +NavigationHelper  +.  + SaveState & ++=' )& +navigationHelper_SaveState* D +;D E +NavigationHelper    +.    + GoBackCommand   * +=  + , +new  - 0 + RelayCommand  1 = +(  = > +(  > ? +)  ? @ +=>  A C +GoBack  D J +(  J K +)  K L +,  L M +(  N O +)  O P +=>  Q S + CanGoBack  T ] +(  ] ^ +)  ^ _ +)  _ ` +;  ` a +Window$$  +.$$  +Current$$  +.$$  + SizeChanged$$ & ++=$$' ) +Window_SizeChanged$$* < +;$$< =! +InvalidateVisualState%% ! +(%%! " +)%%" # +;%%# $ +}&&  + protected((  +void(( % +ListView_SelectionChanged(( 0 +(((0 1 +object((1 7 +sender((8 > +,((> ?% +SelectionChangedEventArgs((@ Y +e((Z [ +)(([ \ +{))  +if//  +(//  +!// & +UsingLogicalPageNavigation// + +(//+ , +)//, - +)//- . +return/// 5 +;//5 6 +NavigationHelper00  +.00  + GoBackCommand00 * +.00* +" +RaiseCanExecuteChanged00+ A +(00A B +)00B C +;00C D! +InvalidateVisualState11 ! +(11! " +)11" # +;11# $ +}22  + protected??  +void?? & +navigationHelper_LoadState?? 1 +(??1 2 +object??2 8 +sender??9 ? +,??? @ +LoadStateEventArgs??A S +e??T U +)??U V +{@@  +ifDD  +(DD  +eDD  +.DD  + PageStateDD  +==DD  +nullDD # +)DD# $ +{EE  +ifHH  +(HH  +!HH & +UsingLogicalPageNavigationHH / +(HH/ 0 +)HH0 1 +)HH1 2 +{II  +ListViewSourceJJ " +.JJ" # +ViewJJ# ' +?JJ' ( +.JJ( ) +MoveCurrentToFirstJJ) ; +(JJ; < +)JJ< = +;JJ= > +}KK  +}LL  +elseMM  +{NN  +ifPP  +(PP  +ePP  +.PP  + PageStatePP  +.PP  + ContainsKeyPP + +(PP+ , +$strPP, : +)PP: ; +)PP; < +{QQ  +ListViewSourceRR " +.RR" # +ViewRR# ' +?RR' ( +.RR( ) + MoveCurrentToRR) 6 +(RR6 7 +eRR7 8 +.RR8 9 + PageStateRR9 B +[RRB C +$strRRC Q +]RRQ R +)RRR S +;RRS T +}SS  +}TT  +}UU  + protected__  +void__ & +navigationHelper_SaveState__ 1 +(__1 2 +object__2 8 +sender__9 ? +,__? @ +SaveStateEventArgs__A S +e__T U +)__U V +{``  +ifaa  +(aa  +ListViewSourceaa  +.aa  +Viewaa # +!=aa$ & +nullaa' + +)aa+ , +{bb  +ecc  +.cc  + PageStatecc  +[cc  +$strcc * +]cc* + +=cc, - +Modelcc. 3 +?cc3 4 +.cc4 5 + SelectedItemcc5 A +;ccA B +}dd  +}ee  + protectedpp  +constpp  +intpp - +!MinimumWidthForSupportingTwoPanespp = +=pp> ? +$numpp@ C +;ppC D + protectedww  +boolww & +UsingLogicalPageNavigationww 1 +(ww1 2 +)ww2 3 +{xx  +returnyy  +Windowyy  +.yy  +Currentyy ! +.yy! " +Boundsyy" ( +.yy( ) +Widthyy) . +<yy/ 0- +!MinimumWidthForSupportingTwoPanesyy1 R +;yyR S +}zz  + protected +  +void +  +Window_SizeChanged + ) +( +) * +object +* 0 +sender +1 7 +, +7 8 +Windows +9 @ +. +@ A +UI +A C +. +C D +Core +D H +. +H I( +WindowSizeChangedEventArgs +I c +e +d e +) +e f +{ + # +InvalidateVisualState + ! +( +! " +) +" # +; +# $ +} +  + protected +  +bool +  + CanGoBack +  +( + ! +) +! " +{ +  +if +  +( + ( +UsingLogicalPageNavigation + * +( +* + +) ++ , +&& +- / +ListView +0 8 +. +8 9 + SelectedItem +9 E +!= +F H +null +I M +) +M N +{ +  +return +  +true +  +; +  +} +  +return +  +NavigationHelper + # +. +# $ + CanGoBack +$ - +( +- . +) +. / +; +/ 0 +} +  + protected +  +void +  +GoBack +  +( +  +) +  +{ +  +if +  +( + ( +UsingLogicalPageNavigation + * +( +* + +) ++ , +&& +- / +ListView +0 8 +. +8 9 + SelectedItem +9 E +!= +F H +null +I M +) +M N +{ +  +ListView +  +. +  + SelectedItem + % += +& ' +null +( , +; +, - +} +  +else +  +{ +  +NavigationHelper +  +. + ! +GoBack +! ' +( +' ( +) +( ) +; +) * +} +  +} +  + protected +  +void + # +InvalidateVisualState + , +( +, - +) +- . +{ +  +var +  + visualState +  += + " +DetermineVisualState + 2 +( +2 3 +) +3 4 +; +4 5 +VisualStateManager +  +. +  + GoToState + ( +( +( ) +this +) - +, +- . + visualState +/ : +, +: ; +false +< A +) +A B +; +B C +NavigationHelper +  +. +  + GoBackCommand + * +. +* +$ +RaiseCanExecuteChanged ++ A +( +A B +) +B C +; +C D +} +  + protected +  +string + " +DetermineVisualState + - +( +- . +) +. / +{ +  +if +  +( +  +! + ( +UsingLogicalPageNavigation + + +( ++ , +) +, - +) +- . +return +  +$str + $ +; +$ % +var +  +logicalPageBack +  += + !( +UsingLogicalPageNavigation +" < +( +< = +) += > +&& +? A +ListView +B J +? +J K +. +K L + SelectedItem +L X +!= +Y [ +null +\ ` +; +` a +return +  +logicalPageBack + " +? +# $ +$str +% 8 +: +9 : +$str +; G +; +G H +} +  + protected +  +override +  +void +  + OnNavigatedTo + - +( +- .! +NavigationEventArgs +. A +e +B C +) +C D +{ +  +NavigationHelper +  +. +  + OnNavigatedTo + * +( +* + +e ++ , +) +, - +; +- . +} +  + protected +  +override +  +void +  +OnNavigatedFrom + / +( +/ 0! +NavigationEventArgs +0 C +e +D E +) +E F +{ +  +NavigationHelper +  +. +  +OnNavigatedFrom + , +( +, - +e +- . +) +. / +; +/ 0 +} +  +} +  +}  +bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsDatabasePage.xaml.cs + namespace  + ModernKeePass +  +.  +Views  +{  +public + +sealed  +partial  +class  +SettingsDatabasePage 4 +{    +public + +  +SettingsDatabasePage + + # +( + +# $ +) + +$ % +{    +InitializeComponent    +(    +)   ! +;  ! " +}    +}  +}  +eC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsNewDatabasePage.xaml.cs + namespace  + ModernKeePass +  +.  +Views  +{  +public + +sealed  +partial  +class # +SettingsNewDatabasePage 7 +{    +public + + # +SettingsNewDatabasePage + + & +( + +& ' +) + +' ( +{    +InitializeComponent    +(    +)   ! +;  ! " +}    +}  +}  +^C:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSavePage.xaml.cs + namespace  + ModernKeePass +  +.  +Views  +{  +public + +sealed  +partial  +class  +SettingsSavePage 0 +{    +public + +  +SettingsSavePage + +  +( + +  +) + + ! +{    +InitializeComponent    +(    +)   ! +;  ! " +}    +}  +}  +bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSecurityPage.xaml.cs + namespace  + ModernKeePass +  +.  +Views  +{  +public   + +sealed    +partial    +class    +SettingsSecurityPage   4 +{    +public    +SettingsSecurityPage   # +(  # $ +)  $ % +{  +InitializeComponent  +(  +) ! +;! " +}  +private  +void 7 ++CompositeKeyUserControl_OnValidationChecked @ +(@ A +objectA G +senderH N +,N O +PasswordEventArgsP a +eb c +)c d +{ # +ToastNotificationHelper # +.# $ +ShowGenericToast$ 4 +(4 5 +$str5 D +,D E +$strF f +)f g +;g h +}  +}  +}  +aC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsWelcomePage.xaml.cs + namespace  + ModernKeePass +  +.  +Views  +{  +public + +sealed  +partial  +class  +SettingsWelcomePage 3 +{    +public + +  +SettingsWelcomePage + + " +( + +" # +) + +# $ +{    +InitializeComponent    +(    +)   ! +;  ! " +}    +}  +}  +_C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\FirstItemDataTemplateSelector.cs + namespace  + ModernKeePass +  +.  +TemplateSelectors ) +{  +public + +class ) +FirstItemDataTemplateSelector . +:. / +DataTemplateSelector0 D +{  +public  + DataTemplate  + FirstItem % +{& ' +get( + +;+ , +set- 0 +;0 1 +}2 3 +public    + DataTemplate    + OtherItem   % +{  & ' +get  ( + +;  + , +set  - 0 +;  0 1 +}  2 3 + protected    +override    + DataTemplate   ' +SelectTemplateCore  ( : +(  : ; +object  ; A +item  B F +,  F G +DependencyObject  H X + container  Y b +)  b c +{    +var    + itemsControl    +=    + ItemsControl   + +.  + ,) +ItemsControlFromItemContainer  , I +(  I J + container  J S +)  S T +;  T U +var  +returnTemplate  +=  + itemsControl! - +?- . +.. / +IndexFromContainer/ A +(A B + containerB K +)K L +==M O +$numP Q +?R S + FirstItemT ] +:^ _ + OtherItem` i +;i j +return  +returnTemplate ! +;! " +}  +}  +}  +LC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\ListViewWithDisable.cs + namespace  + ModernKeePass +  +.  +Controls  +{  +public + +class  +ListViewWithDisable $ +:$ % +ListView& . +{  + protected    +override    +void   + +PrepareContainerForItemOverride   ? +(  ? @ +DependencyObject  @ P +element  Q X +,  X Y +object  Z ` +item  a e +)  e f +{ + +  +base    +.   + +PrepareContainerForItemOverride   0 +(  0 1 +element  1 8 +,  8 9 +item  : > +)  > ? +;  ? @ +var    + container    +=    +element   # +as  $ & + ListViewItem  ' 3 +;  3 4 +var  + +binaryItem  +=  +item ! +as" $ + +IIsEnabled% / +;/ 0 +if  +(  + container  +==  +null ! +||" $ + +binaryItem% / +==0 2 +null3 7 +)7 8 +return9 ? +;? @ + container  +.  + IsEnabled  += ! + +binaryItem" , +., - + IsEnabled- 6 +;6 7 + container  +.  +IsHitTestVisible & +=' ( + +binaryItem) 3 +.3 4 + IsEnabled4 = +;= > +}  +}  +}  +]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\BreadCrumbUserControl.xaml.cs + namespace  + ModernKeePass +  +.  +Views  +.  + UserControls * +{  +public   + +sealed    +partial    +class   ! +BreadCrumbUserControl   5 +{ + +  +public   ! +BreadCrumbUserControl   $ +(  $ % +)  % & +{    +InitializeComponent    +(    +)   ! +;  ! " +}  +public  + IEnumerable  +<  + IPwEntity $ +>$ % + ItemsSource& 1 +{  +get  +{  +return  +(  + IEnumerable % +<% & + IPwEntity& / +>/ 0 +)0 1 +GetValue1 9 +(9 : +ItemsSourceProperty: M +)M N +;N O +}P Q +set  +{  +SetValue  +(  +ItemsSourceProperty . +,. / +value0 5 +)5 6 +;6 7 +}8 9 +}  +public  +static  +readonly  +DependencyProperty 1 +ItemsSourceProperty2 E +=F G +DependencyProperty  +.  +Register ' +(' ( +$str  +,  +typeof  +(  + IEnumerable " +<" # + IPwEntity# , +>, - +)- . +,. / +typeof  +( ! +BreadCrumbUserControl , +), - +,- . +new  +PropertyMetadata $ +($ % +new% ( +Stack) . +<. / + IPwEntity/ 8 +>8 9 +(9 : +): ; +,; < +(= > +o> ? +,? @ +argsA E +)E F +=>G I +{J K +}L M +)M N +)N O +;O P +}  +} T +_C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\CompositeKeyUserControl.xaml.cs + namespace  + ModernKeePass +  +.  +Views  +.  + UserControls * +{  +public + +sealed  +partial  +class # +CompositeKeyUserControl 7 +{  +public  +CompositeKeyVm  +Model # +=>$ & +Grid' + +.+ , + DataContext, 7 +as8 : +CompositeKeyVm; I +;I J +public  +bool  + CreateNew  +{  +get  +{  +return  +(  +bool  +)  +GetValue ' +(' ( +CreateNewProperty( 9 +)9 : +;: ; +}< = +set  +{  +SetValue  +(  +CreateNewProperty , +,, - +value. 3 +)3 4 +;4 5 +}6 7 +}  +public  +static  +readonly  +DependencyProperty 1 +CreateNewProperty2 C +=D E +DependencyProperty  +.  +Register ' +(' ( +$str  +,  +typeof  +(  +bool  +)  +,  +typeof  +( # +CompositeKeyUserControl . +). / +,/ 0 +new  +PropertyMetadata $ +($ % +false% * +,* + +(, - +o- . +,. / +args0 4 +)4 5 +=>6 8 +{9 : +}; < +)< = +)= > +;> ? +public    +bool    + UpdateKey    +{!!  +get""  +{""  +return""  +(""  +bool""  +)""  +GetValue"" ' +(""' ( +UpdateKeyProperty""( 9 +)""9 : +;"": ; +}""< = +set##  +{##  +SetValue##  +(##  +UpdateKeyProperty## , +,##, - +value##. 3 +)##3 4 +;##4 5 +}##6 7 +}$$  +public%%  +static%%  +readonly%%  +DependencyProperty%% 1 +UpdateKeyProperty%%2 C +=%%D E +DependencyProperty&&  +.&&  +Register&& ' +(&&' ( +$str''  +,''  +typeof((  +(((  +bool((  +)((  +,((  +typeof))  +()) # +CompositeKeyUserControl)) . +))). / +,))/ 0 +new**  +PropertyMetadata** $ +(**$ % +false**% * +,*** + +(**, - +o**- . +,**. / +args**0 4 +)**4 5 +=>**6 8 +{**9 : +}**; < +)**< = +)**= > +;**> ? +public,,  +string,,  + ButtonLabel,, ! +{--  +get..  +{..  +return..  +(..  +string..  +).. ! +GetValue..! ) +(..) * +ButtonLabelProperty..* = +)..= > +;..> ? +}..@ A +set//  +{//  +SetValue//  +(//  +ButtonLabelProperty// . +,//. / +value//0 5 +)//5 6 +;//6 7 +}//8 9 +}00  +public11  +static11  +readonly11  +DependencyProperty11 1 +ButtonLabelProperty112 E +=11F G +DependencyProperty22  +.22  +Register22 ' +(22' ( +$str33  +,33  +typeof44  +(44  +string44  +)44  +,44  +typeof55  +(55 # +CompositeKeyUserControl55 . +)55. / +,55/ 0 +new66  +PropertyMetadata66 $ +(66$ % +$str66% ) +,66) * +(66+ , +o66, - +,66- . +args66/ 3 +)663 4 +=>665 7 +{668 9 +}66: ; +)66; < +)66< = +;66= > +public99  +bool99 # +ShowComplexityIndicator99 + +=>99, . + CreateNew99/ 8 +||999 ; + UpdateKey99< E +;99E F +public;; # +CompositeKeyUserControl;; & +(;;& ' +);;' ( +{<<  +InitializeComponent==  +(==  +)== ! +;==! " +}>>  +public@@  +event@@ ( +PasswordCheckingEventHandler@@ 1 +ValidationChecking@@2 D +;@@D E +publicAA  +delegateAA  +voidAA ( +PasswordCheckingEventHandlerAA 9 +(AA9 : +objectAA: @ +senderAAA G +,AAG H + EventArgsAAI R +eAAS T +)AAT U +;AAU V +publicBB  +eventBB ' +PasswordCheckedEventHandlerBB 0 +ValidationCheckedBB1 B +;BBB C +publicCC  +delegateCC  +voidCC ' +PasswordCheckedEventHandlerCC 8 +(CC8 9 +objectCC9 ? +senderCC@ F +,CCF G +PasswordEventArgsCCH Y +eCCZ [ +)CC[ \ +;CC\ ] +privateEE  +asyncEE  +voidEE  +OpenButton_OnClickEE - +(EE- . +objectEE. 4 +senderEE5 ; +,EE; < +RoutedEventArgsEE= L +eEEM N +)EEN O +{FF  +ValidationCheckingGG  +?GG  +.GG  +InvokeGG & +(GG& ' +thisGG' + +,GG+ , +newGG- 0 + EventArgsGG1 : +(GG: ; +)GG; < +)GG< = +;GG= > +ifII  +(II  + UpdateKeyII  +)II  +{JJ  +ModelKK  +.KK  + UpdateKeyKK  +(KK  +)KK ! +;KK! " +ValidationCheckedLL ! +?LL! " +.LL" # +InvokeLL# ) +(LL) * +thisLL* . +,LL. / +newLL0 3 +PasswordEventArgsLL4 E +(LLE F +ModelLLF K +.LLK L + RootGroupLLL U +)LLU V +)LLV W +;LLW X +}MM  +elseNN  +{OO  +varPP  +resourcePP  +=PP  +newPP " +ResourcesServicePP# 3 +(PP3 4 +)PP4 5 +;PP5 6 +varQQ  +oldLabelQQ  +=QQ  + ButtonLabelQQ * +;QQ* + + ButtonLabelRR  +=RR  +resourceRR & +.RR& ' +GetResourceValueRR' 7 +(RR7 8 +$strRR8 M +)RRM N +;RRN O +ifSS  +(SS  +awaitSS  + +DispatcherSS $ +.SS$ % + RunTaskAsyncSS% 1 +(SS1 2 +asyncSS2 7 +(SS8 9 +)SS9 : +=>SS; = +awaitSS> C +ModelSSD I +.SSI J + OpenDatabaseSSJ V +(SSV W + CreateNewSSW ` +)SS` a +)SSa b +)SSb c +{TT  +ValidationCheckedUU % +?UU% & +.UU& ' +InvokeUU' - +(UU- . +thisUU. 2 +,UU2 3 +newUU4 7 +PasswordEventArgsUU8 I +(UUI J +ModelUUJ O +.UUO P + RootGroupUUP Y +)UUY Z +)UUZ [ +;UU[ \ +}VV  + ButtonLabelWW  +=WW  +oldLabelWW & +;WW& ' +}XX  +}YY  +private[[  +void[[  +PasswordBox_KeyDown[[ ( +([[( ) +object[[) / +sender[[0 6 +,[[6 7 +KeyRoutedEventArgs[[8 J +e[[K L +)[[L M +{\\  +if]]  +(]]  +e]]  +.]]  +Key]]  +==]]  + +VirtualKey]] # +.]]# $ +Enter]]$ ) +&&]]* , +Model]]- 2 +.]]2 3 +IsValid]]3 : +)]]: ; +{^^  +OpenButton_OnClick__ " +(__" # +sender__# ) +,__) * +e__+ , +)__, - +;__- . +eaa  +.aa  +Handledaa  +=aa  +trueaa  +;aa ! +}bb  +}cc  +privateee  +asyncee  +voidee  +KeyFileButton_Clickee . +(ee. / +objectee/ 5 +senderee6 < +,ee< = +RoutedEventArgsee> M +eeeN O +)eeO P +{ff  +vargg  +pickergg  +=gg  +newhh  +FileOpenPickerhh " +{ii  +ViewModejj  +=jj  +PickerViewModejj - +.jj- . +Listjj. 2 +,jj2 3" +SuggestedStartLocationkk * +=kk+ , +PickerLocationIdkk- = +.kk= > +DocumentsLibrarykk> N +}ll  +;ll  +pickermm  +.mm  +FileTypeFiltermm ! +.mm! " +Addmm" % +(mm% & +$strmm& , +)mm, - +;mm- . +varpp  +filepp  +=pp  +awaitpp  +pickerpp # +.pp# $ +PickSingleFileAsyncpp$ 7 +(pp7 8 +)pp8 9 +;pp9 : +ifqq  +(qq  +fileqq  +==qq  +nullqq  +)qq  +returnqq $ +;qq$ % +Modelrr  +.rr  +KeyFilerr  +=rr  +filerr  +;rr ! +}ss  +privateuu  +asyncuu  +voiduu % +CreateKeyFileButton_Clickuu 4 +(uu4 5 +objectuu5 ; +senderuu< B +,uuB C +RoutedEventArgsuuD S +euuT U +)uuU V +{vv  +varww  + +savePickerww  +=ww  +newww  +FileSavePickerww! / +{xx " +SuggestedStartLocationyy & +=yy' ( +PickerLocationIdyy) 9 +.yy9 : +DocumentsLibraryyy: J +,yyJ K +SuggestedFileNamezz ! +=zz" # +$strzz$ ) +}{{  +;{{  + +savePicker||  +.||  +FileTypeChoices|| & +.||& ' +Add||' * +(||* + +$str||+ 5 +,||5 6 +new||7 : +List||; ? +<||? @ +string||@ F +>||F G +{||H I +$str||J P +}||Q R +)||R S +;||S T +var~~  +file~~  +=~~  +await~~  + +savePicker~~ ' +.~~' ( +PickSaveFileAsync~~( 9 +(~~9 : +)~~: ; +;~~; < +if  +(  +file  +==  +null  +)  +return $ +;$ % +Model +  +. +  + CreateKeyFile +  +( +  +file + $ +) +$ % +; +% & +} +  +} +  +} 1 +JC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\TextBoxWithButton.cs + namespace  + ModernKeePass +  +.  +Controls  +{  +public + +class  +TextBoxWithButton " +:# $ +TextBox% , +{    +public + +  +string + +  + ButtonSymbol + + " +{    +get    +{    +return    +(    +string    +)   ! +GetValue  ! ) +(  ) * +ButtonSymbolProperty  * > +)  > ? +;  ? @ +}  A B +set    +{    +SetValue    +(    +ButtonSymbolProperty   / +,  / 0 +value  1 6 +)  6 7 +;  7 8 +}  9 : +}  +public  +static  +readonly  +DependencyProperty 1 +ButtonSymbolProperty2 F +=G H +DependencyProperty  +.  +Register ' +(' ( +$str  +,  +typeof  +(  +string  +)  +,  +typeof  +(  +TextBoxWithButton ( +)( ) +,) * +new  +PropertyMetadata $ +($ % +$str% / +,/ 0 +(1 2 +o2 3 +,3 4 +args5 9 +)9 : +=>; = +{> ? +}@ A +)A B +)B C +;C D +public  +event  + EventHandler ! +<! " +RoutedEventArgs" 1 +>1 2 + ButtonClick3 > +;> ? +public  +string  + ButtonTooltip # +{  +get  +{  +return  +(  +string  +) ! +GetValue! ) +() *! +ButtonTooltipProperty* ? +)? @ +;@ A +}B C +set  +{  +SetValue  +( ! +ButtonTooltipProperty 0 +,0 1 +value2 7 +)7 8 +;8 9 +}: ; +}  +public  +static  +readonly  +DependencyProperty 1! +ButtonTooltipProperty2 G +=H I +DependencyProperty  +.  +Register ' +(' ( +$str  +,  +typeof  +(  +string  +)  +,  +typeof    +(    +TextBoxWithButton   ( +)  ( ) +,  ) * +new!!  +PropertyMetadata!! $ +(!!$ % +string!!% + +.!!+ , +Empty!!, 1 +,!!1 2 +(!!3 4 +o!!4 5 +,!!5 6 +args!!7 ; +)!!; < +=>!!= ? +{!!@ A +}!!B C +)!!C D +)!!D E +;!!E F +public##  +bool##  +IsButtonEnabled## # +{$$  +get%%  +{%%  +return%%  +(%%  +bool%%  +)%%  +GetValue%% ' +(%%' (# +IsButtonEnabledProperty%%( ? +)%%? @ +;%%@ A +}%%B C +set&&  +{&&  +SetValue&&  +(&& # +IsButtonEnabledProperty&& 2 +,&&2 3 +value&&4 9 +)&&9 : +;&&: ; +}&&< = +}''  +public((  +static((  +readonly((  +DependencyProperty(( 1# +IsButtonEnabledProperty((2 I +=((J K +DependencyProperty))  +.))  +Register)) ' +())' ( +$str** ! +,**! " +typeof++  +(++  +bool++  +)++  +,++  +typeof,,  +(,,  +TextBoxWithButton,, ( +),,( ) +,,,) * +new--  +PropertyMetadata-- $ +(--$ % +true--% ) +,--) * +(--+ , +o--, - +,--- . +args--/ 3 +)--3 4 +=>--5 7 +{--8 9 +}--: ; +)--; < +)--< = +;--= > +public//  + +FlyoutBase//  + ButtonFlyout// & +{00  +get11  +{11  +return11  +(11  + +FlyoutBase11 $ +)11$ % +GetValue11% - +(11- . +ButtonFlyoutProperty11. B +)11B C +;11C D +}11E F +set22  +{22  +SetValue22  +(22  +ButtonFlyoutProperty22 / +,22/ 0 +value221 6 +)226 7 +;227 8 +}229 : +}33  +public44  +static44  +readonly44  +DependencyProperty44 1 +ButtonFlyoutProperty442 F +=44G H +DependencyProperty55  +.55  +Register55 ' +(55' ( +$str66  +,66  +typeof77  +(77  + +FlyoutBase77 ! +)77! " +,77" # +typeof88  +(88  +TextBoxWithButton88 ( +)88( ) +,88) * +new99  +PropertyMetadata99 $ +(99$ % +null99% ) +,99) * +(99+ , +o99, - +,99- . +args99/ 3 +)993 4 +=>995 7 +{998 9 +}99: ; +)99; < +)99< = +;99= > + protected;;  +override;;  +void;;  +OnApplyTemplate;; / +(;;/ 0 +);;0 1 +{<<  +base==  +.==  +OnApplyTemplate==  +(== ! +)==! " +;==" # +var>>  + actionButton>>  +=>>  +GetTemplateChild>> / +(>>/ 0 +$str>>0 > +)>>> ? +as>>@ B +Button>>C I +;>>I J +if??  +(??  + actionButton??  +!=??  +null?? $ +)??$ % +{@@  + actionButtonAA  +.AA  +ClickAA " ++=AA# % +(AA& ' +senderAA' - +,AA- . +eAA/ 0 +)AA0 1 +=>AA2 4 + ButtonClickAA5 @ +?AA@ A +.AAA B +InvokeAAB H +(AAH I +senderAAI O +,AAO P +eAAQ R +)AAR S +;AAS T +}BB  +}CC  +}DD  +}EE  +WC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\BooleanToVisibilityConverter.cs + namespace  + ModernKeePass +  +.  + +Converters " +{  +public + +class ( +BooleanToVisibilityConverter - +:. / +IValueConverter0 ? +{  +public    +object    +Convert    +(    +object   $ +value  % * +,  * + +Type  , 0 + +targetType  1 ; +,  ; < +object  = C + parameter  D M +,  M N +string  O U +language  V ^ +)  ^ _ +{ + +  +var    +boolean    +=    +value    +is   " +bool  # ' +?  ( ) +(  * + +bool  + / +)  / 0 +value  1 6 +:  7 8 +false  9 > +;  > ? +return    +boolean    +?    + +Visibility   ' +.  ' ( +Visible  ( / +:  0 1 + +Visibility  2 < +.  < = + Collapsed  = F +;  F G +}    +public  +object  + ConvertBack ! +(! " +object" ( +value) . +,. / +Type0 4 + +targetType5 ? +,? @ +objectA G + parameterH Q +,Q R +stringS Y +languageZ b +)b c +{  +var  + +visibility  +=  +value " +is# % + +Visibility& 0 +?1 2 +(3 4 + +Visibility4 > +)> ? +value@ E +:F G + +VisibilityH R +.R S +VisibleS Z +;Z [ +switch  +(  + +visibility  +)  +{  +case  + +Visibility  +.  +Visible ' +:' ( +return) / +true0 4 +;4 5 +case  + +Visibility  +.  + Collapsed ) +:) * +return+ 1 +false2 7 +;7 8 +default  +:  +throw  +new ' +ArgumentOutOfRangeException 9 +(9 : +): ; +;; < +}  +}  +}  +}  +PC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ColorToBrushConverter.cs + namespace  + ModernKeePass +  +.  + +Converters " +{  +public + +class ! +ColorToBrushConverter & +:' ( +IValueConverter) 8 +{    +public + +  +object + +  +Convert + +  +( + +  +object + + $ +value + +% * +, + +* + +Type + +, 0 + +targetType + +1 ; +, + +; < +object + += C + parameter + +D M +, + +M N +string + +O U +language + +V ^ +) + +^ _ +{    +var    +color    +=    +value    +is    +Color  ! & +?  ' ( +(  ) * +Color  * / +?  / 0 +)  0 1 +value  2 7 +:  8 9 +Color  : ? +.  ? @ +Empty  @ E +;  E F +if    +(    +color    +==    +Color    +.    +Empty   $ +&&  % ' + parameter  ( 1 +is  2 4 +SolidColorBrush  5 D +)  D E +return  F L +(  M N +SolidColorBrush  N ] +)  ] ^ + parameter  _ h +;  h i +return  +new  +SolidColorBrush & +(& ' +Windows' . +.. / +UI/ 1 +.1 2 +Color2 7 +.7 8 +FromArgb8 @ +(@ A +color  +.  +Value  +.  +A  +,  +color  +.  +Value  +.  +R  +,  +color  +.  +Value  +.  +G  +,  +color  +.  +Value  +.  +B  +)  +)  +;  +}  +public  +object  + ConvertBack ! +(! " +object" ( +value) . +,. / +Type0 4 + +targetType5 ? +,? @ +objectA G + parameterH Q +,Q R +stringS Y +languageZ b +)b c +{  +throw  +new # +NotImplementedException - +(- . +). / +;/ 0 +}  +}  +}  +[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DoubleToSolidColorBrushConverter.cs + namespace  + ModernKeePass +  +.  + +Converters " +{  +public + +class , + DoubleToSolidColorBrushConverter 1 +:2 3 +IValueConverter4 C +{    +public + +  +object + +  +Convert + +  +( + +  +object + + $ +value + +% * +, + +* + +Type + +, 0 + +targetType + +1 ; +, + +; < +object + += C + parameter + +D M +, + +M N +string + +O U +language + +V ^ +) + +^ _ +{    +try    +{    +var  + currentValue  +=! " +(# $ +double$ * +)* + +value, 1 +;1 2 +var  +maxValue  +=  +double % +.% & +Parse& + +(+ , + parameter, 5 +as6 8 +string9 ? +)? @ +;@ A +var  +green  +=  +System " +." # +Convert# * +.* + +ToByte+ 1 +(1 2 + currentValue2 > +/? @ +maxValueA I +*J K +byteL P +.P Q +MaxValueQ Y +)Y Z +;Z [ +var  +red  +=  +(  +byte  +)  +(! " +byte" & +.& ' +MaxValue' / +-0 1 +green2 7 +)7 8 +;8 9 +return  +new  +SolidColorBrush * +(* + +Color+ 0 +.0 1 +FromArgb1 9 +(9 : +$num: = +,= > +red? B +,B C +greenD I +,I J +$numK L +)L M +)M N +;N O +}  +catch  +(  +OverflowException $ +)$ % +{  +return  +new  +SolidColorBrush * +(* + +Color+ 0 +.0 1 +FromArgb1 9 +(9 : +$num: = +,= > +$num? @ +,@ A +byteB F +.F G +MaxValueG O +,O P +$numQ R +)R S +)S T +;T U +}  +}  +public  +object  + ConvertBack ! +(! " +object" ( +value) . +,. / +Type0 4 + +targetType5 ? +,? @ +objectA G + parameterH Q +,Q R +stringS Y +languageZ b +)b c +{  +throw  +new # +NotImplementedException - +(- . +). / +;/ 0 +}  +}  +}  +^C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\InverseBooleanToVisibilityConverter.cs + namespace  + ModernKeePass +  +.  + +Converters " +{  +public + +class / +#InverseBooleanToVisibilityConverter 4 +:5 6 +IValueConverter7 F +{  +public    +object    +Convert    +(    +object   $ +value  % * +,  * + +Type  , 0 + +targetType  1 ; +,  ; < +object  = C + parameter  D M +,  M N +string  O U +language  V ^ +)  ^ _ +{ + +  +var    +boolean    +=    +value    +is   " +bool  # ' +?  ( ) +(  * + +bool  + / +)  / 0 +value  0 5 +:  6 7 +false  8 = +;  = > +return    +boolean    +?    + +Visibility   ' +.  ' ( + Collapsed  ( 1 +:  2 3 + +Visibility  4 > +.  > ? +Visible  ? F +;  F G +}    +public  +object  + ConvertBack ! +(! " +object" ( +value) . +,. / +Type0 4 + +targetType5 ? +,? @ +objectA G + parameterH Q +,Q R +stringS Y +languageZ b +)b c +{  +var  + +visibility  +=  +value " +is# % + +Visibility& 0 +?1 2 +(3 4 + +Visibility4 > +)> ? +value? D +:E F + +VisibilityG Q +.Q R +VisibleR Y +;Y Z +switch  +(  + +visibility  +)  +{  +case  + +Visibility  +.  +Visible ' +:' ( +return) / +false0 5 +;5 6 +case  + +Visibility  +.  + Collapsed ) +:) * +return+ 1 +true2 6 +;6 7 +default  +:  +throw  +new ' +ArgumentOutOfRangeException 9 +(9 : +): ; +;; < +}  +}  +}  +}  +QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\PluralizationConverter.cs + namespace  + ModernKeePass +  +.  + +Converters " +{  +public + +class " +PluralizationConverter ' +:( ) +IValueConverter* 9 +{  +public  +object  +Convert  +(  +object $ +value% * +,* + +Type, 0 + +targetType1 ; +,; < +object= C + parameterD M +,M N +stringO U +languageV ^ +)^ _ +{    +var + + % +pluralizationOptionString + + ) += + +* + + parameter + +, 5 +as + +6 8 +string + +9 ? +; + +? @ +var    +pluralizationOptions   $ +=  % &% +pluralizationOptionString  ' @ +?  @ A +.  A B +Split  B G +(  G H +new  H K +[  K L +]  L M +{  N O +$str  P S +}  T U +,  U V +StringSplitOptions  W i +.  i j +RemoveEmptyEntries  j | +)  | } +;  } ~ +if    +(    +pluralizationOptions   $ +==  % ' +null  ( , +||  - / +pluralizationOptions  0 D +.  D E +Length  E K +!=  L N +$num  O P +)  P Q +return  R X +string  Y _ +.  _ ` +Empty  ` e +;  e f +var    +count    +=    +value    +is    +int  ! $ +?  % & +(  ' ( +int  ( + +)  + , +value  - 2 +:  3 4 +$num  5 6 +;  6 7 +var  +text  +=  +count  +==  +$num ! +?" # +pluralizationOptions$ 8 +[8 9 +$num9 : +]: ; +:< = +pluralizationOptions> R +[R S +$numS T +]T U +;U V +return  +$"  +{  +count  +}  +{  +text " +}" # +"# $ +;$ % +}  +public  +object  + ConvertBack ! +(! " +object" ( +value) . +,. / +Type0 4 + +targetType5 ? +,? @ +objectA G + parameterH Q +,Q R +stringS Y +languageZ b +)b c +{  +throw  +new # +NotImplementedException - +(- . +). / +;/ 0 +}  +}  +}  +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ProgressBarLegalValuesConverter.cs + namespace  + ModernKeePass +  +.  + +Converters " +{  +public + +class + +ProgressBarLegalValuesConverter 0 +:1 2 +IValueConverter3 B +{  +public  +object  +Convert  +(  +object $ +value% * +,* + +Type, 0 + +targetType1 ; +,; < +object= C + parameterD M +,M N +stringO U +languageV ^ +)^ _ +{    +var + + # +legalValuesOptionString + + ' += + +( ) + parameter + +* 3 +as + +4 6 +string + +7 = +; + += > +var    +legalValuesOptions   " +=  # $# +legalValuesOptionString  % < +?  < = +.  = > +Split  > C +(  C D +new  D G +[  G H +]  H I +{  J K +$str  L O +}  P Q +,  Q R +StringSplitOptions  S e +.  e f +RemoveEmptyEntries  f x +)  x y +;  y z +if    +(    +legalValuesOptions   " +==  # % +null  & * +||  + - +legalValuesOptions  . @ +.  @ A +Length  A G +!=  H J +$num  K L +)  L M +return  N T +$num  U V +;  V W +var  +minValue  +=  +double ! +.! " +Parse" ' +(' ( +legalValuesOptions( : +[: ; +$num; < +]< = +)= > +;> ? +var  +maxValue  +=  +double ! +.! " +Parse" ' +(' ( +legalValuesOptions( : +[: ; +$num; < +]< = +)= > +;> ? +var  +count  +=  +value  +is  +double! ' +?( ) +(* + +double+ 1 +)1 2 +value2 7 +:8 9 +$num: ; +;; < +if  +(  +count  +>  +maxValue  +) ! +return" ( +maxValue) 1 +;1 2 +if  +(  +count  +<  +minValue  +) ! +return" ( +minValue) 1 +;1 2 +return  +count  +;  +}  +public  +object  + ConvertBack ! +(! " +object" ( +value) . +,. / +Type0 4 + +targetType5 ? +,? @ +objectA G + parameterH Q +,Q R +stringS Y +languageZ b +)b c +{  +throw  +new # +NotImplementedException - +(- . +). / +;/ 0 +}  +}  +}  +OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\TextToWidthConverter.cs + namespace  + ModernKeePass +  +.  + +Converters " +{  +public + +class  +TextToWidthConverter % +:& ' +IValueConverter( 7 +{  +public  +object  +Convert  +(  +object $ +value% * +,* + +Type, 0 + +targetType1 ; +,; < +object= C + parameterD M +,M N +stringO U +languageV ^ +)^ _ +{    +var + +  +fontSize + +  += + +  +double + + ! +. + +! " +Parse + +" ' +( + +' ( + parameter + +( 1 +as + +2 4 +string + +5 ; +) + +; < +; + +< = +var    +text    +=    +value    +as    +string   & +;  & ' +return    +text    +?    +.    +Length    +*   ! +fontSize  " * +??  + - +$num  . / +;  / 0 +}    +public  +object  + ConvertBack ! +(! " +object" ( +value) . +,. / +Type0 4 + +targetType5 ? +,? @ +objectA G + parameterH Q +,Q R +stringS Y +languageZ b +)b c +{  +throw  +new # +NotImplementedException - +(- . +). / +;/ 0 +}  +}  +}  +HC:\Sources\Other\ModernKeePass\ModernKeePass\Events\PasswordEventArgs.cs + namespace  + ModernKeePass +  +.  +Events  +{  +public + +class  +PasswordEventArgs " +:" # + EventArgs$ - +{  +public  +GroupVm  + RootGroup  +{! " +get# & +;& ' +set( + +;+ , +}- . +public + +  +PasswordEventArgs + +  +( + + ! +GroupVm + +! ( +groupVm + +) 0 +) + +0 1 +{    + RootGroup    +=    +groupVm    +;    +}    +}  +}  +EC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IIsEnabled.cs + namespace  + ModernKeePass +  +.  + +Interfaces " +{  +public + + interface  + +IIsEnabled  +{  +bool  + IsEnabled  +{  +get  +;  +}  +}  +}  +DC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IPwEntity.cs + namespace  + ModernKeePass +  +.  + +Interfaces " +{  +public + + interface  + IPwEntity  +{  +GroupVm  + ParentGroup  +{  +get ! +;! " +}# $ +GroupVm    + PreviousGroup    +{    +get   # +;  # $ +}  % & +int + +  +IconId + +  +{ + +  +get + +  +; + +  +} + +  +string    +Id    +{    +get    +;    +}    +string    +Name    +{    +get    +;    +set    +;    +}   ! + IEnumerable    +<    + IPwEntity    +>    + +BreadCrumb   ) +{  * + +get  , / +;  / 0 +}  1 2 +bool  + +IsEditMode  +{  +get  +;  +}  +bool  +IsRecycleOnDelete  +{  +get! $ +;$ % +}& ' +void  +Move  +(  +GroupVm  + destination % +)% & +;& ' +void  + CommitDelete  +(  +)  +;  +void  + +UndoDelete  +(  +)  +;  +void!!  +Save!!  +(!!  +)!!  +;!!  +void%%  + MarkForDelete%%  +(%%  +string%% ! +recycleBinTitle%%" 1 +)%%1 2 +;%%2 3 +}&&  +}''  +CC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPage.xaml.cs + namespace  + ModernKeePass +  +.  +Views  +{  +public   + +sealed    +partial    +class    +MainPage   ( +{    +public  +new  +MainVm  +Model  +=> " +(# $ +MainVm$ * +)* + + DataContext+ 6 +;6 7 +public  +MainPage  +(  +)  +{  +InitializeComponent  +(  +) ! +;! " +ListView  +=  + MenuListView # +;# $ +ListViewSource  +=  +MenuItemsSource , +;, - +}  +private  +new  +void % +ListView_SelectionChanged 2 +(2 3 +object3 9 +sender: @ +,@ A% +SelectionChangedEventArgsB [ +e\ ] +)] ^ +{  +base  +. % +ListView_SelectionChanged * +(* + +sender+ 1 +,1 2 +e3 4 +)4 5 +;5 6 +var  + selectedItem  +=  +Model $ +.$ % + SelectedItem% 1 +as2 4 +MainMenuItemVm5 C +;C D +if  +(  + selectedItem  +==  +null $ +)$ % + MenuFrame& / +./ 0 +Navigate0 8 +(8 9 +typeof9 ? +(? @ + WelcomePage@ K +)K L +)L M +;M N +else  + selectedItem  +.  + Destination ) +.) * +Navigate* 2 +(2 3 + selectedItem3 ? +.? @ +PageType@ H +,H I + selectedItemJ V +.V W + ParameterW ` +)` a +;a b +}  + protected  +override  +void  + OnNavigatedTo - +(- . +NavigationEventArgs. A +eB C +)C D +{    +base!!  +.!!  + OnNavigatedTo!!  +(!!  +e!!  +)!! ! +;!!! " + DataContext""  +=""  +new""  +MainVm"" $ +(""$ % +Frame""% * +,""* + + MenuFrame"", 5 +)""5 6 +;""6 7 +}##  +}$$  +}%%  +SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\AboutPage.xaml.cs + namespace  + ModernKeePass +  +.  +Views  +{  +public + +sealed  +partial  +class  + AboutPage ) +{    +public + +  + AboutPage + +  +( + +  +) + +  +{    +InitializeComponent    +(    +)   ! +;  ! " +}    +}  +}  +YC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\NewDatabasePage.xaml.cs + namespace   + ModernKeePass   +  +.    +Views    +{ + +  +public + +sealed  +partial  +class  +NewDatabasePage / +{  +public  +NewVm  +Model  +=>  +(  +NewVm $ +)$ % + DataContext% 0 +;0 1 +public  +NewDatabasePage  +(  +)  +{  +InitializeComponent  +(  +) ! +;! " +}  +private  +async  +void  +ButtonBase_OnClick - +(- . +object. 4 +sender5 ; +,; < +RoutedEventArgs= L +eM N +)N O +{  +var  + +savePicker  +=  +new  +FileSavePicker! / +{ " +SuggestedStartLocation & +=' ( +PickerLocationId) 9 +.9 : +DocumentsLibrary: J +,J K +SuggestedFileName ! +=" # +$str$ 2 +}  +;  + +savePicker  +.  +FileTypeChoices & +.& ' +Add' * +(* + +$str+ A +,A B +newC F +ListG K +<K L +stringL R +>R S +{T U +$strV ] +}^ _ +)_ ` +;` a +var    +file    +=    +await    + +savePicker   ' +.  ' ( +PickSaveFileAsync  ( 9 +(  9 : +)  : ; +;  ; < +if!!  +(!!  +file!!  +==!!  +null!!  +)!!  +return!! $ +;!!$ % +Model""  +.""  +OpenFile""  +(""  +file""  +)""  +;"" ! +}##  +}$$  +}%%  +GC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPage.xaml.cs + namespace  + ModernKeePass +  +.  +Views  +{  +public   + +sealed    +partial    +class    + SettingsPage   , +{    +public  +new  + +SettingsVm  +Model # +=>$ & +(' ( + +SettingsVm( 2 +)2 3 + DataContext3 > +;> ? +public  + SettingsPage  +(  +)  +{  +InitializeComponent  +(  +) ! +;! " +ListView  +=  + MenuListView # +;# $ +ListViewSource  +=  +MenuItemsSource , +;, - +}  +private  +new  +void % +ListView_SelectionChanged 2 +(2 3 +object3 9 +sender: @ +,@ A% +SelectionChangedEventArgsB [ +e\ ] +)] ^ +{  +base  +. % +ListView_SelectionChanged * +(* + +sender+ 1 +,1 2 +e3 4 +)4 5 +;5 6 +var  + selectedItem  +=  +Model $ +.$ % + SelectedItem% 1 +as2 4 +ListMenuItemVm5 C +;C D + MenuFrame  +?  +.  +Navigate  +(  + selectedItem , +==- / +null0 4 +?5 6 +typeof7 = +(= > +SettingsWelcomePage> Q +)Q R +:S T + selectedItemU a +.a b +PageTypeb j +)j k +;k l +}  +}  +}  +UC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\WelcomePage.xaml.cs + namespace  + ModernKeePass +  +.  +Views  +{  +public + +sealed  +partial  +class  + WelcomePage + +{    +public + +  + WelcomePage + +  +( + +  +) + +  +{    +InitializeComponent    +(    +)   ! +;  ! " +}    +}  +}  +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\AboutVm.cs + namespace  + ModernKeePass +  +.  + +ViewModels " +{  +public + +class  +AboutVm  +{  +private  +readonly  +Package  +_package! ) +;) * +public    +string    +Name    +=>    +_package   & +.  & ' + DisplayName  ' 2 +;  2 3 +public    +string    +Version    +{    +get    +{  +var  +version  +=  +_package & +.& ' +Id' ) +.) * +Version* 1 +;1 2 +return  +$"  +{  +version ! +.! " +Major" ' +}' ( +.( ) +{) * +version* 1 +.1 2 +Minor2 7 +}7 8 +"8 9 +;9 : +}  +}  +public  +AboutVm  +(  +)  +:  +this  +(  +Package ' +.' ( +Current( / +)/ 0 +{1 2 +}3 4 +public  +AboutVm  +(  +Package  +package & +)& ' +{  +_package  +=  +package  +;  +}  +}  +} m +IC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\CompositeKeyVm.cs + namespace   + ModernKeePass   +  +.    + +ViewModels   " +{   +public + +class  +CompositeKeyVm  +: % +NotifyPropertyChangedBase! : +{  +public  +enum  + StatusTypes  +{  +Normal  +=  +$num  +,  +Error  +=  +$num  +,  +Warning  +=  +$num  +,  +Success  +=  +$num  +}  +public  +IDatabaseService  +Database ( +{) * +get+ . +;. / +set0 3 +;3 4 +}5 6 +public  +bool  + HasPassword  +{  +get  +{  +return  + _hasPassword % +;% & +}' ( +set  +{  + SetProperty  +(  +ref  + _hasPassword , +,, - +value. 3 +)3 4 +;4 5 +OnPropertyChanged   ! +(  ! " +$str  " + +)  + , +;  , - +}!!  +}""  +public$$  +bool$$  + +HasKeyFile$$  +{%%  +get&&  +{&&  +return&&  + _hasKeyFile&& $ +;&&$ % +}&&& ' +set''  +{((  + SetProperty))  +())  +ref))  + _hasKeyFile)) + +,))+ , +value))- 2 +)))2 3 +;))3 4 +OnPropertyChanged** ! +(**! " +$str**" + +)**+ , +;**, - +}++  +},,  +public..  +bool..  +HasUserAccount.. " +{//  +get00  +{00  +return00  +_hasUserAccount00 ( +;00( ) +}00* + +set11  +{22  + SetProperty33  +(33  +ref33  +_hasUserAccount33 / +,33/ 0 +value331 6 +)336 7 +;337 8 +OnPropertyChanged44 ! +(44! " +$str44" + +)44+ , +;44, - +}55  +}66  +public88  +bool88  +IsValid88  +=>88  +!88  + +_isOpening88 * +&&88+ - +(88. / + HasPassword88/ : +||88; = + +HasKeyFile88> H +&&88I K +KeyFile88L S +!=88T V +null88W [ +||88\ ^ +HasUserAccount88_ m +)88m n +;88n o +public::  +string::  +Status::  +{;;  +get<<  +{<<  +return<<  +_status<<  +;<< ! +}<<" # +set==  +{==  + SetProperty==  +(==  +ref== ! +_status==" ) +,==) * +value==+ 0 +)==0 1 +;==1 2 +}==3 4 +}>>  +public@@  +int@@  + +StatusType@@  +{AA  +getBB  +{BB  +returnBB  +(BB  +intBB  +)BB  + _statusTypeBB ) +;BB) * +}BB+ , +setCC  +{CC  + SetPropertyCC  +(CC  +refCC ! + _statusTypeCC" - +,CC- . +(CC/ 0 + StatusTypesCC0 ; +)CC; < +valueCC< A +)CCA B +;CCB C +}CCD E +}DD  +publicFF  +stringFF  +PasswordFF  +{GG  +getHH  +{HH  +returnHH  + _passwordHH " +;HH" # +}HH$ % +setII  +{JJ  + _passwordKK  +=KK  +valueKK ! +;KK! " +OnPropertyChangedLL ! +(LL! " +$strLL" ? +)LL? @ +;LL@ A + +StatusTypeMM  +=MM  +(MM  +intMM ! +)MM! " + StatusTypesMM" - +.MM- . +NormalMM. 4 +;MM4 5 +StatusNN  +=NN  +stringNN  +.NN  +EmptyNN % +;NN% & +}OO  +}PP  +publicRR  + StorageFileRR  +KeyFileRR " +{SS  +getTT  +{TT  +returnTT  +_keyFileTT ! +;TT! " +}TT# $ +setUU  +{VV  +_keyFileWW  +=WW  +valueWW  +;WW ! + KeyFileTextXX  +=XX  +valueXX # +?XX# $ +.XX$ % +NameXX% ) +;XX) * +OnPropertyChangedYY ! +(YY! " +$strYY" + +)YY+ , +;YY, - +}ZZ  +}[[  +public]]  +string]]  + KeyFileText]] ! +{^^  +get__  +{__  +return__  + _keyFileText__ % +;__% & +}__' ( +set``  +{``  + SetProperty``  +(``  +ref`` ! + _keyFileText``" . +,``. / +value``0 5 +)``5 6 +;``6 7 +}``8 9 +}aa  +publiccc  +GroupVmcc  + RootGroupcc  +{cc! " +getcc# & +;cc& ' +setcc( + +;cc+ , +}cc- . +publicee  +doubleee ' +PasswordComplexityIndicatoree 1 +=>ee2 4 +QualityEstimationee5 F +.eeF G +EstimatePasswordBitseeG [ +(ee[ \ +Passwordee\ d +?eed e +.eee f + ToCharArrayeef q +(eeq r +)eer s +)ees t +;eet u +privategg  +boolgg  + _hasPasswordgg ! +;gg! " +privatehh  +boolhh  + _hasKeyFilehh  +;hh ! +privateii  +boolii  +_hasUserAccountii $ +;ii$ % +privatejj  +booljj  + +_isOpeningjj  +;jj  +privatekk  +stringkk  + _passwordkk  +=kk! " +stringkk# ) +.kk) * +Emptykk* / +;kk/ 0 +privatell  +stringll  +_statusll  +;ll  +privatemm  + StatusTypesmm  + _statusTypemm ' +;mm' ( +privatenn  + StorageFilenn  +_keyFilenn $ +;nn$ % +privateoo  +stringoo  + _keyFileTextoo # +;oo# $ +privatepp  +readonlypp  +IResourceServicepp ) + _resourcepp* 3 +;pp3 4 +publicrr  +CompositeKeyVmrr  +(rr  +)rr  +:rr ! +thisrr" & +(rr& ' +DatabaseServicerr' 6 +.rr6 7 +Instancerr7 ? +,rr? @ +newrrA D +ResourcesServicerrE U +(rrU V +)rrV W +)rrW X +{rrY Z +}rr[ \ +publictt  +CompositeKeyVmtt  +(tt  +IDatabaseServicett . +databasett/ 7 +,tt7 8 +IResourceServicett9 I +resourcettJ R +)ttR S +{uu  + _resourcevv  +=vv  +resourcevv  +;vv ! + _keyFileTextww  +=ww  + _resourceww $ +.ww$ % +GetResourceValueww% 5 +(ww5 6 +$strww6 R +)wwR S +;wwS T +Databasexx  +=xx  +databasexx  +;xx  +}yy  +public{{  +async{{  +Task{{  +<{{  +bool{{  +>{{  + OpenDatabase{{ , +({{, - +bool{{- 1 + createNew{{2 ; +){{; < +{||  +try}}  +{~~  + +_isOpening  +=  +true ! +;! " +await +  +Database +  +. +  +Open + # +( +# $ +CreateCompositeKey +$ 6 +( +6 7 +) +7 8 +, +8 9 + createNew +: C +) +C D +; +D E +await +  +Task +  +. +  +Run +  +( +  +( +  +) + ! +=> +" $ + RootGroup +% . += +/ 0 +Database +1 9 +. +9 : + RootGroup +: C +) +C D +; +D E +return +  +true +  +; +  +} +  +catch +  +( +  +ArgumentException + $ +) +$ % +{ +  +var +  + errorMessage +  += +! " +new +# & + StringBuilder +' 4 +( +4 5 +$" +5 7 +{ +7 8 + _resource +8 A +. +A B +GetResourceValue +B R +( +R S +$str +S j +) +j k +} +k l +\n +l n +" +n o +) +o p +; +p q +if +  +( +  + HasPassword +  +) +  + errorMessage +! - +. +- . + +AppendLine +. 8 +( +8 9 + _resource +9 B +. +B C +GetResourceValue +C S +( +S T +$str +T s +) +s t +) +t u +; +u v +if +  +( +  + +HasKeyFile +  +) +  + errorMessage + , +. +, - + +AppendLine +- 7 +( +7 8 + _resource +8 A +. +A B +GetResourceValue +B R +( +R S +$str +S q +) +q r +) +r s +; +s t +if +  +( +  +HasUserAccount + " +) +" # + errorMessage +$ 0 +. +0 1 + +AppendLine +1 ; +( +; < + _resource +< E +. +E F +GetResourceValue +F V +( +V W +$str +W u +) +u v +) +v w +; +w x + UpdateStatus +  +( +  + errorMessage + ) +. +) * +ToString +* 2 +( +2 3 +) +3 4 +, +4 5 + StatusTypes +6 A +. +A B +Error +B G +) +G H +; +H I +} +  +catch +  +( +  + Exception +  +e +  +) +  +{ +  +var +  +error +  += +  +$" +  +{ +  + _resource + ( +. +( ) +GetResourceValue +) 9 +( +9 : +$str +: Q +) +Q R +} +R S +{ +S T +e +T U +. +U V +Message +V ] +} +] ^ +" +^ _ +; +_ ` + UpdateStatus +  +( +  +error + " +, +" # + StatusTypes +$ / +. +/ 0 +Error +0 5 +) +5 6 +; +6 7 +} +  +finally +  +{ +  + +_isOpening +  += +  +false + " +; +" # +} +  +return +  +false +  +; +  +} +  +public +  +void +  + UpdateKey +  +( +  +) +  +{ +  +Database +  +. +  + CompositeKey + ! += +" # +CreateCompositeKey +$ 6 +( +6 7 +) +7 8 +; +8 9 + UpdateStatus +  +( +  + _resource + " +. +" # +GetResourceValue +# 3 +( +3 4 +$str +4 I +) +I J +, +J K + StatusTypes +L W +. +W X +Success +X _ +) +_ ` +; +` a +} +  +public +  +void +  + CreateKeyFile + ! +( +! " + StorageFile +" - +file +. 2 +) +2 3 +{ +  + +KcpKeyFile +  +. +  +Create +  +( +  +file + " +, +" # +null +$ ( +) +( ) +; +) * +KeyFile +  += +  +file +  +; +  +} +  +private +  +void +  + UpdateStatus + ! +( +! " +string +" ( +text +) - +, +- . + StatusTypes +/ : +type +; ? +) +? @ +{ +  +Status +  += +  +text +  +; +  + +StatusType +  += +  +( +  +int +  +) +  +type + " +; +" # +} +  +private +  + CompositeKey +  +CreateCompositeKey + / +( +/ 0 +) +0 1 +{ +  +var +  + compositeKey +  += +  +new + " + CompositeKey +# / +( +/ 0 +) +0 1 +; +1 2 +if +  +( +  + HasPassword +  +) +  + compositeKey + ) +. +) * + +AddUserKey +* 4 +( +4 5 +new +5 8 + KcpPassword +9 D +( +D E +Password +E M +) +M N +) +N O +; +O P +if +  +( +  + +HasKeyFile +  +&& +  +KeyFile + % +!= +& ( +null +) - +) +- . + compositeKey +/ ; +. +; < + +AddUserKey +< F +( +F G +new +G J + +KcpKeyFile +K U +( +U V +IOConnectionInfo +V f +. +f g +FromFile +g o +( +o p +KeyFile +p w +) +w x +) +x y +) +y z +; +z { +if +  +( +  +HasUserAccount +  +) +  + compositeKey + , +. +, - + +AddUserKey +- 7 +( +7 8 +new +8 ; +KcpUserAccount +< J +( +J K +) +K L +) +L M +; +M N +return +  + compositeKey +  +; +  +} +  +} +  +}  +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\ListMenuItemVm.cs + namespace  + ModernKeePass +  +.  + +ViewModels " +{  +public + +class  +ListMenuItemVm  +: !% +NotifyPropertyChangedBase" ; +,; < + +IIsEnabled= G +,G H +ISelectableModelI Y +{    +private + +  +bool + +  + _isSelected + +  +; + + ! +public    +string    +Title    +{    +get   ! +;  ! " +set  # & +;  & ' +}  ( ) +public  +string  +Group  +{  +get ! +;! " +set# & +;& ' +}( ) +=* + +$str, / +;/ 0 +public  +Type  +PageType  +{  +get " +;" # +set$ ' +;' ( +}) * +public  +Symbol  + +SymbolIcon  +{! " +get# & +;& ' +set( + +;+ , +}- . +public  +bool  + IsEnabled  +{  +get # +;# $ +set% ( +;( ) +}* + +=, - +true. 2 +;2 3 +public  +bool  + +IsSelected  +{  +get  +{  +return  + _isSelected $ +;$ % +}& ' +set  +{  + SetProperty  +(  +ref ! + _isSelected" - +,- . +value/ 4 +)4 5 +;5 6 +}7 8 +}  +public  +override  +string  +ToString ' +(' ( +)( ) +{  +return  +Title  +;  +}  +}  +}  +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\MainMenuItemVm.cs + namespace  + ModernKeePass +  +.  + +ViewModels " +{  +public + +class  +MainMenuItemVm  +:  +ListMenuItemVm! / +{  +public  +object  + Parameter  +{ ! +get" % +;% & +set' * +;* + +}, - +public  +Frame  + Destination  +{! " +get# & +;& ' +set( + +;+ , +}- . +}    +} + +  +MC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\RecentItemVm.cs + namespace  + ModernKeePass +  +.  + +ViewModels " +{  +public + +class  + RecentItemVm  +: % +NotifyPropertyChangedBase 8 +,8 9 +ISelectableModel: J +,J K + IRecentItemL W +{    +private + +  +bool + +  + _isSelected + +  +; + + ! +public    + StorageFile    + DatabaseFile   ' +{  ( ) +get  * - +;  - . +}  / 0 +public    +string    +Token    +{    +get   ! +;  ! " +}  # $ +public  +string  +Name  +{  +get  +; ! +}" # +public  +string  +Path  +=>  + DatabaseFile * +?* + +.+ , +Path, 0 +;0 1 +public  +bool  + +IsSelected  +{  +get  +{  +return  + _isSelected $ +;$ % +}& ' +set  +{  + SetProperty  +(  +ref ! + _isSelected" - +,- . +value/ 4 +)4 5 +;5 6 +}7 8 +}  +public  + RecentItemVm  +(  +)  +{  +}  +public  + RecentItemVm  +(  +string " +token# ( +,( ) +string* 0 +metadata1 9 +,9 : + IStorageItem; G +fileH L +)L M +{  +Token  +=  +token  +;  +Name  +=  +metadata  +;  + DatabaseFile  +=  +file  +as " + StorageFile# . +;. / +}  +public  +void  +OpenDatabaseFile $ +($ % +)% & +{    +OpenDatabaseFile!!  +(!!  +DatabaseService!! , +.!!, - +Instance!!- 5 +)!!5 6 +;!!6 7 +}""  +public$$  +void$$  +OpenDatabaseFile$$ $ +($$$ % +IDatabaseService$$% 5 +database$$6 > +)$$> ? +{%%  +database&&  +.&&  + DatabaseFile&& ! +=&&" # + DatabaseFile&&$ 0 +;&&0 1 +}''  +public))  +void))  +UpdateAccessTime)) $ +())$ % +)))% & +{**  +UpdateAccessTime++  +(++  + RecentService++ * +.++* + +Instance+++ 3 +)++3 4 +;++4 5 +},,  +public..  +async..  +void..  +UpdateAccessTime.. * +(..* + +IRecentService..+ 9 +recent..: @ +)..@ A +{//  +await00  +recent00  +.00  + GetFileAsync00 % +(00% & +Token00& + +)00+ , +;00, - +}11  +}22  +}33 ; +JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\EntryDetailPage.xaml.cs + namespace   + ModernKeePass   +  +.    +Views    +{   +public + +sealed  +partial  +class  +EntryDetailPage / +{  +public  +EntryVm  +Model  +=>  +( ! +EntryVm! ( +)( ) + DataContext* 5 +;5 6 +public  +NavigationHelper  +NavigationHelper 0 +{1 2 +get3 6 +;6 7 +}8 9 +public  +EntryDetailPage  +(  +)  +{  +InitializeComponent  +(  +) ! +;! " +NavigationHelper  +=  +new " +NavigationHelper# 3 +(3 4 +this4 8 +)8 9 +;9 : +NavigationHelper  +.  + LoadState & ++=' )& +navigationHelper_LoadState* D +;D E +}    +private--  +void-- & +navigationHelper_LoadState-- / +(--/ 0 +object--0 6 +sender--7 = +,--= > +LoadStateEventArgs--? Q +e--R S +)--S T +{--U V +}--V W + protected::  +override::  +void::  + OnNavigatedTo:: - +(::- . +NavigationEventArgs::. A +e::B C +)::C D +{;;  +NavigationHelper<<  +.<<  + OnNavigatedTo<< * +(<<* + +e<<+ , +)<<, - +;<<- . +if==  +(==  +!==  +(==  +e==  +.==  + Parameter==  +is==  +EntryVm==! ( +)==( ) +)==) * +return==+ 1 +;==1 2 + DataContext>>  +=>>  +(>>  +EntryVm>> " +)>>" # +e>># $ +.>>$ % + Parameter>>% . +;>>. / +}??  + protectedAA  +overrideAA  +voidAA  +OnNavigatedFromAA / +(AA/ 0 +NavigationEventArgsAA0 C +eAAD E +)AAE F +{BB  +NavigationHelperCC  +.CC  +OnNavigatedFromCC , +(CC, - +eCC- . +)CC. / +;CC/ 0 +}DD  +privateHH  +voidHH  +DeleteButton_ClickHH ' +(HH' ( +objectHH( . +senderHH/ 5 +,HH5 6 +RoutedEventArgsHH7 F +eHHG H +)HHH I +{II  +varJJ  +resourceJJ  +=JJ  +newJJ  +ResourcesServiceJJ / +(JJ/ 0 +)JJ0 1 +;JJ1 2 +varKK  +messageKK  +=KK  +ModelKK  +.KK  +IsRecycleOnDeleteKK 1 +?LL  +resourceLL  +.LL  +GetResourceValueLL + +(LL+ , +$strLL, H +)LLH I +:MM  +resourceMM  +.MM  +GetResourceValueMM + +(MM+ , +$strMM, G +)MMG H +;MMH I +varNN  +textNN  +=NN  +ModelNN  +.NN  +IsRecycleOnDeleteNN . +?NN/ 0 +resourceNN1 9 +.NN9 : +GetResourceValueNN: J +(NNJ K +$strNNK Z +)NNZ [ +:NN\ ] +resourceNN^ f +.NNf g +GetResourceValueNNg w +(NNw x +$str NNx  +) +NN  +; +NN  +MessageDialogHelperOO  +.OO  +ShowActionDialogOO 0 +(OO0 1 +resourceOO1 9 +.OO9 : +GetResourceValueOO: J +(OOJ K +$strOOK ^ +)OO^ _ +,OO_ ` +messageOOa h +,OOh i +resourcePP  +.PP  +GetResourceValuePP ) +(PP) * +$strPP* D +)PPD E +,PPE F +resourceQQ  +.QQ  +GetResourceValueQQ ) +(QQ) * +$strQQ* D +)QQD E +,QQE F +aQQG H +=>QQI K +{RR # +ToastNotificationHelperSS ' +.SS' ( +ShowMovedToastSS( 6 +(SS6 7 +ModelSS7 < +,SS< = +resourceSS> F +.SSF G +GetResourceValueSSG W +(SSW X +$strSSX h +)SSh i +,SSi j +textSSk o +)SSo p +;SSp q +ModelTT  +.TT  + MarkForDeleteTT # +(TT# $ +resourceTT$ , +.TT, - +GetResourceValueTT- = +(TT= > +$strTT> O +)TTO P +)TTP Q +;TTQ R +ifUU  +(UU  +FrameUU  +.UU  + CanGoBackUU # +)UU# $ +FrameUU% * +.UU* + +GoBackUU+ 1 +(UU1 2 +)UU2 3 +;UU3 4 +}VV  +,VV  +nullVV  +)VV  +;VV  +}WW  +privateYY  +voidYY  +RestoreButton_ClickYY ( +(YY( ) +objectYY) / +senderYY0 6 +,YY6 7 +RoutedEventArgsYY8 G +eYYH I +)YYI J +{ZZ  +var[[  +resource[[  +=[[  +new[[  +ResourcesService[[ / +([[/ 0 +)[[0 1 +;[[1 2# +ToastNotificationHelper\\ # +.\\# $ +ShowMovedToast\\$ 2 +(\\2 3 +Model\\3 8 +,\\8 9 +resource\\: B +.\\B C +GetResourceValue\\C S +(\\S T +$str\\T i +)\\i j +,\\j k +resource\\l t +.\\t u +GetResourceValue \\u  +( +\\  +$str +\\  +) +\\  +) +\\  +; +\\  +if]]  +(]]  +Frame]]  +.]]  + CanGoBack]]  +)]]  +Frame]]! & +.]]& ' +GoBack]]' - +(]]- . +)]]. / +;]]/ 0 +}^^  +private``  +void`` ) +EntryDetailPage_OnSizeChanged`` 2 +(``2 3 +object``3 9 +sender``: @ +,``@ A +SizeChangedEventArgs``B V +e``W X +)``X Y +{aa  +VisualStateManagerbb  +.bb  + GoToStatebb ( +(bb( ) +thisbb) - +,bb- . +ebb/ 0 +.bb0 1 +NewSizebb1 8 +.bb8 9 +Widthbb9 > +<bb? @ +$numbbA D +?bbE F +$strbbG N +:bbO P +$strbbQ X +,bbX Y +truebbZ ^ +)bb^ _ +;bb_ ` +}cc  +privateee  +voidee 7 ++HamburgerMenuUserControl_OnSelectionChangedee @ +(ee@ A +objecteeA G +sendereeH N +,eeN O% +SelectionChangedEventArgseeP i +eeej k +)eek l +{ff  +vargg  +listViewgg  +=gg  +sendergg ! +asgg" $ +ListViewgg% - +;gg- . +EntryVmhh  +entryhh  +;hh  +switchii  +(ii  +listViewii  +?ii  +.ii  + SelectedIndexii + +)ii+ , +{jj  +casekk  +-kk  +$numkk  +:kk  +returnll  +;ll  +defaultmm  +:mm  +entrynn  +=nn  +listViewnn $ +?nn$ % +.nn% & + SelectedItemnn& 2 +asnn3 5 +EntryVmnn6 = +;nn= > +breakoo  +;oo  +}pp  + +StackPanelrr  +.rr  + DataContextrr " +=rr# $ +entryrr% * +;rr* + +}ss  +}tt  +}uu r +JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\GroupDetailPage.xaml.cs + namespace  + ModernKeePass +  +.  +Views  +{  +public + +sealed  +partial  +class  +GroupDetailPage / +{  +public  +NavigationHelper  +NavigationHelper 0 +{1 2 +get3 6 +;6 7 +}8 9 +public  +GroupVm  +Model  +=>  +( ! +GroupVm! ( +)( ) + DataContext) 4 +;4 5 +public  +GroupDetailPage  +(  +)  +{  +InitializeComponent    +(    +)   ! +;  ! " +NavigationHelper!!  +=!!  +new!! " +NavigationHelper!!# 3 +(!!3 4 +this!!4 8 +)!!8 9 +;!!9 : +NavigationHelper""  +.""  + LoadState"" & ++=""' )& +navigationHelper_LoadState""* D +;""D E +}##  +private00  +void00 & +navigationHelper_LoadState00 / +(00/ 0 +object000 6 +sender007 = +,00= > +LoadStateEventArgs00? Q +e00R S +)00S T +{00U V +}00V W + protected==  +override==  +void==  + OnNavigatedTo== - +(==- . +NavigationEventArgs==. A +e==B C +)==C D +{>>  +NavigationHelper??  +.??  + OnNavigatedTo?? * +(??* + +e??+ , +)??, - +;??- . +ifAA  +(AA  +eAA  +.AA  + ParameterAA  +isAA  +PasswordEventArgsAA 0 +)AA0 1 + DataContextBB  +=BB  +(BB  +(BB  +PasswordEventArgsBB 1 +)BB1 2 +eBB3 4 +.BB4 5 + ParameterBB5 > +)BB> ? +.BB? @ + RootGroupBB@ I +;BBI J +elseCC  +ifCC  +(CC  +eCC  +.CC  + ParameterCC  +isCC! # +GroupVmCC$ + +)CC+ , + DataContextDD  +=DD  +(DD  +GroupVmDD & +)DD& ' +eDD( ) +.DD) * + ParameterDD* 3 +;DD3 4 +}EE  + protectedGG  +overrideGG  +voidGG  +OnNavigatedFromGG / +(GG/ 0 +NavigationEventArgsGG0 C +eGGD E +)GGE F +{HH  +NavigationHelperII  +.II  +OnNavigatedFromII , +(II, - +eII- . +)II. / +;II/ 0 +}JJ  +privatePP  +voidPP # +groups_SelectionChangedPP , +(PP, - +objectPP- 3 +senderPP4 : +,PP: ;% +SelectionChangedEventArgsPP< U +ePPV W +)PPW X +{QQ  +varRR  +listViewRR  +=RR  +senderRR ! +asRR" $ +ListViewRR% - +;RR- . +GroupVmSS  +groupSS  +;SS  +switchTT  +(TT  +listViewTT  +?TT  +.TT  + SelectedIndexTT + +)TT+ , +{UU  +caseVV  +-VV  +$numVV  +:VV  +returnWW  +;WW  +defaultXX  +:XX  +groupYY  +=YY  +listViewYY $ +?YY$ % +.YY% & + SelectedItemYY& 2 +asYY3 5 +GroupVmYY6 = +;YY= > +breakZZ  +;ZZ  +}[[  +Frame\\  +.\\  +Navigate\\  +(\\  +typeof\\ ! +(\\! " +GroupDetailPage\\" 1 +)\\1 2 +,\\2 3 +group\\4 9 +)\\9 : +;\\: ; +}]]  +private__  +void__ $ +entries_SelectionChanged__ - +(__- . +object__. 4 +sender__5 ; +,__; <% +SelectionChangedEventArgs__= V +e__W X +)__X Y +{``  +EntryVmaa  +entryaa  +;aa  +switchbb  +(bb  +GridViewbb  +.bb  + SelectedIndexbb * +)bb* + +{cc  +casedd  +-dd  +$numdd  +:dd  +returnee  +;ee  +defaultff  +:ff  +entrygg  +=gg  +GridViewgg $ +.gg$ % + SelectedItemgg% 1 +asgg2 4 +EntryVmgg5 < +;gg< = +breakhh  +;hh  +}ii  +Framejj  +.jj  +Navigatejj  +(jj  +typeofjj ! +(jj! " +EntryDetailPagejj" 1 +)jj1 2 +,jj2 3 +entryjj4 9 +)jj9 : +;jj: ; +}kk  +privatemm  +voidmm  +DeleteButton_Clickmm ' +(mm' ( +objectmm( . +sendermm/ 5 +,mm5 6 +RoutedEventArgsmm7 F +emmG H +)mmH I +{nn  +varoo  +resourceoo  +=oo  +newoo  +ResourcesServiceoo / +(oo/ 0 +)oo0 1 +;oo1 2 +varpp  +messagepp  +=pp  +Modelpp  +.pp  +IsRecycleOnDeletepp 1 +?qq  +resourceqq  +.qq  +GetResourceValueqq + +(qq+ , +$strqq, H +)qqH I +:rr  +resourcerr  +.rr  +GetResourceValuerr + +(rr+ , +$strrr, G +)rrG H +;rrH I +varss  +textss  +=ss  +Modelss  +.ss  +IsRecycleOnDeletess . +?ss/ 0 +resourcess1 9 +.ss9 : +GetResourceValuess: J +(ssJ K +$strssK Z +)ssZ [ +:ss\ ] +resourcess^ f +.ssf g +GetResourceValuessg w +(ssw x +$str ssx  +) +ss  +; +ss  +MessageDialogHelpertt  +.tt  +ShowActionDialogtt 0 +(tt0 1 +resourcett1 9 +.tt9 : +GetResourceValuett: J +(ttJ K +$strttK ^ +)tt^ _ +,tt_ ` +messagetta h +,tth i +resourceuu  +.uu  +GetResourceValueuu ) +(uu) * +$struu* D +)uuD E +,uuE F +resourcevv  +.vv  +GetResourceValuevv ) +(vv) * +$strvv* D +)vvD E +,vvE F +avvG H +=>vvI K +{ww # +ToastNotificationHelperxx + +.xx+ , +ShowMovedToastxx, : +(xx: ; +Modelxx; @ +,xx@ A +resourcexxB J +.xxJ K +GetResourceValuexxK [ +(xx[ \ +$strxx\ l +)xxl m +,xxm n +textxxo s +)xxs t +;xxt u +Modelyy  +.yy  + MarkForDeleteyy ' +(yy' ( +resourceyy( 0 +.yy0 1 +GetResourceValueyy1 A +(yyA B +$stryyB S +)yyS T +)yyT U +;yyU V +ifzz  +(zz  +Framezz  +.zz  + CanGoBackzz ' +)zz' ( +Framezz) . +.zz. / +GoBackzz/ 5 +(zz5 6 +)zz6 7 +;zz7 8 +}{{  +,{{  +null{{  +){{  +;{{  +}||  +private~~  +void~~  +RestoreButton_Click~~ ( +(~~( ) +object~~) / +sender~~0 6 +,~~6 7 +RoutedEventArgs~~8 G +e~~H I +)~~I J +{  +var +  +resource +  += +  +new +  +ResourcesService + / +( +/ 0 +) +0 1 +; +1 2% +ToastNotificationHelper + # +. +# $ +ShowMovedToast +$ 2 +( +2 3 +Model +3 8 +, +8 9 +resource +: B +. +B C +GetResourceValue +C S +( +S T +$str +T i +) +i j +, +j k +resource +  +. +  +GetResourceValue + ) +( +) * +$str +* 9 +) +9 : +) +: ; +; +; < +if +  +( +  +Frame +  +. +  + CanGoBack +  +) +  +Frame +! & +. +& ' +GoBack +' - +( +- . +) +. / +; +/ 0 +} +  +private +  +void + , +SemanticZoom_ViewChangeStarted + 3 +( +3 4 +object +4 : +sender +; A +, +A B. + SemanticZoomViewChangedEventArgs +C c +e +d e +) +e f +{ +  +if +  +( +  +e +  +. + " +IsSourceZoomedInView + & +== +' ) +false +* / +) +/ 0 +{ +  +e +  +. +  +DestinationItem + ! +. +! " +Item +" & += +' ( +e +) * +. +* + + +SourceItem ++ 5 +. +5 6 +Item +6 : +; +: ; +} +  +} +  +private +  +void + % +CreateEntry_ButtonClick + , +( +, - +object +- 3 +sender +4 : +, +: ; +RoutedEventArgs +< K +e +L M +) +M N +{ +  +Frame +  +. +  +Navigate +  +( +  +typeof + ! +( +! " +EntryDetailPage +" 1 +) +1 2 +, +2 3 +Model +4 9 +. +9 : + AddNewEntry +: E +( +E F +) +F G +) +G H +; +H I +} +  +private +  +void + % +CreateGroup_ButtonClick + , +( +, - +object +- 3 +sender +4 : +, +: ; +RoutedEventArgs +< K +e +L M +) +M N +{ +  +Frame +  +. +  +Navigate +  +( +  +typeof + ! +( +! " +GroupDetailPage +" 1 +) +1 2 +, +2 3 +Model +4 9 +. +9 : + AddNewGroup +: E +( +E F +) +F G +) +G H +; +H I +} +  +private +  +void + ( +GridView_DragItemsStarting + / +( +/ 0 +object +0 6 +sender +7 = +, += >( +DragItemsStartingEventArgs +? Y +e +Z [ +) +[ \ +{ +  +e +  +. +  +Cancel +  += +  +! +  +Model +  +. +  + +IsEditMode + ( +; +( ) +e +  +. +  +Data +  +. +  +RequestedOperation + % += +& '" +DataPackageOperation +( < +. +< = +Move += A +; +A B +} +  +private +  +void + . + SearchBox_OnSuggestionsRequested + 5 +( +5 6 + SearchBox +6 ? +sender +@ F +, +F G4 +&SearchBoxSuggestionsRequestedEventArgs +H n +args +o s +) +s t +{ +  +var +  +imageUri +  += + ) +RandomAccessStreamReference + 6 +. +6 7 + CreateFromUri +7 D +( +D E +new +E H +Uri +I L +( +L M +$str M  +)   +)   +;   +var +  +results +  += +  +Model +  +. +  + +SubEntries + * +. +* + +Where ++ 0 +( +0 1 +e +1 2 +=> +3 5 +e +6 7 +. +7 8 +Name +8 < +. +< = +IndexOf += D +( +D E +args +E I +. +I J + QueryText +J S +, +S T +StringComparison +U e +. +e f +OrdinalIgnoreCase +f w +) +w x +>= +y { +$num +| } +) +} ~ +. +~  +Take   +(   +$num   +)   +;   +foreach +  +( +  +var +  +result +  +in + " +results +# * +) +* + +{ +  +args +  +. +  +Request +  +. + ( +SearchSuggestionCollection + 7 +. +7 8$ +AppendResultSuggestion +8 N +( +N O +result +O U +. +U V +Name +V Z +, +Z [ +result +\ b +. +b c + ParentGroup +c n +. +n o +Name +o s +, +s t +result +u { +. +{ | +Id +| ~ +, +~  +imageUri   +,   +string   +.   +Empty   +)   +;   +} +  +} +  +private +  +void + 0 +"SearchBox_OnResultSuggestionChosen + 7 +( +7 8 + SearchBox +8 A +sender +B H +, +H I6 +(SearchBoxResultSuggestionChosenEventArgs +J r +args +s w +) +w x +{ +  +var +  +entry +  += +  +Model +  +. +  + +SubEntries + ( +. +( ) +FirstOrDefault +) 7 +( +7 8 +e +8 9 +=> +: < +e += > +. +> ? +Id +? A +== +B D +args +E I +. +I J +Tag +J M +) +M N +; +N O +Frame +  +. +  +Navigate +  +( +  +typeof + ! +( +! " +EntryDetailPage +" 1 +) +1 2 +, +2 3 +entry +4 9 +) +9 : +; +: ; +} +  +private +  +void + + +GroupDetailPage_OnSizeChanged + 2 +( +2 3 +object +3 9 +sender +: @ +, +@ A" +SizeChangedEventArgs +B V +e +W X +) +X Y +{ +  +VisualStateManager +  +. +  + GoToState + ( +( +( ) +this +) - +, +- . +e +/ 0 +. +0 1 +NewSize +1 8 +. +8 9 +Width +9 > +< +? @ +$num +A D +? +E F +$str +G N +: +O P +$str +Q X +, +X Y +true +Z ^ +) +^ _ +; +_ ` +} +  +} +  +}  +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\OpenDatabasePage.xaml.cs + namespace + +  + ModernKeePass + + +  +. + +  +Views + +  +{   +public + +sealed  +partial  +class  +OpenDatabasePage 0 +{  +private  +Frame  + +_mainFrame  +; ! +public  +OpenVm  +Model  +=>  +(  +OpenVm & +)& ' + DataContext' 2 +;2 3 +public  +OpenDatabasePage  +(  +) ! +{  +InitializeComponent  +(  +) ! +;! " +}  + protected  +override  +void  + OnNavigatedTo - +(- . +NavigationEventArgs. A +eB C +)C D +{  +base  +.  + OnNavigatedTo  +(  +e  +) ! +;! " + +_mainFrame  +=  +e  +.  + Parameter $ +as% ' +Frame( - +;- . +}  +private    +async    +void    +ButtonBase_OnClick   - +(  - . +object  . 4 +sender  5 ; +,  ; < +RoutedEventArgs  = L +e  M N +)  N O +{!!  +var""  +picker""  +=""  +new##  +FileOpenPicker## " +{$$  +ViewMode%%  +=%%  +PickerViewMode%% - +.%%- . +List%%. 2 +,%%2 3" +SuggestedStartLocation&& * +=&&+ , +PickerLocationId&&- = +.&&= > +DocumentsLibrary&&> N +}''  +;''  +picker((  +.((  +FileTypeFilter(( ! +.((! " +Add((" % +(((% & +$str((& - +)((- . +;((. / +var++  +file++  +=++  +await++  +picker++ # +.++# $ +PickSingleFileAsync++$ 7 +(++7 8 +)++8 9 +;++9 : +if,,  +(,,  +file,,  +==,,  +null,,  +),,  +return,, $ +;,,$ % +Model--  +.--  +OpenFile--  +(--  +file--  +)--  +;-- ! +}..  +}//  +}00  +]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\RecentDatabasesPage.xaml.cs + namespace  + ModernKeePass +  +.  +Views  +{  +public + +sealed  +partial  +class  +RecentDatabasesPage 3 +{    +public + +  +RecentDatabasesPage + + " +( + +" # +) + +# $ +{    +InitializeComponent    +(    +)   ! +;  ! " +}    +}  +}  +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\SaveDatabasePage.xaml.cs + namespace   + ModernKeePass   +  +.    +Views    +{   +public + +sealed  +partial  +class  +SaveDatabasePage 0 +{  +private  +Frame  + +_mainFrame  +; ! +public  +SaveVm  +Model  +=>  +(  +SaveVm & +)& ' + DataContext' 2 +;2 3 +public  +SaveDatabasePage  +(  +) ! +{  +InitializeComponent  +(  +) ! +;! " +}  + protected  +override  +void  + OnNavigatedTo - +(- . +NavigationEventArgs. A +eB C +)C D +{  +base  +.  + OnNavigatedTo  +(  +e  +) ! +;! " + +_mainFrame  +=  +e  +.  + Parameter $ +as% ' +Frame( - +;- . +}  +private  +async  +void  +SaveButton_OnClick - +(- . +object. 4 +sender5 ; +,; < +RoutedEventArgs= L +eM N +)N O +{    +await!!  +Model!!  +.!!  +Save!!  +(!!  +)!!  +;!!  + +_mainFrame""  +.""  +Navigate""  +(""  +typeof"" & +(""& ' +MainPage""' / +)""/ 0 +)""0 1 +;""1 2 +}##  +private%%  +async%%  +void%%  +SaveAsButton_OnClick%% / +(%%/ 0 +object%%0 6 +sender%%7 = +,%%= > +RoutedEventArgs%%? N +e%%O P +)%%P Q +{&&  +var''  + +savePicker''  +=''  +new''  +FileSavePicker''! / +{(( " +SuggestedStartLocation)) & +=))' ( +PickerLocationId))) 9 +.))9 : +DocumentsLibrary)): J +,))J K +SuggestedFileName** ! +=**" # +$str**$ 2 +}++  +;++  + +savePicker,,  +.,,  +FileTypeChoices,, & +.,,& ' +Add,,' * +(,,* + +$str,,+ A +,,,A B +new,,C F +List,,G K +<,,K L +string,,L R +>,,R S +{,,T U +$str,,V ] +},,^ _ +),,_ ` +;,,` a +var..  +file..  +=..  +await..  + +savePicker.. ' +...' ( +PickSaveFileAsync..( 9 +(..9 : +)..: ; +;..; < +if//  +(//  +file//  +==//  +null//  +)//  +return// $ +;//$ % +Model00  +.00  +Save00  +(00  +file00  +)00  +;00  + +_mainFrame22  +.22  +Navigate22  +(22  +typeof22 & +(22& ' +MainPage22' / +)22/ 0 +)220 1 +;221 2 +}33  +}44  +}55  +GC:\Sources\Other\ModernKeePass\ModernKeePass\Properties\AssemblyInfo.cs +[  +assembly  +: + + AssemblyTitle  +(  +$str ( +)( ) +]) * +[  +assembly  +: + +AssemblyDescription  +(  +$str b +)b c +]c d +[   +assembly    +:   +! +AssemblyConfiguration    +(   ! +$str  ! # +)  # $ +]  $ % +[ + +  +assembly + +  +: + + + +AssemblyCompany + +  +( + +  +$str + + # +) + +# $ +] + +$ % +[   +assembly    +:   + +AssemblyProduct    +(    +$str   * +)  * + +]  + , +[   +assembly    +:   + +AssemblyCopyright    +(    +$str   / +)  / 0 +]  0 1 +[   +assembly    +:   + +AssemblyTrademark    +(    +$str    +)    +]   ! +[  +assembly  +: + +AssemblyCulture  +(  +$str  +)  +]  +[  +assembly  +: + +AssemblyVersion  +(  +$str % +)% & +]& ' +[  +assembly  +: + +AssemblyFileVersion  +(  +$str ) +)) * +]* + +[  +assembly  +: + + +ComVisible  +(  +false  +)  +]  +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\EntryVm.cs + namespace   + ModernKeePass   +  +.    + +ViewModels   " +{   +public + +class  +EntryVm  +: " +INotifyPropertyChanged 1 +,1 2 + IPwEntity3 < +,< = +ISelectableModel> N +{  +public  +GroupVm  + ParentGroup " +{# $ +get% ( +;( ) +private* 1 +set2 5 +;5 6 +}7 8 +public  +GroupVm  + PreviousGroup $ +{% & +get' * +;* + +private, 3 +set4 7 +;7 8 +}9 : +public  +System  +.  +Drawing  +.  +Color # +?# $ +BackgroundColor% 4 +=>5 7 +_pwEntry8 @ +?@ A +.A B +BackgroundColorB Q +;Q R +public  +System  +.  +Drawing  +.  +Color # +?# $ +ForegroundColor% 4 +=>5 7 +_pwEntry8 @ +?@ A +.A B +ForegroundColorB Q +;Q R +public  +bool # +IsRevealPasswordEnabled + +=>, . +!/ 0 +string0 6 +.6 7 + IsNullOrEmpty7 D +(D E +PasswordE M +)M N +;N O +public  +bool  + +HasExpired  +=> ! +HasExpirationDate" 3 +&&4 6 +_pwEntry7 ? +.? @ + +ExpiryTime@ J +<K L +DateTimeM U +.U V +NowV Y +;Y Z +public  +double ' +PasswordComplexityIndicator 1 +=>2 4 +QualityEstimation5 F +.F G +EstimatePasswordBitsG [ +([ \ +Password\ d +?d e +.e f + ToCharArrayf q +(q r +)r s +)s t +;t u +public  +bool $ +UpperCasePatternSelected , +{- . +get/ 2 +;2 3 +set4 7 +;7 8 +}9 : +=; < +true= A +;A B +public  +bool $ +LowerCasePatternSelected , +{- . +get/ 2 +;2 3 +set4 7 +;7 8 +}9 : +=; < +true= A +;A B +public  +bool ! +DigitsPatternSelected ) +{* + +get, / +;/ 0 +set1 4 +;4 5 +}6 7 +=8 9 +true: > +;> ? +public  +bool  +MinusPatternSelected ( +{) * +get+ . +;. / +set0 3 +;3 4 +}5 6 +public  +bool % +UnderscorePatternSelected - +{. / +get0 3 +;3 4 +set5 8 +;8 9 +}: ; +public  +bool  +SpacePatternSelected ( +{) * +get+ . +;. / +set0 3 +;3 4 +}5 6 +public  +bool " +SpecialPatternSelected * +{+ , +get- 0 +;0 1 +set2 5 +;5 6 +}7 8 +public  +bool # +BracketsPatternSelected + +{, - +get. 1 +;1 2 +set3 6 +;6 7 +}8 9 +public  +string  + CustomChars ! +{" # +get$ ' +;' ( +set) , +;, - +}. / +=0 1 +string2 8 +.8 9 +Empty9 > +;> ? +public    +PwUuid    +IdUuid    +=>    +_pwEntry   ( +?  ( ) +.  ) * +Uuid  * . +;  . / +public!!  +string!!  +Id!!  +=>!!  +_pwEntry!! $ +?!!$ % +.!!% & +Uuid!!& * +.!!* + + ToHexString!!+ 6 +(!!6 7 +)!!7 8 +;!!8 9 +public""  +bool""  +IsRecycleOnDelete"" % +=>""& ( + _database"") 2 +.""2 3 +RecycleBinEnabled""3 D +&&""E G +!""H I + ParentGroup""I T +.""T U + +IsSelected""U _ +;""_ ` +public##  + IEnumerable##  +<##  + IPwEntity## $ +>##$ % + +BreadCrumb##& 0 +=>##1 3 +new##4 7 +List##8 < +<##< = + IPwEntity##= F +>##F G +(##G H + ParentGroup##H S +.##S T + +BreadCrumb##T ^ +)##^ _ +{##` a + ParentGroup##a l +}##l m +;##m n +public''  +bool''  + +IsSelected''  +{''  +get''! $ +;''$ % +set''& ) +;'') * +}''+ , +=''- . +true''/ 3 +;''3 4 +public))  +double))  +PasswordLength)) $ +{**  +get++  +{++  +return++  +_passwordLength++ ( +;++( ) +}++* + +set,,  +{--  +_passwordLength..  +=.. ! +value.." ' +;..' (! +NotifyPropertyChanged// % +(//% & +$str//& 6 +)//6 7 +;//7 8 +}00  +}11  +public33  +string33  +Name33  +{44  +get55  +{55  +return55  + GetEntryValue55 & +(55& ' +PwDefs55' - +.55- . + +TitleField55. 8 +)558 9 +;559 : +}55; < +set66  +{66  + SetEntryValue66  +(66  +PwDefs66 & +.66& ' + +TitleField66' 1 +,661 2 +value663 8 +)668 9 +;669 : +}66; < +}77  +public::  +string::  +UserName::  +{;;  +get<<  +{<<  +return<<  + GetEntryValue<< & +(<<& ' +PwDefs<<' - +.<<- . + UserNameField<<. ; +)<<; < +;<<< = +}<<> ? +set==  +{==  + SetEntryValue==  +(==  +PwDefs== & +.==& ' + UserNameField==' 4 +,==4 5 +value==6 ; +)==; < +;==< = +}==> ? +}>>  +public@@  +string@@  +Password@@  +{AA  +getBB  +{BB  +returnBB  + GetEntryValueBB & +(BB& ' +PwDefsBB' - +.BB- . + PasswordFieldBB. ; +)BB; < +;BB< = +}BB> ? +setCC  +{DD  + SetEntryValueEE  +(EE  +PwDefsEE $ +.EE$ % + PasswordFieldEE% 2 +,EE2 3 +valueEE4 9 +)EE9 : +;EE: ;! +NotifyPropertyChangedFF % +(FF% & +$strFF& 0 +)FF0 1 +;FF1 2! +NotifyPropertyChangedGG % +(GG% & +$strGG& C +)GGC D +;GGD E +}HH  +}II  +publicKK  +stringKK  +UrlKK  +{LL  +getMM  +{MM  +returnMM  + GetEntryValueMM & +(MM& ' +PwDefsMM' - +.MM- . +UrlFieldMM. 6 +)MM6 7 +;MM7 8 +}MM9 : +setNN  +{NN  + SetEntryValueNN  +(NN  +PwDefsNN & +.NN& ' +UrlFieldNN' / +,NN/ 0 +valueNN1 6 +)NN6 7 +;NN7 8 +}NN9 : +}OO  +publicQQ  +stringQQ  +NotesQQ  +{RR  +getSS  +{SS  +returnSS  + GetEntryValueSS & +(SS& ' +PwDefsSS' - +.SS- . + +NotesFieldSS. 8 +)SS8 9 +;SS9 : +}SS; < +setTT  +{TT  + SetEntryValueTT  +(TT  +PwDefsTT & +.TT& ' + +NotesFieldTT' 1 +,TT1 2 +valueTT3 8 +)TT8 9 +;TT9 : +}TT; < +}UU  +publicWW  +intWW  +IconIdWW  +{XX  +getYY  +{ZZ  +if[[  +([[  +_pwEntry[[  +?[[  +.[[  +IconId[[ $ +!=[[% ' +null[[( , +)[[, - +return[[. 4 +([[5 6 +int[[6 9 +)[[9 : +_pwEntry[[; C +?[[C D +.[[D E +IconId[[E K +;[[K L +return\\  +-\\  +$num\\  +;\\  +}]]  +}^^  +public``  +DateTimeOffset``  + +ExpiryDate`` ( +{aa  +getbb  +{bb  +returnbb  +newbb  +DateTimeOffsetbb + +(bb+ , +_pwEntrybb, 4 +.bb4 5 + +ExpiryTimebb5 ? +.bb? @ +Datebb@ D +)bbD E +;bbE F +}bbG H +setcc  +{cc  +ifcc  +(cc  +HasExpirationDatecc ' +)cc' ( +_pwEntrycc) 1 +.cc1 2 + +ExpiryTimecc2 < +=cc= > +valuecc? D +.ccD E +DateTimeccE M +;ccM N +}ccO P +}dd  +publicff  +TimeSpanff  + +ExpiryTimeff " +{gg  +gethh  +{hh  +returnhh  +_pwEntryhh ! +.hh! " + +ExpiryTimehh" , +.hh, - + TimeOfDayhh- 6 +;hh6 7 +}hh8 9 +setii  +{ii  +ifii  +(ii  +HasExpirationDateii ' +)ii' ( +_pwEntryii) 1 +.ii1 2 + +ExpiryTimeii2 < +=ii= > +_pwEntryii? G +.iiG H + +ExpiryTimeiiH R +.iiR S +DateiiS W +.iiW X +AddiiX [ +(ii[ \ +valueii\ a +)iia b +;iib c +}iid e +}jj  +publicll  +boolll  + +IsEditModell  +{mm  +getnn  +{nn  +returnnn  + +IsSelectednn # +&&nn$ & + _isEditModenn' 2 +;nn2 3 +}nn4 5 +setoo  +{pp  + _isEditModeqq  +=qq  +valueqq # +;qq# $! +NotifyPropertyChangedrr % +(rr% & +$strrr& 2 +)rr2 3 +;rr3 4 +}ss  +}tt  +publicvv  +boolvv  + IsVisiblevv  +{ww  +getxx  +{xx  +returnxx  + +_isVisiblexx # +;xx# $ +}xx% & +setyy  +{zz  + +_isVisible{{  +={{  +value{{ " +;{{" #! +NotifyPropertyChanged|| % +(||% & +$str||& 1 +)||1 2 +;||2 3 +}}}  +}~~  +public +  +bool +  +IsRevealPassword + $ +{ +  +get +  +{ +  +return +  +_isRevealPassword + * +; +* + +} +, - +set +  +{ +  +_isRevealPassword + ! += +" # +value +$ ) +; +) *# +NotifyPropertyChanged + % +( +% & +$str +& 8 +) +8 9 +; +9 : +} +  +} +  +public +  +bool +  +HasExpirationDate + % +{ +  +get +  +{ +  +return +  +_pwEntry + ! +. +! " +Expires +" ) +; +) * +} ++ , +set +  +{ +  +_pwEntry +  +. +  +Expires +  += +! " +value +# ( +; +( )# +NotifyPropertyChanged + % +( +% & +$str +& 9 +) +9 : +; +: ; +} +  +} +  +public +  + IEnumerable +  +< +  + IPwEntity + $ +> +$ % +History +& - +{ +  +get +  +{ +  +var +  +history +  += +  +new + ! +List +" & +< +& ' +EntryVm +' . +> +. / +{ +0 1 +this +1 5 +} +5 6 +; +6 7 +foreach +  +( +  +var +  + historyEntry + ) +in +* , +_pwEntry +- 5 +. +5 6 +History +6 = +) += > +{ +  +history +  +. +  +Add +  +( +  +new + # +EntryVm +$ + +( ++ , + historyEntry +, 8 +, +8 9 + ParentGroup +: E +) +E F +{ +G H + +IsSelected +H R += +S T +false +U Z +} +Z [ +) +[ \ +; +\ ] +} +  +return +  +history +  +; +  +} +  +} +  +public +  +event + ) +PropertyChangedEventHandler + 0 +PropertyChanged +1 @ +; +@ A +private +  +readonly +  +PwEntry +  +_pwEntry +! ) +; +) * +private +  +readonly +  +IDatabaseService + ) + _database +* 3 +; +3 4 +private +  +readonly +  +IResourceService + ) + _resource +* 3 +; +3 4 +private +  +bool +  + _isEditMode +  +; + ! +private +  +bool +  +_isRevealPassword + & +; +& ' +private +  +double +  +_passwordLength + & += +' ( +$num +) + +; ++ , +private +  +bool +  + +_isVisible +  += + ! +true +" & +; +& ' +private +  +void + # +NotifyPropertyChanged + * +( +* + +string ++ 1 + propertyName +2 > +) +> ? +{ +  +PropertyChanged +  +? +  +. +  +Invoke + # +( +# $ +this +$ ( +, +( ) +new +* -& +PropertyChangedEventArgs +. F +( +F G + propertyName +G S +) +S T +) +T U +; +U V +} +  +public +  +EntryVm +  +( +  +) +  +{ +  +} +  +internal +  +EntryVm +  +( +  +PwEntry +  +entry +! & +, +& ' +GroupVm +( / +parent +0 6 +) +6 7 +: +8 9 +this +: > +( +> ? +entry +? D +, +D E +parent +F L +, +L M +DatabaseService +N ] +. +] ^ +Instance +^ f +, +f g +new +h k +ResourcesService +l | +( +| } +) +} ~ +) +~  +{   +}   +public +  +EntryVm +  +( +  +PwEntry +  +entry + $ +, +$ % +GroupVm +& - +parent +. 4 +, +4 5 +IDatabaseService +6 F +database +G O +, +O P +IResourceService +Q a +resource +b j +) +j k +{ +  + _database +  += +  +database +  +; + ! + _resource +  += +  +resource +  +; + ! +_pwEntry +  += +  +entry +  +; +  + ParentGroup +  += +  +parent +  +; + ! +} +  +public +  +void +  +GeneratePassword + $ +( +$ % +) +% & +{ +  +var +  + pwProfile +  += +  +new +  + PwProfile + ) +{ +  + GeneratorType +  += + # +PasswordGeneratorType + 5 +. +5 6 +CharSet +6 = +, += > +Length +  += +  +( +  +uint +  +) +  +PasswordLength + - +, +- . +CharSet +  += +  +new +  + PwCharSet + ' +( +' ( +) +( ) +} +  +; +  +if +  +( + & +UpperCasePatternSelected + ( +) +( ) + pwProfile +* 3 +. +3 4 +CharSet +4 ; +. +; < +Add +< ? +( +? @ + PwCharSet +@ I +. +I J + UpperCase +J S +) +S T +; +T U +if +  +( + & +LowerCasePatternSelected + ( +) +( ) + pwProfile +* 3 +. +3 4 +CharSet +4 ; +. +; < +Add +< ? +( +? @ + PwCharSet +@ I +. +I J + LowerCase +J S +) +S T +; +T U +if +  +( + # +DigitsPatternSelected + % +) +% & + pwProfile +' 0 +. +0 1 +CharSet +1 8 +. +8 9 +Add +9 < +( +< = + PwCharSet += F +. +F G +Digits +G M +) +M N +; +N O +if +  +( + $ +SpecialPatternSelected + & +) +& ' + pwProfile +( 1 +. +1 2 +CharSet +2 9 +. +9 : +Add +: = +( += > + PwCharSet +> G +. +G H + SpecialChars +H T +) +T U +; +U V +if +  +( + " +MinusPatternSelected + $ +) +$ % + pwProfile +& / +. +/ 0 +CharSet +0 7 +. +7 8 +Add +8 ; +( +; < +$char +< ? +) +? @ +; +@ A +if +  +( + ' +UnderscorePatternSelected + ) +) +) * + pwProfile ++ 4 +. +4 5 +CharSet +5 < +. +< = +Add += @ +( +@ A +$char +A D +) +D E +; +E F +if +  +( + " +SpacePatternSelected + $ +) +$ % + pwProfile +& / +. +/ 0 +CharSet +0 7 +. +7 8 +Add +8 ; +( +; < +$char +< ? +) +? @ +; +@ A +if +  +( + % +BracketsPatternSelected + ' +) +' ( + pwProfile +) 2 +. +2 3 +CharSet +3 : +. +: ; +Add +; > +( +> ? + PwCharSet +? H +. +H I +Brackets +I Q +) +Q R +; +R S + pwProfile +  +. +  +CharSet +  +. +  +Add + ! +( +! " + CustomChars +" - +) +- . +; +. / +ProtectedString +  +password + $ +; +$ % + PwGenerator +  +. +  +Generate +  +( + ! +out +! $ +password +% - +, +- . + pwProfile +/ 8 +, +8 9 +null +: > +, +> ? +new +@ C# +CustomPwGeneratorPool +D Y +( +Y Z +) +Z [ +) +[ \ +; +\ ] +_pwEntry +  +? +  +. +  +Strings +  +. +  +Set + ! +( +! " +PwDefs +" ( +. +( ) + PasswordField +) 6 +, +6 7 +password +8 @ +) +@ A +; +A B# +NotifyPropertyChanged + ! +( +! " +$str +" , +) +, - +; +- .# +NotifyPropertyChanged + ! +( +! " +$str +" ; +) +; < +; +< =# +NotifyPropertyChanged + ! +( +! " +$str +" ? +) +? @ +; +@ A +} +  +private +  +string +  + GetEntryValue + $ +( +$ % +string +% + +key +, / +) +/ 0 +{ +  +return +  +_pwEntry +  +? +  +. +  +Strings + $ +. +$ % +GetSafe +% , +( +, - +key +- 0 +) +0 1 +. +1 2 + +ReadString +2 < +( +< = +) += > +; +> ? +} +  +private +  +void +  + SetEntryValue + " +( +" # +string +# ) +key +* - +, +- . +string +/ 5 +newValue +6 > +) +> ? +{ +  +_pwEntry +  +? +  +. +  +Strings +  +. +  +Set + ! +( +! " +key +" % +, +% & +new +' * +ProtectedString ++ : +( +: ; +true +; ? +, +? @ +newValue +A I +) +I J +) +J K +; +K L +} +  +public +  +void +  + MarkForDelete + ! +( +! " +string +" ( +recycleBinTitle +) 8 +) +8 9 +{ +  +if +  +( +  + _database +  +. +  +RecycleBinEnabled + + +&& +, . + _database +/ 8 +. +8 9 + +RecycleBin +9 C +? +C D +. +D E +IdUuid +E K +== +L N +null +O S +) +S T + _database +  +. +  +CreateRecycleBin + * +( +* + +recycleBinTitle ++ : +) +: ; +; +; < +Move +  +( +  + _database +  +. +  +RecycleBinEnabled + , +&& +- / +! +0 1 + ParentGroup +1 < +. +< = + +IsSelected += G +? +H I + _database +J S +. +S T + +RecycleBin +T ^ +: +_ ` +null +a e +) +e f +; +f g +} +  +public +  +void +  + +UndoDelete +  +( +  +) +  +{ +  +Move +  +( +  + PreviousGroup +  +) +  +; +  +} +  +public +  +void +  +Move +  +( +  +GroupVm +  + destination +! , +) +, - +{ +  + PreviousGroup +  += +  + ParentGroup + ' +; +' ( + PreviousGroup +  +. +  +Entries + ! +. +! " +Remove +" ( +( +( ) +this +) - +) +- . +; +. / +if +  +( +  + destination +  +== +  +null + # +) +# $ +{ +  + _database +  +. +  +AddDeletedItem + ( +( +( ) +IdUuid +) / +) +/ 0 +; +0 1 +return +  +; +  +} +  + ParentGroup +  += +  + destination + % +; +% & + ParentGroup +  +. +  +Entries +  +. +  +Add + # +( +# $ +this +$ ( +) +( ) +; +) * +} +  +public +  +void +  + CommitDelete +  +( + ! +) +! " +{ +  +_pwEntry +  +. +  + ParentGroup +  +. + ! +Entries +! ( +. +( ) +Remove +) / +( +/ 0 +_pwEntry +0 8 +) +8 9 +; +9 : +if +  +( +  +! +  + _database +  +. +  +RecycleBinEnabled + , +|| +- / + PreviousGroup +0 = +. += > + +IsSelected +> H +) +H I + _database +J S +. +S T +AddDeletedItem +T b +( +b c +IdUuid +c i +) +i j +; +j k +} +  +public +  +void +  +Save +  +( +  +) +  +{ +  + _database +  +. +  +Save +  +( +  +) +  +; +  +} +  +public +  +PwEntry +  + +GetPwEntry + ! +( +! " +) +" # +{ +  +return +  +_pwEntry +  +; +  +} +  +public +  +override +  +string +  +ToString + ' +( +' ( +) +( ) +{ +  +return +  + +IsSelected +  +? +  + _resource + ) +. +) * +GetResourceValue +* : +( +: ; +$str +; I +) +I J +: +K L +_pwEntry +M U +. +U V" +LastModificationTime +V j +. +j k +ToString +k s +( +s t +$str +t w +) +w x +; +x y +} +  +} +  +}  +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\GroupVm.cs + namespace   + ModernKeePass   +  +.    + +ViewModels   " +{   +public   + +class    +GroupVm    +:   % +NotifyPropertyChangedBase   4 +,  4 5 + IPwEntity  6 ? +,  ? @ +ISelectableModel  A Q +{  +public  +GroupVm  + ParentGroup " +{# $ +get% ( +;( ) +private* 1 +set2 5 +;5 6 +}7 8 +public  +GroupVm  + PreviousGroup $ +{% & +get' * +;* + +private, 3 +set4 7 +;7 8 +}9 : +public  +ObservableCollection # +<# $ +EntryVm$ + +>+ , +Entries- 4 +{  +get  +{  +return  +_entries ! +;! " +}# $ +private  +set  +{  + SetProperty % +(% & +ref& ) +_entries* 2 +,2 3 +value4 9 +)9 : +;: ; +}< = +}  +public  + IEnumerable  +<  +EntryVm " +>" # + +SubEntries$ . +{  +get  +{  +var  + +subEntries  +=  +new! $ +List% ) +<) * +EntryVm* 1 +>1 2 +(2 3 +)3 4 +;4 5 + +subEntries  +.  +AddRange # +(# $ +Entries$ + +)+ , +;, - +foreach  +(  +var  +group " +in# % +Groups& , +), - +{  + +subEntries    +.    +AddRange   ' +(  ' ( +group  ( - +.  - . + +SubEntries  . 8 +)  8 9 +;  9 : +}!!  +return##  + +subEntries## ! +;##! " +}$$  +}%%  +public''  +ObservableCollection'' # +<''# $ +GroupVm''$ + +>''+ , +Groups''- 3 +{''4 5 +get''6 9 +;''9 : +set''; > +;''> ? +}''@ A +=''B C +new''D G +ObservableCollection''H \ +<''\ ] +GroupVm''] d +>''d e +(''e f +)''f g +;''g h +public))  +PwUuid))  +IdUuid))  +=>))  +_pwGroup)) ( +?))( ) +.))) * +Uuid))* . +;)). / +public**  +string**  +Id**  +=>**  +IdUuid** " +?**" # +.**# $ + ToHexString**$ / +(**/ 0 +)**0 1 +;**1 2 +public++  +bool++  + IsNotRoot++  +=>++  + ParentGroup++! , +!=++- / +null++0 4 +;++4 5 +public--  +bool--  + ShowRestore--  +=>-- " + IsNotRoot--# , +&&--- / + ParentGroup--0 ; +.--; < + +IsSelected--< F +;--F G +public//  +bool//  +IsRecycleOnDelete// % +=>//& ( + _database//) 2 +.//2 3 +RecycleBinEnabled//3 D +&&//E G +!//H I + +IsSelected//I S +&&//T V +!//W X + ParentGroup//X c +.//c d + +IsSelected//d n +;//n o +public44  +bool44  + +IsSelected44  +{55  +get66  +{66  +return66  + _database66 " +!=66# % +null66& * +&&66+ - + _database66. 7 +.667 8 +RecycleBinEnabled668 I +&&66J L + _database66M V +.66V W + +RecycleBin66W a +?66a b +.66b c +Id66c e +==66f h +Id66i k +;66k l +}66m n +set77  +{88  +if99  +(99  +value99  +&&99  +_pwGroup99 % +!=99& ( +null99) - +)99- . + _database99/ 8 +.998 9 + +RecycleBin999 C +=99D E +this99F J +;99J K +}::  +};;  +public==  +IOrderedEnumerable== ! +<==! " + IGrouping==" + +<==+ , +char==, 0 +,==0 1 +EntryVm==2 9 +>==9 : +>==: ; +EntriesZoomedOut==< L +=>==M O +from==P T +e==U V +in==W Y +Entries==Z a +group>>  +e>>  +by>>  +e>>  +.>>  +Name>>  +.>>  +ToUpper>> % +(>>% & +)>>& ' +.>>' ( +FirstOrDefault>>( 6 +(>>6 7 +)>>7 8 +into>>9 = +grp>>> A +orderby??  +grp??  +.??  +Key??  +select@@  +grp@@  +;@@  +publicBB  +stringBB  +NameBB  +{CC  +getDD  +{DD  +returnDD  +_pwGroupDD ! +==DD" $ +nullDD% ) +?DD* + +stringDD, 2 +.DD2 3 +EmptyDD3 8 +:DD9 : +_pwGroupDD; C +.DDC D +NameDDD H +;DDH I +}DDJ K +setEE  +{EE  +_pwGroupEE  +.EE  +NameEE  +=EE ! +valueEE" ' +;EE' ( +}EE) * +}FF  +publicHH  +intHH  +IconIdHH  +{II  +getJJ  +{KK  +ifLL  +(LL  +_pwGroupLL  +?LL  +.LL  +IconIdLL $ +!=LL% ' +nullLL( , +)LL, - +returnLL. 4 +(LL5 6 +intLL6 9 +)LL9 : +_pwGroupLL; C +?LLC D +.LLD E +IconIdLLE K +;LLK L +returnMM  +-MM  +$numMM  +;MM  +}NN  +setOO  +{OO  +_pwGroupOO  +.OO  +IconIdOO ! +=OO" # +(OO$ % +PwIconOO% + +)OO+ , +valueOO, 1 +;OO1 2 +}OO3 4 +}PP  +publicRR  +boolRR  + +IsEditModeRR  +{SS  +getTT  +{TT  +returnTT  + _isEditModeTT $ +;TT$ % +}TT& ' +setUU  +{UU  + SetPropertyUU  +(UU  +refUU ! + _isEditModeUU" - +,UU- . +valueUU/ 4 +)UU4 5 +;UU5 6 +}UU7 8 +}VV  +publicXX  +boolXX  + IsMenuClosedXX  +{YY  +getZZ  +{ZZ  +returnZZ  + _isMenuClosedZZ & +;ZZ& ' +}ZZ( ) +set[[  +{[[  + SetProperty[[  +([[  +ref[[ ! + _isMenuClosed[[" / +,[[/ 0 +value[[1 6 +)[[6 7 +;[[7 8 +}[[9 : +}\\  +public^^  + IEnumerable^^  +<^^  + IPwEntity^^ $ +>^^$ % + +BreadCrumb^^& 0 +{__  +get``  +{aa  +varbb  +groupsbb  +=bb  +newbb  +Stackbb! & +<bb& ' +GroupVmbb' . +>bb. / +(bb/ 0 +)bb0 1 +;bb1 2 +varcc  +groupcc  +=cc  +thiscc  +;cc ! +whiledd  +(dd  +groupdd  +.dd  + ParentGroupdd ( +!=dd) + +nulldd, 0 +)dd0 1 +{ee  +groupff  +=ff  +groupff ! +.ff! " + ParentGroupff" - +;ff- . +groupsgg  +.gg  +Pushgg  +(gg  +groupgg % +)gg% & +;gg& ' +}hh  +returnjj  +groupsjj  +;jj  +}kk  +}ll  +privatenn  +readonlynn  +PwGroupnn  +_pwGroupnn! ) +;nn) * +privateoo  +readonlyoo  +IDatabaseServiceoo ) + _databaseoo* 3 +;oo3 4 +privatepp  +boolpp  + _isEditModepp  +;pp ! +privateqq  +PwEntryqq  +_reorderedEntryqq ' +;qq' ( +privaterr  +ObservableCollectionrr $ +<rr$ % +EntryVmrr% , +>rr, - +_entriesrr. 6 +=rr7 8 +newrr9 < +ObservableCollectionrr= Q +<rrQ R +EntryVmrrR Y +>rrY Z +(rrZ [ +)rr[ \ +;rr\ ] +privatess  +boolss  + _isMenuClosedss " +=ss# $ +truess% ) +;ss) * +publicuu  +GroupVmuu  +(uu  +)uu  +{uu  +}uu  +internalww  +GroupVmww  +(ww  +PwGroupww  +pwGroupww! ( +,ww( ) +GroupVmww* 1 +parentww2 8 +,ww8 9 +PwUuidww: @ + recycleBinIdwwA M +=wwN O +nullwwP T +)wwT U +:wwV W +thiswwX \ +(ww\ ] +pwGroupww] d +,wwd e +parentwwf l +,wwl m +DatabaseServicexx  +.xx  +Instancexx $ +,xx$ % + recycleBinIdxx& 2 +)xx2 3 +{yy  +}yy +  +public{{  +GroupVm{{  +({{  +PwGroup{{  +pwGroup{{ & +,{{& ' +GroupVm{{( / +parent{{0 6 +,{{6 7 +IDatabaseService{{8 H +database{{I Q +,{{Q R +PwUuid{{S Y + recycleBinId{{Z f +={{g h +null{{i m +){{m n +{||  +_pwGroup}}  +=}}  +pwGroup}}  +;}}  + _database~~  +=~~  +database~~  +;~~ ! + ParentGroup  +=  +parent  +; ! +if +  +( +  + recycleBinId +  +!= +  +null + $ +&& +% ' +_pwGroup +( 0 +. +0 1 +Uuid +1 5 +. +5 6 +Equals +6 < +( +< = + recycleBinId += I +) +I J +) +J K + _database +L U +. +U V + +RecycleBin +V ` += +a b +this +c g +; +g h +Entries +  += +  +new + " +ObservableCollection + . +< +. / +EntryVm +/ 6 +> +6 7 +( +7 8 +pwGroup +8 ? +. +? @ +Entries +@ G +. +G H +Select +H N +( +N O +e +O P +=> +Q S +new +T W +EntryVm +X _ +( +_ ` +e +` a +, +a b +this +c g +) +g h +) +h i +) +i j +; +j k +Entries +  +. +  +CollectionChanged + % ++= +& (' +Entries_CollectionChanged +) B +; +B C +Groups +  += +  +new + " +ObservableCollection + - +< +- . +GroupVm +. 5 +> +5 6 +( +6 7 +pwGroup +7 > +. +> ? +Groups +? E +. +E F +Select +F L +( +L M +g +M N +=> +O Q +new +R U +GroupVm +V ] +( +] ^ +g +^ _ +, +_ ` +this +a e +, +e f + recycleBinId +g s +) +s t +) +t u +) +u v +; +v w +} +  +private +  +void + ' +Entries_CollectionChanged + . +( +. / +object +/ 5 +sender +6 < +, +< =. + NotifyCollectionChangedEventArgs +> ^ +e +_ ` +) +` a +{ +  +switch +  +( +  +e +  +. +  +Action +  +) +  +{ +  +case + + +NotifyCollectionChangedAction + 2 +. +2 3 +Remove +3 9 +: +9 : +var +  +oldIndex +  += +! " +( +# $ +uint +$ ( +) +( ) +e +* + +. ++ , +OldStartingIndex +, < +; +< = +_reorderedEntry + $ += +% & +_pwGroup +' / +. +/ 0 +Entries +0 7 +. +7 8 +GetAt +8 = +( += > +oldIndex +> F +) +F G +; +G H +_pwGroup +  +. +  +Entries + $ +. +$ % +RemoveAt +% - +( +- . +oldIndex +. 6 +) +6 7 +; +7 8 +break +  +; +  +case + + +NotifyCollectionChangedAction + 2 +. +2 3 +Add +3 6 +: +6 7 +if +  +( +  +_reorderedEntry + ' +== +( * +null ++ / +) +/ 0 +_pwGroup +1 9 +. +9 : +AddEntry +: B +( +B C +( +C D +( +D E +EntryVm +E L +) +L M +e +N O +. +O P +NewItems +P X +[ +X Y +$num +Y Z +] +Z [ +) +[ \ +. +\ ] + +GetPwEntry +] g +( +g h +) +h i +, +i j +true +k o +) +o p +; +p q +else +  +_pwGroup + ! +. +! " +Entries +" ) +. +) * +Insert +* 0 +( +0 1 +( +1 2 +uint +2 6 +) +6 7 +e +7 8 +. +8 9 +NewStartingIndex +9 I +, +I J +_reorderedEntry +K Z +) +Z [ +; +[ \ +break +  +; +  +} +  +} +  +public +  +GroupVm +  + AddNewGroup + " +( +" # +string +# ) +name +* . += +/ 0 +$str +1 3 +) +3 4 +{ +  +var +  +pwGroup +  += +  +new +  +PwGroup + % +( +% & +true +& * +, +* + +true +, 0 +, +0 1 +name +2 6 +, +6 7 +PwIcon +8 > +. +> ? +Folder +? E +) +E F +; +F G +_pwGroup +  +. +  +AddGroup +  +( +  +pwGroup + % +, +% & +true +' + +) ++ , +; +, - +var +  +newGroup +  += +  +new +  +GroupVm + & +( +& ' +pwGroup +' . +, +. / +this +0 4 +) +4 5 +{ +6 7 +Name +7 ; += +< = +name +> B +, +B C + +IsEditMode +D N += +O P +string +Q W +. +W X + IsNullOrEmpty +X e +( +e f +name +f j +) +j k +} +k l +; +l m +Groups +  +. +  +Add +  +( +  +newGroup +  +) +  +; + ! +return +  +newGroup +  +; +  +} +  +public +  +EntryVm +  + AddNewEntry + " +( +" # +) +# $ +{ +  +var +  +pwEntry +  += +  +new +  +PwEntry + % +( +% & +true +& * +, +* + +true +, 0 +) +0 1 +; +1 2 +var +  +newEntry +  += +  +new +  +EntryVm + & +( +& ' +pwEntry +' . +, +. / +this +0 4 +) +4 5 +{ +6 7 + +IsEditMode +7 A += +B C +true +D H +} +H I +; +I J +newEntry +  +. +  +GeneratePassword + % +( +% & +) +& ' +; +' ( +Entries +  +. +  +Add +  +( +  +newEntry +  +) + ! +; +! " +return +  +newEntry +  +; +  +} +  +public +  +void +  + MarkForDelete + ! +( +! " +string +" ( +recycleBinTitle +) 8 +) +8 9 +{ +  +if +  +( +  + _database +  +. +  +RecycleBinEnabled + + +&& +, . + _database +/ 8 +. +8 9 + +RecycleBin +9 C +? +C D +. +D E +IdUuid +E K +== +L N +null +O S +) +S T + _database +  +. +  +CreateRecycleBin + * +( +* + +recycleBinTitle ++ : +) +: ; +; +; < +Move +  +( +  + _database +  +. +  +RecycleBinEnabled + , +&& +- / +! +0 1 + +IsSelected +1 ; +? +< = + _database +> G +. +G H + +RecycleBin +H R +: +S T +null +U Y +) +Y Z +; +Z [ +} +  +public +  +void +  + +UndoDelete +  +( +  +) +  +{ +  +Move +  +( +  + PreviousGroup +  +) +  +; +  +} +  +public +  +void +  +Move +  +( +  +GroupVm +  + destination +! , +) +, - +{ +  + PreviousGroup +  += +  + ParentGroup + ' +; +' ( + PreviousGroup +  +. +  +Groups +  +. + ! +Remove +! ' +( +' ( +this +( , +) +, - +; +- . + PreviousGroup +  +. +  +_pwGroup + " +. +" # +Groups +# ) +. +) * +Remove +* 0 +( +0 1 +_pwGroup +1 9 +) +9 : +; +: ; +if +  +( +  + destination +  +== +  +null + # +) +# $ +{ +  + _database +  +. +  +AddDeletedItem + ( +( +( ) +IdUuid +) / +) +/ 0 +; +0 1 +return +  +; +  +} +  + ParentGroup +  += +  + destination + % +; +% & + ParentGroup +  +. +  +Groups +  +. +  +Add + " +( +" # +this +# ' +) +' ( +; +( ) + ParentGroup +  +. +  +_pwGroup +  +. + ! +AddGroup +! ) +( +) * +_pwGroup +* 2 +, +2 3 +true +4 8 +) +8 9 +; +9 : +} +  +public +  +void +  + CommitDelete +  +( + ! +) +! " +{ +  +_pwGroup +  +. +  + ParentGroup +  +. + ! +Groups +! ' +. +' ( +Remove +( . +( +. / +_pwGroup +/ 7 +) +7 8 +; +8 9 +if +  +( +  + _database +  +. +  +RecycleBinEnabled + + +&& +, . +! +/ 0 + PreviousGroup +0 = +. += > + +IsSelected +> H +) +H I + _database +J S +. +S T + +RecycleBin +T ^ +. +^ _ +_pwGroup +_ g +. +g h +AddGroup +h p +( +p q +_pwGroup +q y +, +y z +true +{  +)   +;   +else +  + _database +  +. +  +AddDeletedItem + ) +( +) * +IdUuid +* 0 +) +0 1 +; +1 2 +} +  +public +  +void +  +Save +  +( +  +) +  +{ +  + _database +  +. +  +Save +  +( +  +) +  +; +  +} +  +public +  +void +  + SortEntries +  +( +  +) + ! +{ +  +var +  +comparer +  += +  +new +  +PwEntryComparer + . +( +. / +PwDefs +/ 5 +. +5 6 + +TitleField +6 @ +, +@ A +true +B F +, +F G +false +H M +) +M N +; +N O +try +  +{ +  +_pwGroup +  +. +  +Entries +  +. + ! +Sort +! % +( +% & +comparer +& . +) +. / +; +/ 0 +Entries +  += +  +new + " +ObservableCollection + 2 +< +2 3 +EntryVm +3 : +> +: ; +( +; < +Entries +< C +. +C D +OrderBy +D K +( +K L +e +L M +=> +N P +e +Q R +. +R S +Name +S W +) +W X +) +X Y +; +Y Z +} +  +catch +  +( +  + Exception +  +e +  +) +  +{ + ! +MessageDialogHelper + # +. +# $ +ShowErrorDialog +$ 3 +( +3 4 +e +4 5 +) +5 6 +; +6 7 +} +  +} +  +public +  +void +  + +SortGroups +  +( +  +) +  +{ +  +try +  +{ +  +_pwGroup +  +. +  + SortSubGroups + & +( +& ' +false +' , +) +, - +; +- . +Groups +  += +  +new + " +ObservableCollection + 1 +< +1 2 +GroupVm +2 9 +> +9 : +( +: ; +Groups +; A +. +A B +OrderBy +B I +( +I J +g +J K +=> +L N +g +O P +. +P Q +Name +Q U +) +U V +. +V W +ThenBy +W ] +( +] ^ +g +^ _ +=> +` b +g +c d +. +d e +_pwGroup +e m +== +n p +null +q u +) +u v +) +v w +; +w x +OnPropertyChanged + ! +( +! " +$str +" * +) +* + +; ++ , +} +  +catch +  +( +  + Exception +  +e +  +) +  +{ + ! +MessageDialogHelper + # +. +# $ +ShowErrorDialog +$ 3 +( +3 4 +e +4 5 +) +5 6 +; +6 7 +} +  +} +  +public +  +override +  +string +  +ToString + ' +( +' ( +) +( ) +{ +  +return +  +Name +  +; +  +} +  +} +  +}  +NC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsNewVm.cs + namespace  + ModernKeePass +  +.  + +ViewModels " +{  +public + +class  + SettingsNewVm  +{  +private    +readonly    +ISettingsService   ) + _settings  * 3 +;  3 4 +public    + SettingsNewVm    +(    +)    +:    +this  ! % +(  % & +SettingsService  & 5 +.  5 6 +Instance  6 > +)  > ? +{    +}   +  +public  + SettingsNewVm  +(  +ISettingsService - +settings. 6 +)6 7 +{  + _settings  +=  +settings  +; ! +}  +public  +bool  +IsCreateSample " +{  +get  +{  +return  + _settings " +." # + +GetSetting# - +<- . +bool. 2 +>2 3 +(3 4 +$str4 < +)< = +;= > +}? @ +set  +{  + _settings  +.  + +PutSetting & +(& ' +$str' / +,/ 0 +value1 6 +)6 7 +;7 8 +}9 : +}  +public  + IEnumerable  +<  +string ! +>! " + FileFormats# . +=>/ 1 +new2 5 +[6 7 +]7 8 +{8 9 +$str9 < +,< = +$str> A +}A B +;B C +public  +string  +FileFormatVersion ' +{  +get  +{  +return  + _settings " +." # + +GetSetting# - +<- . +string. 4 +>4 5 +(5 6 +$str6 I +)I J +;J K +}L M +set  +{  + _settings  +.  + +PutSetting & +(& ' +$str' : +,: ; +value< A +)A B +;B C +}D E +}  +}    +}!! 3 +EC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SettingsVm.cs + namespace   + ModernKeePass   +  +.    + +ViewModels   " +{ + +  +public   + +class    + +SettingsVm    +:   % +NotifyPropertyChangedBase   7 +,  7 8 +IHasSelectableObject  9 M +{    +private    +ListMenuItemVm    + _selectedItem   , +;  , - +private  +IOrderedEnumerable " +<" # + IGrouping# , +<, - +string- 3 +,3 4 +ListMenuItemVm5 C +>C D +>D E + +_menuItemsF P +;P Q +public  +IOrderedEnumerable ! +<! " + IGrouping" + +<+ , +string, 2 +,2 3 +ListMenuItemVm4 B +>B C +>C D + MenuItemsE N +{  +get  +{  +return  + +_menuItems # +;# $ +}% & +set  +{  + SetProperty  +(  +ref ! + +_menuItems" , +,, - +value. 3 +)3 4 +;4 5 +}6 7 +}  +public  +ISelectableModel  + SelectedItem , +{  +get  +{  +return  + _selectedItem & +;& ' +}( ) +set  +{  +if  +(  + _selectedItem ! +==" $ +value% * +)* + +return, 2 +;2 3 +if  +(  + _selectedItem ! +!=" $ +null% ) +)) * +{  + _selectedItem ! +.! " + +IsSelected" , +=- . +false/ 4 +;4 5 +}    + SetProperty""  +(""  +ref""  + _selectedItem"" - +,""- . +(""/ 0 +ListMenuItemVm""0 > +)""> ? +value""? D +)""D E +;""E F +if$$  +($$  + _selectedItem$$ ! +!=$$" $ +null$$% ) +)$$) * +{%%  + _selectedItem&& ! +.&&! " + +IsSelected&&" , +=&&- . +true&&/ 3 +;&&3 4 +}''  +}((  +}))  +public++  + +SettingsVm++  +(++  +)++  +:++  +this++ " +(++" # +DatabaseService++# 2 +.++2 3 +Instance++3 ; +,++; < +new++= @ +ResourcesService++A Q +(++Q R +)++R S +)++S T +{++U V +}++W X +public--  + +SettingsVm--  +(--  +IDatabaseService-- * +database--+ 3 +,--3 4 +IResourceService--5 E +resource--F N +)--N O +{..  +var//  + menuItems//  +=//  +new//  +ObservableCollection// 4 +<//4 5 +ListMenuItemVm//5 C +>//C D +{00  +new11  +ListMenuItemVm11 " +{22  +Title33  +=33  +resource33 $ +.33$ % +GetResourceValue33% 5 +(335 6 +$str336 K +)33K L +,33L M +Group44  +=44  +resource44 $ +.44$ % +GetResourceValue44% 5 +(445 6 +$str446 T +)44T U +,44U V + +SymbolIcon55  +=55  +Symbol55! ' +.55' ( +Add55( + +,55+ , +PageType66  +=66  +typeof66 % +(66% &# +SettingsNewDatabasePage66& = +)66= > +,66> ? + +IsSelected77  +=77  +true77! % +}88  +,88  +new99  +ListMenuItemVm99 " +{::  +Title;;  +=;;  +resource;; $ +.;;$ % +GetResourceValue;;% 5 +(;;5 6 +$str;;6 L +);;L M +,;;M N +Group<<  +=<<  +resource<< $ +.<<$ % +GetResourceValue<<% 5 +(<<5 6 +$str<<6 T +)<<T U +,<<U V + +SymbolIcon==  +===  +Symbol==! ' +.==' ( +Save==( , +,==, - +PageType>>  +=>>  +typeof>> % +(>>% & +SettingsSavePage>>& 6 +)>>6 7 +}??  +,??  +new@@  +ListMenuItemVm@@ " +{AA  +TitleBB  +=BB  +resourceBB $ +.BB$ % +GetResourceValueBB% 5 +(BB5 6 +$strBB6 O +)BBO P +,BBP Q +GroupCC  +=CC  +resourceCC $ +.CC$ % +GetResourceValueCC% 5 +(CC5 6 +$strCC6 Q +)CCQ R +,CCR S + +SymbolIconDD  +=DD  +SymbolDD! ' +.DD' ( +SettingDD( / +,DD/ 0 +PageTypeEE  +=EE  +typeofEE % +(EE% & +SettingsDatabasePageEE& : +)EE: ; +,EE; < + IsEnabledFF  +=FF  +databaseFF ( +.FF( ) +IsOpenFF) / +}GG  +,GG  +newHH  +ListMenuItemVmHH " +{II  +TitleJJ  +=JJ  +resourceJJ $ +.JJ$ % +GetResourceValueJJ% 5 +(JJ5 6 +$strJJ6 P +)JJP Q +,JJQ R +GroupKK  +=KK  +resourceKK $ +.KK$ % +GetResourceValueKK% 5 +(KK5 6 +$strKK6 Q +)KKQ R +,KKR S + +SymbolIconLL  +=LL  +SymbolLL! ' +.LL' ( + PermissionsLL( 3 +,LL3 4 +PageTypeMM  +=MM  +typeofMM % +(MM% & +SettingsSecurityPageMM& : +)MM: ; +,MM; < + IsEnabledNN  +=NN  +databaseNN ( +.NN( ) +IsOpenNN) / +}OO  +}PP  +;PP  + SelectedItemQQ  +=QQ  + menuItemsQQ $ +.QQ$ % +FirstOrDefaultQQ% 3 +(QQ3 4 +mQQ4 5 +=>QQ6 8 +mQQ9 : +.QQ: ; + +IsSelectedQQ; E +)QQE F +;QQF G + MenuItemsSS  +=SS  +fromSS  +itemSS ! +inSS" $ + menuItemsSS% . +groupSS/ 4 +itemSS5 9 +bySS: < +itemSS= A +.SSA B +GroupSSB G +intoSSH L +grpSSM P +orderbySSQ X +grpSSY \ +.SS\ ] +KeySS] ` +selectSSa g +grpSSh k +;SSk l +}TT  +}UU  +}VV U +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\MainVm.cs + namespace + +  + ModernKeePass + + +  +. + +  + +ViewModels + + " +{   +public   + +class    +MainVm    +:   % +NotifyPropertyChangedBase   3 +,  3 4 +IHasSelectableObject  5 I +{    +private  +IOrderedEnumerable " +<" # + IGrouping# , +<, - +string- 3 +,3 4 +MainMenuItemVm5 C +>C D +>D E +_mainMenuItemsF T +;T U +private  +MainMenuItemVm  + _selectedItem , +;, - +public  +string  +Name  +{  +get  +; ! +}" # +=$ % +Package& - +.- . +Current. 5 +.5 6 + DisplayName6 A +;A B +public  +IOrderedEnumerable ! +<! " + IGrouping" + +<+ , +string, 2 +,2 3 +MainMenuItemVm4 B +>B C +>C D + MainMenuItemsE R +{  +get  +{  +return  +_mainMenuItems ' +;' ( +}) * +set  +{  + SetProperty  +(  +ref ! +_mainMenuItems" 0 +,0 1 +value2 7 +)7 8 +;8 9 +}: ; +}  +public  +ISelectableModel  + SelectedItem , +{  +get  +{  +return  + _selectedItem & +;& ' +}( ) +set  +{  +if  +(  + _selectedItem ! +==" $ +value% * +)* + +return, 2 +;2 3 +if  +(  + _selectedItem ! +!=" $ +null% ) +)) * +{    + _selectedItem!! ! +.!!! " + +IsSelected!!" , +=!!- . +false!!/ 4 +;!!4 5 +}""  + SetProperty$$  +($$  +ref$$  + _selectedItem$$ - +,$$- . +($$/ 0 +MainMenuItemVm$$0 > +)$$> ? +value$$? D +)$$D E +;$$E F +if&&  +(&&  + _selectedItem&& ! +!=&&" $ +null&&% ) +)&&) * +{''  + _selectedItem(( ! +.((! " + +IsSelected((" , +=((- . +true((/ 3 +;((3 4 +}))  +}**  +}++  +public--  +MainVm--  +(--  +)--  +{--  +}--  +internal//  +MainVm//  +(//  +Frame//  +referenceFrame// , +,//, - +Frame//. 3 +destinationFrame//4 D +)//D E +://F G +this//H L +(//L M +referenceFrame//M [ +,//[ \ +destinationFrame//] m +,//m n +DatabaseService00  +.00  +Instance00 $ +,00$ % +new00& ) +ResourcesService00* : +(00: ; +)00; < +,00< = + RecentService00> K +.00K L +Instance00L T +)00T U +{11  +}11 +  +public33  +MainVm33  +(33  +Frame33  +referenceFrame33 * +,33* + +Frame33, 1 +destinationFrame332 B +,33B C +IDatabaseService33D T +database33U ] +,33] ^ +IResourceService33_ o +resource33p x +,33x y +IRecentService 33z  +recent +33  +) +33  +{44  +var55  +isDatabaseOpen55  +=55  +database55! ) +!=55* , +null55- 1 +&&552 4 +database555 = +.55= > +IsOpen55> D +;55D E +var77  + mainMenuItems77  +=77  +new77 # +ObservableCollection77$ 8 +<778 9 +MainMenuItemVm779 G +>77G H +{88  +new99  +MainMenuItemVm99 " +{::  +Title;;  +=;;  +resource;; $ +.;;$ % +GetResourceValue;;% 5 +(;;5 6 +$str;;6 H +);;H I +,;;I J +PageType<<  +=<<  +typeof<< % +(<<% & +OpenDatabasePage<<& 6 +)<<6 7 +,<<7 8 + Destination==  +=== ! +destinationFrame==" 2 +,==2 3 + Parameter>>  +=>>  +referenceFrame>> . +,>>. / + +SymbolIcon??  +=??  +Symbol??! ' +.??' ( +Page2??( - +,??- . + +IsSelected@@  +=@@  +database@@! ) +!=@@* , +null@@- 1 +&&@@2 4 +database@@5 = +.@@= > + +IsFileOpen@@> H +&&@@I K +!@@L M +database@@M U +.@@U V +IsOpen@@V \ +}AA  +,AA  +newBB  +MainMenuItemVmBB " +{CC  +TitleDD  +=DD  +resourceDD $ +.DD$ % +GetResourceValueDD% 5 +(DD5 6 +$strDD6 G +)DDG H +,DDH I +PageTypeEE  +=EE  +typeofEE % +(EE% & +NewDatabasePageEE& 5 +)EE5 6 +,EE6 7 + DestinationFF  +=FF ! +destinationFrameFF" 2 +,FF2 3 + ParameterGG  +=GG  +referenceFrameGG . +,GG. / + +SymbolIconHH  +=HH  +SymbolHH! ' +.HH' ( +AddHH( + +}II  +,II  +newJJ  +MainMenuItemVmJJ " +{KK  +TitleLL  +=LL  +resourceLL $ +.LL$ % +GetResourceValueLL% 5 +(LL5 6 +$strLL6 H +)LLH I +,LLI J +PageTypeMM  +=MM  +typeofMM % +(MM% & +SaveDatabasePageMM& 6 +)MM6 7 +,MM7 8 + DestinationNN  +=NN ! +destinationFrameNN" 2 +,NN2 3 + ParameterOO  +=OO  +referenceFrameOO . +,OO. / + +SymbolIconPP  +=PP  +SymbolPP! ' +.PP' ( +SavePP( , +,PP, - + +IsSelectedQQ  +=QQ  +isDatabaseOpenQQ! / +,QQ/ 0 + IsEnabledRR  +=RR  +isDatabaseOpenRR . +}SS  +,SS  +newTT  +MainMenuItemVmTT " +{UU  +TitleVV  +=VV  +resourceVV $ +.VV$ % +GetResourceValueVV% 5 +(VV5 6 +$strVV6 J +)VVJ K +,VVK L +PageTypeWW  +=WW  +typeofWW % +(WW% & +RecentDatabasesPageWW& 9 +)WW9 : +,WW: ; + DestinationXX  +=XX ! +destinationFrameXX" 2 +,XX2 3 + ParameterYY  +=YY  +referenceFrameYY . +,YY. / + +SymbolIconZZ  +=ZZ  +SymbolZZ! ' +.ZZ' ( +CopyZZ( , +,ZZ, - + +IsSelected[[  +=[[  +(\\  +database\\ ! +==\\" $ +null\\% ) +||\\* , +database\\- 5 +.\\5 6 +IsClosed\\6 > +)\\> ? +&&\\@ B +recent]]  +.]]  + +EntryCount]] ) +>]]* + +$num]], - +,]]- . + IsEnabled^^  +=^^  +recent^^ & +.^^& ' + +EntryCount^^' 1 +>^^2 3 +$num^^4 5 +}__  +,__  +new``  +MainMenuItemVm`` " +{aa  +Titlebb  +=bb  +resourcebb $ +.bb$ % +GetResourceValuebb% 5 +(bb5 6 +$strbb6 L +)bbL M +,bbM N +PageTypecc  +=cc  +typeofcc % +(cc% & + SettingsPagecc& 2 +)cc2 3 +,cc3 4 + Destinationdd  +=dd ! +referenceFramedd" 0 +,dd0 1 + +SymbolIconee  +=ee  +Symbolee! ' +.ee' ( +Settingee( / +}ff  +,ff  +newgg  +MainMenuItemVmgg " +{hh  +Titleii  +=ii  +resourceii $ +.ii$ % +GetResourceValueii% 5 +(ii5 6 +$strii6 I +)iiI J +,iiJ K +PageTypejj  +=jj  +typeofjj % +(jj% & + AboutPagejj& / +)jj/ 0 +,jj0 1 + Destinationkk  +=kk ! +destinationFramekk" 2 +,kk2 3 + +SymbolIconll  +=ll  +Symbolll! ' +.ll' ( +Helpll( , +}mm  +,mm  +newnn  +MainMenuItemVmnn " +{oo  +Titlepp  +=pp  +resourcepp $ +.pp$ % +GetResourceValuepp% 5 +(pp5 6 +$strpp6 J +)ppJ K +,ppK L +PageTypeqq  +=qq  +typeofqq % +(qq% & + +DonatePageqq& 0 +)qq0 1 +,qq1 2 + Destinationrr  +=rr ! +destinationFramerr" 2 +,rr2 3 + +SymbolIconss  +=ss  +Symbolss! ' +.ss' ( +Shopss( , +}tt  +}uu  +;uu  + SelectedItemww  +=ww  + mainMenuItemsww ( +.ww( ) +FirstOrDefaultww) 7 +(ww7 8 +mww8 9 +=>ww: < +mww= > +.ww> ? + +IsSelectedww? I +)wwI J +;wwJ K +ifzz  +(zz  +databasezz  +!=zz  +nullzz  +&&zz! # +databasezz$ , +.zz, - +IsOpenzz- 3 +)zz3 4 + mainMenuItems{{  +.{{  +Add{{ ! +({{! " +new{{" % +MainMenuItemVm{{& 4 +{||  +Title}}  +=}}  +database}} $ +.}}$ % +Name}}% ) +,}}) * +PageType~~  +=~~  +typeof~~ % +(~~% & +GroupDetailPage~~& 5 +)~~5 6 +,~~6 7 + Destination  += ! +referenceFrame" 0 +,0 1 + Parameter +  += +  +database + ( +. +( ) + RootGroup +) 2 +, +2 3 +Group +  += +  +$str + ' +, +' ( + +SymbolIcon +  += +  +Symbol +! ' +. +' ( +ProtectedDocument +( 9 +} +  +) +  +; +  + MainMenuItems +  += +  +from +  +item +! % +in +& ( + mainMenuItems +) 6 +group +7 < +item += A +by +B D +item +E I +. +I J +Group +J O +into +P T +grp +U X +orderby +Y ` +grp +a d +. +d e +Key +e h +select +i o +grp +p s +; +s t +} +  +} +  +}  +@C:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\NewVm.cs + namespace  + ModernKeePass +  +.  + +ViewModels " +{  +public + +class  +NewVm  +:  +OpenVm  +{  +public  +string  +Password  +{  +get! $ +;$ % +set& ) +;) * +}+ , +}  +}  +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\OpenVm.cs + namespace  + ModernKeePass +  +.  + +ViewModels " +{  +public + +class  +OpenVm  +: % +NotifyPropertyChangedBase 2 +{    +public + +  +bool + +  +ShowPasswordBox + + # +=> + +$ & + _database + +' 0 +. + +0 1 + +IsFileOpen + +1 ; +; + +; < +public    +string    +Name    +=>    + _database   ' +?  ' ( +.  ( ) +Name  ) - +;  - . +private  +readonly  +IDatabaseService ) + _database* 3 +;3 4 +public  +OpenVm  +(  +)  +:  +this  +(  +DatabaseService . +.. / +Instance/ 7 +)7 8 +{9 : +}; < +public  +OpenVm  +(  +IDatabaseService & +database' / +)/ 0 +{  + _database  +=  +database  +; ! +if  +(  +database  +==  +null  +||! # +!$ % +database% - +.- . + +IsFileOpen. 8 +)8 9 +return: @ +;@ A +OpenFile  +(  +database  +.  + DatabaseFile * +)* + +;+ , +}  +public  +void  +OpenFile  +(  + StorageFile ( +file) - +)- . +{  +OpenFile  +(  +file  +,  + RecentService ( +.( ) +Instance) 1 +)1 2 +;2 3 +}  +public  +void  +OpenFile  +(  + StorageFile ( +file) - +,- . +IRecentService/ = +recent> D +)D E +{  + _database    +.    + DatabaseFile   " +=  # $ +file  % ) +;  ) * +OnPropertyChanged!!  +(!!  +$str!! $ +)!!$ % +;!!% & +OnPropertyChanged""  +(""  +$str"" / +)""/ 0 +;""0 1 +AddToRecentList##  +(##  +file##  +,## ! +recent##" ( +)##( ) +;##) * +}$$  +private&&  +void&&  +AddToRecentList&& $ +(&&$ % + StorageFile&&% 0 +file&&1 5 +,&&5 6 +IRecentService&&7 E +recent&&F L +)&&L M +{''  +recent((  +.((  +Add((  +(((  +file((  +,((  +file(( ! +.((! " + DisplayName((" - +)((- . +;((. / +}))  +}**  +}++  +CC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\RecentVm.cs + namespace  + ModernKeePass +  +.  + +ViewModels " +{  +public + +class  +RecentVm  +: % +NotifyPropertyChangedBase 5 +,5 6 +IHasSelectableObject7 K +{    +private + +  +readonly + +  +IRecentService + + ' +_recent + +( / +; + +/ 0 +private    +ISelectableModel    + _selectedItem  ! . +;  . / +private    +ObservableCollection   $ +<  $ % + IRecentItem  % 0 +>  0 1 + _recentItems  2 > +=  ? @ +new  A D +ObservableCollection  E Y +<  Y Z + IRecentItem  Z e +>  e f +(  f g +)  g h +;  h i +public  +ObservableCollection # +<# $ + IRecentItem$ / +>/ 0 + RecentItems1 < +{  +get  +{  +return  + _recentItems % +;% & +}' ( +set  +{  + SetProperty  +(  +ref ! + _recentItems" . +,. / +value0 5 +)5 6 +;6 7 +}8 9 +}  +public  +ISelectableModel  + SelectedItem , +{  +get  +{  +return  + _selectedItem & +;& ' +}( ) +set  +{  +if  +(  + _selectedItem ! +==" $ +value% * +)* + +return, 2 +;2 3 +if  +(  + _selectedItem ! +!=" $ +null% ) +)) * +{  + _selectedItem ! +.! " + +IsSelected" , +=- . +false/ 4 +;4 5 +}  + SetProperty  +(  +ref  + _selectedItem - +,- . +value/ 4 +)4 5 +;5 6 +if!!  +(!!  + _selectedItem!! ! +==!!" $ +null!!% ) +)!!) * +return!!+ 1 +;!!1 2 + _selectedItem""  +.""  + +IsSelected"" ( +="") * +true""+ / +;""/ 0 +}##  +}$$  +public&&  +RecentVm&&  +(&&  +)&&  +:&&  +this&&  +(&&! " + RecentService&&" / +.&&/ 0 +Instance&&0 8 +)&&8 9 +{''  +}'' +  +public))  +RecentVm))  +())  +IRecentService)) & +recent))' - +)))- . +{**  +_recent++  +=++  +recent++  +;++  + RecentItems,,  +=,,  +_recent,, ! +.,,! " + GetAllFiles,," - +(,,- . +),,. / +;,,/ 0 +if--  +(--  + RecentItems--  +.--  +Count-- ! +>--" # +$num--$ % +)--% & + SelectedItem..  +=..  + RecentItems.. * +[..* + +$num..+ , +].., - +as... 0 + RecentItemVm..1 = +;..= > +}//  +public11  +void11  +ClearAll11  +(11  +)11  +{22  +_recent33  +.33  +ClearAll33  +(33  +)33  +;33  + RecentItems44  +.44  +Clear44  +(44  +)44  +;44  +}55  +}66  +}77  +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SaveVm.cs + namespace  + ModernKeePass +  +.  + +ViewModels " +{  +public + +class  +SaveVm  +{    +private + +  +readonly + +  +IDatabaseService + + ) + _database + +* 3 +; + +3 4 +public    +SaveVm    +(    +)    +:    +this    +(    +DatabaseService   . +.  . / +Instance  / 7 +)  7 8 +{  9 : +}  ; < +public    +SaveVm    +(    +IDatabaseService   & +database  ' / +)  / 0 +{  + _database  +=  +database  +; ! +}  +public  +async  +Task  +Save  +(  +bool # +close$ ) +=* + +true, 0 +)0 1 +{  + _database  +.  +Save  +(  +)  +;  +if  +(  +close  +)  +await  + _database  +.  +Close % +(% & +)& ' +;' ( +}  +public  +void  +Save  +(  + StorageFile $ +file% ) +)) * +{  + _database  +.  +Save  +(  +file  +)  +; ! +}  +}  +} @ +SC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsDatabaseVm.cs + namespace   + ModernKeePass   +  +.    + +ViewModels   " +{   +public + +class  +SettingsDatabaseVm # +:# $% +NotifyPropertyChangedBase% > +,> ? +IHasSelectableObject@ T +{  +private  +readonly  +IDatabaseService ) + _database* 3 +;3 4 +private  +GroupVm  + _selectedItem % +;% & +public  +bool  + HasRecycleBin ! +{  +get  +{  +return  + _database " +." # +RecycleBinEnabled# 4 +;4 5 +}6 7 +set  +{  + _database  +.  +RecycleBinEnabled + +=, - +value. 3 +;3 4 +OnPropertyChanged ! +(! " +$str" 1 +)1 2 +;2 3 +}  +}  +public  +bool  +IsNewRecycleBin # +{  +get    +{    +return    + _database   " +.  " # + +RecycleBin  # - +==  . 0 +null  1 5 +;  5 6 +}  7 8 +set!!  +{""  +if##  +(##  +value##  +)##  + _database## $ +.##$ % + +RecycleBin##% / +=##0 1 +null##2 6 +;##6 7 +}$$  +}%%  +public''  +ObservableCollection'' # +<''# $ +GroupVm''$ + +>''+ , +Groups''- 3 +{''4 5 +get''6 9 +;''9 : +set''; > +;''> ? +}''@ A +public))  + IEnumerable))  +<))  +string)) ! +>))! " +Ciphers))# * +{**  +get++  +{,,  +for--  +(--  +var--  +inx--  +=--  +$num--  +;-- ! +inx--" % +<--& ' + +CipherPool--( 2 +.--2 3 + +GlobalPool--3 = +.--= > + EngineCount--> I +;--I J +inx--K N +++--N P +)--P Q +{..  +yield//  +return//  + +CipherPool//! + +.//+ , + +GlobalPool//, 6 +[//6 7 +inx//7 : +]//: ; +.//; < + DisplayName//< G +;//G H +}00  +}11  +}22  +public44  +int44  + CipherIndex44  +{55  +get66  +{77  +for88  +(88  +var88  +inx88  +=88  +$num88  +;88 ! +inx88" % +<88& ' + +CipherPool88( 2 +.882 3 + +GlobalPool883 = +.88= > + EngineCount88> I +;88I J +++88K M +inx88M P +)88P Q +{99  +if::  +(::  + +CipherPool:: " +.::" # + +GlobalPool::# - +[::- . +inx::. 1 +]::1 2 +.::2 3 + +CipherUuid::3 = +.::= > +Equals::> D +(::D E + _database::E N +.::N O + +DataCipher::O Y +)::Y Z +)::Z [ +return::\ b +inx::c f +;::f g +};;  +return<<  +-<<  +$num<<  +;<<  +}==  +set>>  +{>>  + _database>>  +.>>  + +DataCipher>> & +=>>' ( + +CipherPool>>) 3 +.>>3 4 + +GlobalPool>>4 > +[>>> ? +value>>? D +]>>D E +.>>E F + +CipherUuid>>F P +;>>P Q +}>>R S +}??  +publicAA  + IEnumerableAA  +<AA  +stringAA ! +>AA! " + CompressionsAA# / +=>AA0 2 +EnumAA3 7 +.AA7 8 +GetNamesAA8 @ +(AA@ A +typeofAAA G +(AAG H" +PwCompressionAlgorithmAAH ^ +)AA^ _ +)AA_ ` +.AA` a +TakeAAa e +(AAe f +(AAf g +intAAg j +)AAj k# +PwCompressionAlgorithm AAk  +. +AA  +Count +AA  +) +AA  +; +AA  +publicCC  +stringCC  +CompressionNameCC % +{DD  +getEE  +{EE  +returnEE  +EnumEE  +.EE  +GetNameEE % +(EE% & +typeofEE& , +(EE, -" +PwCompressionAlgorithmEE- C +)EEC D +,EED E + _databaseEEF O +.EEO P +CompressionAlgorithmEEP d +)EEd e +;EEe f +}EEg h +setFF  +{FF  + _databaseFF  +.FF  +CompressionAlgorithmFF 0 +=FF1 2 +(FF3 4" +PwCompressionAlgorithmFF4 J +)FFJ K +EnumFFK O +.FFO P +ParseFFP U +(FFU V +typeofFFV \ +(FF\ ]" +PwCompressionAlgorithmFF] s +)FFs t +,FFt u +valueFFv { +)FF{ | +;FF| } +}FF~  +}GG  +publicHH  + IEnumerableHH  +<HH  +stringHH ! +>HH! " +KeyDerivationsHH# 1 +=>HH2 4 +KdfPoolHH5 < +.HH< = +EnginesHH= D +.HHD E +SelectHHE K +(HHK L +eHHL M +=>HHN P +eHHQ R +.HHR S +NameHHS W +)HHW X +;HHX Y +publicJJ  +stringJJ  +KeyDerivationNameJJ ' +{KK  +getLL  +{LL  +returnLL  +KdfPoolLL  +.LL ! +GetLL! $ +(LL$ % + _databaseLL% . +.LL. / + KeyDerivationLL/ < +.LL< = +KdfUuidLL= D +)LLD E +.LLE F +NameLLF J +;LLJ K +}LLL M +setMM  +{MM  + _databaseMM  +.MM  + KeyDerivationMM ) +=MM* + +KdfPoolMM, 3 +.MM3 4 +EnginesMM4 ; +.MM; < +FirstOrDefaultMM< J +(MMJ K +eMMK L +=>MMM O +eMMP Q +.MMQ R +NameMMR V +==MMW Y +valueMMZ _ +)MM_ ` +?MM` a +.MMa b +GetDefaultParametersMMb v +(MMv w +)MMw x +;MMx y +}MMz { +}NN  +publicPP  +ISelectableModelPP  + SelectedItemPP , +{QQ  +getRR  +{RR  +returnRR  +GroupsRR  +.RR  +FirstOrDefaultRR . +(RR. / +gRR/ 0 +=>RR1 3 +gRR4 5 +.RR5 6 + +IsSelectedRR6 @ +)RR@ A +;RRA B +}RRC D +setSS  +{TT  +ifUU  +(UU  + _selectedItemUU ! +==UU" $ +valueUU% * +||UU+ - +IsNewRecycleBinUU. = +)UU= > +returnUU? E +;UUE F +ifVV  +(VV  + _selectedItemVV ! +!=VV" $ +nullVV% ) +)VV) * +{WW  + _selectedItemXX ! +.XX! " + +IsSelectedXX" , +=XX- . +falseXX/ 4 +;XX4 5 +}YY  + SetProperty[[  +([[  +ref[[  + _selectedItem[[ - +,[[- . +([[/ 0 +GroupVm[[0 7 +)[[7 8 +value[[8 = +)[[= > +;[[> ? +if]]  +(]]  + _selectedItem]] ! +!=]]" $ +null]]% ) +)]]) * +{^^  + _selectedItem__ ! +.__! " + +IsSelected__" , +=__- . +true__/ 3 +;__3 4 +}``  +}aa  +}bb  +publicdd  +SettingsDatabaseVmdd ! +(dd! " +)dd" # +:dd$ % +thisdd& * +(dd* + +DatabaseServicedd+ : +.dd: ; +Instancedd; C +)ddC D +{ddE F +}ddG H +publicff  +SettingsDatabaseVmff ! +(ff! " +IDatabaseServiceff" 2 +databaseff3 ; +)ff; < +{gg  + _databasehh  +=hh  +databasehh  +;hh ! +Groupsii  +=ii  + _databaseii  +?ii  +.ii  + RootGroupii ) +.ii) * +Groupsii* 0 +;ii0 1 +}jj  +}kk  +}ll T +`C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\HamburgerMenuUserControl.xaml.cs + namespace  + ModernKeePass +  +.  +Views  +.  + UserControls * +{   +public + + + +sealed + +  +partial + +  +class + + $ +HamburgerMenuUserControl + + 8 +{    +public   $ +HamburgerMenuUserControl   ' +(  ' ( +)  ( ) +{    +InitializeComponent  +(  +) ! +;! " +}  +public  +string  + HeaderLabel ! +{  +get  +{  +return  +(  +string  +) ! +GetValue! ) +() * +HeaderLabelProperty* = +)= > +;> ? +}@ A +set  +{  +SetValue  +(  +HeaderLabelProperty . +,. / +value0 5 +)5 6 +;6 7 +}8 9 +}  +public  +static  +readonly  +DependencyProperty 1 +HeaderLabelProperty2 E +=F G +DependencyProperty  +.  +Register ' +(' ( +$str  +,  +typeof  +(  +string  +)  +,  +typeof  +( $ +HamburgerMenuUserControl / +)/ 0 +,0 1 +new  +PropertyMetadata $ +($ % +$str% - +,- . +(/ 0 +o0 1 +,1 2 +args3 7 +)7 8 +=>9 ; +{< = +}> ? +)? @ +)@ A +;A B +public  +string  + ButtonLabel ! +{  +get  +{  +return  +(  +string  +) ! +GetValue! ) +() * +ButtonLabelProperty* = +)= > +;> ? +}@ A +set    +{    +SetValue    +(    +ButtonLabelProperty   . +,  . / +value  0 5 +)  5 6 +;  6 7 +}  8 9 +}!!  +public""  +static""  +readonly""  +DependencyProperty"" 1 +ButtonLabelProperty""2 E +=""F G +DependencyProperty##  +.##  +Register## ' +(##' ( +$str$$  +,$$  +typeof%%  +(%%  +string%%  +)%%  +,%%  +typeof&&  +(&& $ +HamburgerMenuUserControl&& / +)&&/ 0 +,&&0 1 +new''  +PropertyMetadata'' $ +(''$ % +$str''% - +,''- . +(''/ 0 +o''0 1 +,''1 2 +args''3 7 +)''7 8 +=>''9 ; +{''< = +}''> ? +)''? @ +)''@ A +;''A B +public))  +string))  +DisplayMemberPath)) ' +{**  +get++  +{++  +return++  +(++  +string++  +)++ ! +GetValue++! ) +(++) *% +DisplayMemberPathProperty++* C +)++C D +;++D E +}++F G +set,,  +{,,  +SetValue,,  +(,, % +DisplayMemberPathProperty,, 4 +,,,4 5 +value,,6 ; +),,; < +;,,< = +},,> ? +}--  +public..  +static..  +readonly..  +DependencyProperty.. 1% +DisplayMemberPathProperty..2 K +=..L M +DependencyProperty//  +.//  +Register// ' +(//' ( +$str00 # +,00# $ +typeof11  +(11  +string11  +)11  +,11  +typeof22  +(22 $ +HamburgerMenuUserControl22 / +)22/ 0 +,220 1 +new33  +PropertyMetadata33 $ +(33$ % +$str33% , +,33, - +(33. / +o33/ 0 +,330 1 +args332 6 +)336 7 +=>338 : +{33; < +}33= > +)33> ? +)33? @ +;33@ A +public55  +object55  + ResizeTarget55 " +{66  +get77  +{77  +return77  +GetValue77 ! +(77! " +ResizeTargetProperty77" 6 +)776 7 +;777 8 +}779 : +set88  +{88  +SetValue88  +(88  +ResizeTargetProperty88 / +,88/ 0 +value881 6 +)886 7 +;887 8 +}889 : +}99  +public::  +static::  +readonly::  +DependencyProperty:: 1 +ResizeTargetProperty::2 F +=::G H +DependencyProperty;;  +.;;  +Register;; ' +(;;' ( +$str<<  +,<<  +typeof==  +(==  +object==  +)==  +,==  +typeof>>  +(>> $ +HamburgerMenuUserControl>> / +)>>/ 0 +,>>0 1 +new??  +PropertyMetadata?? $ +(??$ % +null??% ) +,??) * +(??+ , +o??, - +,??- . +args??/ 3 +)??3 4 +=>??5 7 +{??8 9 +}??: ; +)??; < +)??< = +;??= > +publicAA  + +VisibilityAA  +IsButtonVisibleAA ) +{BB  +getCC  +{CC  +returnCC  +(CC  + +VisibilityCC $ +)CC$ % +GetValueCC% - +(CC- .# +IsButtonVisiblePropertyCC. E +)CCE F +;CCF G +}CCH I +setDD  +{DD  +SetValueDD  +(DD # +IsButtonVisiblePropertyDD 2 +,DD2 3 +valueDD4 9 +)DD9 : +;DD: ; +}DD< = +}EE  +publicFF  +staticFF  +readonlyFF  +DependencyPropertyFF 1# +IsButtonVisiblePropertyFF2 I +=FFJ K +DependencyPropertyGG  +.GG  +RegisterGG ' +(GG' ( +$strHH ! +,HH! " +typeofII  +(II  + +VisibilityII ! +)II! " +,II" # +typeofJJ  +(JJ $ +HamburgerMenuUserControlJJ / +)JJ/ 0 +,JJ0 1 +newKK  +PropertyMetadataKK $ +(KK$ % + +VisibilityKK% / +.KK/ 0 + CollapsedKK0 9 +,KK9 : +(KK; < +oKK< = +,KK= > +argsKK? C +)KKC D +=>KKE G +{KKH I +}KKJ K +)KKK L +)KKL M +;KKM N +publicMM  + IEnumerableMM  +<MM  + IPwEntityMM $ +>MM$ % + ItemsSourceMM& 1 +{NN  +getOO  +{OO  +returnOO  +(OO  + IEnumerableOO % +<OO% & + IPwEntityOO& / +>OO/ 0 +)OO0 1 +GetValueOO1 9 +(OO9 : +ItemsSourcePropertyOO: M +)OOM N +;OON O +}OOP Q +setPP  +{PP  +SetValuePP  +(PP  +ItemsSourcePropertyPP . +,PP. / +valuePP0 5 +)PP5 6 +;PP6 7 +}PP8 9 +}QQ  +publicSS  +staticSS  +readonlySS  +DependencyPropertySS 1 +ItemsSourcePropertySS2 E +=SSF G +DependencyPropertyTT  +.TT  +RegisterTT ' +(TT' ( +$strUU  +,UU  +typeofVV  +(VV  + IEnumerableVV " +<VV" # + IPwEntityVV# , +>VV, - +)VV- . +,VV. / +typeofWW  +(WW $ +HamburgerMenuUserControlWW / +)WW/ 0 +,WW0 1 +newXX  +PropertyMetadataXX $ +(XX$ % +newXX% ( +ListXX) - +<XX- . + IPwEntityXX. 7 +>XX7 8 +(XX8 9 +)XX9 : +,XX: ; +(XX< = +oXX= > +,XX> ? +argsXX@ D +)XXD E +=>XXF H +{XXI J +}XXK L +)XXL M +)XXM N +;XXN O +publicZZ  +objectZZ  + SelectedItemZZ " +{[[  +get\\  +{\\  +return\\  +GetValue\\ ! +(\\! " +SelectedItemProperty\\" 6 +)\\6 7 +;\\7 8 +}\\9 : +set]]  +{]]  +SetValue]]  +(]]  +SelectedItemProperty]] / +,]]/ 0 +value]]1 6 +)]]6 7 +;]]7 8 +}]]9 : +}^^  +public__  +static__  +readonly__  +DependencyProperty__ 1 +SelectedItemProperty__2 F +=__G H +DependencyProperty``  +.``  +Register`` ' +(``' ( +$straa  +,aa  +typeofbb  +(bb  +objectbb  +)bb  +,bb  +typeofcc  +(cc $ +HamburgerMenuUserControlcc / +)cc/ 0 +,cc0 1 +newdd  +PropertyMetadatadd $ +(dd$ % +nulldd% ) +,dd) * +(dd+ , +odd, - +,dd- . +argsdd/ 3 +)dd3 4 +=>dd5 7 +{dd8 9 +}dd: ; +)dd; < +)dd< = +;dd= > +publicff  +eventff ( +SelectionChangedEventHandlerff 1 +SelectionChangedff2 B +;ffB C +publicgg  +delegategg  +voidgg ( +SelectionChangedEventHandlergg 9 +(gg9 : +objectgg: @ +senderggA G +,ggG H% +SelectionChangedEventArgsggI b +eggc d +)ggd e +;gge f +privatehh  +voidhh ' +Selector_OnSelectionChangedhh 0 +(hh0 1 +objecthh1 7 +senderhh8 > +,hh> ?% +SelectionChangedEventArgshh@ Y +ehhZ [ +)hh[ \ +{ii  +SelectionChangedjj  +?jj  +.jj  +Invokejj $ +(jj$ % +senderjj% + +,jj+ , +ejj- . +)jj. / +;jj/ 0 +}kk  +publicmm  +eventmm % +ButtonClickedEventHandlermm . + ButtonClickedmm/ < +;mm< = +publicnn  +delegatenn  +voidnn % +ButtonClickedEventHandlernn 6 +(nn6 7 +objectnn7 = +sendernn> D +,nnD E +RoutedEventArgsnnF U +ennV W +)nnW X +;nnX Y +privateoo  +voidoo  +ButtonBase_OnClickoo ' +(oo' ( +objectoo( . +senderoo/ 5 +,oo5 6 +RoutedEventArgsoo7 F +eooG H +)ooH I +{pp  + ButtonClickedqq  +?qq  +.qq  +Invokeqq ! +(qq! " +senderqq" ( +,qq( ) +eqq* + +)qq+ , +;qq, - +}rr  +}ss  +}tt  \ No newline at end of file diff --git a/ModernKeePass10/.sonarqube/out/0/output-cs/token-type.pb b/ModernKeePass10/.sonarqube/out/0/output-cs/token-type.pb new file mode 100644 index 0000000..e22ce1d --- /dev/null +++ b/ModernKeePass10/.sonarqube/out/0/output-cs/token-type.pb @@ -0,0 +1,2160 @@ + +GC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\ClipboardAction.cs +  +  +  +   +     # 3 5 <                           ) .        1   ( . 0 6 7 = @ F G V Y \ ] m n t      $ - 3    ! " - E Y       +KC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\NavigateToUrlAction.cs +  +  +  +  +   +    $ ' 7 9 @  + +   + +                    ( -        1   ( - / 5 6 < ? E F Y \ _ ` p q w      $ - 3        !   & .      #     +HC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\SetupFocusAction.cs +  +  +  +  +  +     +        !   $ 4   6 =                    !   1 6        1   ( 6 8 > ? F I O P ` c f g w x |      $ - 3     * @ . 8 +8C:\Sources\Other\ModernKeePass\ModernKeePass\App.xaml.cs +  +  +  +  +  +  +  +  +   + + +  +   +   +   + ` +     [    +          b  S         + M ((  ((  ((* 0 ((9 T ** O ++  ,,  --  -- 6 .., 0 22  22  22! . 446 : 55 # 55B D 55E R 55T c 77  77  77# % 77& = 996 : :: # ::F H ::I ` ::b q >>  ?? b @@ Z AA  BB Q CC  CC  CC  CC! % CC1 I FF  FF  FF8 U II  II  II  II, ? NN  NN  NN) < RR  RR# + TT > XX  XX " XX3 5 XX6 ; ZZ T [[ 4 \\  \\ ! ^^ a __  __ % __H \ __g h `` + dd  dd0 I ff M hh ' hh? O hhQ } ll 8 mm  pp  pp  pp - rr  rr/ G ss  ss) - uu [ vv _ ww  xx' - xx. 6 z~  + 6 +  + 2 +  +  +  +  +& , +5 ; +  + % +6 8 +9 > +  + * +  +) - + ' +9 H +J v +  +  +  +- 1 +3 8 +  +  +' - +. 6 + # + ' +9 H +J t +  + ; +  + J + H +  + & +/ H +  +  +  + 6 +  + ^ + c + # +  + K + F +  +  +  +( . +7 J +  +  + * +  +  + # +8 E +G K +  +% * +  +  + ' +  + Y +  + J +  +  +  +0 F +  +  +  + % +  +? @ +B D +E P + % +& . +  +  +OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\IntToSymbolConverter.cs +  +  +  +  +   +    % ( 7  + +   + +   + + $  + +, 0  + += C  + +O U                 ! ' ( .         # ) * 0     % + , 2                 + 1 2 8     - 3 4 :     / 5 6 <     # ) * 0     % + , 2     & , - 3     ( . / 5     % + , 2     - 3 4 :     $ * + 1           % +   , 2 !!  !!  !!# ) !!* 0 ""  ""  ""% + "", 2 ##  ##  $$  $$  $$# ) $$* 0 %%  %%  %%+ 1 %%2 8 &&  &&  &&, 2 &&3 9 ''  ''  ''& , ''- 3 ((  ((  (($ * ((+ 1 ))  ))  ))+ 1 ))2 8 **  **  **" ( **) / ++ 5 ,, @ --  --  --% + --, 2 ..  ..  ..% + .., 2 //  //  //* 0 //1 7 00 2 11  11  22  22  22" ( 22) / 33  33  33% + 33, 2 44  44  44# ) 44* 0 55  55  55# ) 55* 0 66  66  66) / 660 6 77  77  77' - 77. 4 88 5 99  99  99& , 99- 3 ::  ::  ::% + ::, 2 ;;  ;;  ;;" ( ;;) / << 6 ==  ==  >>  >>  ??  ??  ??+ 1 ??2 8 @@ 7 AA  AA  AA) / AA0 6 BB  BB  BB% + BB, 2 CC  CC  CC! ' CC( . DD  DD  DD' - DD. 4 EE  EE  EE" ( EE) / FF  FF  FF" ( FF) / GG  GG  GG% + GG, 2 HH  HH  HH" ( HH) / II  II  II" ( II) / JJ 2 KK 6 LL 4 MM 3 NN  NN  NN# ) NN* 0 OO  OO  OO) / OO0 6 PP  PP  PP( . PP/ 5 QQ  QQ  QQ & UU  UU  UU" ( UU0 4 UUA G UUS Y WW  WW  XX  Zg  hh  hh  ii  ii !  j  +  +  + ! +RC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\DatabaseOpenedException.cs +  +   +    ( * 3 +JC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ILicenseService.cs +  +  +  +   +    $        "   $ 2   ? B  + +   + +   + + ! +RC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IProxyInvocationHandler.cs +  +   +    ,     $ . 7 = +IC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentService.cs +  +  +  +   +    #          + +   + +   + +( .        (   6 :   Q U           $ *     +FC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentItem.cs +  +   +       # &             +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IResourceService.cs +   +    %    & +MC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SingletonServiceBase.cs +  +   +      . / 0 2 7 8 9 < ?        $ % &        !  + +   + +   + +  +`C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\SelectableDataTemplateSelector.cs +  +  +  +   +    / 1 E           ' *   , /  + +   + +   + +( +  + +- 0            '   ; A   H X   ( * + ;   ' + +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsSaveVm.cs +  +  +   +          )  + +   + +   + +" &  + +' 6            .         . ; = A   ' 4 6 ; +TC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\DonatePage.xaml.cs + ^ +     Q    +        *  + +   + + $ +HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\DatabaseService.cs +  +  +  +  +  +  +  +  +   + + +  +   +   +   +  +   +     " 6 7 F I Y      # 2 5 6 @      )                     # & ( +             "" # ''  ''  ))  ))  ++  ++  ,,  ,,2 7 //  //  11  11  22  44  66  66  66 5 88 % <<  <<  >>  >>  ??  ??" ' BB  BB  DD  DD  EE  EE/ 4 HH  HH % JJ  JJ  KK  KK, 1 NN  NN  PP  PP  QQ  QQ. 3 TT  TT  UU  UU  UUJ N VV  VV  VV1 5 WW  WW  WW! $ WW& ) YY  YY  YY# ' YY( 7 ]]  ]]  ]] / cc  dd # ee  ff @ gg [ hh 7 ii  ii  ii  ii + ii1 5 iiB G kk > ll  nn  nn  pp  pp  pp 3 tt  tt# 3 uu  yy 1 zz  zz- 1 zz3 ; {{  {{: @ {{B U ||  ~~  ~~  , 3 8 @ + ! +  +9 < += M + 2 + S +  +) - +/ ? +  +  + - + 3 +  + ' +? C +v z +  + / +  +  +  + + +  +  +  +  +  + G +  +  +  +  +  +  +! $ +% 5 + 0 +  +) - +/ ? +Z ] +^ n +  +  +  +  + ' +  + A +  + < +  +  + $ +  +  +# 3 +L P +R U +V f +  +  +  + / +  +  +  +  + $ +3 7 + 8 +  +% ) ++ ; +  +# ' +  +  +, 0 +  +  +# ) ++ . +/ > +C K +  +  +% + +$ ( +! $ +% + +  +  ++ . +/ 6 +7 ; += A +C L +N T +] a ++ . +/ 6 +7 ; += A +C J +L R +[ _ ++ . +/ 6 +7 ; += A +C M +O U +^ b +  +  +  +! % +' + + ! +. 1 +2 A +  + ! +1 4 +5 D +  + ! +, / +0 ? +  + ! +1 4 +5 D +  + ! +. 1 +2 A + 3 +/ 3 +  +  + ! +# ' + ! +. 1 +2 A + ! + ! +1 4 +5 D +  + ! +, / +0 ? +  +! 3 + ! +1 4 +5 D +  +  + 3 +4 K +M S +/ 3 +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISettingsService.cs +   +    %       ) * : A B C      ! , - +JC:\Sources\Other\ModernKeePass\ModernKeePass\Common\MessageDialogHelper.cs +  +  +  +  +  +  +   + + +  + +   + +   + + +    "                   2 8   @ F   T Z   m s +    +     <      ' * + 4  &         + 8 D T  ) M V X a c h   ! $ % 3 - =   ( *   M T   T U ""/ E ""G J ""K O ""P V ""Z a $$  $$  %%  %%  &&  ))  ))  ))  ))/ F ))R b ++ . ++0 2 ++2 ; ++J w ++w x  ++z  +++  66  66  66  66  661 : 88  88 ! 88# ) 99 < ::  ::[ _ << & ==  @@  @@  @@  @@  @@8 > @@F L BB  BB; ? DD & EE  HH  HH  HH $ HH7 = HHE K HHU [  HHo  +HH  JJ < KK  KK # KK$ 1 MM 5 NN' * NN+ 4 PP > QQ0 1 SS C TT/ 0 VV 7 +GC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NavigationHelper.cs +  +  +  +  +  +  +  +  +   + + +  +   +      Y  W  X  ]  F      B  T    O  S            + !! B "" N ## N $$  %%  && ^ ''  (( ^ ))  **  ++  ,, ^ -- f .. S //  00 H 11  22 2 33  44  55 J 66  77 4 88  99  ::  ;;! . << + <<  << ! <<$ 4 >>  >>  >>  >>! $ ??  ??  ?? ! ??$ * ??+ / AA  BB S CC  DD U EE U FF ` GG  GG  GG $ II  KK J LL I MM 5 NN  SS \ TT  TT  TT. 4 UU  UU- 3 WW L XX  ZZ  [[  `` G aa  ff  hh  ii  pp  qq  ss  tt Y uu Y vv / ww  xx c yy M zz  {{  {{  }}    & * +% ( +) 5 + " + " +  +  +! & +  + V + Z +  + f + P +  +  +  +  +  +) - +( + +, 8 + " + " +  +  + K + @ +  +  + C + + +  +  +  +  +  +  +! % +) - +  + N + C +  +  + C + . +  +  +  +  +  +  +! % +) - +  + K + U +  +  +  +  +  +  + " +& * +< @ +  + N + X +  +  +  +  +  +  + " +& * +? C +  + ` + c + G +  + K + _ +  +  +< J + # +  + ` +  +  + ; + : + ) +@ J +  +# & ++ . += @ +  +! ' +  + 4 +  +7 A +  +: D +  +8 B +  +  +  +  +( + +# - + R + $ +  +/ 3 +  +  +  +- 0 +# - + R + $ +  +2 6 +  + _ + a + C +  + K + _ +  +  +/ 9 +  +  + L +  +2 8 + R +  +  +  +  +  +! % +< @ +  +$ ( +B F +  +  +  + H + F + G +  +  +  + * +  + ? + > + B + " +  +  +  + * +  + I + N + N +  + _ + @ +  +  +" 5 +  + . +D H +  + # +& * +  +$ 2 + \ + # +  +" & +  +$ ( +  +" ) + @ +  +  +& * +  +# ' +) , +- ? +M Q +  + \ + _ +  +  +  +& * +  +# ' +) , +- ? +N X +Y _ +a g +t x +  + J + N + N +  + _ + @ +  +  +$ 7 +  + . +D H +  +  + * ++ 1 +3 9 +  +  +" & +  + # +% ( +) ; +  + ` +  + + +  +  + . +/ 5 +> P +  + ` +  + + +  +  + . +/ 5 +> P +  + V +  + + +  + # +& / +  + U + 3 +  +  +  +, / +1 8 +9 < +  + J + I +  +  +  +  +" ( +6 9 +; B +C F +  + U +  + . + U + 3 +  + $ + J + I +  +  + ! +" ( +> H +I O +Q W +  +  +  +  + V +  + + +  + # +& / +  + H +  +  +  +  +" ( +6 9 +; B +C F +  + U +  + h +  + ! +" , +- 3 +5 ; +  +  +PC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NotifyPropertyChangedBase.cs +  +  +  +   +    * - C            0           ) /   ? A   $ (   * -   . F     # $ & ) * + 6 7 @ P R X h j     ! "         +KC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ObservableDictionary.cs +  +  +  +  +       [  + +         +        %   ( 6   7 =   ? E      : = Q R X    7 8 H Q W        # 7 : < C D G      # % , - 0      ! # ) 9 < = G H N P V      + , 2 4 :     & 6 ? E          $ "" ! ""# & ""' K &&  &&  &&  &&$ * ((  ))  ))" 2 ,,  ,,  ,, $ ,,% + ,,- 3 ..  11  11  11 ( 11) 5 116 < 11> D 33  33  33 ! 99  99  99 ! ;;  ;;  ==  ==& 6 >>  >>  @@  @@  CC  CC  CC ' CC( . CC0 6 EE  FF  FF  FF7 : GG  GG; ? II  II& 6 JJ  JJ  LL  LL  OO  OO  OO  OO ! QQ  SS  SS  UU  WW  WW( - XX  XX& 6 \\  \\  ^^  ^^  __  ``  ``  ``  bb  bb& 6 ff  ff  ff ! hh  hh  hh  kk  kk  kk & mm  mm  pp  pp  pp & pp, / pp0 6 rr  rr  rr5 8 uu  uu  uu ! ww  ww  ww  zz  zz  zz ) zz* 0 zz2 8 ||  ||      +  +  +  +  +  +  +  +  +  +  + ' +( . +0 6 +  +  + & +: E +  +  +  +  + ' +( . +0 6 +A D +  +  +  +  +! % +  +- 2 + +CC:\Sources\Other\ModernKeePass\ModernKeePass\Common\RelayCommand.cs +  +  +  +  +  +  +   + +     C    0    E  H  I    +      (              "    9        !    :    >      "         $$  %% " &&  '' > (( H ))  ))  )) " )), 0 ))1 5 ++  ++  ,,  ,,  ,, / ,,0 9 11  22 ` 33  44 $ 55 x 66  77 V 88  88  88 % ::  ::" & ::) - ==  >> R ??  @@ $ AA x BB  CC  CC  CC " HH  II J JJ M KK  LL  MM  MM  OO  PP  PP  RR  RR '( +HC:\Sources\Other\ModernKeePass\ModernKeePass\Common\SuspensionManager.cs +  +  +  +  +  +  +  +  +   + + +  +   +   +     _  b  ^  ]            +      ! " ( * 0 B E F P Q W Y _         0 3 4 8 9 =       4 G    [  A    I !! _ "" I ##  $$  $$  $$  $$! ' $$) / &&  &&  ))  ** Z ++ X ,, 9 --  ..  ..  ..  ..  00  00  33  44 [ 55 X 66 ` 77  88  99 d ::  ::  ::  ::  <<  >> F ??  ??  ??0 2 AA  BB  BB8 ; HH c II  JJ  JJ+ . JJ/ ; KK & KK4 7 KK8 N KKO U KKV ` KKa g KKi o NN d OO  OO# ( OO) 8  OOs  PP  PP  PP+ 0 RR% & RR( 2 SS  VV  VV  XX  XX  XX 4 \\  ]] d ^^ ` __ a ``  aa  bb ] cc b dd ^ ee [ ff  gg  gg  gg  gg  gg. 4 ggF J ii  ii * ii+ 1 ii3 9 kk  mm A nn  nn# ( nn) 8 oo  oo # oo/ 4 qq 4 rr * rr8 ; rr< R rrS Y rrZ d rre k rrm s ss% / ss0 6 ss8 > vv E ww  ww  ww0 2 yy  zz  zz8 ; zzG M +  +  +  +  + 4 +  +  + ) +  +0 G +I O +P V +Y _ +` q +t x +  +  + ) +  +0 L +N T +U [ +^ d +e v +y } +  +  + ) +  +0 D +F L +M W +X ^ +` f +j p q    +  +  +  + ) +* / +F I +J N +O \ +] b +  + c + [ + b + Q + [ + L +  + Y + 3 + ^ + 9 + ] + b +  +  +  +) . +6 < +N T +f j +  +@ D +  +  + 3 +4 l +  += A +  +  + 3 4  +  +  +3 6 + s + 1 +" % +& 3 +4 9 + ? +  + d + ^ +  +  + X +  +  +  +  ++ 0 + a + ` +! ' +  +  +8 ; +  + a + ] + X + \ + [ +  +  + X + _ + X + Y + 1 +  +  +  +! ' +) / +F K +  + ( +) / +1 7 +  + " +  +' - +  +' + + P +  +9 < += G +H N +P V +" , +- 3 +5 ; +  + I +! $ +% / +0 6 +8 > +  +  +  +  +8 = +  +  +' 3 +* 0 +< H +  +  +  +5 : +  + # + + +  + + +. 7 +  + ) +  + ) +* 3 +  + - +GC:\Sources\Other\ModernKeePass\ModernKeePass\Services\LicenseService.cs +  +  +  +  +  +     +           " 6   7 E   H W            "    " # ) + 9 F I  9       ! % A D E L M Q        $ !!  !!  !!  !!  !!( . ##  ##" ' ##( 2 $$  &&  && * ((  ((  ((! & ))  )) * ** k ++ & ,,  00  00  00! & 11  11 * 22  22  22! / 33  33 * 44  44  44! / 55  66  66  66 9 ::  ::  ::  :: ) ::B F ::V \ <<  <<  << ) ==  == " @@  @@  @@) - EE  EE  EE( , GG  +FC:\Sources\Other\ModernKeePass\ModernKeePass\Services\RecentService.cs +  +  +  +  +  +  +  +      +           ! 5   6 C   F T            8   @ ]        # $ / = A X \      1 2 =      !     > P  " # /           ##  ##  ## $ ##+ 1 ((  ((  --  --  --  -- & --5 ; //  //  +IC:\Sources\Other\ModernKeePass\ModernKeePass\Services\ResourcesService.cs +  +  +   +    ! # 3       0 <            '   : H           ' -       5 7   7 8   J K   P Q   +HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SettingsService.cs +  +  +  +  +   +     # 7 8 G J Z  + +   + +   + + %  + +0 ?                %   0 1   A H   I J        ! @ F G H    '         " ( 3 4     +NC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ToastNotificationHelper.cs +  +  +  +  +  +  +   + + +  + +   + +   + + /               * 3   < B   K Q   $ & ' . 1 8 ; B   " : N _   E K   H J m n     = E      '    (    &   2 :      - ! ) 9 :    $ ##  ##  ##  ##, 2 ##: @ %%  %%" : %%N _ &&  &&E K ''  ((  **  **  ** - ,,! ) ,,9 : .. $ 11  11  11  11* 3 +`C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DiscreteIntToSolidColorBrushConverter.cs +  +  +  +  +   +    6 9 H  + +   + +   + + $  + +, 0  + += C  + +O U        '            " # 2 3 9        " # 2 3 9        " # 2 3 9      # $ 3 4 :     " ( 0 4 A G S Y      - +[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\EmptyStringToVisibilityConverter.cs +  +  +  +     + * , ;            $   , 0   = C   O U            &   < B           0 :   G Q     " ( 0 4 A G S Y      - +QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\NullToBooleanConverter.cs +  +  +   +    ' * 9      $ , 0 = C O U  + +   + +            " (   0 4   A G   S Y      - +HC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\SaveException.cs +  +   +     ! *       . 1            & +SC:\Sources\Other\ModernKeePass\ModernKeePass\Extensions\DispatcherTaskExtensions.cs +  +  +  +   +      0                   ! "   1 2   4 8   9 G  + +   + +   + +   + + 6  + +B X       ' *   + ?   @ A       0 5   3 8          V         . 2 3 A      3 ? U   + 0 9 > G M N S +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IDatabaseService.cs +  +  +  +  +  +  +   + + +  + +   + + %               ! $   & )  "     ! $     " %   # & ( +   $ ' ) ,     ! $   6 9 ; >   & ) + .                  "     $ ( 5 :            $        " !!  !!  !!& * +OC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IHasSelectableObject.cs +   +    )   ( + - 0 +KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISelectableModel.cs +   +    %      " +SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\BasePages\LayoutAwarePageBase.cs +  +  +  +  +  +  +  +      +        $   & *      K  '       3 6       + . 0 3      + = @ B E      + 4 7 9 <    "  *  " # 3 4 8  F  8   - 0   1 = "" 7 ## H $$  ((  ((  ((1 7 ((@ Y ** _ ++ _ ,, ` -- b ..  //  /// 5 44  55 ^ 66 A 77  88 ! 99 T ::  ;; \ << a == J >> V ??  ??  ??2 8 ??A S AA L BB Z DD  DD # FF c GG \ HH  MM  OO O PP  PP, : RRC Q WW  XX a YY b ZZ P [[  \\ q ]] ] ^^ ' __  __  __2 8 __A S aa  aa' + cc * ii \ jj Q kk + ll ] mm Y nn  pp  pp  pp  pp@ C rr  ss X tt  uu R vv  ww  ww  yy  yy  ||  }} 0 ~~   ; + X +  +  +* 0 +I c +  +  +  +I M +  +  +  +  +  +  +I M + ] + a + [ +  +( , +  +  +  +  +  +) - +< A +  + ` +  +  + _ + _ + ` +  +  +  +  + $ + Q +  +\ ` +  +% 8 +; G + I + I +  + L + ; + @ + J + J +  +  +  +. A +  +  +  +0 C +bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsDatabasePage.xaml.cs + ^ +     Q    +        4  + +   + + # +eC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsNewDatabasePage.xaml.cs + { +     h    +        7  + +   + + & +^C:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSavePage.xaml.cs + ^ +     Q    +        0  + +   + +  +bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSecurityPage.xaml.cs + ^ +  +  +       Q  + +     +                4        #     A G P a  # 5 D F f +aC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsWelcomePage.xaml.cs + ^ +     Q    +        3  + +   + + " +_C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\FirstItemDataTemplateSelector.cs +  +  +   +    . 0 D     ( + - 0           ( +   - 0            '   ; A   H X        +   P Q   +LC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\ListViewWithDisable.cs +  +  +  +   +    $ & .               @ P   Z `           $ &   ' 3   " $ % /    ! 3 7 9 ? +]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\BreadCrumbUserControl.xaml.cs +  +  +  + ` +     +                5        $      $      % & /   0 5        1        " # ,    ,    $ % ( ) . / 8 +_C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\CompositeKeyUserControl.xaml.cs +  +  +  +  +  +  +  +  +   + + +     +   +        7     8 : ; I             . 3        1            .    $ % *         ""  ""  ""  ##  ##. 3 %%  %%  %%  %% 1 &&  ''  ((  ((  ))  )) . **  ** $ **% * ,,  ,,  ..  ..  ..  //  //0 5 11  11  11  11 1 22  33  44  44  55  55 . 66  66 $ 66% ) 99  99  ;;  ;; & @@  @@  @@ 1 AA  AA  AA  AA 9 AA: @ AAI R BB  BB  BB 0 CC  CC  CC  CC 8 CC9 ? CCH Y EE  EE  EE  EE. 4 EE= L GG' + GG- 0 GG1 : II  LL* . LL0 3 LL4 E NN  PP  PP " PP# 3 QQ  RR8 M SS  SS  SS2 7 SS> C UU. 2 UU4 7 UU8 I [[  [[  [[) / [[8 J ]]  ]] # `` 7 aa  ee  ee  ee  ee/ 5 ee> M gg  hh  hh " jj - kk- = mm& , oo G pp  pp  qq  qq  qq $ uu  uu  uu  uu5 ; uuD S ww  ww  ww! / yy) 9 zz$ ) ||+ 5 ||7 : ||; ? ||@ F ||J P ~~  ~~       $ +JC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\TextBoxWithButton.cs +  +  +  +  +   +    " % ,  + +   + +                    1 6        1            (    $ % /      ! " 1             2 7        1                ( !!  !! $ !!% + ##  ##  %%  %%  %%  &&  &&4 9 ((  ((  ((  (( 1 ))  ** ! ++  ++  ,,  ,, ( --  -- $ --% ) //  //  11  11  11 $ 22  221 6 44  44  44  44 1 55  66  77  77 ! 88  88 ( 99  99 $ 99% ) ;;  ;;  ;;  ==  >>  >>0 > >>@ B >>C I ??  ?? $ +WC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\BooleanToVisibilityConverter.cs +  +  +  +   +    - 0 ?            $   , 0   = C   O U        "   # '   + /   9 >        '   2 <  $     " ( 0 4 A G S Y   # % & 0 4 > H R       ) / 0 4     + 1 2 7        9 +PC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ColorToBrushConverter.cs +  +  +  +  +   +    & ) 8  + +   + +   + + $  + +, 0  + += C  + +O U           ! &   * /   : ?           2 4   5 D   F L   N ]      & 2 7     " ( 0 4 A G S Y      - +[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DoubleToSolidColorBrushConverter.cs +  +  +  +  +   +    1 4 C  + +   + +   + + $  + +, 0  + += C  + +O U       $ *    % 6 8 9 ?   # * L P     " &      * + 0 : = K L    $      * + 0 : = ? @ B F Q R     " ( 0 4 A G S Y      - +^C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\InverseBooleanToVisibilityConverter.cs +  +  +  +   +    4 7 F            $   , 0   = C   O U        "   # '   + /   8 =        '   4 >  $     " ( 0 4 A G S Y   # % & 0 4 > G Q       ) / 0 5     + 1 2 6        9 +QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\PluralizationConverter.cs +  +  +   +    ' * 9      $ , 0 = C O U  + +   + +6 8  + +9 ?       H K   P S   W i       ( ,   O P   R X   Y _           ! $   ( +   5 6    ! 9 : S T     # $  $     " ( 0 4 A G S Y      - +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ProgressBarLegalValuesConverter.cs +  +  +   +    0 3 B      $ , 0 = C O U  + +   + +4 6  + +7 =       D G   L O   S e       & *   K L   N T   U V    ! ; <    ! ; <     ! ' + 1 : ;   " (   " (       " ( 0 4 A G S Y      - +OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\TextToWidthConverter.cs +  +  +   +    % ( 7      $ , 0 = C O U  + +   + + !  + +2 4  + +5 ;            &       . /     " ( 0 4 A G S Y      - +HC:\Sources\Other\ModernKeePass\ModernKeePass\Events\PasswordEventArgs.cs +  +  +   +    " $ -     # & ( +  + +   + +   + +! ( +EC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IIsEnabled.cs +   +         +DC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IPwEntity.cs +  +  +   +        !        #  + +   + +                                , /       ! $    2    S                        !     !!  ""  ## ! $$  %%  %% ! +CC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPage.xaml.cs +  +  +  + ^ +       + + Q        +                (       $ *           3 9 B [     2 4 5 C    $ 9 ? @ K         . A !!  ""  "" $ +SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\AboutPage.xaml.cs + ^ +     Q    +        )  + +   + +  +YC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\NewDatabasePage.xaml.cs +  +  +  +  +  + ^ +          Q      +        /      $           . 4 = L     ! / ) 9 $ 2 + A C F G K L R V ]         !!  !!  !! $ +GC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPage.xaml.cs +  +  + ^ +       ]  + + $        +                ,       ( 2           3 9 B [     2 4 5 C 0 4 7 = > Q +UC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\WelcomePage.xaml.cs + ^ +     Q    +        +  + +   + +  +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\AboutVm.cs +  +   +                                     ( ) 8 9        '       +IC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\CompositeKeyVm.cs +  +  +  +  +  +  +  +  +   + + +  +    +     ! :                   + . 0 3             . 3   " + $$  $$  &&  &&  ''  ))  ))- 2 **" + ..  ..  00  00  11  33  331 6 44" + 88  88  88W [ ::  ::  <<  <<  ==  == ! ==+ 0 @@  @@  BB  BB  BB  CC  CC ! CC0 ; CC< A FF  FF  HH  HH  II  KK ! LL" ? MM ! MM" - NN  RR  RR  TT  TT  UU  WW  XX # YY" + ]]  ]]  __  __  ``  `` ! ``0 5 cc  cc  cc# & cc( + ee  ee  ee5 F gg  gg  hh  hh  ii  ii  jj  jj  kk  kk  kk# ) ll  ll  mm  mm  nn  nn  oo  oo  pp  pp  pp ) rr  rr  rr" & rr' 6 rrA D rrE U tt  tt  tt . tt9 I ww6 R {{  {{  {{  {{  {{- 1 }}   ! +  +  +  +  +  +  + $ +  +# & +' 4 +5 7 +S j +l n +n o +  +T s +  +S q +  +W u +6 A +  +  +  +  +: Q +^ _ +$ / +  + " +  +  +  +  +4 I +L W +  +  +" - + 0 +  +$ ( +  +  +" ( +/ : +  +  +  +  + " +# / +  +5 8 +9 D +  +) - +G J +K U +V f +  +8 ; +< J +  +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\ListMenuItemVm.cs +  +  +  +  +   +     " ; = G I Y  + +   + +             !   # &      ! # & , /      " $ '     # & ( +      # % ( . 2            ! / 4         +OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\MainMenuItemVm.cs +  +   +     ! /     " % ' *     # & ( + +MC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\RecentItemVm.cs +  +  +  +  +   +      8 : J L W  + +   + +            * -            !                      ! / 4          " * 0 ; G  " # .     !! , $$  $$  $$% 5 ))  ))  ++ * ..  ..  ..  ..+ 9 00  +JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\EntryDetailPage.xaml.cs +  +  +  +  +  +  +     +        ^  G    +        /     ! (    Y  4       3 6      " # 3 4 8 ""  ## o $$ Q %%  && ! '' T ((  )) e ** c ++ M ,, h --  --  --0 6 --? Q 11 ] 22 Q 33  44 g 55 ; 66 ? 77 P 88 M ::  ::  ::  ::. A ==  ==  ==! ( ==+ 1 >> " AA  AA  AA  AA0 C HH  HH  HH( . HH7 F JJ  JJ  JJ / KK  LL, H MM, G NN  NNK Z  NNx  OO  OOK ^ PP* D QQ* D SS ' SSX h TT> O UU  VV  YY  YY  YY) / YY8 G [[  [[  [[ / \\ # \\T i +\\  ]]  ``  ``  ``3 9 ``B V bb  bb) - bbA D bbG N bbQ X bbZ ^ ee  ee  eeA G eeP i gg  gg" $ gg% - hh  ii  kk  kk  ll  mm  nn3 5 nn6 = oo  +JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\GroupDetailPage.xaml.cs +  +  +  +  +  +  +  +  +   + + +  +   +  e +     \      +        /    K  '       3 6     ! (     !! " !!# 3 !!4 8 %%  && ^ '' A ((  )) ! ** T ++  ,, \ -- a .. J // V 00  00  000 6 00? Q 44 I 55 I 66  77 L 88 ; 99 @ :: J ;; J <<  ==  ==  ==  ==. A AA  AA  AA 0 BB 1 CC  CC  CC! # CC$ + DD & GG  GG  GG  GG0 C PP  PP  PP- 3 PP< U RR  RR" $ RR% - SS  TT  VV  VV  WW  XX  YY3 5 YY6 = ZZ  \\ ! \\" 1 __  __  __. 4 __= V aa  bb  dd  dd  ee  ff  gg2 4 gg5 < hh  jj ! jj" 1 mm  mm  mm( . mm7 F oo  oo  oo / pp  qq, H rr, G ss  ssK Z  ssx  tt  ttK ^ uu* D vv* D xx + xx\ l yyB S zz  {{  ~~  ~~  ~~) / ~~8 G +  +  + / + # +T i +* 9 +  +  +  +4 : +C c + n +  +* / +  +  +- 3 +< K + ! +" 1 +  +  +- 3 +< K + ! +" 1 +  +  +0 6 +? Y +( < +  +  +6 ? +H n +  + 6 +E H +I L M  +  +U e +| }   +  +  + "   +  +  +8 A +J r +  + ! +" 1 +  +  +3 9 +B V +  +) - +A D +G N +Q X +Z ^ +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\OpenDatabasePage.xaml.cs +  +  +  +  +  +  + ^ + + +         Q    +        0          &           . A   % ' ( -               . 4   = L ""  ##  ## " %% - &&- = ((& - ** G ++  ++  ,,  ,,  ,, $ +]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\RecentDatabasesPage.xaml.cs + { +     h    +        3  + +   + + " +ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\SaveDatabasePage.xaml.cs +  +  +  +  +  +  +  +  ^ +        Q    +        0          &           . A   % ' ( -       . 4 = L !!  "" & ""' / %%  %%  %%  %%0 6 %%? N ''  ''  ''! / ))) 9 **$ 2 ,,+ A ,,C F ,,G K ,,L R ,,V ] ..  ..  //  //  // $ 22 & 22' / +GC:\Sources\Other\ModernKeePass\ModernKeePass\Properties\AssemblyInfo.cs +  +  + M + M +       (      b           ! #  + +   + +   + + #            *            /                   + M +  +  +  +  +  +  + T + # + '      %      )      ' +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\EntryVm.cs +  +  +  +  +  +  +  +  +   + + +  +    +      1 3 < > N     % ( * 1 2 5     ' * , 3 4 7    #    #     0 6     M U     5 F     / 2 4 7 = A     / 2 4 7 = A     , / 1 4 : >     + . 0 3     0 3 5 8     + . 0 3     - 0 2 5     . 1 3 6     $ ' ) , 2 8         !!  !!  ""  ""  ##  ##  ## $ ##4 7 ##8 < ##= F $$  %% > &&  ''  ''  ''! $ ''& ) ''/ 3 ))  ))  ++  ++  ,,  .." ' //& 6 33  33  55  55  55' - 66  66 & 663 8 ::  ::  <<  <<  <<' - ==  == & ==6 ; @@  @@  BB  BB  BB' - CC  EE $ EE4 9 FF& 0 GG& C KK  KK  MM  MM  MM' - NN  NN & NN1 6 QQ  QQ  SS  SS  SS' - TT  TT & TT3 8 WW  WW  YY  [[  [[( , [[. 4 [[6 9 \\  \\  ``  ``  bb  bb  bb  bb + cc  cc  cc? D ff  ff  hh  hh  ii  ii  ii\ a ll  ll  nn  nn  oo  qq # rr& 2 vv  vv  xx  xx  yy  {{ " ||& 1 +  +  +  +  +  +$ ) +& 8 +  +  +  +  +  +# ( +& 9 +  +  + $ +  +  + ! +" & +' . +1 5 +  +  +* , + # +$ + +U Z +  +  +  + 0 +  +  +  +  +  + ) +  +  + ) +  +  +  +  +  +  +) + +  +  +" & +  +  ++ 1 +$ ( +* - +. F +  +  +  +  +  +( / +: > +N ] +h k +l | +  +  +  +& - +6 F +Q a +  +  +  +  + ) + 5 +  +  + ' +  +@ I +  +@ I +  += F +  +> G +  +< ? +  +A D +  +< ? +  +? H +  +  +! $ +: > +@ C +D Y +" ( +" , +" ; +" ? +  +  +% + +  +  +  +# ) +/ 5 +' * ++ : +; ? +  +  +" ( +  +O S +a e +  +  +  +  +  +) - +  + # +  +$ ( +  +  +  +  +  +  +  +  +  +  +  +  +; I +t w" +BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\GroupVm.cs +  +  +  +  +  +  +  +  +   +      +            4   6 ?   A Q     % ( * 1 2 5     ' * , 3 4 7    # $ +         & ) 4 9      "     ! $ % ) * 1     # % ##  ''  '' # ''$ + ''6 9 ''; > ''D G ''H \ ''] d ))  ))  **  **  ++  ++  ++0 4 --  --  //  //  11  22 2 33  44  44  66  66  66& * 77  99  99  99) - 99F J ==  == ! ==" + ==, 0 ==2 9 ==P T ==W Y >>  >>  >>9 = ??  @@  BB  BB  DD  DD  DD% ) DD, 2 EE  EE" ' HH  HH  JJ  LL  LL( , LL. 4 LL6 9 MM  MM  OO  OO% + OO, 1 RR  RR  TT  TT  UU  UU ! UU/ 4 XX  XX  ZZ  ZZ  [[  [[ ! [[1 6 ^^  ^^  ^^ $ ``  bb  bb  bb! & bb' . cc  cc  dd  dd, 0 jj  nn  nn  nn  oo  oo  oo ) pp  pp  qq  qq  rr  rr $ rr% , rr9 < rr= Q rrR Y ss  ss  ss% ) uu  uu  ww  ww  ww  ww* 1 ww: @ wwP T wwX \ xx  {{  {{  {{  {{( / {{8 H {{S Y {{i m +  + $ +c g +  + . +/ 6 +T W +X _ +c g +  + - +. 5 +R U +V ] +a e +  +  +/ 5 +> ^ +  +  + 2 +  +$ ( +  +  + 2 +  ++ / +E L +Y Z +k o +  +2 6 +  +  +  +# ) +1 3 +  +  + % +& * +, 0 +8 > +' + +  +  + & +0 4 +Q W +  +  +  +  +  + % +& * +, 0 +  +  + & +0 4 +D H +  +  +  +" ( +  +O S +U Y +  +  +  +  +  +( , +  + # +  +# ' +4 8 +  +  +  +{  +  +  +  +  +  +  +  + . +/ 5 +B F +H M +  +  + 2 +3 : +  +  + # +  +  +  +' , +  + 1 +2 9 +q u +" * +  +  + # +  +  +  +  +NC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsNewVm.cs +  +  +  +   +                )           ! %   & 5      -         . 2 4 <   ' / 1 6      ! 2 5 9 < > A         . 4 6 I   ' : < A +EC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SettingsVm.cs +  +  +  +  +  +  +  +      +            7   9 M            " # , - 3 5 C    ! " + , 2 4 B        ! . 3             % * , 2   % ) / 4 ""  ""0 > ""? D $$  $$% ) &&/ 3 ++  ++  ++ " ++# 2 ++= @ ++A Q --  --  -- * --5 E //  //  // 4 //5 C 11  11 " 336 K 446 T 55! ' 66 % 66& = 77! % 99  99 " ;;6 L <<6 T ==! ' >> % >>& 6 @@  @@ " BB6 O CC6 Q DD! ' EE % EE& : HH  HH " JJ6 P KK6 Q LL! ' MM % MM& : SS  SS" $ SS/ 4 SS: < SSH L SSQ X SSa g +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\MainVm.cs +  +  +  +  +  +  +  +  + + +     +            3   5 I    " # , - 3 5 C           & -    ! " + , 2 4 B        ! 2 7             % * , 2   % ) !!/ 4 $$  $$0 > $$? D &&  &&% ) ((/ 3 --  --  //  //  //  //. 3 //H L 00  00& ) 00* : 00> K 33  33  33  33, 1 33D T 33_ o  33z  55  55- 1 77  77 # 77$ 8 779 G 99  99 " ;;6 H << % <<& 6 ??! ' @@- 1 BB  BB " DD6 G EE % EE& 5 HH! ' JJ  JJ " LL6 H MM % MM& 6 PP! ' TT  TT " VV6 J WW % WW& 9 ZZ! ' \\% ) ]], - ^^4 5 ``  `` " bb6 L cc % cc& 2 ee! ' gg  gg " ii6 I jj % jj& / ll! ' nn  nn " pp6 J qq % qq& 0 ss! ' vv O yy 8 zz  zz  {{" % {{& 4 ~~ % ~~& 5 + ' +! ' +  +& ( +7 < +B D +P T +Y ` +i o +@C:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\NewVm.cs +   +           ! $ & ) +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\OpenVm.cs +  +  +  +  +   +      2  + +   + +               )        .      &     : @      (  (      ( / = !! $ "" / &&  &&  &&% 0 &&7 E +CC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\RecentVm.cs +  +  +  +  +   +      5 7 K  + +   + +   + + '                $   % 0   A D   E Y   Z e    # $ /        ! 0 5             % * , 2   % ) / 4   / 4 !!  !!% ) !!+ 1 ""+ / &&  &&  &&  &&" / ))  ))  )) & --  --$ % ..+ , ... 0 ..1 = 11  11  +AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SaveVm.cs +  +  +  +  +   +      + +   + +   + + )                .            &        # , 0          $ +SC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsDatabaseVm.cs +  +  +  +  +  +  +  +  +   + + +  +    #  +    # % > @ T      )               . 3 " 1               1 5 !!  ##  ##  ##2 6 ''  '' # ''$ + ''6 9 ''; > ))  ))  )) ! ++  --  --  --  --( 2 //  //  //! + 44  44  66  88  88  88  88( 2 ::  :: " ::\ b <<  <<  >>  >>) 3 >>? D AA  AA  AA ! AA3 7 AAA G AAH ^ AAg j  AAk  CC  CC  EE  EE  EE  EE& , EE- C FF  FF4 J FFK O FFV \ FF] s FFv { HH  HH  HH ! HH5 < JJ  JJ  LL  LL  LL  MM  MM, 3 MMZ _ PP  PP  RR  RR  SS  UU  UU% * UU? E VV  VV% ) XX/ 4 [[  [[0 7 [[8 = ]]  ]]% ) __/ 3 dd  dd ! dd& * dd+ : ff  ff ! ff" 2 +`C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\HamburgerMenuUserControl.xaml.cs +  +  +  +  + ` +   + + +  + +   + +   + +   + + 8        '             0 5        1            /    $ % -                 0 5 ""  ""  ""  "" 1 ##  $$  %%  %%  &&  && / ''  '' $ ''% - ))  ))  ++  ++  ++  ,,  ,,6 ; ..  ..  ..  .. 1 //  00 # 11  11  22  22 / 33  33 $ 33% , 55  55  77  77  88  881 6 ::  ::  ::  :: 1 ;;  <<  ==  ==  >>  >> / ??  ?? $ ??% ) AA  AA  CC  CC  CC $ DD  DD4 9 FF  FF  FF  FF 1 GG  HH ! II  II ! JJ  JJ / KK  KK $ KK% / MM  MM  MM $ OO  OO  OO % OO& / PP  PP0 5 SS  SS  SS  SS 1 TT  UU  VV  VV " VV# , WW  WW / XX  XX $ XX% ( XX) - XX. 7 ZZ  ZZ  \\  \\  ]]  ]]1 6 __  __  __  __ 1 ``  aa  bb  bb  cc  cc / dd  dd $ dd% ) ff  ff  ff 1 gg  gg  gg  gg 9 gg: @ ggI b hh  hh  hh1 7 hh@ Y mm  mm  mm . nn  nn  nn  nn 6 nn7 = nnF U oo  oo  oo( . oo7 F \ No newline at end of file diff --git a/ModernKeePass10/.sonarqube/out/sonar-project.properties b/ModernKeePass10/.sonarqube/out/sonar-project.properties new file mode 100644 index 0000000..39199fb --- /dev/null +++ b/ModernKeePass10/.sonarqube/out/sonar-project.properties @@ -0,0 +1,210 @@ +sonar.projectKey=ModernKeePass +sonar.working.directory=C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\.sonarqube\\out\\.sonar +sonar.projectBaseDir=C:\\Sources\\Other\\ModernKeePass\\ModernKeePass + +A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.projectKey=ModernKeePass:A0CFC681-769B-405A-8482-0CDEE595A91F +A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.projectName=ModernKeePass.App +A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.projectBaseDir=C:\\Sources\\Other\\ModernKeePass\\ModernKeePass +A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.sourceEncoding=utf-8 +A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.sources=\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Actions\\ClipboardAction.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Actions\\NavigateToUrlAction.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Actions\\SetupFocusAction.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\App.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\IntToSymbolConverter.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Exceptions\\DatabaseOpenedException.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\ILicenseService.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IProxyInvocationHandler.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IRecentService.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IRecentItem.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IResourceService.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Services\\SingletonServiceBase.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\TemplateSelectors\\SelectableDataTemplateSelector.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\Items\\SettingsSaveVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\DonatePage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Services\\DatabaseService.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\ISettingsService.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Common\\MessageDialogHelper.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Common\\NavigationHelper.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Common\\NotifyPropertyChangedBase.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Common\\ObservableDictionary.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Common\\RelayCommand.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Common\\SuspensionManager.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Services\\LicenseService.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Services\\RecentService.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Services\\ResourcesService.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Services\\SettingsService.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Common\\ToastNotificationHelper.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\DiscreteIntToSolidColorBrushConverter.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\EmptyStringToVisibilityConverter.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\NullToBooleanConverter.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Exceptions\\SaveException.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Extensions\\DispatcherTaskExtensions.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IDatabaseService.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IHasSelectableObject.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\ISelectableModel.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\BasePages\\LayoutAwarePageBase.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsDatabasePage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsNewDatabasePage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsSavePage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsSecurityPage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsWelcomePage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\TemplateSelectors\\FirstItemDataTemplateSelector.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Controls\\ListViewWithDisable.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\UserControls\\BreadCrumbUserControl.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\UserControls\\CompositeKeyUserControl.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Controls\\TextBoxWithButton.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\BooleanToVisibilityConverter.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\ColorToBrushConverter.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\DoubleToSolidColorBrushConverter.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\InverseBooleanToVisibilityConverter.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\PluralizationConverter.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\ProgressBarLegalValuesConverter.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\TextToWidthConverter.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Events\\PasswordEventArgs.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IIsEnabled.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IPwEntity.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\AboutPage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\NewDatabasePage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\WelcomePage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\AboutVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\CompositeKeyVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\Items\\ListMenuItemVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\Items\\MainMenuItemVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\Items\\RecentItemVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\EntryDetailPage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\GroupDetailPage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\OpenDatabasePage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\RecentDatabasesPage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\SaveDatabasePage.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Properties\\AssemblyInfo.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\EntryVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\GroupVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\Items\\SettingsNewVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\SettingsVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\MainVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\NewVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\OpenVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\RecentVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\SaveVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\Items\\SettingsDatabaseVm.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\UserControls\\HamburgerMenuUserControl.xaml.cs",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\description.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.Entry.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.Filter.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.Group.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.New.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.Open.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.Recent.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.Semantic.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.Settings.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\Entry.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\Filter.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\Group.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\New.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\Open.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\Recent.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\Semantic.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\Settings.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\keywords.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\privacyPolicy.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\releaseNotes.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\websiteUrl.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\description.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.Entry.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.Filter.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.Group.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.New.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.Open.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.Recent.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.Semantic.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.Settings.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\Entry.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\Filter.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\Group.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\New.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\Open.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\Recent.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\Semantic.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\Settings.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\keywords.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\privacyPolicy.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\releaseNotes.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\websiteUrl.txt",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Logo.scale-100.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Logo.scale-140.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Logo.scale-180.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Logo.scale-80.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.scale-100.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.scale-140.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.scale-180.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.scale-80.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.targetsize-16.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.targetsize-256.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.targetsize-32.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.targetsize-48.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SplashScreen.scale-100.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SplashScreen.scale-140.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SplashScreen.scale-180.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square310x310Logo.scale-100.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square310x310Logo.scale-140.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square310x310Logo.scale-180.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square310x310Logo.scale-80.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square70x70Logo.scale-100.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square70x70Logo.scale-140.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square70x70Logo.scale-180.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square70x70Logo.scale-80.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\StoreLogo.scale-100.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\StoreLogo.scale-140.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\StoreLogo.scale-180.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Wide310x150Logo.scale-100.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Wide310x150Logo.scale-140.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Wide310x150Logo.scale-180.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Wide310x150Logo.scale-80.png",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\packages.config",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Strings\\fr-FR\\Resources.resw",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Strings\\fr-FR\\CodeBehind.resw",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Strings\\en-US\\CodeBehind.resw",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Strings\\en-US\\Resources.resw",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Styles\\Colors.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsSavePage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\UserControls\\BreadCrumbUserControl.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\UserControls\\CompositeKeyUserControl.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\AboutPage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\EntryDetailPage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\GroupDetailPage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\DonatePage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\NewDatabasePage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\OpenDatabasePage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\RecentDatabasesPage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\SaveDatabasePage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\WelcomePage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsDatabasePage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsNewDatabasePage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsSecurityPage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsWelcomePage.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Styles\\HamburgerButtonStyle.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Styles\\ListViewLeftIndicatorStyle.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Styles\\NoBorderButtonStyle.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Styles\\Styles.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Styles\\TextBoxWithButtonStyle.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\UserControls\\HamburgerMenuUserControl.xaml",\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\App.xaml" + +A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.cs.roslyn.reportFilePath=C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\bin\\Debug\\ModernKeePass.exe.RoslynCA.json +A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.cs.analyzer.projectOutPath=C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\.sonarqube\\out\\0 +A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.cs.analyzer.projectOutPaths=\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\.sonarqube\\out\\0" +A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.cs.roslyn.reportFilePaths=\ +"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\bin\\Debug\\ModernKeePass.exe.RoslynCA.json" + +sonar.organization=geogeob +sonar.host.url=https://sonarcloud.io +sonar.visualstudio.enable=false + +sonar.modules=A0CFC681-769B-405A-8482-0CDEE595A91F + diff --git a/ModernKeePass10/.sonarqube/out/summary.md b/ModernKeePass10/.sonarqube/out/summary.md new file mode 100644 index 0000000..e604fd9 --- /dev/null +++ b/ModernKeePass10/.sonarqube/out/summary.md @@ -0,0 +1,3 @@ +Analysis succeeded for SonarQube project "", version [Analysis results](https://sonarcloud.io/dashboard/index/ModernKeePass) +- Product projects: 1, test projects: 0 +- Invalid projects: 0, skipped projects: 0, excluded projects: 0 diff --git a/ModernKeePass10/Actions/ClipboardAction.cs b/ModernKeePass10/Actions/ClipboardAction.cs new file mode 100644 index 0000000..6f758f0 --- /dev/null +++ b/ModernKeePass10/Actions/ClipboardAction.cs @@ -0,0 +1,27 @@ +using Windows.ApplicationModel.DataTransfer; +using Windows.UI.Xaml; +using Microsoft.Xaml.Interactivity; + +namespace ModernKeePass.Actions +{ + public class ClipboardAction : DependencyObject, IAction + { + public string Text + { + get => (string)GetValue(TextProperty); + set => SetValue(TextProperty, value); + } + + public static readonly DependencyProperty TextProperty = + DependencyProperty.Register("Text", typeof(string), typeof(ClipboardAction), new PropertyMetadata(string.Empty)); + + public object Execute(object sender, object parameter) + { + if (string.IsNullOrEmpty(Text)) return null; + var dataPackage = new DataPackage { RequestedOperation = DataPackageOperation.Copy }; + dataPackage.SetText(Text); + Clipboard.SetContent(dataPackage); + return null; + } + } +} diff --git a/ModernKeePass10/Actions/DeleteEntityAction.cs b/ModernKeePass10/Actions/DeleteEntityAction.cs new file mode 100644 index 0000000..d72c1df --- /dev/null +++ b/ModernKeePass10/Actions/DeleteEntityAction.cs @@ -0,0 +1,65 @@ +using System.Windows.Input; +using Windows.UI.Xaml; +using Autofac; +using Microsoft.Xaml.Interactivity; +using ModernKeePass.Common; +using ModernKeePass.Domain.Entities; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.Actions +{ + public class DeleteEntityAction : DependencyObject, IAction + { + private readonly IResourceService _resourceService; + private readonly IDatabaseService _databaseService; + + public Entity Entity + { + get => (Entity)GetValue(EntityProperty); + set => SetValue(EntityProperty, value); + } + + public static readonly DependencyProperty EntityProperty = + DependencyProperty.Register("Entity", typeof(Entity), typeof(DeleteEntityAction), + new PropertyMetadata(null)); + + public ICommand Command + { + get => (ICommand)GetValue(CommandProperty); + set => SetValue(CommandProperty, value); + } + + public static readonly DependencyProperty CommandProperty = + DependencyProperty.Register("Command", typeof(ICommand), typeof(DeleteEntityAction), + new PropertyMetadata(null)); + + public DeleteEntityAction(): this(App.Container.Resolve(), App.Container.Resolve()) + { } + + public DeleteEntityAction(IResourceService resourceService, IDatabaseService databaseService) + { + _resourceService = resourceService; + _databaseService = databaseService; + } + + public object Execute(object sender, object parameter) + { + var type = Entity is GroupEntity ? "Group" : "Entry"; + + var message = _databaseService.IsRecycleBinEnabled + ? _resourceService.GetResourceValue($"{type}RecyclingConfirmation") + : _resourceService.GetResourceValue($"{type}DeletingConfirmation"); + var text = _databaseService.IsRecycleBinEnabled ? _resourceService.GetResourceValue($"{type}Recycled") : _resourceService.GetResourceValue($"{type}Deleted"); + MessageDialogHelper.ShowActionDialog(_resourceService.GetResourceValue("EntityDeleteTitle"), message, + _resourceService.GetResourceValue("EntityDeleteActionButton"), + _resourceService.GetResourceValue("EntityDeleteCancelButton"), a => + { + ToastNotificationHelper.ShowMovedToast(Entity, _resourceService.GetResourceValue("EntityDeleting"), text); + //Entity.MarkForDelete(_resourceService.GetResourceValue("RecycleBinTitle")); + Command.Execute(null); + }, null).GetAwaiter(); + + return null; + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Actions/NavigateToUrlAction.cs b/ModernKeePass10/Actions/NavigateToUrlAction.cs new file mode 100644 index 0000000..2bdbc54 --- /dev/null +++ b/ModernKeePass10/Actions/NavigateToUrlAction.cs @@ -0,0 +1,33 @@ +using System; +using Windows.UI.Xaml; +using Microsoft.Xaml.Interactivity; +using ModernKeePass.Common; + +namespace ModernKeePass.Actions +{ + public class NavigateToUrlAction : DependencyObject, IAction + { + public string Url + { + get => (string)GetValue(UrlProperty); + set => SetValue(UrlProperty, value); + } + + public static readonly DependencyProperty UrlProperty = + DependencyProperty.Register("Url", typeof(string), typeof(NavigateToUrlAction), new PropertyMetadata(string.Empty)); + + public object Execute(object sender, object parameter) + { + try + { + var uri = new Uri(Url); + return Windows.System.Launcher.LaunchUriAsync(uri).GetAwaiter().GetResult(); + } + catch (Exception ex) + { + MessageDialogHelper.ShowErrorDialog(ex).GetAwaiter(); + return false; + } + } + } +} diff --git a/ModernKeePass10/Actions/SetupFocusAction.cs b/ModernKeePass10/Actions/SetupFocusAction.cs new file mode 100644 index 0000000..e704277 --- /dev/null +++ b/ModernKeePass10/Actions/SetupFocusAction.cs @@ -0,0 +1,27 @@ +using System.Threading.Tasks; +using Windows.UI.Core; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Microsoft.Xaml.Interactivity; + +namespace ModernKeePass.Actions +{ + public class SetupFocusAction : DependencyObject, IAction + { + public Control TargetObject + { + get => (Control)GetValue(TargetObjectProperty); + set => SetValue(TargetObjectProperty, value); + } + + public static readonly DependencyProperty TargetObjectProperty = + DependencyProperty.Register("TargetObject", typeof(Control), typeof(SetupFocusAction), new PropertyMetadata(null)); + + public object Execute(object sender, object parameter) + { + return Task.Factory.StartNew( + () => Dispatcher.RunAsync(CoreDispatcherPriority.Low, + () => TargetObject?.Focus(FocusState.Programmatic))); + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Actions/ToastAction.cs b/ModernKeePass10/Actions/ToastAction.cs new file mode 100644 index 0000000..0a00fda --- /dev/null +++ b/ModernKeePass10/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 => (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 => (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/ModernKeePass10/App.xaml b/ModernKeePass10/App.xaml new file mode 100644 index 0000000..74c3611 --- /dev/null +++ b/ModernKeePass10/App.xaml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/App.xaml.cs b/ModernKeePass10/App.xaml.cs new file mode 100644 index 0000000..6b2afcb --- /dev/null +++ b/ModernKeePass10/App.xaml.cs @@ -0,0 +1,221 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Threading.Tasks; +using Windows.ApplicationModel; +using Windows.ApplicationModel.Activation; +using Windows.Storage; +using Windows.Storage.AccessCache; +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 Autofac; +using Microsoft.AppCenter; +using Microsoft.AppCenter.Analytics; +using ModernKeePass.Common; +using ModernKeePass.Composition; +using ModernKeePass.Domain.Dtos; +using ModernKeePass.Domain.Exceptions; +using ModernKeePass.Domain.Interfaces; +using ModernKeePass.Views; + +// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227 + +namespace ModernKeePass +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + sealed partial class App + { + private readonly IDatabaseService _databaseService; + + public static IContainer Container { get; 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)); + + InitializeComponent(); + Suspending += OnSuspending; + Resuming += OnResuming; + UnhandledException += OnUnhandledException; + + // Setup DI + var builder = new ContainerBuilder(); + builder.RegisterModule(); + builder.RegisterModule(); + Container = builder.Build(); + + _databaseService = Container.Resolve(); + } + + #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 + var exception = unhandledExceptionEventArgs.Exception; + var realException = + exception is TargetInvocationException && + exception.InnerException != null + ? 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 => + { + var savePicker = new FileSavePicker + { + SuggestedStartLocation = PickerLocationId.DocumentsLibrary, + SuggestedFileName = $"{_databaseService.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); + } + } + + /// + /// Invoked when the application is launched normally by the end user. Other entry points + /// will be used such as when the application is launched to open a specific file. + /// + /// Details about the launch request and process. + protected override async void OnLaunched(LaunchActivatedEventArgs args) + { + await OnLaunchOrActivated(args); + } + + protected override async void OnActivated(IActivatedEventArgs args) + { + await OnLaunchOrActivated(args); + } + + private async Task OnLaunchOrActivated(IActivatedEventArgs e) + { + // 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)) + { + // Create a Frame to act as the navigation context and navigate to the first page + rootFrame = new Frame(); + // Set the default language + + rootFrame.NavigationFailed += OnNavigationFailed; + + if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) + { + // 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 + } + + // Place the frame in the current Window + Window.Current.Content = rootFrame; + } + + if (e is LaunchActivatedEventArgs lauchActivatedEventArgs && rootFrame.Content == null) + { + rootFrame.Navigate(typeof(MainPage10), lauchActivatedEventArgs.Arguments); + } + + // Ensure the current window is active + Window.Current.Activate(); + } + + private void OnResuming(object sender, object e) + { + var currentFrame = Window.Current.Content as Frame; + + try + { + //_databaseService.ReOpen(); +#if DEBUG + ToastNotificationHelper.ShowGenericToast(_databaseService.Name, "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"); +#endif + } + } + + /// + /// Invoked when Navigation to a certain page fails + /// + /// The Frame which failed navigation + /// Details about the navigation failure + private void OnNavigationFailed(object sender, NavigationFailedEventArgs e) + { + throw new NavigationException(e.SourcePageType); + } + + /// + /// Invoked when application execution is being suspended. Application state is saved + /// without knowing whether the application will be terminated or resumed with the contents + /// of memory still intact. + /// + /// The source of the suspend request. + /// Details about the suspend request. + 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(); + } + catch (Exception exception) + { + ToastNotificationHelper.ShowErrorToast(exception); + } + await SuspensionManager.SaveAsync(); + deferral.Complete(); + } + + /// + /// Invoked when application is launched from opening a file in Windows Explorer + /// + /// Details about the file being opened + protected override void OnFileActivated(FileActivatedEventArgs args) + { + base.OnFileActivated(args); + var rootFrame = new Frame(); + rootFrame.Navigate(typeof(MainPage10), args.Files[0] as StorageFile); + Window.Current.Content = rootFrame; + Window.Current.Activate(); + } + + #endregion + } +} diff --git a/ModernKeePass10/Assets/Logo.scale-100.png b/ModernKeePass10/Assets/Logo.scale-100.png new file mode 100644 index 0000000000000000000000000000000000000000..35e3d15a4b326be548ecd51c7b773280bbc862c9 GIT binary patch literal 1907 zcmaKtdpr{g8^=fPVjQA&*%B;`y|0!9Hb;vBme+_)Fnqd z_+ifa?qVW`(Nf^f^kEVp!X0b?FM2@SLm`B-cD4opUZqL$Zweo3@qam9CjtP{Z@#-g zdtk9Q03a%M$)br~^B=jm4B)T%yrb|z_drw9vJ@A8tP1ZZ};9+WgpU)@%N=m@q zBc13RZfQj$YGjl{B~(Bxnr$=0`?rU&-CNB_WwSgW>Ok284jV1iZdiJ@#U~U$P8v zc$KBKEkCDg=DZS{hc~&V=sbZ(Y0|qR?h@kBF=9fJcE^#&1)BwB#T4&fU|bN271or| zlZp9%txe2c+U$B%CS~LazyCLRa|UobV)wL}73GC#HGFMIbr3maQ}K5o9KUfDOs-8L zO!}G}z>|y?+ie)5*rREG+?<)#G11N9jHT^vZsny3wF{JiCmpYzQYl%59mxlCKJ3v> zAcLlVD%3HA-e6*UC;G#w_!dVKsXRuvu;2M<1P@($G$#0B%$-Mcnx%{(L=<6X&PX*Ka-_Z6O ztNoZY6JKtr2gS&=gDUm1Urx@C>%dxXO##A!p@u}W*Y?4TP*5AUH#RRUVk zNh{*e$?Y5W%Mh(1DeR|O8nZB;O#tz&YE9;E@Aqrpx;FexO@hiQ>opkb{hKJik@gke z6Dmng>{amTrwZqOg3ih=uM|B%MR+PIn$oJH%bX7mH47FT~+YG3Z@AKqxpyLOD0iVYmi@Vl{qqNu#Q z!uzDMgT+-`%~?vY&B}({f3Eb5#J&7ySuv$y3W-Ivz}jD%Xr4MT3*#yHZ!t~RKc?@+ z=q6;q&U!k`9^mHakyV&0B$}E;0V_2>(-*Z<0#wYF|7566K!t?zt94!#oJ61MEvJLx2nbIOHTHMaIM!$(M zQSQ7(Po7CL?=~+Ud(svqv~^~vnX&;5M}O^A1paPbVezqMtg?*_YS>=)c058fD6raF zg$;0=@QiPwMqf+L4M?O$*I0@K*%nt?85Bq>tKm@K5~*v=EhmNtBGjL;6-uS~+hI^# zN|*NdP{1F?$hzV#6KmBvlGg2kZ^wW6kl3{VEhE;&k*2%72RIH`#%(9bIxb;`B3Cfl zzr9i0+0-=owmfXfuz>uy7V!?DJ2oL;|HMsXvnWD5+uW>t=Uo-JJ$_hxV0>g@CbJg( ztFc8Jh?L5v&ded8UGAYB#kX-4ek4LC)s6Tpr4-GpdE>KnN=b(qrT(^>X~59$32Hv) zVd2TnC`JFuFP<3k@7;uyx1S|&k%d(^cS#XR6f|!z;z1iq1vu!$WVxdlZRFLJA=8{k zVd4vao+}eqoZ7`z248tK4@a973y|aMTIG-S9<2-tCMEjEKF$w7FgZch3uty$PQFDS zh)dH(VonK9o$NuB!pQP94+Hy|tXHP&dW%7~B!sNqk|5q6QTGs8ShyS8NZ40@c6tqEg9XQtykAayak=~@Ahpibo>3EpomqbcdH2YGUyJui^s`-Lim{yS8R_u2 zgXcjLXFPVxYgMxy4XE`#C^Bv>az#R+xwdyYnbc6)0pbP^-{L$R=?F`A|5Q-Z4e(?$Bv_g`=>GE}@xV~XNx6vZm6(!@zGE)H zTv>ye!eq-Gzi5XG2FL%GbOpeytmZT0J!{PzV`ThT$?4z21zeBU8Cl?K#;5rqW|kU~ zcC=M#R7uS(UdHNp6I)AqFL+*`$G>}yNgyyrPHM>4wzy9o_`g0cVK|vw8PxANu#=sa zGL5{Kpf2^lD1AyFZ|a4Rk3eL7#+1nW9m-L3ntL=L`N_`Wv4unQlJxo{oWPwcHwID< zz*dKg$59-fraI=lr=cA}40YlMbXE}NTwgQpmIdjQNm{my$+}Hi3!Pb}Df|P!f6$Vd z`iwxrKpHb!^Euj~7l;7?+Y9<83(j&sdN_ymCINahz}v$&T>9+r&iA=X_AYiWY|yd) E0pv1xkN^Mx literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/Logo.scale-140.png b/ModernKeePass10/Assets/Logo.scale-140.png new file mode 100644 index 0000000000000000000000000000000000000000..cc4eac338885cfbb91833f572fb1f9a340973ee0 GIT binary patch literal 2552 zcmbuBdo&aLAIIr8O43>$M5!_5mZ`?vYHYboi=q%SDdc`@STjshRFYgu>gVz>&#Ga` z?Quyp&%2?5E%Po!?*2d4A71zwbGp@B6$z=X*Zq_4(`ly?fr?MsBCd zP6-JKIa{=)v}}J$FRwY(g~2$Ic90S2&C*)wMOnx1Ib?7d@W|G}ADv+PDxUG}fZoFDH^&x@9I0lEF)mSzLg*v)b2} zABzI66T7SO)dD$D7EuiY5HgPi5yA;lLSj7F2NU>ku_|a?LBWyGu_OBuDSS1gqN2rZ zg}t4%Xie(&D%yu^dt3#!d#P8%E9?TKE*SHb!d!1b_#I}l zm$cYnTg+!A)6>tbO5GSnacz6DPvHGDWZ$|e%r}YlQ-rYJv_Nf&Enq8<`m7z?D6-Wo zv|@X6k)jhvrQl;}aps^45cslHuleNJG8xA!(=MHkm+Nj^o9IoUVQfddOMMcG7MPqo*?|Lo?cEVEG@fCzfJgZ_e5)$2i=*U#xN<&d}WF^cin{ zF~+-*-}!|NyB4>={!Q~){e+~?J#0YSSi!lz^j{ZHgNu`pm zI8jNC;4ne@W}7d|B9y4aH94FS8;nTsmrL7B{}AzXm1i)vmS{_&1|rPh zK}ZmF*PE4rY;6}`)Gv)wBly>=ah30!s;_=A5GGK4jtxK~7-J!vD6oT?DTH^-KeE|Z z@!T%#90EPSy*TbZTO5cwC-%dSq9PI#r<(IZQru?bY;!UPP2?6BVdahq^=oFJP{v zE|XNO$W0&)Q6<+xBQ&#Jkk_?e^_2rh8(Oq4%+_R%<$jRly09y=Y@ztt(uv^BD zd^5cWZhMh*SIZ=nC{H~u&pn7Oh>S$wYaaTk(L=Y-ljNywJvGAket%EV+~8xvP_%be z9wD75uW?G(%%x$)`V2v$?mo!IWTQT#{TVnV%$PY)84n9KI9v0*M9`TGp2{r7xON|G z=?L-fEi+qLqNV|~W8I@6IP(DgIqetWBP>|mMtjClIHubH!L~})UeX$M_jB#OMZy{nM}G;byTB{$se!w z#C&!f=_poR&qGk#l>jnn+R$a%&Y@(moYp*}*nGEp!2XQ3WbphGl4T0k?41O1+pZfR zD(gfpG|7($q9PMSpZ6zhwv?!P#)BoL>z`Nl+Qk;haM#@t6&hv0@2sz>kl`z5djhJo z5^nVs_$i>}|C5ILAJ8s5W9K7X=noh6y0Ih0yrgVyG_PoczDgR;5&($;$dUc8t&}ym zs`NVV42!(zvW@u_CYy|1-WZy5+Bg+1mL6;fCx5yJ$dI#mx<}*RY=0^@90v2x4YFH~ zAGs;u^~9bOf2>b@xi!MDWN5NukT+w4N_S8PP-V7uJ7$gY-pWl32Jf;p*oztzRER#r zMg5A^R&UxT^I!P?k?3;;ew9_FC~G?{S?o7`oT?3_yd7e>M1V*A!IbRh{Wa~MuJBjQ zrU~~tl2YkQfu5<;A^6P&9llqq|4JZagP(kT}h|~xY5QKnqL8M6uHPlEz2!cUYDN9u%9l@Z2 z^cQK1A%qrsAh0Ne5RjJ8^Wx6FdH>$b{@6Qn=9^RJn>lyRJvZg91^DDI62AZdfRm=T zjjREHV*)>ghl_22V|Po~a4f_cYyha~2U6JzrxuG>*B7t*56ygtA%18fu9>n){f(n8VMk`93ARw>%cLck3z4?M zQ8U5{?{+)CZjRaz3I{@Puy4;Cm3^k2^rn$y>`5xn#~E;KIHmVv^kV!+*1G)A zj5GJp44FHRsZhccC=da1xHDQReEJW3d;+#Z4oqKG>4_J_MhligB*V-0$JFCSSIzR) z$RKkQNYIEy(2a&A`{%zDS*pDj^-0X8I45Cdu3AhbtlEIwKUR1r-lav8%nqR!fnzww*CyB zE0t2c)(W3k_vyu3-d0^SuaKrIrQfX6BZuP+eY{DAK0Wn%(DaSdI4d38wUsToo|0^* ztEvU{JL76csF_IdwZ;%HRio8|2@qlK7|i6)CyH+D)sGa$oP`1ZSs` zUhqNtAa-#9rXkXp*~{MipK81l=Okw%eN}DL1i^QclPza;Ts#n_noiQv`1)&ag{2F;YR$MqRn*+ad=qiq z+s%1Xvzh_p;k9BQWU-lhG(sd`>iqejudiQPTbe!$e|q_Ikzp9Yd+}-2}-b$5zkFhM=4F z5rY1fv-^|XTLk6lyiqb1q}vpW(6)hhuJ3qQzJ)MXOxt&k41MTyogrL8^3bMbem*+i ze(fTBdIv`B%kI1F*l;7OK48X9ck)Br=e<>$oh>sONf84Lwz8%W&Nk8Bop&FS8Z^pk zU7D2+H@F>#>$w?c1XI20{CbWa-FnwX74+%pK$wSE=r-NQe^iP+Ev+jGya4XG<)m>m z%2cY>RdYAk%*7`UA;|Bs7|;FlEdhR8w`v*>7@?bAA%t*elMCjc9B~~a=Fxh0+Yj<) z-kC1isj9O@M`h|h-@+sv3YUOX-Xk-PcNvL?| z28p=}y4)5-3e3GEM^?;=`hyioZa-+MABq?16K(az-qZEUoDlwl75YUK5BiHsL~rV|{uO43cUt+S8!oYP)AJq1NxW!eaj8jf$(TOR zbD^+AuoIm5tUXenR4j|Lx^0e9LQJJrLd9Jh!^yW2yHOcGP?_1*{f;-A=`VM8S)5>* zMa{MeGZ(2S{PR4njrZSq(gS0{4N1PP{F1H+YOigoH7EF(6^`bK2(xBe^J}9v5sxb! z5*8Z_r}FThN;-eQ2CcggW~YEBF1N#7u;)9lV+*t*Cs%xzRjaJVvhkCwQ?(iRLA(&q z-&dsWdYQQpnJ1Nfnd&h*j?Kn5L^Wedr%PLx&M02DM^n6q8}VME`xjDIBUcvP?5p2T z@9aibLie){Jsam1UJC>LQGT3eQk+t=)eSKpra!m2c5=chATZFjwNDYn+c43jf-fy# z@9UcH75Ff|ZL=hpNT?g5hP^tcWulNIk6`4gWM}orQfi@kPM>z#i<5fNk3#N{e2K*+ zJtPMkpSwJ0t7p7}r??fmWGM}jv*kCM#kw;u9zPv_cGLPJI4EtX5s%-}h-1tOG9EfV z$BGzc=CwIpaLX>#3o%bGTLL3JP8XNKHj1gXep|&2*u7HjN)e)5|J{_~?~`XXt^1e# z(ve|vZuv%R{qLo~=6g%Cll{$YQw9$#Pl+(Zw^k_NmcKZV7 ziB6?rl0`8l`yH>!&7^xIUdWrBd{vGdjgjKx*W}Km{2sdZt4FGnf^UGw)_mh7Y_@#X zBXKEQhR=ieSOu(TSC}M56kkXCf|8QX3%#r63 zOvavCJd|J%^bi#*Acq!jX)fhR;p&}yqhgE}5pj@_R6~LcQ=*CohwaCfU;~9>tC{1b zEtHig^x{ec+XajrsIfOq$vigMz+f<&k3Mfozzvvg4>P_(+;8C_$=L_)3~QZ1X}Jy_jHXKJ{MV{H^}BxU9-UUlka$J@*k zwkh4MBwe$K;Mv0EnWcgq16{Ne5@Rek<5W+~7F~S*vC1egcz_2jQgGKT4%68HN{*%+ zF^Y!&@Um2b21T*kD^d{pb&%9LIORZ@%IN57v1-Oo2}#I7`?ySrT`QTF0$Sg~LJouc zR$>k$7okiO<^K39*y~k}?6JzqIf#Qj{(|GMJk(K+CG~wjHcUsU`sp+{?he@6)jBcW zR1OMrf>X^nxyiI7Vzp(&0o;)!;nyk(Oi~FttXF>9PB&?O7KH=h<7|bV=kzk)Nsy1T^VL@_&O)NFN09|!^3}Q1T?guAY2J8 z+-{%z4I1kg!ltzh8>zXst@ZlmG7P|RD+n;b$^8Pt26J@%IVg{N$!k|SId*_|Ps-D_ zB)q@@9oxfAtado`V$bBEfy#HbG-{;4@AV^VBg$dddP*m<632h(5P)F5M}4`ke!kMAVpj#Jac$fnQchV<=H2JV zacoO0g-}%$?Lk<$copy${l5n?MIwELn(77EP!o1Ja!asBSYUMp0IJgi8bH_pIJlnt zgS+YfNdhV$_;Ko@w%! zN469txo8_!c`Rhvm6k^`&%4gK=iJjj_x{fJ{l4>^-|vs_uP@0H0o$m&T^RrXY=pZy zdCQgjlN;8_w@t`FzFdF=Z4GbY005}9{3Ngq zUlIZUtYyQUpuXgw$$>ar)^XkS-+~GL!oJRieZ>*g5=K{1ZLJF$rL%I=m8ZYc)O7<` zW7XK?%7&{uomd9mo^bsF?M>wmH<}2>RFK%Pp1x=-!Tf9I6X8TfIrYgR_0UN%r<>C~ zI1|OJmac!rBpfOJvDm~A*?isxl;`W5DK1ZRrT|Ssmr2^@<;v#Vq-TPC*6~y4{`1bI;#=zNk zDfr&IY*A_I>%rD7v_~P`suXdS0=miI_-t$FeXEjhko=fNTbRf@cjLjb2NULvP zlu`O&pw4(6wn}m^S**{DtIe>e3QgV-r+XxB(s@C)7*sKvbhV>=WW8m{_+{0Kh_tmr zJ~ifmkKM3?;M5L@*)ReXqHF9 z7PTSZw=-qM@^Fd5H*K27Xw_7gwo{vat&_pia)#ZKEC7*EN%4V)o7IfZ57oJn7f zXvZxu@kjm6?_5%4QQC^_@ZSgONK8^VUH;~0ONUkSGo8UrG-{WR$ML&3)M)wwbOF~d z_0l$|kIk%g$u`3ZiZ9VKzBy8 zPn{Kec<=+AN8mScg1aY6*#&=~nOAXCJ>Bfa6WpSV`QtJ9?jI-KhIyD{g9^1Ea ziW2lJEu4BYtPVF+)?$wGmwe-Py%p9@+LM;tQAMVaDM(#~f4~@}?LO>MlNwDEa#Hba zuQ}{SH>&8}UU#CgS^;kFizzS}%B3@7BTI3m1qJQL@}#y#=yjO<77+Qt<=`Dws&%-% z3P7+t<-f2*RY7wVUGy<8fB!$^Hs0}V7%nj)n?yd8w_oDu=$RNKT|LF{mzw-(>Xmq+ WF%hJI(O_YP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0#QjsK~zXfV=NCn z@}FS<027p^I~cW?Zh)l3rKHWzVCp2!AS%VlAS}Vb@bBM$hPN+%FuZ*9jp6vt=M2vt ze1)nc42ZH=PL-FzBT61@F+Onh^jn5)iywd;LkJMGSl2?BAv8;sfsKP1D#F0<@$E05 z;oljUm>I!7=M`Xs$}li|{_u-oarX^|N4GyiMX&?B7MnVYGX$rrKzR%d*U!FVIJogC z!-E^2pdt{UZ7R&*79qzVF3Sbx|N8NlVOHZ6h9`Hwfce+}&cr1s%Ff^$uL$KaFzj3V zm|~(g88D-oD43ZvS2ngfYoA=FdLLmb}V}cW)lMc{{ClJKj$vPpWpw$ zd@B!0oW8~?YHTkCWif!W3CK6Zg4a*KqXfC8F~kGt0IS8I!~y~!ADln*8q6jIoIUUg z%3@&9FcN~YPytqpVR8HQ^KS-mIWBPiB?YrX^@9K?kzxZ_vs1?^Ybc9y@c#8rhR*CW zP#ywc_!zmMpe4ZYG00+2X+;QtN-cgN?7@f(eti4GaAfN`OB literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/ModernKeePass-SmallLogo.scale-140.png b/ModernKeePass10/Assets/ModernKeePass-SmallLogo.scale-140.png new file mode 100644 index 0000000000000000000000000000000000000000..15db30d13da475ff0dadb5f49a021bf0d97fda71 GIT binary patch literal 907 zcmV;619bd}P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D10YF6K~z{r?U!vx zQ(+XxkFRZv<=aNSVG*g3nnD?s6{8O!5g0}9U!#JEpf46tQJ?Zl5LARg1Q9_Ry+IV1 zL}?ZZCMLa@B2I0xOvTpJ&DlNoo}t^_b6?zbY;b>Y*>eutp8xZl^PK10xaxgPvk(Ks z(`VG93)LE3sMf@c(6Gx>_6ie}ZM8z0)c_fp2C#6?)Z`2}2i@Qta>KCwAGE)Bg4^Y# zUo4CT3td^10=B9gC@4!K4;vKO^6D3~ymr9E*fe?7p;~CNAps7Y%7>!z4Du+)>+!*} zyS>o*W|%z6QI(_S)MPkzshBBpnhW_*pNkK>Z$`ZS#H4uGdwdmC9$ro!5jX%vNi%g$_(NEG;-%QrcZ$cSSS zZeQ$#AD>6bBd~o>u1Gu!S)tY(BkVYsN0vb2V>`TiF-Vp&Fn{mWeC2c44@T^f7IVS0S)zbvebe3SbwWKATMzvN;b+@5J{mZu(ZNLmOx$5L~6kuefxBP zEP=J$VUt5rD6SOirk~!falZ6~%cllMz+wxzOT%PNA}chKLW5V@-sGfFcwia(**Qj* zkgIDpq>~jINuicZBaH+)nt#(Me7aiy&`7|V9XMAol6CZaZ8?7%Ay|f<-09)RT7bfA zyK~7BE`SHuzL6zHQs~u36*O9W273O&jdLAjiD8D`zmt)|v~+=o$zYm0?a=@;^thu1 zWvOH>K6rCsp0Z#H#bR$xl@3QRUe7Gw7-P9fNmrLTKHsdU`a&~_+jl}4ONo$y)$5#Yf)m(QI3GnTK1yg9Wq35X9 h=t8wd7pg4){{e?;8w-l=e+vKr002ovPDHLkV1nntpRxb| literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/ModernKeePass-SmallLogo.scale-180.png b/ModernKeePass10/Assets/ModernKeePass-SmallLogo.scale-180.png new file mode 100644 index 0000000000000000000000000000000000000000..cd2a9a59b225db4df77a18c33b8dca3b1afbef8c GIT binary patch literal 1059 zcmV+;1l;?HP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1Gq^28CD=2v!CX^dX`MgCg@&)Q2d7f}(;x2oZfKLuiu< z3oEUtOv4hF7IDi3QB%`2t#_WsM(53&cjwJhd(-=Y%sFRZ-uvHs&bjC6l$~Du8ypa4 z`gAxnVQNDYrZzNTYQtfLP09gnFzO&W!54h}bufps4Mul9HaIX0ZB6~q-rNtZ4L|t5 z>hew)8CHHqP*fPc{Q9(Dh)ebZXBQ`mTBoCB07?p);q~KI_%$>_QTtIun1Apr*tjDE zViOG%v7Mf-L3sJF1&Z%C^E+!Vb_>Il%gBlVH=PSb?4z#gJ6u0o%?q^$yP8MRrU1x1 z93?3VYpApRC-n6UQAC{3C{NgXVlnsyx>H0RvUUvXXY1}TSiZqX5g}hbc5}7!4VvqE zc~N8NJ!bH=7!~gWD^uoyyWW+)nFubzwKG-x4$486u++>@SiL2Xyoun8Ji1ZO3zNci zhBK_#XoPiXLA+pdu-48UDx0t{tk|52A>kg7lo~+ZM4sJkf-A>AFo{C23u3c4f217R zxnsZ_O!4gpBA7eucx)1eE1bSBT<{>Qp*y)>px|1atTU;*V-POnyoXN}T@*2aH7B-^ z*04z!wscEHeedd5c=6yHdGf%t%RO1i)np$f9q((g!HB^uEMbjMSkdh!SshD? zC;1J0-Hiw9I%b(KdD1Wm3tBi^kmHyxrA4jeDGUB~+4DB?Ojuf6F_?tKTlhho%FS0* zNlKpzg<*%pT4#Ytn2{TD&3R|x!AgSXT77K~c_#22Wr0bU-cwk#jh}nTnmp=jgu;CM zbYxkFX{5@zoG3_v!n_8uCXcWfPY8?kB5xF&RPfxCf=Sq^o2$s0em=hG;D=)=Bva9r zvtue?O+`szI=wO%NTm?F=9nWX%*!y7EOjASV;z}( literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/ModernKeePass-SmallLogo.scale-80.png b/ModernKeePass10/Assets/ModernKeePass-SmallLogo.scale-80.png new file mode 100644 index 0000000000000000000000000000000000000000..bea8813272c5ee73941025d4cda6a03823fc3fec GIT binary patch literal 607 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 P+hA|wc%uBcPu%|i7MG&h literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/ModernKeePass-SplashScreen.scale-140.png b/ModernKeePass10/Assets/ModernKeePass-SplashScreen.scale-140.png new file mode 100644 index 0000000000000000000000000000000000000000..65c5a7e6e1a6fe0b607f47a67db4effc14dfb411 GIT binary patch literal 6856 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 literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/SmallLogo.scale-100.png b/ModernKeePass10/Assets/SmallLogo.scale-100.png new file mode 100644 index 0000000000000000000000000000000000000000..b8e7c318bebc72255492b6a265f66fc75621dae7 GIT binary patch literal 700 zcmV;t0z>_YP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0#QjsK~zXfV=NCn z@}FS<027p^I~cW?Zh)l3rKHWzVCp2!AS%VlAS}Vb@bBM$hPN+%FuZ*9jp6vt=M2vt ze1)nc42ZH=PL-FzBT61@F+Onh^jn5)iywd;LkJMGSl2?BAv8;sfsKP1D#F0<@$E05 z;oljUm>I!7=M`Xs$}li|{_u-oarX^|N4GyiMX&?B7MnVYGX$rrKzR%d*U!FVIJogC z!-E^2pdt{UZ7R&*79qzVF3Sbx|N8NlVOHZ6h9`Hwfce+}&cr1s%Ff^$uL$KaFzj3V zm|~(g88D-oD43ZvS2ngfYoA=FdLLmb}V}cW)lMc{{ClJKj$vPpWpw$ zd@B!0oW8~?YHTkCWif!W3CK6Zg4a*KqXfC8F~kGt0IS8I!~y~!ADln*8q6jIoIUUg z%3@&9FcN~YPytqpVR8HQ^KS-mIWBPiB?YrX^@9K?kzxZ_vs1?^Ybc9y@c#8rhR*CW zP#ywc_!zmMpe4ZYG00+2X+;QtN-cgN?7@f(eti4GaAfN`OB literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/SmallLogo.scale-140.png b/ModernKeePass10/Assets/SmallLogo.scale-140.png new file mode 100644 index 0000000000000000000000000000000000000000..15db30d13da475ff0dadb5f49a021bf0d97fda71 GIT binary patch literal 907 zcmV;619bd}P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D10YF6K~z{r?U!vx zQ(+XxkFRZv<=aNSVG*g3nnD?s6{8O!5g0}9U!#JEpf46tQJ?Zl5LARg1Q9_Ry+IV1 zL}?ZZCMLa@B2I0xOvTpJ&DlNoo}t^_b6?zbY;b>Y*>eutp8xZl^PK10xaxgPvk(Ks z(`VG93)LE3sMf@c(6Gx>_6ie}ZM8z0)c_fp2C#6?)Z`2}2i@Qta>KCwAGE)Bg4^Y# zUo4CT3td^10=B9gC@4!K4;vKO^6D3~ymr9E*fe?7p;~CNAps7Y%7>!z4Du+)>+!*} zyS>o*W|%z6QI(_S)MPkzshBBpnhW_*pNkK>Z$`ZS#H4uGdwdmC9$ro!5jX%vNi%g$_(NEG;-%QrcZ$cSSS zZeQ$#AD>6bBd~o>u1Gu!S)tY(BkVYsN0vb2V>`TiF-Vp&Fn{mWeC2c44@T^f7IVS0S)zbvebe3SbwWKATMzvN;b+@5J{mZu(ZNLmOx$5L~6kuefxBP zEP=J$VUt5rD6SOirk~!falZ6~%cllMz+wxzOT%PNA}chKLW5V@-sGfFcwia(**Qj* zkgIDpq>~jINuicZBaH+)nt#(Me7aiy&`7|V9XMAol6CZaZ8?7%Ay|f<-09)RT7bfA zyK~7BE`SHuzL6zHQs~u36*O9W273O&jdLAjiD8D`zmt)|v~+=o$zYm0?a=@;^thu1 zWvOH>K6rCsp0Z#H#bR$xl@3QRUe7Gw7-P9fNmrLTKHsdU`a&~_+jl}4ONo$y)$5#Yf)m(QI3GnTK1yg9Wq35X9 h=t8wd7pg4){{e?;8w-l=e+vKr002ovPDHLkV1nntpRxb| literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/SmallLogo.scale-180.png b/ModernKeePass10/Assets/SmallLogo.scale-180.png new file mode 100644 index 0000000000000000000000000000000000000000..cd2a9a59b225db4df77a18c33b8dca3b1afbef8c GIT binary patch literal 1059 zcmV+;1l;?HP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1Gq^28CD=2v!CX^dX`MgCg@&)Q2d7f}(;x2oZfKLuiu< z3oEUtOv4hF7IDi3QB%`2t#_WsM(53&cjwJhd(-=Y%sFRZ-uvHs&bjC6l$~Du8ypa4 z`gAxnVQNDYrZzNTYQtfLP09gnFzO&W!54h}bufps4Mul9HaIX0ZB6~q-rNtZ4L|t5 z>hew)8CHHqP*fPc{Q9(Dh)ebZXBQ`mTBoCB07?p);q~KI_%$>_QTtIun1Apr*tjDE zViOG%v7Mf-L3sJF1&Z%C^E+!Vb_>Il%gBlVH=PSb?4z#gJ6u0o%?q^$yP8MRrU1x1 z93?3VYpApRC-n6UQAC{3C{NgXVlnsyx>H0RvUUvXXY1}TSiZqX5g}hbc5}7!4VvqE zc~N8NJ!bH=7!~gWD^uoyyWW+)nFubzwKG-x4$486u++>@SiL2Xyoun8Ji1ZO3zNci zhBK_#XoPiXLA+pdu-48UDx0t{tk|52A>kg7lo~+ZM4sJkf-A>AFo{C23u3c4f217R zxnsZ_O!4gpBA7eucx)1eE1bSBT<{>Qp*y)>px|1atTU;*V-POnyoXN}T@*2aH7B-^ z*04z!wscEHeedd5c=6yHdGf%t%RO1i)np$f9q((g!HB^uEMbjMSkdh!SshD? zC;1J0-Hiw9I%b(KdD1Wm3tBi^kmHyxrA4jeDGUB~+4DB?Ojuf6F_?tKTlhho%FS0* zNlKpzg<*%pT4#Ytn2{TD&3R|x!AgSXT77K~c_#22Wr0bU-cwk#jh}nTnmp=jgu;CM zbYxkFX{5@zoG3_v!n_8uCXcWfPY8?kB5xF&RPfxCf=Sq^o2$s0em=hG;D=)=Bva9r zvtue?O+`szI=wO%NTm?F=9nWX%*!y7EOjASV;z}( literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/SmallLogo.scale-80.png b/ModernKeePass10/Assets/SmallLogo.scale-80.png new file mode 100644 index 0000000000000000000000000000000000000000..bea8813272c5ee73941025d4cda6a03823fc3fec GIT binary patch literal 607 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 P+hA|wc%uBcPu%|i7MG&h literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/SplashScreen.scale-140.png b/ModernKeePass10/Assets/SplashScreen.scale-140.png new file mode 100644 index 0000000000000000000000000000000000000000..65c5a7e6e1a6fe0b607f47a67db4effc14dfb411 GIT binary patch literal 6856 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 literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/Square310x310Logo.scale-100.png b/ModernKeePass10/Assets/Square310x310Logo.scale-100.png new file mode 100644 index 0000000000000000000000000000000000000000..fddfbb5505bea2c86882db1b44c6342395bce428 GIT binary patch literal 3556 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 literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/Square310x310Logo.scale-180.png b/ModernKeePass10/Assets/Square310x310Logo.scale-180.png new file mode 100644 index 0000000000000000000000000000000000000000..355ca308bd9812b4bb9218ebc0336b32b2b61e7e GIT binary patch literal 6864 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

_B;2WrG=A9ZC<1vf-UjSXi2N)}~EwH`{`xeTG} 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 NSeROyR2jP^{2hg2La6`% literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/Square70x70Logo.scale-100.png b/ModernKeePass10/Assets/Square70x70Logo.scale-100.png new file mode 100644 index 0000000000000000000000000000000000000000..e412aaba329de3224029e4a9217290fb19da2fa2 GIT binary patch literal 1217 zcmV;y1U~zTP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1Xf8zK~#8N?VNo~ zO<@?opK{BsTuCAdDa2$^8d}nrt@&DpSvK=AUlYq_#Qb5*M)QYZ{9$c0n~%k4i(%L` z`Pg!&hJ2(@NlK+9C4J~Qy-N39)J)x3zoT_qN+Tzw@5w<2_qI5ClQ=Jx=Vk z6MI)Y8QAK0)RRWV5`GuO4goNF67JnNIwqRzA9cAVKOVFiid zKw>zM7!D+c1Bu~4VmOc(4t5jcJirNj{M=x2_)v&iGzyk(2!z>d5lUChh{zOesn1T0=V4!nE@ve}+9CBhrF9-0c9 z4}^fHw=0{~58cGzZL@Gq04&=Sq+EGf1WxgU?MFgkRDcJY(Fa|`xEcpQd}1&}FY#kD zd@zm_=l_J9$KT<7b`?~V*0Xo`n1;A2t7qagFE%3|>A@GjG{%Fj;z-Sp26%d>6teDr zQ;w~{)#e{K2Z+jLikqni;X(K!Y^1-3KteLVzfK> z2MuDQ4lt8g%w=pO7YyE4PQ6!MiD5B5>_`k@F}&6CC_{a@%L21iL2fl0b$}~IMrST0 z27~VOXxl4$5F(zadzbMp-kQm<8(d!nn=H;^r)tYGf9P!&pNQ}El zy{NL7g-UeIU#JTh`~iHJ|MLqMgSsI{p%|X7H{#@W$9+nAZrGAmF_26Dw zQR`138+8e#>z+VjIFJ|)B!&Z}YYM(SgT!zkF&sz?2NJ`9#Bd-n97qfY62n2Y@}+-a fKoA5$*a3jQ+~|i2d+IbE00000NkvXXu0mjftsX2@ literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/Square70x70Logo.scale-140.png b/ModernKeePass10/Assets/Square70x70Logo.scale-140.png new file mode 100644 index 0000000000000000000000000000000000000000..569866f78c35138eb35c2936be4eb6ac379fd982 GIT binary patch literal 1508 zcmaKsdo&XY9LMK9V_a_y*KG5MU5Dh&EstTEA&=z|L*C~ikCT}u8#V7o3RC2nWf7ry zg-cY*O?l)!^crCZwb0e=+;i_=o%8wrzUTY<{r&r0!WilZqT)WI9czx#KJ_dmgv`yg*E(d?`;)mx<1?vv^3PePkq83i{cwdpUG7WfK>3>v_L1P7 zGRkKT@Wz^{ka`YSeQrlJpcG82Q6@^{u_v86puBpTYF22Jd{YeHvf;Z-Z~4?E+u@$Z z;cn>EocQdO%cGHI{W&mld72KKM537Jv(6pSE&*U zlk;f^BJ@~V?{E6Y@3cTPw96PlA;tM}DT6+pleyW^Ml3pYCQ8<9!(IkSNL0fVg|wZ` zyX43DVi-Z$%U9H2QYuaB;ZW-E0HV7P$M=1$FjbWeBU9 z%_i10rqzIIs!n`7kjl0Z%8HfND{sVSIlI!rtJ;b-{ekw^wl*?28zs*0x2nlrTv|Op z#;|*e#Jkh7pEs_qY&Gkk?^1ry%XV@%M?Lqn(xiBC+ZT&B3lJ>S7ynb@4B`UuGxz@0 z&@0LeMu!Qu?@D+QIcq%@qJj~Mn9;)FAjHCHrY5i9px1J}3p@t9y$4?L-PcvAnEqw4 zfNy?)HCwpT*Sk|h(-l%hI*#f@EYX0O6GOBJS9lDkqMW}V5AF0peZ{0a?p0*izzy0L z!a$#cx6}wT?0TzXilo7Vz5F~kyv=m$(!Br*X}ZsCA&44{>L;tFPJyMCjP0W;!_$e` z5rIslipMBS2Id&ZKr0G9$L;mQA-n}~10xhlSb?IUm2?~Rk(Pb)AN-;+6y4p93a_~n zRba{x?Ws4Ni$<|FOD|rq&dT4~dPu6Y;qYQY<5WObGnWZm%wI>VVDDy2A}6BlmDAgG?bLX^rrf)J^#&8o zLFj9v5LZ-EP5|pTdrLPhBKqtgi)8R$hB#)ocH&Rzg^kEUcqT Q_OO`&XcX4E-V#s#8zj@f2LJ#7 literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/Square70x70Logo.scale-180.png b/ModernKeePass10/Assets/Square70x70Logo.scale-180.png new file mode 100644 index 0000000000000000000000000000000000000000..6b9816990373781f1664065609cfcb35c2b042d5 GIT binary patch literal 1776 zcmaKsX*3&%8iu1(N`>~uaz@>zRc(YSGdh!zT8dy=VrgOxMYN^1s#qe@^wc)COI6!g zN@|HMqE!uJo7~h$TNG_9MN&HvH^N}DpuKwL+#h$&J@-53{oeDwf4=Y6ljZK}1X9&i z1pok`OFtp6>^u3Z4k_>Nxl^>veN(_+ak2w64eG7z2c=M3lq~?zoPT&X_~3q4iTTMF z4*;n5e3ioMTXoj}0Oj;cNLviys)&Eb#q+uza2M4Z#>iG&Et$z3rZs# zdlS?)wgh3&N*TIQ492J&I2G$5b7Feo8Cuc4nqPcCVE8eQ5)T6vnf~5vbZw8; zzkov~q=++fz)7)MYMueuhKDO>W$FVb2sKA6(TB=mN<*3{p{i{2^qFG2b(fQWt$X#Q zzAf{=r3_f;OFCq@q~H=m7;A|&zU{CwmLN|i9iVQWI0MC1UpL4;Era1!vN6UOVtpEM zWlrn;l!Xxj`$dz*%xILnA9j#=-*qp`JZjD!Lgnee8Q5!Oy_y|Z!`&r&#W`sK7q`26 zy?xX_GG*v+O*XUig~Kf4aFrhheKTfGa9_F+?XOi_#w zYT%6=fo{N!W}O@o`r#GNEx{&Su1^ZVZpW<)PTV+GZrt{x`47amLh|;@{EWcm-_m0O zNrag%V+22rUO~}$?83t7oQt1H5o$p-Y|tOMS@1xqN17vNQClqSxB%x4L*=}8AjP?H z@TpijLY1nV;`MCkC0Wx|pgP^gMwhwvb`}o9)-x2X=2kn7dpk}TZpCX&R7P&%ocKSe z-WB6*d}w*zq>21m4t5cIFwd^GrIYB?BCTxgXI6O16Lr<&a`+cY9p;z2=lT{|i-9A< zk~*Ge(6y?Ox*2%1iVw)(f*^8I5=*b+PiZr8kF4igBnUk%{)ibr=I+I&;+~=z@5g6f zb|4ets0e6yL!PgF-PNa#IMnFv_n%_DqCHw}NBmPxKJ%?UpfY;ai9N(aA=l& zI5r0^$i2Hm(_Y;aJr##ufe&TQ7`K`*M+udwpV@TQ$0j`Aj_ORk1trPJiPn*Wy(kfz zYoH=T)XUptxnsjnm$X~8B^7HGrTBw4?2^~x(w&*3&JUa}W_FT<5{%9}%1JTwT({jqRVqM!Tni-~DWU zROB7-OJ{8Zk0Z&`j$(6*U0GzUk*ElHLts;J{YpQ15$1dTdDYIV!q%Db>B3W#8p+B9 z5octzfV4XXTio;SggKvEsW?q2F>QO{6LoQZrzf?NZelP#F!p69a8AIsZrA<>BpALu z?BKjkj~>EAPkiucr|QY8v9d-}7+TEfKsm3oaZI^rp*eWKXaG#mlq zeb!l;2#pgN&xObUfftncqIXolL6u1B`Y}6;X$A4S=C^pbfUe=|4fLR`G!waoT3nWl zjt^4*Z#X7RmQ}sJ^WIz(SFti!$WI6$2R1#14T5VXO`&F9Lz?o9BL%ggmV6xuHFJ9M zT8C?fe|wageXBLPdmigu-k(!>T>pPDb|1a3?lVr}h;OtjHSAlD9Q}Vl{wt?7{zHF2 c(4mu`71YvgL$Ib6+h5yD4z9>1yP%YR1H6lQv;Y7A literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/Square70x70Logo.scale-80.png b/ModernKeePass10/Assets/Square70x70Logo.scale-80.png new file mode 100644 index 0000000000000000000000000000000000000000..368c0d3609c7dbc0570879f0bbcdbaea435eaac2 GIT binary patch literal 1039 zcmV+q1n~QbP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1EfhrK~!i%?V4Rk z6j2n%Ppht9nQfb98m5`1s8no%q@qMfSPz9rAF%Y)2NCs>_zn-4rm~UOwVE#Or)wa3&rOorr_X{gIGlSO@xu0Q%+9u_XJTF3cY?@**KU zHv)Y97Ji4_9iz}t+YN8)`(buwj(X*?#QPx52+mUBO@lB?i-|)bV}fn&(fCN-xgxj; z+!VJOPG3m{Lr%D?LE@|*I35ee3yGi&@S$Gia1ofWLkA~|Qy^rmmU?XI?;3{>=3nsQ zaTmOP)&m`_zhQJ_ioUf4eRH8_v7*=qw`Z(}!)FsDvxfeJeue&pe&&eeG(BV=jDqO+ z5bBv{cwiE4U21~C{y)^?3Y>iqmsS3$trBs)onugT&J5KRpPY(An%@jS#l#dU6a0T?sJ0MD`uqEUXl{$P$RNmU|?cERpfiX{fpVSX(o%Bj2em0BYBGE>s^WU;|4Ff1xi64rT&Loo6V^h}T?V#p4s78}e0aqqInZ0e;J zKN=hQsU?C*dvJ&!S+2t@Q0s4d3kC+Z&Db^C8i%Mgk1m`&nlfiHxc6bc`43FPOb@@4 z#SfgVJYx)5B2{IrLUQ07X(q!g&{&x0aG5R#k1E@RDC-;!sajx=yl~BfpylwvP`&)D z!W}R#(WB?LSxOo9H;MRaHHyk0tV~`$?Iz0+9DHzP!$BY(D+I{!!}gY8Xm1`C+IRpZ z2kU1zhJ(PO@?EmB`{&i2md`h#eeFSpaAn2%8IIu)MLi9#7s$Ls@hCx~k=(W@6Js+% z&4}0+%C0ilH?c@s$iW9wEoBSOV?7qI!obSkIc^LxJixLH53-!21{v=|jiUD8aRug- z?qFnSQm8+j!y(A5Y}6p*eW(IG9aW&GBi$yv?B6L>R8-svz+Wv~VS&Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0&Ph|K~!i%?buCd z6G0RQ@PD^WOdCTCHAbr~8mS)@ty1(-0zrEc@gfm=5TPegT2Fq^i&hW`-V{9OMK6K` z@uK2I38Z={#U3n5MXeNqwUky%YT71S^Cq*3w3}`_vuxD)!LT#48ut$5K&fi1ML5bR^>sBS}88Wch)_QkM%ayTpe!neT}wB8B&{PUF|Vo(jYY zf2|wgU4Aq)`r!4s_^dso*NEFwi35j1XgyqqKyVeGElLk(@H{bs!M<@mW5(ecsa@|u z=e1@WIk{y)5TtIi7bni`Ku32I3s@#;fdn^Js|f0c>E>0+h5_v z`2qANzp`hy?G50})jg>8RT7VcBh2p0ASICf2Sco&$)h_TFf=g1`ips;8pE^upILujB*<1r25Es1 z3V=T7QhJ}JF*-8M`o?QT2?s(ov1#jS*6({U%C1YH)H3R2XG=gz;R^>sbz#u+VEcxZ zHdCl2QsvUvej`eFA8Bq~i}thI`DkTs_q@T!!Eby-9N0(b8!ZRID?<70^_lMnQJJ)c>qEK-X$z=^RL)0Ugnk)6&h zde3O|j40t1q4U#*LK89k?)$G(K#>Ef)fQ_gnKo9?(Z$$TiX1-uI!Sm%=mcBp7s-mu zRF2i!Zw{=;k4))8w$lC#VrBlB)cTKWq)h*yQxru}6h%?&0{jGX_AW0?=TgW30000< KMNUMnLSTaW?@Ye{ literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/StoreLogo.scale-140.png b/ModernKeePass10/Assets/StoreLogo.scale-140.png new file mode 100644 index 0000000000000000000000000000000000000000..d7ff32b72f70402c411eeca5340e16c0e220df4a GIT binary patch literal 961 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 literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Assets/Wide310x150Logo.scale-180.png b/ModernKeePass10/Assets/Wide310x150Logo.scale-180.png new file mode 100644 index 0000000000000000000000000000000000000000..bec913aec131395dc306bef1d5d22387b13876c6 GIT binary patch literal 4484 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 Nur0ySy4vzA{V&&A&1nDt literal 0 HcmV?d00001 diff --git a/ModernKeePass10/Backup/ModernKeePassApp.csproj b/ModernKeePass10/Backup/ModernKeePassApp.csproj new file mode 100644 index 0000000..31ceb9e --- /dev/null +++ b/ModernKeePass10/Backup/ModernKeePassApp.csproj @@ -0,0 +1,489 @@ + + + + + Debug + x86 + UAP + {A0CFC681-769B-405A-8482-0CDEE595A91F} + AppContainerExe + Properties + ModernKeePass + ModernKeePass + en-US + true + 10.0.17134.0 + 10.0.17134.0 + 14 + 512 + {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ModernKeePass_StoreKey.pfx + ED3AA34F46D03498F989901C5DB2742B65D72F60 + True + neutral + Always + + + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_APP + ;2008 + full + ARM + false + prompt + true + + + bin\ARM\Release\ + TRACE;NETFX_CORE;WINDOWS_APP + true + ;2008 + pdbonly + ARM + false + prompt + true + true + + + true + bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_APP + ;2008 + full + x64 + false + prompt + true + + + bin\x64\Release\ + TRACE;NETFX_CORE;WINDOWS_APP + true + ;2008 + pdbonly + x64 + false + prompt + true + true + + + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_APP + ;2008 + full + x86 + false + prompt + true + + + bin\x86\Release\ + TRACE;NETFX_CORE;WINDOWS_APP + true + ;2008 + pdbonly + x86 + false + prompt + true + true + + + + + + + + + App.xaml + + + + + + + + + + + + + + + + + + + + + + GroupsPage.xaml + + + MainPage10.xaml + + + DonatePage.xaml + + + + + + + + + + + + + + + + + + + + + + + + ImportExportPage.xaml + + + SettingsPage10.xaml + + + SettingsDatabasePage.xaml + + + SettingsNewDatabasePage.xaml + + + SettingsSavePage.xaml + + + SettingsSecurityPage.xaml + + + SettingsWelcomePage.xaml + + + + + BreadCrumbUserControl.xaml + + + ColorPickerUserControl.xaml + + + CompositeKeyUserControl.xaml + + + + + + + + + + + + + + MainPage.xaml + + + AboutPage.xaml + + + NewDatabasePage.xaml + + + SettingsPage.xaml + + + WelcomePage.xaml + + + + + + + + EntryDetailPage.xaml + + + GroupDetailPage.xaml + + + OpenDatabasePage.xaml + + + RecentDatabasesPage.xaml + + + SaveDatabasePage.xaml + + + + + + + + + + + + + + HamburgerMenuUserControl.xaml + + + SymbolPickerUserControl.xaml + + + TopMenuUserControl.xaml + + + + + Designer + + + + + + + + + + + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + PreserveNewest + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + PreserveNewest + + + Designer + MSBuild:Compile + PreserveNewest + + + Designer + MSBuild:Compile + PreserveNewest + + + Designer + MSBuild:Compile + PreserveNewest + + + Designer + MSBuild:Compile + PreserveNewest + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 14.0 + + + + \ No newline at end of file diff --git a/ModernKeePass10/Backup/project.json b/ModernKeePass10/Backup/project.json new file mode 100644 index 0000000..9a0731c --- /dev/null +++ b/ModernKeePass10/Backup/project.json @@ -0,0 +1,24 @@ +{ + "dependencies": { + "HockeySDK.UWP": "4.1.6", + "Microsoft.ApplicationInsights": "2.7.2", + "Microsoft.ApplicationInsights.PersistenceChannel": "1.2.3", + "Microsoft.ApplicationInsights.WindowsApps": "1.1.1", + "Microsoft.NETCore.UniversalWindowsPlatform": "6.1.7", + "Microsoft.UI.Xaml": "2.0.180724003-prerelease", + "Microsoft.Xaml.Behaviors.Uwp.Managed": "2.0.0", + "ModernKeePassLib": "2.39.3", + "Portable.BouncyCastle": "1.8.3" + }, + "frameworks": { + "uap10.0.17134": {} + }, + "runtimes": { + "win10-arm": {}, + "win10-arm-aot": {}, + "win10-x86": {}, + "win10-x86-aot": {}, + "win10-x64": {}, + "win10-x64-aot": {} + } +} \ No newline at end of file diff --git a/ModernKeePass10/Common/MessageDialogHelper.cs b/ModernKeePass10/Common/MessageDialogHelper.cs new file mode 100644 index 0000000..385ef4d --- /dev/null +++ b/ModernKeePass10/Common/MessageDialogHelper.cs @@ -0,0 +1,56 @@ +using System; +using System.Threading.Tasks; +using Windows.UI.Popups; + +namespace ModernKeePass.Common +{ + public static class MessageDialogHelper + { + public static async Task ShowActionDialog(string title, string contentText, string actionButtonText, string cancelButtonText, UICommandInvokedHandler actionCommand, UICommandInvokedHandler cancelCommand) + { + // Create the message dialog and set its content + var messageDialog = CreateBasicDialog(title, contentText, cancelButtonText, cancelCommand); + + // Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers + messageDialog.Commands.Add(new UICommand(actionButtonText, actionCommand)); + + // Show the message dialog + await messageDialog.ShowAsync(); + } + + public static async Task ShowErrorDialog(Exception exception) + { + if (exception == null) return; + // Create the message dialog and set its content + var messageDialog = CreateBasicDialog(exception.Message, exception.StackTrace, "OK"); + + // Show the message dialog + await messageDialog.ShowAsync(); + } + + public static async Task ShowNotificationDialog(string title, string message) + { + var dialog = CreateBasicDialog(title, message, "OK"); + + // Show the message dialog + await dialog.ShowAsync(); + } + + private static MessageDialog CreateBasicDialog(string title, string message, string dismissActionText, UICommandInvokedHandler cancelCommand = null) + { + // Create the message dialog and set its content + var messageDialog = new MessageDialog(message, title); + + // Add commands and set their callbacks + messageDialog.Commands.Add(new UICommand(dismissActionText, cancelCommand)); + + // Set the command that will be invoked by default + messageDialog.DefaultCommandIndex = 1; + + // Set the command to be invoked when escape is pressed + messageDialog.CancelCommandIndex = 1; + + return messageDialog; + } + } +} diff --git a/ModernKeePass10/Common/NavigationHelper.cs b/ModernKeePass10/Common/NavigationHelper.cs new file mode 100644 index 0000000..bf6552f --- /dev/null +++ b/ModernKeePass10/Common/NavigationHelper.cs @@ -0,0 +1,433 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; +using Windows.System; +using Windows.UI.Core; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Navigation; + +namespace ModernKeePass.Common +{ + ///

+ /// NavigationHelper aids in navigation between pages. It provides commands used to + /// navigate back and forward as well as registers for standard mouse and keyboard + /// shortcuts used to go back and forward in Windows and the hardware back button in + /// Windows Phone. In addition it integrates SuspensionManger to handle process lifetime + /// management and state management when navigating between pages. + /// + /// + /// To make use of NavigationHelper, follow these two steps or + /// start with a BasicPage or any other Page item template other than BlankPage. + /// + /// 1) Create an instance of the NavigationHelper somewhere such as in the + /// constructor for the page and register a callback for the LoadState and + /// SaveState events. + /// + /// public MyPage() + /// { + /// this.InitializeComponent(); + /// var navigationHelper = new NavigationHelper(this); + /// this.navigationHelper.LoadState += navigationHelper_LoadState; + /// this.navigationHelper.SaveState += navigationHelper_SaveState; + /// } + /// + /// private async void navigationHelper_LoadState(object sender, LoadStateEventArgs e) + /// { } + /// private async void navigationHelper_SaveState(object sender, LoadStateEventArgs e) + /// { } + /// + /// + /// 2) Register the page to call into the NavigationHelper whenever the page participates + /// in navigation by overriding the + /// and events. + /// + /// protected override void OnNavigatedTo(NavigationEventArgs e) + /// { + /// navigationHelper.OnNavigatedTo(e); + /// } + /// + /// protected override void OnNavigatedFrom(NavigationEventArgs e) + /// { + /// navigationHelper.OnNavigatedFrom(e); + /// } + /// + /// + [Windows.Foundation.Metadata.WebHostHidden] + public class NavigationHelper : DependencyObject + { + private Page Page { get; set; } + private Frame Frame => this.Page.Frame; + + /// + /// Initializes a new instance of the class. + /// + /// A reference to the current page used for navigation. + /// This reference allows for frame manipulation and to ensure that keyboard + /// navigation requests only occur when the page is occupying the entire window. + public NavigationHelper(Page page) + { + this.Page = page; + + // When this page is part of the visual tree make two changes: + // 1) Map application view state to visual state for the page + // 2) Handle hardware navigation requests + this.Page.Loaded += (sender, e) => + { +#if WINDOWS_PHONE_APP + Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed; +#else + // Keyboard and mouse navigation only apply when occupying the entire window + if (this.Page.ActualHeight == Window.Current.Bounds.Height && + this.Page.ActualWidth == Window.Current.Bounds.Width) + { + // Listen to the window directly so focus isn't required + Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated += + CoreDispatcher_AcceleratorKeyActivated; + Window.Current.CoreWindow.PointerPressed += + this.CoreWindow_PointerPressed; + } +#endif + }; + + // Undo the same changes when the page is no longer visible + this.Page.Unloaded += (sender, e) => + { +#if WINDOWS_PHONE_APP + Windows.Phone.UI.Input.HardwareButtons.BackPressed -= HardwareButtons_BackPressed; +#else + Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated -= + CoreDispatcher_AcceleratorKeyActivated; + Window.Current.CoreWindow.PointerPressed -= + this.CoreWindow_PointerPressed; +#endif + }; + } + + #region Navigation support + + RelayCommand _goBackCommand; + RelayCommand _goForwardCommand; + + /// + /// used to bind to the back Button's Command property + /// for navigating to the most recent item in back navigation history, if a Frame + /// manages its own navigation history. + /// + /// The is set up to use the virtual method + /// as the Execute Action and for CanExecute. + /// + public RelayCommand GoBackCommand + { + get + { + if (_goBackCommand == null) + { + _goBackCommand = new RelayCommand( + () => this.GoBack(), + () => this.CanGoBack()); + } + return _goBackCommand; + } + set => _goBackCommand = value; + } + /// + /// used for navigating to the most recent item in + /// the forward navigation history, if a Frame manages its own navigation history. + /// + /// The is set up to use the virtual method + /// as the Execute Action and for CanExecute. + /// + public RelayCommand GoForwardCommand + { + get + { + if (_goForwardCommand == null) + { + _goForwardCommand = new RelayCommand( + () => this.GoForward(), + () => this.CanGoForward()); + } + return _goForwardCommand; + } + } + + /// + /// Virtual method used by the property + /// to determine if the can go back. + /// + /// + /// true if the has at least one entry + /// in the back navigation history. + /// + public virtual bool CanGoBack() + { + return this.Frame != null && this.Frame.CanGoBack; + } + /// + /// Virtual method used by the property + /// to determine if the can go forward. + /// + /// + /// true if the has at least one entry + /// in the forward navigation history. + /// + public virtual bool CanGoForward() + { + return this.Frame != null && this.Frame.CanGoForward; + } + + /// + /// Virtual method used by the property + /// to invoke the method. + /// + public virtual void GoBack() + { + if (this.Frame != null && this.Frame.CanGoBack) this.Frame.GoBack(); + } + /// + /// Virtual method used by the property + /// to invoke the method. + /// + public virtual void GoForward() + { + if (this.Frame != null && this.Frame.CanGoForward) this.Frame.GoForward(); + } + +#if WINDOWS_PHONE_APP + /// + /// Invoked when the hardware back button is pressed. For Windows Phone only. + /// + /// Instance that triggered the event. + /// Event data describing the conditions that led to the event. + private void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e) + { + if (this.GoBackCommand.CanExecute(null)) + { + e.Handled = true; + this.GoBackCommand.Execute(null); + } + } +#else + /// + /// Invoked on every keystroke, including system keys such as Alt key combinations, when + /// this page is active and occupies the entire window. Used to detect keyboard navigation + /// between pages even when the page itself doesn't have focus. + /// + /// Instance that triggered the event. + /// Event data describing the conditions that led to the event. + private void CoreDispatcher_AcceleratorKeyActivated(CoreDispatcher sender, + AcceleratorKeyEventArgs e) + { + var virtualKey = e.VirtualKey; + + // Only investigate further when Left, Right, or the dedicated Previous or Next keys + // are pressed + if ((e.EventType == CoreAcceleratorKeyEventType.SystemKeyDown || + e.EventType == CoreAcceleratorKeyEventType.KeyDown) && + (virtualKey == VirtualKey.Left || virtualKey == VirtualKey.Right || + (int)virtualKey == 166 || (int)virtualKey == 167)) + { + var coreWindow = Window.Current.CoreWindow; + var downState = CoreVirtualKeyStates.Down; + bool menuKey = (coreWindow.GetKeyState(VirtualKey.Menu) & downState) == downState; + bool controlKey = (coreWindow.GetKeyState(VirtualKey.Control) & downState) == downState; + bool shiftKey = (coreWindow.GetKeyState(VirtualKey.Shift) & downState) == downState; + bool noModifiers = !menuKey && !controlKey && !shiftKey; + bool onlyAlt = menuKey && !controlKey && !shiftKey; + + if (((int)virtualKey == 166 && noModifiers) || + (virtualKey == VirtualKey.Left && onlyAlt)) + { + // When the previous key or Alt+Left are pressed navigate back + e.Handled = true; + this.GoBackCommand.Execute(null); + } + else if (((int)virtualKey == 167 && noModifiers) || + (virtualKey == VirtualKey.Right && onlyAlt)) + { + // When the next key or Alt+Right are pressed navigate forward + e.Handled = true; + this.GoForwardCommand.Execute(null); + } + } + } + + /// + /// Invoked on every mouse click, touch screen tap, or equivalent interaction when this + /// page is active and occupies the entire window. Used to detect browser-style next and + /// previous mouse button clicks to navigate between pages. + /// + /// Instance that triggered the event. + /// Event data describing the conditions that led to the event. + private void CoreWindow_PointerPressed(CoreWindow sender, + PointerEventArgs e) + { + var properties = e.CurrentPoint.Properties; + + // Ignore button chords with the left, right, and middle buttons + if (properties.IsLeftButtonPressed || properties.IsRightButtonPressed || + properties.IsMiddleButtonPressed) return; + + // If back or foward are pressed (but not both) navigate appropriately + bool backPressed = properties.IsXButton1Pressed; + bool forwardPressed = properties.IsXButton2Pressed; + if (backPressed ^ forwardPressed) + { + e.Handled = true; + if (backPressed) this.GoBackCommand.Execute(null); + if (forwardPressed) this.GoForwardCommand.Execute(null); + } + } +#endif + + #endregion + + #region Process lifetime management + + private String _pageKey; + + /// + /// Register this event on the current page to populate the page + /// with content passed during navigation as well as any saved + /// state provided when recreating a page from a prior session. + /// + public event LoadStateEventHandler LoadState; + /// + /// Register this event on the current page to preserve + /// state associated with the current page in case the + /// application is suspended or the page is discarded from + /// the navigaqtion cache. + /// + public event SaveStateEventHandler SaveState; + + /// + /// Invoked when this page is about to be displayed in a Frame. + /// This method calls , where all page specific + /// navigation and process lifetime management logic should be placed. + /// + /// Event data that describes how this page was reached. The Parameter + /// property provides the group to be displayed. + public void OnNavigatedTo(NavigationEventArgs e) + { + var frameState = SuspensionManager.SessionStateForFrame(this.Frame); + this._pageKey = "Page-" + this.Frame.BackStackDepth; + + if (e.NavigationMode == NavigationMode.New) + { + // Clear existing state for forward navigation when adding a new page to the + // navigation stack + var nextPageKey = this._pageKey; + int nextPageIndex = this.Frame.BackStackDepth; + while (frameState.Remove(nextPageKey)) + { + nextPageIndex++; + nextPageKey = "Page-" + nextPageIndex; + } + + // Pass the navigation parameter to the new page + if (this.LoadState != null) + { + this.LoadState(this, new LoadStateEventArgs(e.Parameter, null)); + } + } + else + { + // Pass the navigation parameter and preserved page state to the page, using + // the same strategy for loading suspended state and recreating pages discarded + // from cache + if (this.LoadState != null) + { + this.LoadState(this, new LoadStateEventArgs(e.Parameter, (Dictionary)frameState[this._pageKey])); + } + } + } + + /// + /// Invoked when this page will no longer be displayed in a Frame. + /// This method calls , where all page specific + /// navigation and process lifetime management logic should be placed. + /// + /// Event data that describes how this page was reached. The Parameter + /// property provides the group to be displayed. + public void OnNavigatedFrom(NavigationEventArgs e) + { + var frameState = SuspensionManager.SessionStateForFrame(this.Frame); + var pageState = new Dictionary(); + if (this.SaveState != null) + { + this.SaveState(this, new SaveStateEventArgs(pageState)); + } + frameState[_pageKey] = pageState; + } + + #endregion + } + + /// + /// Represents the method that will handle the event + /// + public delegate void LoadStateEventHandler(object sender, LoadStateEventArgs e); + /// + /// Represents the method that will handle the event + /// + public delegate void SaveStateEventHandler(object sender, SaveStateEventArgs e); + + /// + /// Class used to hold the event data required when a page attempts to load state. + /// + public class LoadStateEventArgs : EventArgs + { + /// + /// The parameter value passed to + /// when this page was initially requested. + /// + public Object NavigationParameter { get; private set; } + /// + /// A dictionary of state preserved by this page during an earlier + /// session. This will be null the first time a page is visited. + /// + public Dictionary PageState { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The parameter value passed to + /// when this page was initially requested. + /// + /// + /// A dictionary of state preserved by this page during an earlier + /// session. This will be null the first time a page is visited. + /// + public LoadStateEventArgs(Object navigationParameter, Dictionary pageState) + : base() + { + this.NavigationParameter = navigationParameter; + this.PageState = pageState; + } + } + /// + /// Class used to hold the event data required when a page attempts to save state. + /// + public class SaveStateEventArgs : EventArgs + { + /// + /// An empty dictionary to be populated with serializable state. + /// + public Dictionary PageState { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// An empty dictionary to be populated with serializable state. + public SaveStateEventArgs(Dictionary pageState) + : base() + { + this.PageState = pageState; + } + } +} diff --git a/ModernKeePass10/Common/ObservableDictionary.cs b/ModernKeePass10/Common/ObservableDictionary.cs new file mode 100644 index 0000000..af10715 --- /dev/null +++ b/ModernKeePass10/Common/ObservableDictionary.cs @@ -0,0 +1,141 @@ +using System.Collections.Generic; +using System.Linq; +using Windows.Foundation.Collections; + +namespace ModernKeePass.Common +{ + /// + /// Implementation of IObservableMap that supports reentrancy for use as a default view + /// model. + /// + public class ObservableDictionary : IObservableMap + { + private class ObservableDictionaryChangedEventArgs : IMapChangedEventArgs + { + public ObservableDictionaryChangedEventArgs(CollectionChange change, string key) + { + CollectionChange = change; + Key = key; + } + + public CollectionChange CollectionChange { get; private set; } + public string Key { get; private set; } + } + + private readonly Dictionary _dictionary = new Dictionary(); + public event MapChangedEventHandler MapChanged; + + private void InvokeMapChanged(CollectionChange change, string key) + { + var eventHandler = MapChanged; + if (eventHandler != null) + { + eventHandler(this, new ObservableDictionaryChangedEventArgs(change, key)); + } + } + + public void Add(string key, object value) + { + _dictionary.Add(key, value); + InvokeMapChanged(CollectionChange.ItemInserted, key); + } + + public void Add(KeyValuePair item) + { + Add(item.Key, item.Value); + } + + public void AddRange(IEnumerable> values) + { + foreach (var value in values) + { + Add(value); + } + } + + public bool Remove(string key) + { + if (_dictionary.Remove(key)) + { + InvokeMapChanged(CollectionChange.ItemRemoved, key); + return true; + } + return false; + } + + public bool Remove(KeyValuePair item) + { + object currentValue; + if (_dictionary.TryGetValue(item.Key, out currentValue) && + Equals(item.Value, currentValue) && _dictionary.Remove(item.Key)) + { + InvokeMapChanged(CollectionChange.ItemRemoved, item.Key); + return true; + } + return false; + } + + public object this[string key] + { + get => _dictionary[key]; + set + { + _dictionary[key] = value; + InvokeMapChanged(CollectionChange.ItemChanged, key); + } + } + + public void Clear() + { + var priorKeys = _dictionary.Keys.ToArray(); + _dictionary.Clear(); + foreach (var key in priorKeys) + { + InvokeMapChanged(CollectionChange.ItemRemoved, key); + } + } + + public ICollection Keys => _dictionary.Keys; + + public bool ContainsKey(string key) + { + return _dictionary.ContainsKey(key); + } + + public bool TryGetValue(string key, out object value) + { + return _dictionary.TryGetValue(key, out value); + } + + public ICollection Values => _dictionary.Values; + + public bool Contains(KeyValuePair item) + { + return _dictionary.Contains(item); + } + + public int Count => _dictionary.Count; + + public bool IsReadOnly => false; + + public IEnumerator> GetEnumerator() + { + return _dictionary.GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return _dictionary.GetEnumerator(); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + int arraySize = array.Length; + foreach (var pair in _dictionary) + { + if (arrayIndex >= arraySize) break; + array[arrayIndex++] = pair; + } + } + } +} diff --git a/ModernKeePass10/Common/RelayCommand.cs b/ModernKeePass10/Common/RelayCommand.cs new file mode 100644 index 0000000..b651858 --- /dev/null +++ b/ModernKeePass10/Common/RelayCommand.cs @@ -0,0 +1,78 @@ +using System; +using System.Windows.Input; + +namespace ModernKeePass.Common +{ + /// + /// A command whose sole purpose is to relay its functionality + /// to other objects by invoking delegates. + /// The default return value for the CanExecute method is 'true'. + /// needs to be called whenever + /// is expected to return a different value. + /// + public class RelayCommand : ICommand + { + private readonly Action _execute; + private readonly Func _canExecute; + + /// + /// Raised when RaiseCanExecuteChanged is called. + /// + public event EventHandler CanExecuteChanged; + + /// + /// Creates a new command that can always execute. + /// + /// The execution logic. + public RelayCommand(Action execute) + : this(execute, null) + { + } + + /// + /// Creates a new command. + /// + /// The execution logic. + /// The execution status logic. + public RelayCommand(Action execute, Func canExecute) + { + if (execute == null) + throw new ArgumentNullException(nameof(execute)); + _execute = execute; + _canExecute = canExecute; + } + + /// + /// Determines whether this can execute in its current state. + /// + /// + /// Data used by the command. If the command does not require data to be passed, this object can be set to null. + /// + /// true if this command can be executed; otherwise, false. + public bool CanExecute(object parameter) + { + return _canExecute?.Invoke() ?? true; + } + + /// + /// Executes the on the current command target. + /// + /// + /// Data used by the command. If the command does not require data to be passed, this object can be set to null. + /// + public void Execute(object parameter) + { + _execute(); + } + + /// + /// Method used to raise the event + /// to indicate that the return value of the + /// method has changed. + /// + public void RaiseCanExecuteChanged() + { + CanExecuteChanged?.Invoke(this, EventArgs.Empty); + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Common/ResourceHelper.cs b/ModernKeePass10/Common/ResourceHelper.cs new file mode 100644 index 0000000..14d6800 --- /dev/null +++ b/ModernKeePass10/Common/ResourceHelper.cs @@ -0,0 +1,16 @@ +using Windows.ApplicationModel.Resources; + +namespace ModernKeePass.Common +{ + public class ResourceHelper + { + private const string ResourceFileName = "CodeBehind"; + private readonly ResourceLoader _resourceLoader = ResourceLoader.GetForCurrentView(); + + public string GetResourceValue(string key) + { + var resource = _resourceLoader.GetString($"/{ResourceFileName}/{key}"); + return resource; + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Common/SuspensionManager.cs b/ModernKeePass10/Common/SuspensionManager.cs new file mode 100644 index 0000000..3b00613 --- /dev/null +++ b/ModernKeePass10/Common/SuspensionManager.cs @@ -0,0 +1,260 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization; +using System.Threading.Tasks; +using Windows.Storage; +using Windows.Storage.Streams; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace ModernKeePass.Common +{ + /// + /// SuspensionManager captures global session state to simplify process lifetime management + /// for an application. Note that session state will be automatically cleared under a variety + /// of conditions and should only be used to store information that would be convenient to + /// carry across sessions, but that should be discarded when an application crashes or is + /// upgraded. + /// + internal static class SuspensionManager + { + private static Dictionary _sessionState = new Dictionary(); + private static readonly List _knownTypes = new List(); + private const string sessionStateFilename = "_sessionState.xml"; + + /// + /// Provides access to global session state for the current session. This state is + /// serialized by and restored by + /// , so values must be serializable by + /// and should be as compact as possible. Strings + /// and other self-contained data types are strongly recommended. + /// + public static Dictionary SessionState => _sessionState; + + /// + /// List of custom types provided to the when + /// reading and writing session state. Initially empty, additional types may be + /// added to customize the serialization process. + /// + public static List KnownTypes => _knownTypes; + + /// + /// Save the current . Any instances + /// registered with will also preserve their current + /// navigation stack, which in turn gives their active an opportunity + /// to save its state. + /// + /// An asynchronous task that reflects when session state has been saved. + public static async Task SaveAsync() + { + try + { + // Save the navigation state for all registered frames + foreach (var weakFrameReference in _registeredFrames) + { + Frame frame; + if (weakFrameReference.TryGetTarget(out frame)) + { + SaveFrameNavigationState(frame); + } + } + + // Serialize the session state synchronously to avoid asynchronous access to shared + // state + MemoryStream sessionData = new MemoryStream(); + DataContractSerializer serializer = new DataContractSerializer(typeof(Dictionary), _knownTypes); + serializer.WriteObject(sessionData, _sessionState); + + // Get an output stream for the SessionState file and write the state asynchronously + StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(sessionStateFilename, CreationCollisionOption.ReplaceExisting); + using (Stream fileStream = await file.OpenStreamForWriteAsync()) + { + sessionData.Seek(0, SeekOrigin.Begin); + await sessionData.CopyToAsync(fileStream); + } + } + catch (Exception e) + { + throw new SuspensionManagerException(e); + } + } + + /// + /// Restores previously saved . Any instances + /// registered with will also restore their prior navigation + /// state, which in turn gives their active an opportunity restore its + /// state. + /// + /// An optional key that identifies the type of session. + /// This can be used to distinguish between multiple application launch scenarios. + /// An asynchronous task that reflects when session state has been read. The + /// content of should not be relied upon until this task + /// completes. + public static async Task RestoreAsync(String sessionBaseKey = null) + { + _sessionState = new Dictionary(); + + try + { + // Get the input stream for the SessionState file + StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(sessionStateFilename); + using (IInputStream inStream = await file.OpenSequentialReadAsync()) + { + // Deserialize the Session State + DataContractSerializer serializer = new DataContractSerializer(typeof(Dictionary), _knownTypes); + _sessionState = (Dictionary)serializer.ReadObject(inStream.AsStreamForRead()); + } + + // Restore any registered frames to their saved state + foreach (var weakFrameReference in _registeredFrames) + { + Frame frame; + if (weakFrameReference.TryGetTarget(out frame) && (string)frame.GetValue(FrameSessionBaseKeyProperty) == sessionBaseKey) + { + frame.ClearValue(FrameSessionStateProperty); + RestoreFrameNavigationState(frame); + } + } + } + catch (Exception e) + { + throw new SuspensionManagerException(e); + } + } + + private static DependencyProperty FrameSessionStateKeyProperty = + DependencyProperty.RegisterAttached("_FrameSessionStateKey", typeof(String), typeof(SuspensionManager), null); + private static DependencyProperty FrameSessionBaseKeyProperty = + DependencyProperty.RegisterAttached("_FrameSessionBaseKeyParams", typeof(String), typeof(SuspensionManager), null); + private static DependencyProperty FrameSessionStateProperty = + DependencyProperty.RegisterAttached("_FrameSessionState", typeof(Dictionary), typeof(SuspensionManager), null); + private static List> _registeredFrames = new List>(); + + /// + /// Registers a instance to allow its navigation history to be saved to + /// and restored from . Frames should be registered once + /// immediately after creation if they will participate in session state management. Upon + /// registration if state has already been restored for the specified key + /// the navigation history will immediately be restored. Subsequent invocations of + /// will also restore navigation history. + /// + /// An instance whose navigation history should be managed by + /// + /// A unique key into used to + /// store navigation-related information. + /// An optional key that identifies the type of session. + /// This can be used to distinguish between multiple application launch scenarios. + public static void RegisterFrame(Frame frame, String sessionStateKey, String sessionBaseKey = null) + { + if (frame.GetValue(FrameSessionStateKeyProperty) != null) + { + throw new InvalidOperationException("Frames can only be registered to one session state key"); + } + + if (frame.GetValue(FrameSessionStateProperty) != null) + { + throw new InvalidOperationException("Frames must be either be registered before accessing frame session state, or not registered at all"); + } + + if (!string.IsNullOrEmpty(sessionBaseKey)) + { + frame.SetValue(FrameSessionBaseKeyProperty, sessionBaseKey); + sessionStateKey = sessionBaseKey + "_" + sessionStateKey; + } + + // Use a dependency property to associate the session key with a frame, and keep a list of frames whose + // navigation state should be managed + frame.SetValue(FrameSessionStateKeyProperty, sessionStateKey); + _registeredFrames.Add(new WeakReference(frame)); + + // Check to see if navigation state can be restored + RestoreFrameNavigationState(frame); + } + + /// + /// Disassociates a previously registered by + /// from . Any navigation state previously captured will be + /// removed. + /// + /// An instance whose navigation history should no longer be + /// managed. + public static void UnregisterFrame(Frame frame) + { + // Remove session state and remove the frame from the list of frames whose navigation + // state will be saved (along with any weak references that are no longer reachable) + SessionState.Remove((String)frame.GetValue(FrameSessionStateKeyProperty)); + _registeredFrames.RemoveAll((weakFrameReference) => + { + Frame testFrame; + return !weakFrameReference.TryGetTarget(out testFrame) || testFrame == frame; + }); + } + + /// + /// Provides storage for session state associated with the specified . + /// Frames that have been previously registered with have + /// their session state saved and restored automatically as a part of the global + /// . Frames that are not registered have transient state + /// that can still be useful when restoring pages that have been discarded from the + /// navigation cache. + /// + /// Apps may choose to rely on to manage + /// page-specific state instead of working with frame session state directly. + /// The instance for which session state is desired. + /// A collection of state subject to the same serialization mechanism as + /// . + public static Dictionary SessionStateForFrame(Frame frame) + { + var frameState = (Dictionary)frame.GetValue(FrameSessionStateProperty); + + if (frameState == null) + { + var frameSessionKey = (String)frame.GetValue(FrameSessionStateKeyProperty); + if (frameSessionKey != null) + { + // Registered frames reflect the corresponding session state + if (!_sessionState.ContainsKey(frameSessionKey)) + { + _sessionState[frameSessionKey] = new Dictionary(); + } + frameState = (Dictionary)_sessionState[frameSessionKey]; + } + else + { + // Frames that aren't registered have transient state + frameState = new Dictionary(); + } + frame.SetValue(FrameSessionStateProperty, frameState); + } + return frameState; + } + + private static void RestoreFrameNavigationState(Frame frame) + { + var frameState = SessionStateForFrame(frame); + if (frameState.ContainsKey("Navigation")) + { + frame.SetNavigationState((String)frameState["Navigation"]); + } + } + + private static void SaveFrameNavigationState(Frame frame) + { + var frameState = SessionStateForFrame(frame); + frameState["Navigation"] = frame.GetNavigationState(); + } + } + public class SuspensionManagerException : Exception + { + public SuspensionManagerException() + { + } + + public SuspensionManagerException(Exception e) + : base("SuspensionManager failed", e) + { + + } + } +} diff --git a/ModernKeePass10/Common/ToastNotificationHelper.cs b/ModernKeePass10/Common/ToastNotificationHelper.cs new file mode 100644 index 0000000..fb2d7c7 --- /dev/null +++ b/ModernKeePass10/Common/ToastNotificationHelper.cs @@ -0,0 +1,53 @@ +using System; +using Windows.Data.Json; +using Windows.Data.Xml.Dom; +using Windows.UI.Notifications; +using ModernKeePass.Domain.Entities; + +namespace ModernKeePass.Common +{ + public static class ToastNotificationHelper + { + public static void ShowMovedToast(Entity entity, string action, string text) + { + var notificationXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02); + var toastElements = notificationXml.GetElementsByTagName("text"); + toastElements[0].AppendChild(notificationXml.CreateTextNode($"{action} {entity.Name}")); + toastElements[1].AppendChild(notificationXml.CreateTextNode(text)); + var toastNode = notificationXml.SelectSingleNode("/toast"); + + // This is useful only for Windows 10 UWP + var launch = new JsonObject + { + {"entityType", JsonValue.CreateStringValue(entity.GetType().Name)}, + {"entityId", JsonValue.CreateStringValue(entity.Id)} + }; + ((XmlElement)toastNode)?.SetAttribute("launch", launch.Stringify()); + + var toast = new ToastNotification(notificationXml) + { + ExpirationTime = DateTime.Now.AddSeconds(5) + }; + ToastNotificationManager.CreateToastNotifier().Show(toast); + } + + public static void ShowGenericToast(string title, string text) + { + var notificationXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02); + var toastElements = notificationXml.GetElementsByTagName("text"); + toastElements[0].AppendChild(notificationXml.CreateTextNode(title)); + toastElements[1].AppendChild(notificationXml.CreateTextNode(text)); + + var toast = new ToastNotification(notificationXml) + { + ExpirationTime = DateTime.Now.AddSeconds(5) + }; + ToastNotificationManager.CreateToastNotifier().Show(toast); + } + + public static void ShowErrorToast(Exception exception) + { + ShowGenericToast(exception.Source, exception.Message); + } + } +} diff --git a/ModernKeePass10/Controls/ListViewWithDisable.cs b/ModernKeePass10/Controls/ListViewWithDisable.cs new file mode 100644 index 0000000..4b395bc --- /dev/null +++ b/ModernKeePass10/Controls/ListViewWithDisable.cs @@ -0,0 +1,20 @@ +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using ModernKeePass.Application.Common.Interfaces; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.Controls +{ + public class ListViewWithDisable: ListView + { + protected override void PrepareContainerForItemOverride(DependencyObject element, object item) + { + base.PrepareContainerForItemOverride(element, item); + + var binaryItem = item as IIsEnabled; + if (!(element is ListViewItem container) || binaryItem == null) return; + container.IsEnabled = binaryItem.IsEnabled; + container.IsHitTestVisible = binaryItem.IsEnabled; + } + } +} diff --git a/ModernKeePass10/Controls/TextBoxWithButton.cs b/ModernKeePass10/Controls/TextBoxWithButton.cs new file mode 100644 index 0000000..c041b1f --- /dev/null +++ b/ModernKeePass10/Controls/TextBoxWithButton.cs @@ -0,0 +1,56 @@ +using System; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace ModernKeePass.Controls +{ + public class TextBoxWithButton : TextBox + { + public event EventHandler ButtonClick; + + public string ButtonSymbol + { + get => (string)GetValue(ButtonSymbolProperty); + set => SetValue(ButtonSymbolProperty, value); + } + public static readonly DependencyProperty ButtonSymbolProperty = + DependencyProperty.Register( + "ButtonSymbol", + typeof(string), + typeof(TextBoxWithButton), + new PropertyMetadata("", (o, args) => { })); + + public string ButtonTooltip + { + get => (string)GetValue(ButtonTooltipProperty); + set => SetValue(ButtonTooltipProperty, value); + } + public static readonly DependencyProperty ButtonTooltipProperty = + DependencyProperty.Register( + "ButtonTooltip", + typeof(string), + typeof(TextBoxWithButton), + new PropertyMetadata(string.Empty, (o, args) => { })); + + public bool IsButtonEnabled + { + get => (bool)GetValue(IsButtonEnabledProperty); + set => SetValue(IsButtonEnabledProperty, value); + } + public static readonly DependencyProperty IsButtonEnabledProperty = + DependencyProperty.Register( + "IsButtonEnabled", + typeof(bool), + typeof(TextBoxWithButton), + new PropertyMetadata(true, (o, args) => { })); + + protected override void OnApplyTemplate() + { + base.OnApplyTemplate(); + if (GetTemplateChild("ActionButton") is Button actionButton) + { + actionButton.Click += (sender, e) => ButtonClick?.Invoke(sender, e); + } + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Converters/BooleanToVisibilityConverter.cs b/ModernKeePass10/Converters/BooleanToVisibilityConverter.cs new file mode 100644 index 0000000..a4145eb --- /dev/null +++ b/ModernKeePass10/Converters/BooleanToVisibilityConverter.cs @@ -0,0 +1,29 @@ +using System; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Data; + +namespace ModernKeePass.Converters +{ + [Obsolete] + public class BooleanToVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + var boolean = value as bool? ?? false; + return boolean ? Visibility.Visible : Visibility.Collapsed; + } + + // No need to implement this + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + var visibility = value as Visibility? ?? Visibility.Visible; + switch (visibility) + { + case Visibility.Visible: return true; + case Visibility.Collapsed: return false; + default: + throw new ArgumentOutOfRangeException(nameof(value)); + } + } + } +} diff --git a/ModernKeePass10/Converters/ColorToBrushConverter.cs b/ModernKeePass10/Converters/ColorToBrushConverter.cs new file mode 100644 index 0000000..c0c2a10 --- /dev/null +++ b/ModernKeePass10/Converters/ColorToBrushConverter.cs @@ -0,0 +1,22 @@ +using System; +using Windows.UI; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Media; + +namespace ModernKeePass.Converters +{ + public class ColorToBrushConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + var color = value is Color color1 ? color1 : default(Color); + if (color == default(Color) && parameter is SolidColorBrush) return (SolidColorBrush) parameter; + return new SolidColorBrush(color); + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + return (value as SolidColorBrush)?.Color ?? new Color(); + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Converters/DiscreteIntToSolidColorBrushConverter.cs b/ModernKeePass10/Converters/DiscreteIntToSolidColorBrushConverter.cs new file mode 100644 index 0000000..9a4f4ba --- /dev/null +++ b/ModernKeePass10/Converters/DiscreteIntToSolidColorBrushConverter.cs @@ -0,0 +1,27 @@ +using System; +using Windows.UI; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Media; + +namespace ModernKeePass.Converters +{ + public class DiscreteIntToSolidColorBrushConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + var status = System.Convert.ToInt32(value); + switch (status) + { + case 1: return new SolidColorBrush(Colors.Red); + case 3: return new SolidColorBrush(Colors.Yellow); + case 5: return new SolidColorBrush(Colors.Green); + default: return new SolidColorBrush(Colors.Black); + } + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} diff --git a/ModernKeePass10/Converters/DoubleToSolidColorBrushConverter.cs b/ModernKeePass10/Converters/DoubleToSolidColorBrushConverter.cs new file mode 100644 index 0000000..d841805 --- /dev/null +++ b/ModernKeePass10/Converters/DoubleToSolidColorBrushConverter.cs @@ -0,0 +1,31 @@ +using System; +using Windows.UI; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Media; + +namespace ModernKeePass.Converters +{ + public class DoubleToSolidColorBrushConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + try + { + var currentValue = (double) value; + var maxValue = double.Parse(parameter as string); + var green = System.Convert.ToByte(currentValue / maxValue * byte.MaxValue); + var red = (byte) (byte.MaxValue - green); + return new SolidColorBrush(Color.FromArgb(255, red, green, 0)); + } + catch (OverflowException) + { + return new SolidColorBrush(Color.FromArgb(255, 0, byte.MaxValue, 0)); + } + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} diff --git a/ModernKeePass10/Converters/EmptyStringToVisibilityConverter.cs b/ModernKeePass10/Converters/EmptyStringToVisibilityConverter.cs new file mode 100644 index 0000000..dc73ae4 --- /dev/null +++ b/ModernKeePass10/Converters/EmptyStringToVisibilityConverter.cs @@ -0,0 +1,20 @@ +using System; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Data; + +namespace ModernKeePass.Converters +{ + class EmptyStringToVisibilityConverter: IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + var text = value is string ? value.ToString() : string.Empty; + return string.IsNullOrEmpty(text) ? Visibility.Collapsed : Visibility.Visible; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} diff --git a/ModernKeePass10/Converters/IconToSymbolConverter.cs b/ModernKeePass10/Converters/IconToSymbolConverter.cs new file mode 100644 index 0000000..6946405 --- /dev/null +++ b/ModernKeePass10/Converters/IconToSymbolConverter.cs @@ -0,0 +1,122 @@ +using System; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Data; +using ModernKeePass.Domain.Enums; + +namespace ModernKeePass.Converters +{ + public class IconToSymbolConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + var icon = (Icon) value; + switch (icon) + { + case Icon.Delete: return Symbol.Delete; + case Icon.Edit: return Symbol.Edit; + case Icon.Save: return Symbol.Save; + case Icon.Cancel: return Symbol.Cancel; + case Icon.Accept: return Symbol.Accept; + case Icon.Home: return Symbol.Home; + case Icon.Camera: return Symbol.Camera; + case Icon.Setting: return Symbol.Setting; + case Icon.Mail: return Symbol.Mail; + case Icon.Find: return Symbol.Find; + case Icon.Help: return Symbol.Help; + case Icon.Clock: return Symbol.Clock; + case Icon.Crop: return Symbol.Crop; + case Icon.World: return Symbol.World; + case Icon.Flag: return Symbol.Flag; + case Icon.PreviewLink: return Symbol.PreviewLink; + case Icon.Document: return Symbol.Document; + case Icon.ProtectedDocument: return Symbol.ProtectedDocument; + case Icon.ContactInfo: return Symbol.ContactInfo; + case Icon.ViewAll: return Symbol.ViewAll; + case Icon.Rotate: return Symbol.Rotate; + case Icon.List: return Symbol.List; + case Icon.Shop: return Symbol.Shop; + case Icon.BrowsePhotos: return Symbol.BrowsePhotos; + case Icon.Caption: return Symbol.Caption; + case Icon.Repair: return Symbol.Repair; + case Icon.Page: return Symbol.Page2; + case Icon.Paste: return Symbol.Paste; + case Icon.Important: return Symbol.Important; + case Icon.SlideShow: return Symbol.SlideShow; + case Icon.MapDrive: return Symbol.MapDrive; + case Icon.ContactPresence: return Symbol.ContactPresence; + case Icon.Contact: return Symbol.Contact2; + case Icon.Folder: return Symbol.Folder; + case Icon.View: return Symbol.View; + case Icon.Permissions: return Symbol.Permissions; + case Icon.Map: return Symbol.Map; + case Icon.CellPhone: return Symbol.CellPhone; + case Icon.OutlineStar: return Symbol.OutlineStar; + case Icon.Calculator: return Symbol.Calculator; + case Icon.Library: return Symbol.Library; + case Icon.SyncFolder: return Symbol.SyncFolder; + case Icon.GoToStart: return Symbol.GoToStart; + case Icon.ZeroBars: return Symbol.ZeroBars; + case Icon.FourBars: return Symbol.FourBars; + case Icon.Scan: return Symbol.Scan; + case Icon.ReportHacked: return Symbol.ReportHacked; + default: return Symbol.Stop; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + var symbol = (Symbol) value; + switch (symbol) + { + case Symbol.Delete: return Icon.Delete; + case Symbol.Edit: return Icon.Edit; + case Symbol.Save: return Icon.Save; + case Symbol.Cancel: return Icon.Cancel; + case Symbol.Accept: return Icon.Accept; + case Symbol.Home: return Icon.Home; + case Symbol.Camera: return Icon.Camera; + case Symbol.Setting: return Icon.Setting; + case Symbol.Mail: return Icon.Mail; + case Symbol.Find: return Icon.Find; + case Symbol.Help: return Icon.Help; + case Symbol.Clock: return Icon.Clock; + case Symbol.Crop: return Icon.Crop; + case Symbol.World: return Icon.World; + case Symbol.Flag: return Icon.Flag; + case Symbol.PreviewLink: return Icon.PreviewLink; + case Symbol.Document: return Icon.Document; + case Symbol.ProtectedDocument: return Icon.ProtectedDocument; + case Symbol.ContactInfo: return Icon.ContactInfo; + case Symbol.ViewAll: return Icon.ViewAll; + case Symbol.Rotate: return Icon.Rotate; + case Symbol.List: return Icon.List; + case Symbol.Shop: return Icon.Shop; + case Symbol.BrowsePhotos: return Icon.BrowsePhotos; + case Symbol.Caption: return Icon.Caption; + case Symbol.Repair: return Icon.Repair; + case Symbol.Page2: return Icon.Page; + case Symbol.Paste: return Icon.Paste; + case Symbol.Important: return Icon.Important; + case Symbol.SlideShow: return Icon.SlideShow; + case Symbol.MapDrive: return Icon.MapDrive; + case Symbol.ContactPresence: return Icon.ContactPresence; + case Symbol.Contact2: return Icon.Contact; + case Symbol.Folder: return Icon.Folder; + case Symbol.View: return Icon.View; + case Symbol.Permissions: return Icon.Permissions; + case Symbol.Map: return Icon.Map; + case Symbol.CellPhone: return Icon.CellPhone; + case Symbol.OutlineStar: return Icon.OutlineStar; + case Symbol.Calculator: return Icon.Calculator; + case Symbol.Library: return Icon.Library; + case Symbol.SyncFolder: return Icon.SyncFolder; + case Symbol.GoToStart: return Icon.GoToStart; + case Symbol.ZeroBars: return Icon.ZeroBars; + case Symbol.FourBars: return Icon.FourBars; + case Symbol.Scan: return Icon.Scan; + case Symbol.ReportHacked: return Icon.ReportHacked; + default: return Icon.Stop; + } + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Converters/InverseBooleanToVisibilityConverter.cs b/ModernKeePass10/Converters/InverseBooleanToVisibilityConverter.cs new file mode 100644 index 0000000..e354271 --- /dev/null +++ b/ModernKeePass10/Converters/InverseBooleanToVisibilityConverter.cs @@ -0,0 +1,28 @@ +using System; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Data; + +namespace ModernKeePass.Converters +{ + public class InverseBooleanToVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + var boolean = value as bool? ?? false; + return boolean ? Visibility.Collapsed : Visibility.Visible; + } + + // No need to implement this + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + var visibility = value as Visibility? ?? Visibility.Visible; + switch (visibility) + { + case Visibility.Visible: return false; + case Visibility.Collapsed: return true; + default: + throw new ArgumentOutOfRangeException(nameof(value)); + } + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Converters/NullToBooleanConverter.cs b/ModernKeePass10/Converters/NullToBooleanConverter.cs new file mode 100644 index 0000000..667980f --- /dev/null +++ b/ModernKeePass10/Converters/NullToBooleanConverter.cs @@ -0,0 +1,18 @@ +using System; +using Windows.UI.Xaml.Data; + +namespace ModernKeePass.Converters +{ + public class NullToBooleanConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + return value != null; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} diff --git a/ModernKeePass10/Converters/PluralizationConverter.cs b/ModernKeePass10/Converters/PluralizationConverter.cs new file mode 100644 index 0000000..e870363 --- /dev/null +++ b/ModernKeePass10/Converters/PluralizationConverter.cs @@ -0,0 +1,24 @@ +using System; +using Windows.UI.Xaml.Data; + +namespace ModernKeePass.Converters +{ + public class PluralizationConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + var pluralizationOptionString = parameter as string; + var pluralizationOptions = pluralizationOptionString?.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); + if (pluralizationOptions == null || pluralizationOptions.Length != 2) return string.Empty; + var count = value is int ? (int) value : 0; + var text = count == 1 ? pluralizationOptions[0] : pluralizationOptions[1]; + return $"{count} {text}"; + } + + // No need to implement this + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} diff --git a/ModernKeePass10/Converters/ProgressBarLegalValuesConverter.cs b/ModernKeePass10/Converters/ProgressBarLegalValuesConverter.cs new file mode 100644 index 0000000..b6b84f4 --- /dev/null +++ b/ModernKeePass10/Converters/ProgressBarLegalValuesConverter.cs @@ -0,0 +1,27 @@ +using System; +using Windows.UI.Xaml.Data; + +namespace ModernKeePass.Converters +{ + public class ProgressBarLegalValuesConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + var legalValuesOptionString = parameter as string; + var legalValuesOptions = legalValuesOptionString?.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); + if (legalValuesOptions == null || legalValuesOptions.Length != 2) return 0; + + var minValue = double.Parse(legalValuesOptions[0]); + var maxValue = double.Parse(legalValuesOptions[1]); + var count = value is double ? (double)value : 0; + if (count > maxValue) return maxValue; + if (count < minValue) return minValue; + return count; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} diff --git a/ModernKeePass10/Converters/TextToWidthConverter.cs b/ModernKeePass10/Converters/TextToWidthConverter.cs new file mode 100644 index 0000000..c3f1b24 --- /dev/null +++ b/ModernKeePass10/Converters/TextToWidthConverter.cs @@ -0,0 +1,20 @@ +using System; +using Windows.UI.Xaml.Data; + +namespace ModernKeePass.Converters +{ + public class TextToWidthConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + var fontSize = double.Parse(parameter as string); + var text = value as string; + return text?.Length * fontSize ?? 0; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} diff --git a/ModernKeePass10/Events/PasswordEventArgs.cs b/ModernKeePass10/Events/PasswordEventArgs.cs new file mode 100644 index 0000000..51b97a4 --- /dev/null +++ b/ModernKeePass10/Events/PasswordEventArgs.cs @@ -0,0 +1,15 @@ +using System; +using ModernKeePass.Domain.Entities; + +namespace ModernKeePass.Events +{ + public class PasswordEventArgs: EventArgs + { + public GroupEntity RootGroupEntity { get; set; } + + public PasswordEventArgs(GroupEntity groupEntity) + { + RootGroupEntity = groupEntity; + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Extensions/DispatcherTaskExtensions.cs b/ModernKeePass10/Extensions/DispatcherTaskExtensions.cs new file mode 100644 index 0000000..c0ecb9e --- /dev/null +++ b/ModernKeePass10/Extensions/DispatcherTaskExtensions.cs @@ -0,0 +1,32 @@ +using System; +using System.Threading.Tasks; +using Windows.UI.Core; + +namespace ModernKeePass.Extensions +{ + public static class DispatcherTaskExtensions + { + public static async Task RunTaskAsync(this CoreDispatcher dispatcher, + Func> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) + { + var taskCompletionSource = new TaskCompletionSource(); + await dispatcher.RunAsync(priority, async () => + { + try + { + taskCompletionSource.SetResult(await func()); + } + catch (Exception ex) + { + taskCompletionSource.SetException(ex); + } + }); + return await taskCompletionSource.Task; + } + + // There is no TaskCompletionSource so we use a bool that we throw away. + public static async Task RunTaskAsync(this CoreDispatcher dispatcher, + Func func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) => + await RunTaskAsync(dispatcher, async () => { await func(); return false; }, priority); + } +} \ No newline at end of file diff --git a/ModernKeePass10/Package.StoreAssociation.xml b/ModernKeePass10/Package.StoreAssociation.xml new file mode 100644 index 0000000..860d03a --- /dev/null +++ b/ModernKeePass10/Package.StoreAssociation.xml @@ -0,0 +1,368 @@ + + + CN=0719A91A-C322-4EE0-A257-E60733EECF06 + wismna + http://www.w3.org/2001/04/xmlenc#sha256 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + wismna.ModernKeePass + + ModernKeePass + + + + + \ No newline at end of file diff --git a/ModernKeePass10/Package.appxmanifest b/ModernKeePass10/Package.appxmanifest new file mode 100644 index 0000000..927fbda --- /dev/null +++ b/ModernKeePass10/Package.appxmanifest @@ -0,0 +1,55 @@ + + + + + + + + + ModernKeePass + wismna + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + .kdbx + + + + + + KeePass 2.x database + + + .kdbx + + + + + + + .kdbx + + + + + + + + + + \ No newline at end of file diff --git a/ModernKeePass10/Properties/Annotations.cs b/ModernKeePass10/Properties/Annotations.cs new file mode 100644 index 0000000..455ba8f --- /dev/null +++ b/ModernKeePass10/Properties/Annotations.cs @@ -0,0 +1,1065 @@ +/* MIT License + +Copyright (c) 2016 JetBrains http://www.jetbrains.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. */ + +using System; + +#pragma warning disable 1591 +// ReSharper disable UnusedMember.Global +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global +// ReSharper disable IntroduceOptionalParameters.Global +// ReSharper disable MemberCanBeProtected.Global +// ReSharper disable InconsistentNaming + +namespace ModernKeePass.Properties +{ + /// + /// Indicates that the value of the marked element could be null sometimes, + /// so the check for null is necessary before its usage. + /// + /// + /// [CanBeNull] object Test() => null; + /// + /// void UseTest() { + /// var p = Test(); + /// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException' + /// } + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] + public sealed class CanBeNullAttribute : Attribute { } + + /// + /// Indicates that the value of the marked element could never be null. + /// + /// + /// [NotNull] object Foo() { + /// return null; // Warning: Possible 'null' assignment + /// } + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] + public sealed class NotNullAttribute : Attribute { } + + /// + /// Can be appplied to symbols of types derived from IEnumerable as well as to symbols of Task + /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property + /// or of the Lazy.Value property can never be null. + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field)] + public sealed class ItemNotNullAttribute : Attribute { } + + /// + /// Can be appplied to symbols of types derived from IEnumerable as well as to symbols of Task + /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property + /// or of the Lazy.Value property can be null. + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field)] + public sealed class ItemCanBeNullAttribute : Attribute { } + + /// + /// Indicates that the marked method builds string by format pattern and (optional) arguments. + /// Parameter, which contains format string, should be given in constructor. The format string + /// should be in -like form. + /// + /// + /// [StringFormatMethod("message")] + /// void ShowError(string message, params object[] args) { /* do something */ } + /// + /// void Foo() { + /// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string + /// } + /// + [AttributeUsage( + AttributeTargets.Constructor | AttributeTargets.Method | + AttributeTargets.Property | AttributeTargets.Delegate)] + public sealed class StringFormatMethodAttribute : Attribute + { + /// + /// Specifies which parameter of an annotated method should be treated as format-string + /// + public StringFormatMethodAttribute([NotNull] string formatParameterName) + { + FormatParameterName = formatParameterName; + } + + [NotNull] public string FormatParameterName { get; private set; } + } + + /// + /// For a parameter that is expected to be one of the limited set of values. + /// Specify fields of which type should be used as values for this parameter. + /// + [AttributeUsage( + AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field, + AllowMultiple = true)] + public sealed class ValueProviderAttribute : Attribute + { + public ValueProviderAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull] public string Name { get; private set; } + } + + /// + /// Indicates that the function argument should be string literal and match one + /// of the parameters of the caller function. For example, ReSharper annotates + /// the parameter of . + /// + /// + /// void Foo(string param) { + /// if (param == null) + /// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol + /// } + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class InvokerParameterNameAttribute : Attribute { } + + /// + /// Indicates that the method is contained in a type that implements + /// System.ComponentModel.INotifyPropertyChanged interface and this method + /// is used to notify that some property value changed. + /// + /// + /// The method should be non-static and conform to one of the supported signatures: + /// + /// NotifyChanged(string) + /// NotifyChanged(params string[]) + /// NotifyChanged{T}(Expression{Func{T}}) + /// NotifyChanged{T,U}(Expression{Func{T,U}}) + /// SetProperty{T}(ref T, T, string) + /// + /// + /// + /// public class Foo : INotifyPropertyChanged { + /// public event PropertyChangedEventHandler PropertyChanged; + /// + /// [NotifyPropertyChangedInvocator] + /// protected virtual void NotifyChanged(string propertyName) { ... } + /// + /// string _name; + /// + /// public string Name { + /// get { return _name; } + /// set { _name = value; NotifyChanged("LastName"); /* Warning */ } + /// } + /// } + /// + /// Examples of generated notifications: + /// + /// NotifyChanged("Property") + /// NotifyChanged(() => Property) + /// NotifyChanged((VM x) => x.Property) + /// SetProperty(ref myField, value, "Property") + /// + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute + { + public NotifyPropertyChangedInvocatorAttribute() { } + public NotifyPropertyChangedInvocatorAttribute([NotNull] string parameterName) + { + ParameterName = parameterName; + } + + [CanBeNull] public string ParameterName { get; private set; } + } + + /// + /// Describes dependency between method input and output. + /// + /// + ///

Function Definition Table syntax:

+ /// + /// FDT ::= FDTRow [;FDTRow]* + /// FDTRow ::= Input => Output | Output <= Input + /// Input ::= ParameterName: Value [, Input]* + /// Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value} + /// Value ::= true | false | null | notnull | canbenull + /// + /// If method has single input parameter, it's name could be omitted.
+ /// Using halt (or void/nothing, which is the same) for method output + /// means that the methos doesn't return normally (throws or terminates the process).
+ /// Value canbenull is only applicable for output parameters.
+ /// You can use multiple [ContractAnnotation] for each FDT row, or use single attribute + /// with rows separated by semicolon. There is no notion of order rows, all rows are checked + /// for applicability and applied per each program state tracked by R# analysis.
+ ///
+ /// + /// + /// [ContractAnnotation("=> halt")] + /// public void TerminationMethod() + /// + /// + /// [ContractAnnotation("halt <= condition: false")] + /// public void Assert(bool condition, string text) // regular assertion method + /// + /// + /// [ContractAnnotation("s:null => true")] + /// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty() + /// + /// + /// // A method that returns null if the parameter is null, + /// // and not null if the parameter is not null + /// [ContractAnnotation("null => null; notnull => notnull")] + /// public object Transform(object data) + /// + /// + /// [ContractAnnotation("=> true, result: notnull; => false, result: null")] + /// public bool TryParse(string s, out Person result) + /// + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + public sealed class ContractAnnotationAttribute : Attribute + { + public ContractAnnotationAttribute([NotNull] string contract) + : this(contract, false) { } + + public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates) + { + Contract = contract; + ForceFullStates = forceFullStates; + } + + [NotNull] public string Contract { get; private set; } + + public bool ForceFullStates { get; private set; } + } + + /// + /// Indicates that marked element should be localized or not. + /// + /// + /// [LocalizationRequiredAttribute(true)] + /// class Foo { + /// string str = "my string"; // Warning: Localizable string + /// } + /// + [AttributeUsage(AttributeTargets.All)] + public sealed class LocalizationRequiredAttribute : Attribute + { + public LocalizationRequiredAttribute() : this(true) { } + + public LocalizationRequiredAttribute(bool required) + { + Required = required; + } + + public bool Required { get; private set; } + } + + /// + /// Indicates that the value of the marked type (or its derivatives) + /// cannot be compared using '==' or '!=' operators and Equals() + /// should be used instead. However, using '==' or '!=' for comparison + /// with null is always permitted. + /// + /// + /// [CannotApplyEqualityOperator] + /// class NoEquality { } + /// + /// class UsesNoEquality { + /// void Test() { + /// var ca1 = new NoEquality(); + /// var ca2 = new NoEquality(); + /// if (ca1 != null) { // OK + /// bool condition = ca1 == ca2; // Warning + /// } + /// } + /// } + /// + [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)] + public sealed class CannotApplyEqualityOperatorAttribute : Attribute { } + + /// + /// When applied to a target attribute, specifies a requirement for any type marked + /// with the target attribute to implement or inherit specific type or types. + /// + /// + /// [BaseTypeRequired(typeof(IComponent)] // Specify requirement + /// class ComponentAttribute : Attribute { } + /// + /// [Component] // ComponentAttribute requires implementing IComponent interface + /// class MyComponent : IComponent { } + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + [BaseTypeRequired(typeof(Attribute))] + public sealed class BaseTypeRequiredAttribute : Attribute + { + public BaseTypeRequiredAttribute([NotNull] Type baseType) + { + BaseType = baseType; + } + + [NotNull] public Type BaseType { get; private set; } + } + + /// + /// Indicates that the marked symbol is used implicitly (e.g. via reflection, in external library), + /// so this symbol will not be marked as unused (as well as by other usage inspections). + /// + [AttributeUsage(AttributeTargets.All)] + public sealed class UsedImplicitlyAttribute : Attribute + { + public UsedImplicitlyAttribute() + : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } + + public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) + : this(useKindFlags, ImplicitUseTargetFlags.Default) { } + + public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) + : this(ImplicitUseKindFlags.Default, targetFlags) { } + + public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) + { + UseKindFlags = useKindFlags; + TargetFlags = targetFlags; + } + + public ImplicitUseKindFlags UseKindFlags { get; private set; } + + public ImplicitUseTargetFlags TargetFlags { get; private set; } + } + + /// + /// Should be used on attributes and causes ReSharper to not mark symbols marked with such attributes + /// as unused (as well as by other usage inspections) + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.GenericParameter)] + public sealed class MeansImplicitUseAttribute : Attribute + { + public MeansImplicitUseAttribute() + : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } + + public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) + : this(useKindFlags, ImplicitUseTargetFlags.Default) { } + + public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) + : this(ImplicitUseKindFlags.Default, targetFlags) { } + + public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) + { + UseKindFlags = useKindFlags; + TargetFlags = targetFlags; + } + + [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; private set; } + + [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; private set; } + } + + [Flags] + public enum ImplicitUseKindFlags + { + Default = Access | Assign | InstantiatedWithFixedConstructorSignature, + /// Only entity marked with attribute considered used. + Access = 1, + /// Indicates implicit assignment to a member. + Assign = 2, + /// + /// Indicates implicit instantiation of a type with fixed constructor signature. + /// That means any unused constructor parameters won't be reported as such. + /// + InstantiatedWithFixedConstructorSignature = 4, + /// Indicates implicit instantiation of a type. + InstantiatedNoFixedConstructorSignature = 8, + } + + /// + /// Specify what is considered used implicitly when marked + /// with or . + /// + [Flags] + public enum ImplicitUseTargetFlags + { + Default = Itself, + Itself = 1, + /// Members of entity marked with attribute are considered used. + Members = 2, + /// Entity marked with attribute and all its members considered used. + WithMembers = Itself | Members + } + + /// + /// This attribute is intended to mark publicly available API + /// which should not be removed and so is treated as used. + /// + [MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)] + public sealed class PublicAPIAttribute : Attribute + { + public PublicAPIAttribute() { } + + public PublicAPIAttribute([NotNull] string comment) + { + Comment = comment; + } + + [CanBeNull] public string Comment { get; private set; } + } + + /// + /// Tells code analysis engine if the parameter is completely handled when the invoked method is on stack. + /// If the parameter is a delegate, indicates that delegate is executed while the method is executed. + /// If the parameter is an enumerable, indicates that it is enumerated while the method is executed. + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class InstantHandleAttribute : Attribute { } + + /// + /// Indicates that a method does not make any observable state changes. + /// The same as System.Diagnostics.Contracts.PureAttribute. + /// + /// + /// [Pure] int Multiply(int x, int y) => x * y; + /// + /// void M() { + /// Multiply(123, 42); // Waring: Return value of pure method is not used + /// } + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class PureAttribute : Attribute { } + + /// + /// Indicates that the return value of method invocation must be used. + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class MustUseReturnValueAttribute : Attribute + { + public MustUseReturnValueAttribute() { } + + public MustUseReturnValueAttribute([NotNull] string justification) + { + Justification = justification; + } + + [CanBeNull] public string Justification { get; private set; } + } + + /// + /// Indicates the type member or parameter of some type, that should be used instead of all other ways + /// to get the value that type. This annotation is useful when you have some "context" value evaluated + /// and stored somewhere, meaning that all other ways to get this value must be consolidated with existing one. + /// + /// + /// class Foo { + /// [ProvidesContext] IBarService _barService = ...; + /// + /// void ProcessNode(INode node) { + /// DoSomething(node, node.GetGlobalServices().Bar); + /// // ^ Warning: use value of '_barService' field + /// } + /// } + /// + [AttributeUsage( + AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Method | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.GenericParameter)] + public sealed class ProvidesContextAttribute : Attribute { } + + /// + /// Indicates that a parameter is a path to a file or a folder within a web project. + /// Path can be relative or absolute, starting from web root (~). + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class PathReferenceAttribute : Attribute + { + public PathReferenceAttribute() { } + + public PathReferenceAttribute([NotNull, PathReference] string basePath) + { + BasePath = basePath; + } + + [CanBeNull] public string BasePath { get; private set; } + } + + /// + /// An extension method marked with this attribute is processed by ReSharper code completion + /// as a 'Source Template'. When extension method is completed over some expression, it's source code + /// is automatically expanded like a template at call site. + /// + /// + /// Template method body can contain valid source code and/or special comments starting with '$'. + /// Text inside these comments is added as source code when the template is applied. Template parameters + /// can be used either as additional method parameters or as identifiers wrapped in two '$' signs. + /// Use the attribute to specify macros for parameters. + /// + /// + /// In this example, the 'forEach' method is a source template available over all values + /// of enumerable types, producing ordinary C# 'foreach' statement and placing caret inside block: + /// + /// [SourceTemplate] + /// public static void forEach<T>(this IEnumerable<T> xs) { + /// foreach (var x in xs) { + /// //$ $END$ + /// } + /// } + /// + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class SourceTemplateAttribute : Attribute { } + + /// + /// Allows specifying a macro for a parameter of a source template. + /// + /// + /// You can apply the attribute on the whole method or on any of its additional parameters. The macro expression + /// is defined in the property. When applied on a method, the target + /// template parameter is defined in the property. To apply the macro silently + /// for the parameter, set the property value = -1. + /// + /// + /// Applying the attribute on a source template method: + /// + /// [SourceTemplate, Macro(Target = "item", Expression = "suggestVariableName()")] + /// public static void forEach<T>(this IEnumerable<T> collection) { + /// foreach (var item in collection) { + /// //$ $END$ + /// } + /// } + /// + /// Applying the attribute on a template method parameter: + /// + /// [SourceTemplate] + /// public static void something(this Entity x, [Macro(Expression = "guid()", Editable = -1)] string newguid) { + /// /*$ var $x$Id = "$newguid$" + x.ToString(); + /// x.DoSomething($x$Id); */ + /// } + /// + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, AllowMultiple = true)] + public sealed class MacroAttribute : Attribute + { + /// + /// Allows specifying a macro that will be executed for a source template + /// parameter when the template is expanded. + /// + [CanBeNull] public string Expression { get; set; } + + /// + /// Allows specifying which occurrence of the target parameter becomes editable when the template is deployed. + /// + /// + /// If the target parameter is used several times in the template, only one occurrence becomes editable; + /// other occurrences are changed synchronously. To specify the zero-based index of the editable occurrence, + /// use values >= 0. To make the parameter non-editable when the template is expanded, use -1. + /// > + public int Editable { get; set; } + + /// + /// Identifies the target parameter of a source template if the + /// is applied on a template method. + /// + [CanBeNull] public string Target { get; set; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute + { + public AspMvcAreaMasterLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; private set; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute + { + public AspMvcAreaPartialViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; private set; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcAreaViewLocationFormatAttribute : Attribute + { + public AspMvcAreaViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; private set; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcMasterLocationFormatAttribute : Attribute + { + public AspMvcMasterLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; private set; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcPartialViewLocationFormatAttribute : Attribute + { + public AspMvcPartialViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; private set; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] + public sealed class AspMvcViewLocationFormatAttribute : Attribute + { + public AspMvcViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; private set; } + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC action. If applied to a method, the MVC action name is calculated + /// implicitly from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] + public sealed class AspMvcActionAttribute : Attribute + { + public AspMvcActionAttribute() { } + + public AspMvcActionAttribute([NotNull] string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + + [CanBeNull] public string AnonymousProperty { get; private set; } + } + + /// + /// ASP.NET MVC attribute. Indicates that a parameter is an MVC area. + /// Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AspMvcAreaAttribute : Attribute + { + public AspMvcAreaAttribute() { } + + public AspMvcAreaAttribute([NotNull] string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + + [CanBeNull] public string AnonymousProperty { get; private set; } + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is + /// an MVC controller. If applied to a method, the MVC controller name is calculated + /// implicitly from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] + public sealed class AspMvcControllerAttribute : Attribute + { + public AspMvcControllerAttribute() { } + + public AspMvcControllerAttribute([NotNull] string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + + [CanBeNull] public string AnonymousProperty { get; private set; } + } + + /// + /// ASP.NET MVC attribute. Indicates that a parameter is an MVC Master. Use this attribute + /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, String). + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AspMvcMasterAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. Indicates that a parameter is an MVC model type. Use this attribute + /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, Object). + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AspMvcModelTypeAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC + /// partial view. If applied to a method, the MVC partial view name is calculated implicitly + /// from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] + public sealed class AspMvcPartialViewAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. Allows disabling inspections for MVC views within a class or a method. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] + public sealed class AspMvcSuppressViewErrorAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template. + /// Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AspMvcDisplayTemplateAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. Indicates that a parameter is an MVC editor template. + /// Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AspMvcEditorTemplateAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. Indicates that a parameter is an MVC template. + /// Use this attribute for custom wrappers similar to + /// System.ComponentModel.DataAnnotations.UIHintAttribute(System.String). + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AspMvcTemplateAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC view component. If applied to a method, the MVC view name is calculated implicitly + /// from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Controller.View(Object). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] + public sealed class AspMvcViewAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC view component name. + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AspMvcViewComponentAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC view component view. If applied to a method, the MVC view component view name is default. + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] + public sealed class AspMvcViewComponentViewAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. When applied to a parameter of an attribute, + /// indicates that this parameter is an MVC action name. + /// + /// + /// [ActionName("Foo")] + /// public ActionResult Login(string returnUrl) { + /// ViewBag.ReturnUrl = Url.Action("Foo"); // OK + /// return RedirectToAction("Bar"); // Error: Cannot resolve action + /// } + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)] + public sealed class AspMvcActionSelectorAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)] + public sealed class HtmlElementAttributesAttribute : Attribute + { + public HtmlElementAttributesAttribute() { } + + public HtmlElementAttributesAttribute([NotNull] string name) + { + Name = name; + } + + [CanBeNull] public string Name { get; private set; } + } + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + public sealed class HtmlAttributeValueAttribute : Attribute + { + public HtmlAttributeValueAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull] public string Name { get; private set; } + } + + /// + /// Razor attribute. Indicates that a parameter or a method is a Razor section. + /// Use this attribute for custom wrappers similar to + /// System.Web.WebPages.WebPageBase.RenderSection(String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] + public sealed class RazorSectionAttribute : Attribute { } + + /// + /// Indicates how method, constructor invocation or property access + /// over collection type affects content of the collection. + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)] + public sealed class CollectionAccessAttribute : Attribute + { + public CollectionAccessAttribute(CollectionAccessType collectionAccessType) + { + CollectionAccessType = collectionAccessType; + } + + public CollectionAccessType CollectionAccessType { get; private set; } + } + + [Flags] + public enum CollectionAccessType + { + /// Method does not use or modify content of the collection. + None = 0, + /// Method only reads content of the collection but does not modify it. + Read = 1, + /// Method can change content of the collection but does not add new elements. + ModifyExistingContent = 2, + /// Method can add new elements to the collection. + UpdatedContent = ModifyExistingContent | 4 + } + + /// + /// Indicates that the marked method is assertion method, i.e. it halts control flow if + /// one of the conditions is satisfied. To set the condition, mark one of the parameters with + /// attribute. + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class AssertionMethodAttribute : Attribute { } + + /// + /// Indicates the condition parameter of the assertion method. The method itself should be + /// marked by attribute. The mandatory argument of + /// the attribute is the assertion type. + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AssertionConditionAttribute : Attribute + { + public AssertionConditionAttribute(AssertionConditionType conditionType) + { + ConditionType = conditionType; + } + + public AssertionConditionType ConditionType { get; private set; } + } + + /// + /// Specifies assertion type. If the assertion method argument satisfies the condition, + /// then the execution continues. Otherwise, execution is assumed to be halted. + /// + public enum AssertionConditionType + { + /// Marked parameter should be evaluated to true. + IS_TRUE = 0, + /// Marked parameter should be evaluated to false. + IS_FALSE = 1, + /// Marked parameter should be evaluated to null value. + IS_NULL = 2, + /// Marked parameter should be evaluated to not null value. + IS_NOT_NULL = 3, + } + + /// + /// Indicates that the marked method unconditionally terminates control flow execution. + /// For example, it could unconditionally throw exception. + /// + [Obsolete("Use [ContractAnnotation('=> halt')] instead")] + [AttributeUsage(AttributeTargets.Method)] + public sealed class TerminatesProgramAttribute : Attribute { } + + /// + /// Indicates that method is pure LINQ method, with postponed enumeration (like Enumerable.Select, + /// .Where). This annotation allows inference of [InstantHandle] annotation for parameters + /// of delegate type by analyzing LINQ method chains. + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class LinqTunnelAttribute : Attribute { } + + /// + /// Indicates that IEnumerable, passed as parameter, is not enumerated. + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class NoEnumerationAttribute : Attribute { } + + /// + /// Indicates that parameter is regular expression pattern. + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class RegexPatternAttribute : Attribute { } + + /// + /// Prevents the Member Reordering feature from tossing members of the marked class. + /// + /// + /// The attribute must be mentioned in your member reordering patterns + /// + [AttributeUsage( + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum)] + public sealed class NoReorderAttribute : Attribute { } + + /// + /// XAML attribute. Indicates the type that has ItemsSource property and should be treated + /// as ItemsControl-derived type, to enable inner items DataContext type resolve. + /// + [AttributeUsage(AttributeTargets.Class)] + public sealed class XamlItemsControlAttribute : Attribute { } + + /// + /// XAML attribute. Indicates the property of some BindingBase-derived type, that + /// is used to bind some item of ItemsControl-derived type. This annotation will + /// enable the DataContext type resolve for XAML bindings for such properties. + /// + /// + /// Property should have the tree ancestor of the ItemsControl type or + /// marked with the attribute. + /// + [AttributeUsage(AttributeTargets.Property)] + public sealed class XamlItemBindingOfItemsControlAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public sealed class AspChildControlTypeAttribute : Attribute + { + public AspChildControlTypeAttribute([NotNull] string tagName, [NotNull] Type controlType) + { + TagName = tagName; + ControlType = controlType; + } + + [NotNull] public string TagName { get; private set; } + + [NotNull] public Type ControlType { get; private set; } + } + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] + public sealed class AspDataFieldAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] + public sealed class AspDataFieldsAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Property)] + public sealed class AspMethodPropertyAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public sealed class AspRequiredAttributeAttribute : Attribute + { + public AspRequiredAttributeAttribute([NotNull] string attribute) + { + Attribute = attribute; + } + + [NotNull] public string Attribute { get; private set; } + } + + [AttributeUsage(AttributeTargets.Property)] + public sealed class AspTypePropertyAttribute : Attribute + { + public bool CreateConstructorReferences { get; private set; } + + public AspTypePropertyAttribute(bool createConstructorReferences) + { + CreateConstructorReferences = createConstructorReferences; + } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorImportNamespaceAttribute : Attribute + { + public RazorImportNamespaceAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull] public string Name { get; private set; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorInjectionAttribute : Attribute + { + public RazorInjectionAttribute([NotNull] string type, [NotNull] string fieldName) + { + Type = type; + FieldName = fieldName; + } + + [NotNull] public string Type { get; private set; } + + [NotNull] public string FieldName { get; private set; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorDirectiveAttribute : Attribute + { + public RazorDirectiveAttribute([NotNull] string directive) + { + Directive = directive; + } + + [NotNull] public string Directive { get; private set; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class RazorPageBaseTypeAttribute : Attribute + { + public RazorPageBaseTypeAttribute([NotNull] string baseType) + { + BaseType = baseType; + } + public RazorPageBaseTypeAttribute([NotNull] string baseType, string pageName) + { + BaseType = baseType; + PageName = pageName; + } + + [NotNull] public string BaseType { get; private set; } + [CanBeNull] public string PageName { get; private set; } + } + + [AttributeUsage(AttributeTargets.Method)] + public sealed class RazorHelperCommonAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Property)] + public sealed class RazorLayoutAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Method)] + public sealed class RazorWriteLiteralMethodAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Method)] + public sealed class RazorWriteMethodAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class RazorWriteMethodParameterAttribute : Attribute { } +} \ No newline at end of file diff --git a/ModernKeePass10/Properties/AssemblyInfo.cs b/ModernKeePass10/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..3fe678c --- /dev/null +++ b/ModernKeePass10/Properties/AssemblyInfo.cs @@ -0,0 +1,28 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ModernKeePass")] +[assembly: AssemblyDescription("A port of KeePass 2.x to Modern UI as a Windows Store application")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("wismna")] +[assembly: AssemblyProduct("ModernKeePass")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.14.0.0")] +[assembly: AssemblyFileVersion("1.14.0.0")] +[assembly: ComVisible(false)] \ No newline at end of file diff --git a/ModernKeePass10/Properties/default.rd.xml b/ModernKeePass10/Properties/default.rd.xml new file mode 100644 index 0000000..3b69ca7 --- /dev/null +++ b/ModernKeePass10/Properties/default.rd.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/ModernKeePass10/ResourceDictionaries/HamburgerButtonStyle.xaml b/ModernKeePass10/ResourceDictionaries/HamburgerButtonStyle.xaml new file mode 100644 index 0000000..abf2cc6 --- /dev/null +++ b/ModernKeePass10/ResourceDictionaries/HamburgerButtonStyle.xaml @@ -0,0 +1,60 @@ + + + + + diff --git a/ModernKeePass10/ResourceDictionaries/ListViewLeftIndicatorStyle.xaml b/ModernKeePass10/ResourceDictionaries/ListViewLeftIndicatorStyle.xaml new file mode 100644 index 0000000..dc2e1e1 --- /dev/null +++ b/ModernKeePass10/ResourceDictionaries/ListViewLeftIndicatorStyle.xaml @@ -0,0 +1,399 @@ + + + + + diff --git a/ModernKeePass10/ResourceDictionaries/MasterDetailsView.xaml b/ModernKeePass10/ResourceDictionaries/MasterDetailsView.xaml new file mode 100644 index 0000000..671a5e0 --- /dev/null +++ b/ModernKeePass10/ResourceDictionaries/MasterDetailsView.xaml @@ -0,0 +1,197 @@ + + + + + diff --git a/ModernKeePass10/ResourceDictionaries/NoBorderButtonStyle.xaml b/ModernKeePass10/ResourceDictionaries/NoBorderButtonStyle.xaml new file mode 100644 index 0000000..340fedc --- /dev/null +++ b/ModernKeePass10/ResourceDictionaries/NoBorderButtonStyle.xaml @@ -0,0 +1,115 @@ + + + + + diff --git a/ModernKeePass10/ResourceDictionaries/NoBorderToggleButtonStyle.xaml b/ModernKeePass10/ResourceDictionaries/NoBorderToggleButtonStyle.xaml new file mode 100644 index 0000000..c8f45ce --- /dev/null +++ b/ModernKeePass10/ResourceDictionaries/NoBorderToggleButtonStyle.xaml @@ -0,0 +1,204 @@ + + + + + diff --git a/ModernKeePass10/ResourceDictionaries/Styles.xaml b/ModernKeePass10/ResourceDictionaries/Styles.xaml new file mode 100644 index 0000000..8babf67 --- /dev/null +++ b/ModernKeePass10/ResourceDictionaries/Styles.xaml @@ -0,0 +1,1986 @@ + + + + 48 + 48 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/Strings/en-US/CodeBehind.resw b/ModernKeePass10/Strings/en-US/CodeBehind.resw new file mode 100644 index 0000000..e6f4821 --- /dev/null +++ b/ModernKeePass10/Strings/en-US/CodeBehind.resw @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Select key file from disk... + + + Error: + + + - wrong key file + + + - password incorrect + + + Opening... + + + Database composite key updated. + + + Delete + + + Cancel + + + Warning + + + Deleting + + + Restored + + + Entry permanently removed + + + Are you sure you want to delete this entry? + + + Entry moved to the Recycle bin + + + Are you sure you want to send this entry to the recycle bin? + + + Entry returned to its original group + + + Group permanently removed + + + Are you sure you want to delete the whole group and all its entries? + + + Group moved to the Recycle bin + + + Are you sure you want to send the whole group and all its entries to the recycle bin? + + + Group returned to its original group + + + - user account + + + Recycle Bin + + + 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 + + + Database successfully saved! + + + The CSV file needs to be formatted as such: Name of the account;Login;Password;URL;Comments + + \ No newline at end of file diff --git a/ModernKeePass10/Strings/en-US/Resources.resw b/ModernKeePass10/Strings/en-US/Resources.resw new file mode 100644 index 0000000..565ef88 --- /dev/null +++ b/ModernKeePass10/Strings/en-US/Resources.resw @@ -0,0 +1,555 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Dominik Reichl for the KeePass application and file format + + + David Lechner for his PCL adapatation of the KeePass Library and his correlated tests + + + Credits + + + A modern password manager for the Windows Store + + + Homepage: + + + Delete + + + Edit + + + Home + + + Restore + + + Save + + + Settings + + + Sort + + + Entries + + + Groups + + + Donate + + + Like this app? Why not make a small donation to support my work and help me keep it ad-free :) ? + + + Expiration date + + + Password has expired + + + Copy login + + + Copy password + + + Navigate to URL + + + User name or login + + + Notes + + + Password + + + Show password + + + Create new entry + + + Search... + + + New group name... + + + Create new... + + + Create a new password database to the location of your chosing. + + + Browse files... + + + Open an existing password database from your PC. + + + From Url... + + + Open an existing password database from an Internet location (not yet implemented). + + + Also add these characters: + + + Brackets ([], {}, (), ...) + + + Generate + + + Digits (0, 1, 2, ...) + + + Password Length: + + + Lower case (a, b, c, ...) + + + Minus (-) + + + Space ( ) + + + Special (!, $, %, ...) + + + Generate password + + + Underscore (_) + + + Upper case (A, B, C, ...) + + + Clear all + + + Drag and drop entries to reorder them + + + Save as... + + + This will save the currently opened database as a new file and leave it open. + + + Save and close + + + This will save and close the currently opened database. + + + Compression Algorithm + + + Encryption Algorithm + + + Key Derivation Algorithm + + + Recycle bin + + + Disabled + + + Enabled + + + Create a new group + + + Use an existing group + + + Here, you can change some default options when creating a database. + + + KDBX database file version + + + Higher is better, but there may be compatibility issues with older applications + + + Create sample data + + + No + + + Yes + + + Don't save + + + Save + + + This settings is generally recommended. If you enable it, database will automatically be saved on application suspension and closing. However, if your database is huge, saving may be deemed too long by Windows, which will then forcibly kill the app. + + + Auto-save on suspend? + + + Here, you may change your database password, key file, or both. Just click on on + + + Update master key + + + when you're done. Please make sure to remember the password you choose here! + + + Change database security options + + + Update master key + + + Here, you may change the application or the database settings. + + + Select a setting pane on the left to access the options. + + + Settings + + + Want to create a new password database? Do it here. + + + Have an existing password database? Open it here. + + + History + + + Login copied to clipboard + + + Password copied to clipboard + + + URL copied to clipboard + + + Background color + + + Foreground color + + + Icon + + + Create a new entry + + + Home + + + Home + + + Settings + + + Settings + + + Delete + + + Delete + + + Edit + + + Edit + + + More + + + Restore + + + Restore + + + Save + + + Save + + + Sort + + + Sort entries + + + Sort groups + + + Database successfully updated + + + Composite Key + + + New entry name... + + + Search + + + Search + + + Copy login + + + Copy password + + + Navigate to URL + + + Entry restored to its original position + + + Group restored to its original position + + + Import existing data + + + Select a file to import... + + + Format + + + About + + + Donate + + + New + + + Open + + + Recent + + + Save + + + Settings + + + Databases + + + Settings + + + Settings + + + Application + + + Database + + + General + + + New + + + Saving + + + Security + + + New group + + + Groups + + + New entry + + + Rename + + + Icon + + + Additional + + + Settings + + + Main + + + History + + + History + + + OK + + + Set credentials + + \ No newline at end of file diff --git a/ModernKeePass10/Strings/fr-FR/CodeBehind.resw b/ModernKeePass10/Strings/fr-FR/CodeBehind.resw new file mode 100644 index 0000000..80c6ace --- /dev/null +++ b/ModernKeePass10/Strings/fr-FR/CodeBehind.resw @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Choisissez un fichier... + + + Erreur: + + + - mauvais fichier de clé + + + - mot de passe incorrect + + + Ouverture... + + + Clé composite de la base de données mise à jour. + + + Supprimer + + + Annuler + + + Attention + + + Suppression + + + Restauré + + + Entrée supprimée définitivement + + + Êtes-vous sûr de vouloir supprimer cette entrée ? + + + Entrée placée dans la Corbeille + + + Êtes-vous sûr de vouloir placer cette entrée dans la Corbeille ? + + + Entrée replacée dans son groupe d'origine + + + Groupe supprimé définitivement + + + Êtes-vous sûr de vouloir supprimer ce groupe et toutes ses entrées ? + + + Groupe placé dans la Corbeille + + + Êtes-vous sûr de vouloir envoyer ce groupe et toutes ses entrées vers la Corbeille ? + + + Groupe replacé à sa place originelle + + + - compte utilisateur + + + Corbeille + + + 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 + + + Base de données sauvegardée avec succès ! + + + Le fichier CSV doit être formatté de la façon suivante: Nom du compte;Login;Mot de passe;URL;Commentaires + + \ No newline at end of file diff --git a/ModernKeePass10/Strings/fr-FR/Resources.resw b/ModernKeePass10/Strings/fr-FR/Resources.resw new file mode 100644 index 0000000..25bab80 --- /dev/null +++ b/ModernKeePass10/Strings/fr-FR/Resources.resw @@ -0,0 +1,558 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Dominik Reichl pour l'application KeePass et le format de fichier + + + David Lechner pour son adaptation PCL de la blibliothèque KeePass et ses tests associés + + + Crédits + + + Un gestionnaire de mot de passes moderne pour le Windows Store + + + Page d'accueil : + + + Supprimer + + + Editer + + + Accueil + + + Restaurer + + + Sauvegarder + + + Paramètres + + + Trier + + + Entrées + + + Groupes + + + Donner + + + Vous aimez cette app? Pourquoi ne pas faire un petit don afin de m'encourager et d'éviter le recours aux publicités :) ? + + + Date d'expiration + + + Le mot de passe a expiré + + + Copier le login + + + Copier le mot de passe + + + Naviguer vers l'URL + + + Nom d'utilisateur ou login + + + Notes + + + Mot de passe + + + Afficher le mot de passe + + + Créer une nouvelle entrée + + + Rechercher... + + + Nom du nouveau groupe... + + + Créer une nouvelle... + + + Créer une nouvelle base de données de mots de passe à l'endroit de votre choix. + + + Parcourir les fichiers... + + + Ouvrir une base de données de mots de passe existante sur votre PC. + + + Depuis une URL... + + + Ouvrir une base de données de mots de passe depuis Internet (pas encore implementé). + + + Ajouter aussi ces caractères : + + + Parenthèses ([], {}, (), ...) + + + Générer + + + Chiffres (0, 1, 2, ...) + + + Longueur de mot de passe : + + + Minuscules (a, b, c, ...) + + + Moins (-) + + + Espace ( ) + + + Spéciaux (!, $, %, ...) + + + Générer le mot de passe + + + Underscore (_) + + + Majuscules (A, B, C, ...) + + + Supprimer tout + + + Glissez-déposez les entrées pour les réorganiser + + + Sauvegarder sous... + + + Cela va sauvegarder la base de données dans un nouveau fichier et l'ouvrir. + + + Sauvegarder et fermer + + + Cela va sauvegarder et fermer la base de données. + + + Algorithme de compression + + + Algorithme de chiffrement + + + Algorithme de dérivation de clé + + + Corbeille + + + Désactivé + + + Activé + + + Créer un nouveau groupe + + + Utiliser un groupe existant + + + Ici, vous pouvez changer certains options lors de la création d'une nouvelle base de données + + + Version de fichier KDBX + + + Le plus élévé est le mieux, mais vous pourriez rencontrer des problèmes de compatibilité avec des application plus anciennes + + + Créer des données d'exemple + + + Non + + + Oui + + + Ne pas sauvegarder + + + Sauvegarder + + + Ce paramètre est généralement recommandé. Si vous l'activez, la base de données sera sauvegardée automatiquement lors de la suspension et de la fermeture. Cependant, si votre base de données est très volumineuse, il se peut que Windows estime que cela prend trop de temps et tue l'application. + + + Sauvegarder automatiquement lors de la suspension ? + + + Ici, vous pouvez changer le mot de passe maître, le fichier de clé, ou les deux. Cliquez simplement sur + + + Mettre à jour la clé maître + + + quand vous avez fini. Retenez bien le mot de passe que vous utilisez ! + + + Changer les options de sécurité de la base de données + + + Mettre à jour la clé maître + + + Ici, vous pouvez changer les options de l'application ou de la base de données. + + + Choisissez un élément dans le menu de gauche. + + + Paramètres + + + Pour créer une nouvelle base de données de mots de passe, c'est ici. + + + Pour ouvrir une base de données existante, c'est ici. + + + Historique + + + Login copié dans le presse-papiers + + + Mot de passe copié dans le presse-papiers + + + URL copié dans le presse-papiers + + + Couleur d'arrière plan + + + Couleur du texte + + + Icône + + + Créer une nouvelle entrée + + + Accueil + + + Accueil + + + Paramètres + + + Paramètres + + + Supprimer + + + Supprimer + + + Editer + + + Editer + + + Plus + + + Restaurer + + + Restaurer + + + Sauvegarder + + + Sauvegarder + + + Trier + + + Trier les entrées + + + Trier les groupes + + + Base de données mise à jour + + + Clé maître + + + Nom de la nouvelle entrée... + + + Recherche + + + Rechercher + + + Copier le login + + + Copier le mot de passe + + + Naviguer vers l'URL + + + Entrée replacée à son emplacement d'origine + + + Groupe replacée à son emplacement d'origine + + + Importer des données existantes + + + Sélectionnez un fichier à importer... + + + Format + + + Le fichier CSV doit être formatté de la façon suivante: Nom du compte;Login;Mot de passe:URL;Commentaires + + + A propos + + + Donation + + + Nouveau + + + Ouvrir + + + Récents + + + Sauvegarder + + + Paramètres + + + Bases de données + + + Paramètres + + + Paramètres + + + Application + + + Base de données + + + Général + + + Nouveau + + + Sauvegardes + + + Sécurité + + + Nouveau groupe + + + Groupes + + + Nouvelle entrée + + + Renommer + + + Icône + + + Additionel + + + Paramètres + + + Principal + + + Historique + + + Historique + + + OK + + + Sauvegarder + + \ No newline at end of file diff --git a/ModernKeePass10/TemplateSelectors/FirstItemDataTemplateSelector.cs b/ModernKeePass10/TemplateSelectors/FirstItemDataTemplateSelector.cs new file mode 100644 index 0000000..e363d22 --- /dev/null +++ b/ModernKeePass10/TemplateSelectors/FirstItemDataTemplateSelector.cs @@ -0,0 +1,18 @@ +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace ModernKeePass.TemplateSelectors +{ + public class FirstItemDataTemplateSelector: DataTemplateSelector + { + public DataTemplate FirstItem { get; set; } + public DataTemplate OtherItem { get; set; } + + protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) + { + var itemsControl = ItemsControl.ItemsControlFromItemContainer(container); + var returnTemplate = itemsControl?.IndexFromContainer(container) == 0 ? FirstItem : OtherItem; + return returnTemplate; + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/TemplateSelectors/SelectableDataTemplateSelector.cs b/ModernKeePass10/TemplateSelectors/SelectableDataTemplateSelector.cs new file mode 100644 index 0000000..115beb5 --- /dev/null +++ b/ModernKeePass10/TemplateSelectors/SelectableDataTemplateSelector.cs @@ -0,0 +1,18 @@ +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using ModernKeePass.Application.Common.Interfaces; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.TemplateSelectors +{ + public class SelectableDataTemplateSelector: DataTemplateSelector + { + public DataTemplate TrueItem { get; set; } + public DataTemplate FalseItem { get; set; } + + protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) + { + return item is ISelectableModel isSelectableItem && isSelectableItem.IsSelected ? TrueItem : FalseItem; + } + } +} diff --git a/ModernKeePass10/ViewModels/AboutViewModel.cs b/ModernKeePass10/ViewModels/AboutViewModel.cs new file mode 100644 index 0000000..6b75e02 --- /dev/null +++ b/ModernKeePass10/ViewModels/AboutViewModel.cs @@ -0,0 +1,27 @@ +using Windows.ApplicationModel; + +namespace ModernKeePass.ViewModels +{ + public class AboutViewModel + { + private readonly Package _package; + + public string Name => _package.DisplayName; + + public string Version + { + get + { + var version = _package.Id.Version; + return $"{version.Major}.{version.Minor}"; + } + } + + public AboutViewModel() : this(Package.Current) { } + + public AboutViewModel(Package package) + { + _package = package; + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/ViewModels/EntriesViewModel.cs b/ModernKeePass10/ViewModels/EntriesViewModel.cs new file mode 100644 index 0000000..c566fa7 --- /dev/null +++ b/ModernKeePass10/ViewModels/EntriesViewModel.cs @@ -0,0 +1,71 @@ +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using Autofac; +using ModernKeePass.Domain.AOP; +using ModernKeePass.Domain.Entities; +using ModernKeePass.Domain.Interfaces; +using ModernKeePass.ViewModels.ListItems; + +namespace ModernKeePass.ViewModels +{ + public class EntriesViewModel : NotifyPropertyChangedBase + { + private readonly IDatabaseService _databaseService; + private readonly GroupItemViewModel _parentGroupViewModel; + //private Entry _reorderedEntry; + private EntryItemViewModel _selectedEntry; + + public ObservableCollection Entries { get; set; } + + public EntryItemViewModel SelectedEntry + { + get => _selectedEntry; + set + { + _selectedEntry = value; + OnPropertyChanged(nameof(SelectedEntry)); + } + } + + public EntriesViewModel(GroupItemViewModel parentGroup): this(App.Container.Resolve(), parentGroup) + { } + + public EntriesViewModel(IDatabaseService databaseService, GroupItemViewModel parentParentGroupViewModel) + { + _databaseService = databaseService; + _parentGroupViewModel = parentParentGroupViewModel; + Entries = new ObservableCollection(); + foreach (var entry in parentParentGroupViewModel.Entries) + { + Entries.Add(entry); + } + Entries.CollectionChanged += EntriesOnCollectionChanged; + } + + private void EntriesOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + // TODO: rewrite this (with service) + switch (e.Action) + { + case NotifyCollectionChangedAction.Remove: + /*var oldIndex = (uint)e.OldStartingIndex; + _reorderedEntry = _group.Group.Entries.GetAt(oldIndex); + _group.Group.Entries.RemoveAt(oldIndex);*/ + _databaseService.DeleteEntity((Entity)e.OldItems[0]); + break; + case NotifyCollectionChangedAction.Add: + /*if (_reorderedEntry == null) _group.Group.AddEntry(((EntryItemViewModel)e.NewItems[0]).Entry, true); + else _group.Group.Entries.Insert((uint)e.NewStartingIndex, _reorderedEntry);*/ + _databaseService.AddEntity(_parentGroupViewModel.GroupEntity, (Entity)e.NewItems[0]); + break; + } + } + + public void AddNewEntry(string text) + { + var entry = new EntryItemViewModel(new EntryEntity(), _parentGroupViewModel) {Name = text}; + Entries.Add(entry); + SelectedEntry = entry; + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/ViewModels/GroupsViewModel.cs b/ModernKeePass10/ViewModels/GroupsViewModel.cs new file mode 100644 index 0000000..5f40e70 --- /dev/null +++ b/ModernKeePass10/ViewModels/GroupsViewModel.cs @@ -0,0 +1,57 @@ +using Autofac; +using ModernKeePass.Domain.AOP; +using ModernKeePass.Domain.Entities; +using ModernKeePass.Domain.Enums; +using ModernKeePass.Domain.Interfaces; +using ModernKeePass.ViewModels.ListItems; + +namespace ModernKeePass.ViewModels +{ + public class GroupsViewModel : NotifyPropertyChangedBase + { + private string _title; + private string _newGroupName; + + public string Title + { + get => _title; + set + { + _title = value; + OnPropertyChanged(nameof(Title)); + } + } + + // TODO: check why binding not working + public string NewGroupName + { + get => _newGroupName; + set + { + _newGroupName = value; + OnPropertyChanged(nameof(NewGroupName)); + } + } + + public GroupItemViewModel RootItemViewModel { get; set; } + + public GroupsViewModel(): this(App.Container.Resolve().RootGroupEntity) + { } + + public GroupsViewModel(GroupEntity groupEntity) + { + Title = groupEntity.Name; + RootItemViewModel = new GroupItemViewModel(groupEntity, null); + } + + public void AddNewGroup(string groupName = "") + { + var group = new GroupEntity + { + Name = groupName, + Icon = Icon.Folder, + }; + RootItemViewModel.Children.Add(new GroupItemViewModel(group, RootItemViewModel)); + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/ViewModels/ListItems/EntryItemViewModel.cs b/ModernKeePass10/ViewModels/ListItems/EntryItemViewModel.cs new file mode 100644 index 0000000..4d027c5 --- /dev/null +++ b/ModernKeePass10/ViewModels/ListItems/EntryItemViewModel.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using Windows.UI; +using Autofac; +using ModernKeePass.Domain.AOP; +using ModernKeePass.Domain.Entities; +using ModernKeePass.Domain.Enums; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.ViewModels.ListItems +{ + public class EntryItemViewModel : NotifyPropertyChangedBase + { + private readonly ISecurityService _securityService; + + public EntryEntity EntryEntity { get; } + public GroupItemViewModel Parent { get; } + + public bool HasExpired => HasExpirationDate && EntryEntity.ExpirationDate < DateTime.Now; + + public bool HasUrl => !string.IsNullOrEmpty(Url); + + public double PasswordComplexityIndicator => _securityService.EstimatePasswordComplexity(Password); + + public string Name + { + get => EntryEntity.Name; + set + { + EntryEntity.Name = value; + OnPropertyChanged(nameof(Name)); + } + } + + public string UserName + { + get => EntryEntity.UserName; + set => EntryEntity.UserName = value; + } + + public string Password + { + get => EntryEntity.Password; + set + { + EntryEntity.Password = value; + OnPropertyChanged(); + } + } + + public string Url + { + get => EntryEntity.Url?.ToString(); + set => EntryEntity.Url = new Uri(value); + } + + public string Notes + { + get => EntryEntity.Notes; + set => EntryEntity.Notes = value; + } + + public Icon Icon + { + get => HasExpired ? Icon.Important : EntryEntity.Icon; + set => EntryEntity.Icon = value; + } + + public DateTimeOffset ExpiryDate + { + get => EntryEntity.ExpirationDate; + set + { + if (!HasExpirationDate) return; + EntryEntity.ExpirationDate = value; + } + } + + public TimeSpan ExpiryTime + { + get => EntryEntity.ExpirationDate.TimeOfDay; + set + { + if (!HasExpirationDate) return; + EntryEntity.ExpirationDate = EntryEntity.ExpirationDate.Date.Add(value); + } + } + + public bool HasExpirationDate + { + get => EntryEntity.HasExpirationDate; + set + { + EntryEntity.HasExpirationDate = value; + OnPropertyChanged(); + } + } + + public Color BackgroundColor + { + get => Color.FromArgb(EntryEntity.BackgroundColor.A, EntryEntity.BackgroundColor.R, EntryEntity.BackgroundColor.G, EntryEntity.BackgroundColor.B); + set + { + EntryEntity.BackgroundColor = System.Drawing.Color.FromArgb(value.A, value.R, value.G, value.B); + OnPropertyChanged(); + } + } + + public Color ForegroundColor + { + get => Color.FromArgb(EntryEntity.ForegroundColor.A, EntryEntity.ForegroundColor.R, EntryEntity.ForegroundColor.G, EntryEntity.ForegroundColor.B); + set + { + EntryEntity.ForegroundColor = System.Drawing.Color.FromArgb(value.A, value.R, value.G, value.B); + OnPropertyChanged(); + } + } + + public IEnumerable History + { + get + { + var history = new Stack(); + foreach (var historyEntry in EntryEntity.History) + { + history.Push(new EntryItemViewModel(_securityService, historyEntry, Parent)); + } + history.Push(this); + + return history; + } + } + public Dictionary AdditionalFields => EntryEntity.AdditionalFields; + + public EntryItemViewModel(EntryEntity entryEntity, GroupItemViewModel parentGroup): this(App.Container.Resolve(), entryEntity, parentGroup) + { } + + public EntryItemViewModel(ISecurityService securityService, EntryEntity entryEntity, GroupItemViewModel parentGroup) + { + _securityService = securityService; + EntryEntity = entryEntity; + Parent = parentGroup; + } + + public override string ToString() => EntryEntity.LastModificationDate.ToString("g"); + } +} \ No newline at end of file diff --git a/ModernKeePass10/ViewModels/ListItems/GroupItemViewModel.cs b/ModernKeePass10/ViewModels/ListItems/GroupItemViewModel.cs new file mode 100644 index 0000000..8806192 --- /dev/null +++ b/ModernKeePass10/ViewModels/ListItems/GroupItemViewModel.cs @@ -0,0 +1,101 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using Autofac; +using ModernKeePass.Domain.AOP; +using ModernKeePass.Domain.Entities; +using ModernKeePass.Domain.Enums; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.ViewModels.ListItems +{ + public class GroupItemViewModel: NotifyPropertyChangedBase + { + private readonly IDatabaseService _databaseService; + //private Group _reorderedGroup; + private bool _isEditMode; + + public GroupEntity GroupEntity { get; } + public GroupItemViewModel ParentViewModel { get; } + + public bool IsEditMode + { + get => _isEditMode; + set + { + _isEditMode = value; + OnPropertyChanged(); + } + } + + public string Text + { + get => GroupEntity.Name; + set + { + GroupEntity.Name = value; + OnPropertyChanged(); + } + } + + public IEnumerable SubEntries + { + get + { + var subEntries = new List(); + subEntries.AddRange(Entries); + foreach (var group in Children) + { + subEntries.AddRange(group.SubEntries); + } + + return subEntries; + } + } + + public Icon Symbol => GroupEntity.Icon; + public List Entries { get; } + public ObservableCollection Children { get; set; } = new ObservableCollection(); + + public GroupItemViewModel(GroupEntity groupEntity, GroupItemViewModel parent): this(App.Container.Resolve(), groupEntity, parent) + { } + + public GroupItemViewModel(IDatabaseService databaseService, GroupEntity groupEntity, GroupItemViewModel parentViewModel) + { + _databaseService = databaseService; + GroupEntity = groupEntity; + ParentViewModel = parentViewModel; + + Entries = new List(); + foreach (var entry in groupEntity.Entries) + { + Entries.Add(new EntryItemViewModel(entry, this)); + } + + foreach (var subGroup in groupEntity.SubGroups) + { + Children.Add(new GroupItemViewModel(subGroup, this)); + } + Children.CollectionChanged += Children_CollectionChanged; + } + + // TODO: not triggered when reordering + private void Children_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Remove: + /*var oldIndex = (uint)e.OldStartingIndex; + _reorderedGroup = Group.SubGroups.GetAt(oldIndex); + Group.SubGroups.RemoveAt(oldIndex);*/ + _databaseService.DeleteEntity((Entity)e.OldItems[0]); + break; + case NotifyCollectionChangedAction.Add: + /*if (_reorderedGroup == null) Group.AddGroup(((GroupItem)e.NewItems[0]).Group, true); + else Group.Groups.Insert((uint)e.NewStartingIndex, _reorderedGroup);*/ + _databaseService.AddEntity(ParentViewModel.GroupEntity, (Entity)e.NewItems[0]); + break; + } + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/ViewModels/ListItems/ListMenuItemViewModel.cs b/ModernKeePass10/ViewModels/ListItems/ListMenuItemViewModel.cs new file mode 100644 index 0000000..419440a --- /dev/null +++ b/ModernKeePass10/ViewModels/ListItems/ListMenuItemViewModel.cs @@ -0,0 +1,31 @@ +using System; +using Windows.UI.Xaml.Controls; +using ModernKeePass.Application.Common.Interfaces; +using ModernKeePass.Domain.AOP; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.ViewModels.ListItems +{ + public class ListMenuItemViewModel : NotifyPropertyChangedBase, IIsEnabled, ISelectableModel + { + private bool _isSelected; + + public string Title { get; set; } + + public string Group { get; set; } = "_"; + public Type PageType { get; set; } + public Symbol SymbolIcon { get; set; } + public bool IsEnabled { get; set; } = true; + + public bool IsSelected + { + get => _isSelected; + set => SetProperty(ref _isSelected, value); + } + + public override string ToString() + { + return Title; + } + } +} diff --git a/ModernKeePass10/ViewModels/ListItems/MainMenuItemViewModel.cs b/ModernKeePass10/ViewModels/ListItems/MainMenuItemViewModel.cs new file mode 100644 index 0000000..11822a0 --- /dev/null +++ b/ModernKeePass10/ViewModels/ListItems/MainMenuItemViewModel.cs @@ -0,0 +1,10 @@ +using Windows.UI.Xaml.Controls; + +namespace ModernKeePass.ViewModels.ListItems +{ + public class MainMenuItemViewModel: ListMenuItemViewModel + { + public object Parameter { get; set; } + public Frame Destination { get; set; } + } +} diff --git a/ModernKeePass10/ViewModels/ListItems/RecentItemViewModel.cs b/ModernKeePass10/ViewModels/ListItems/RecentItemViewModel.cs new file mode 100644 index 0000000..32c3e0d --- /dev/null +++ b/ModernKeePass10/ViewModels/ListItems/RecentItemViewModel.cs @@ -0,0 +1,36 @@ +using System.Threading.Tasks; +using Autofac; +using ModernKeePass.Application.Common.Interfaces; +using ModernKeePass.Domain.AOP; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.ViewModels.ListItems +{ + public class RecentItemViewModel: NotifyPropertyChangedBase, ISelectableModel + { + private readonly IRecentService _recentService; + private bool _isSelected; + + public string Token { get; set; } + public string Name { get; set; } + + public bool IsSelected + { + get => _isSelected; + set => SetProperty(ref _isSelected, value); + } + + public RecentItemViewModel(): this (App.Container.Resolve()) + { } + + public RecentItemViewModel(IRecentService recentService) + { + _recentService = recentService; + } + + public async Task UpdateAccessTime() + { + await _recentService.Get(Token); + } + } +} diff --git a/ModernKeePass10/ViewModels/ListItems/SettingsDatabaseViewModel.cs b/ModernKeePass10/ViewModels/ListItems/SettingsDatabaseViewModel.cs new file mode 100644 index 0000000..1457637 --- /dev/null +++ b/ModernKeePass10/ViewModels/ListItems/SettingsDatabaseViewModel.cs @@ -0,0 +1,101 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using Autofac; +using ModernKeePass.Domain.AOP; +using ModernKeePass.Domain.Entities; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.ViewModels.ListItems +{ + // TODO: implement Kdf settings + public class SettingsDatabaseViewModel: NotifyPropertyChangedBase + { + private readonly IDatabaseService _databaseService; + private readonly ICryptographyService _cryptographyService; + + public bool HasRecycleBin + { + get => _databaseService.IsRecycleBinEnabled; + set { + // TODO: do something here + } + } + + public bool IsNewRecycleBin + { + get => _databaseService.RecycleBin == null; + set + { + // TODO: make this work + if (value) _databaseService.AddEntity(_databaseService.RootGroupEntity, new Entity{Name = "Recycle Bin"}); + } + } + + public ObservableCollection Groups { get; set; } + + public ObservableCollection Ciphers => new ObservableCollection(_cryptographyService.Ciphers); + + public IEnumerable Compressions => _cryptographyService.CompressionAlgorithms; + + public IEnumerable KeyDerivations => _cryptographyService.KeyDerivations; + + public Entity SelectedCipher + { + get => Ciphers.FirstOrDefault(c => c.Id == _databaseService.Cipher.Id); + set + { + if (_databaseService.Cipher != value) + { + _databaseService.Cipher = value; + //OnPropertyChanged(nameof(SelectedCipher)); + } + } + } + public Entity SelectedKeyDerivation + { + get => _databaseService.KeyDerivation; + set + { + if (_databaseService.KeyDerivation != value) + { + _databaseService.KeyDerivation = value; + OnPropertyChanged(nameof(SelectedKeyDerivation)); + } + } + } + public string SelectedCompression + { + get => _databaseService.Compression; + set + { + if (_databaseService.Compression != value) + { + _databaseService.Compression = value; + OnPropertyChanged(nameof(SelectedCompression)); + } + } + } + public GroupEntity SelectedRecycleBin + { + get => _databaseService.RecycleBin; + set + { + if (_databaseService.RecycleBin != value) + { + _databaseService.RecycleBin = value; + OnPropertyChanged(nameof(SelectedRecycleBin)); + } + } + } + + public SettingsDatabaseViewModel() : this(App.Container.Resolve(), App.Container.Resolve()) { } + + public SettingsDatabaseViewModel(IDatabaseService databaseService, ICryptographyService cryptographyService) + { + _databaseService = databaseService; + _cryptographyService = cryptographyService; + Groups = new ObservableCollection(_databaseService.RootGroupEntity.SubGroups); + } + } +} diff --git a/ModernKeePass10/ViewModels/ListItems/SettingsNewViewModel.cs b/ModernKeePass10/ViewModels/ListItems/SettingsNewViewModel.cs new file mode 100644 index 0000000..4d4f551 --- /dev/null +++ b/ModernKeePass10/ViewModels/ListItems/SettingsNewViewModel.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using Autofac; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.ViewModels.ListItems +{ + public class SettingsNewViewModel + { + private readonly ISettingsService _settings; + + public SettingsNewViewModel() : this(App.Container.Resolve()) + { } + + public SettingsNewViewModel(ISettingsService settings) + { + _settings = settings; + } + + public bool IsCreateSample + { + get => _settings.GetSetting("Sample"); + set => _settings.PutSetting("Sample", value); + } + + public IEnumerable FileFormats => new []{"2", "4"}; + + public string FileFormatVersion + { + get => _settings.GetSetting("DefaultFileFormat", "2"); + set => _settings.PutSetting("DefaultFileFormat", value); + } + } +} diff --git a/ModernKeePass10/ViewModels/ListItems/SettingsSaveViewModel.cs b/ModernKeePass10/ViewModels/ListItems/SettingsSaveViewModel.cs new file mode 100644 index 0000000..1e724c2 --- /dev/null +++ b/ModernKeePass10/ViewModels/ListItems/SettingsSaveViewModel.cs @@ -0,0 +1,24 @@ +using Autofac; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.ViewModels.ListItems +{ + public class SettingsSaveViewModel + { + private readonly ISettingsService _settings; + + public SettingsSaveViewModel() : this(App.Container.Resolve()) + { } + + public SettingsSaveViewModel(ISettingsService settings) + { + _settings = settings; + } + + public bool IsSaveSuspend + { + get => _settings.GetSetting("SaveSuspend", true); + set => _settings.PutSetting("SaveSuspend", value); + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/ViewModels/MainViewModel.cs b/ModernKeePass10/ViewModels/MainViewModel.cs new file mode 100644 index 0000000..cae3277 --- /dev/null +++ b/ModernKeePass10/ViewModels/MainViewModel.cs @@ -0,0 +1,30 @@ +using Windows.Storage; +using Autofac; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.ViewModels +{ + public class MainViewModel + { + private readonly IDatabaseService _databaseService; + private readonly IRecentService _recentService; + + public bool IsDatabaseOpened => _databaseService.IsOpen; + public bool HasRecentItems => _recentService.HasEntries; + + public string OpenedDatabaseName => _databaseService.Name; + public IStorageFile File { get; set; } + + public MainViewModel() + { + _databaseService = App.Container.Resolve(); + _recentService = App.Container.Resolve(); + } + + public MainViewModel(IDatabaseService databaseService, IRecentService recentService) + { + _databaseService = databaseService; + _recentService = recentService; + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/ViewModels/NewViewModel.cs b/ModernKeePass10/ViewModels/NewViewModel.cs new file mode 100644 index 0000000..97ba903 --- /dev/null +++ b/ModernKeePass10/ViewModels/NewViewModel.cs @@ -0,0 +1,99 @@ +using System; +using Windows.Storage; +using Windows.Storage.AccessCache; +using ModernKeePass.Converters; +using ModernKeePass.Domain.Entities; +using ModernKeePass.Domain.Enums; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.ViewModels +{ + public class NewViewModel : OpenViewModel + { + private string _importFormatHelp; + private readonly IDatabaseService _databaseService; + private readonly IImportService _importService; + private readonly ISettingsService _settingsService; + + public string Password { get; set; } + + public bool IsImportChecked { get; set; } + + public IStorageFile ImportFile { get; set; } + + public string ImportFileExtensionFilter { get; set; } = "*"; + + public ImportFormat ImportFormat { get; set; } + + public string ImportFormatHelp + { + get => _importFormatHelp; + set + { + _importFormatHelp = value; + OnPropertyChanged(nameof(ImportFormatHelp)); + } + } + + public NewViewModel() + { } + + public NewViewModel(IDatabaseService databaseService, IImportService importService, ISettingsService settingsService) + { + _databaseService = databaseService; + _importService = importService; + _settingsService = settingsService; + } + + public void PopulateInitialData() + { + if (_settingsService.GetSetting("Sample") && !IsImportChecked) CreateSampleData(_databaseService.RootGroupEntity); + else if (IsImportChecked && ImportFile != null) + { + var token = StorageApplicationPermissions.FutureAccessList.Add(ImportFile); + _importService.Import(ImportFormat, token, _databaseService.RootGroupEntity); + StorageApplicationPermissions.FutureAccessList.Remove(token); + } + } + + private void CreateSampleData(GroupEntity groupEntity) + { + var converter = new IconToSymbolConverter(); + + groupEntity.SubGroups.Add(new GroupEntity + { + Name = "Banking", + Icon = Icon.Calculator + }); + + groupEntity.SubGroups.Add(new GroupEntity + { + Name = "Email", + Icon = Icon.Mail + }); + + groupEntity.SubGroups.Add(new GroupEntity + { + Name = "Internet", + Icon = Icon.World + }); + + groupEntity.Entries.Add(new EntryEntity + { + Name = "Sample Entry", + UserName = "Username", + Url = new Uri("https://keepass.info"), + Password = "Password", + Notes = "You may safely delete this sample" + }); + + groupEntity.Entries.Add(new EntryEntity + { + Name = "Sample Entry #2", + UserName = "Michael321", + Url = new Uri("https://keepass.info/help/base/kb/testform.html"), + Password = "12345" + }); + } + } +} diff --git a/ModernKeePass10/ViewModels/Old/EntryVm.cs b/ModernKeePass10/ViewModels/Old/EntryVm.cs new file mode 100644 index 0000000..8c49ae6 --- /dev/null +++ b/ModernKeePass10/ViewModels/Old/EntryVm.cs @@ -0,0 +1,322 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Input; +using ModernKeePass.Common; +using ModernKeePass.Interfaces; +using ModernKeePass.Services; +using ModernKeePassLib; +using ModernKeePassLib.Cryptography.PasswordGenerator; +using ModernKeePassLib.Security; +using ModernKeePassLib.Cryptography; + +namespace ModernKeePass.ViewModels +{ + public class EntryVm : INotifyPropertyChanged, IPwEntity, ISelectableModel + { + public GroupVm ParentGroup { get; private set; } + public GroupVm PreviousGroup { get; private set; } + public bool IsRevealPasswordEnabled => !string.IsNullOrEmpty(Password); + public bool HasExpired => HasExpirationDate && _pwEntry.ExpiryTime < DateTime.Now; + public double PasswordComplexityIndicator => QualityEstimation.EstimatePasswordBits(Password?.ToCharArray()); + public bool UpperCasePatternSelected { get; set; } = true; + public bool LowerCasePatternSelected { get; set; } = true; + public bool DigitsPatternSelected { get; set; } = true; + public bool MinusPatternSelected { get; set; } + public bool UnderscorePatternSelected { get; set; } + public bool SpacePatternSelected { get; set; } + public bool SpecialPatternSelected { get; set; } + public bool BracketsPatternSelected { get; set; } + public string CustomChars { get; set; } = string.Empty; + public PwUuid IdUuid => _pwEntry?.Uuid; + public string Id => _pwEntry?.Uuid.ToHexString(); + public bool IsRecycleOnDelete => _database.IsRecycleBinEnabled && !ParentGroup.IsSelected; + public IEnumerable BreadCrumb => new List(ParentGroup.BreadCrumb) {ParentGroup}; + /// + /// Determines if the Entry is current or from history + /// + public bool IsSelected { get; set; } = true; + + public double PasswordLength + { + get => _passwordLength; + set + { + _passwordLength = value; + NotifyPropertyChanged("PasswordLength"); + } + } + + public string Name + { + get => GetEntryValue(PwDefs.TitleField); + set => SetEntryValue(PwDefs.TitleField, new ProtectedString(true, value)); + } + + + public string UserName + { + get => GetEntryValue(PwDefs.UserNameField); + set => SetEntryValue(PwDefs.UserNameField, new ProtectedString(true, value)); + } + + public string Password + { + get => GetEntryValue(PwDefs.PasswordField); + set + { + SetEntryValue(PwDefs.PasswordField, new ProtectedString(true, value)); + NotifyPropertyChanged("Password"); + NotifyPropertyChanged("PasswordComplexityIndicator"); + } + } + + public string Url + { + get => GetEntryValue(PwDefs.UrlField); + set => SetEntryValue(PwDefs.UrlField, new ProtectedString(true, value)); + } + + public string Notes + { + get => GetEntryValue(PwDefs.NotesField); + set => SetEntryValue(PwDefs.NotesField, new ProtectedString(true, value)); + } + + public int IconId + { + get + { + if (HasExpired) return (int) PwIcon.Expired; + if (_pwEntry?.IconId != null) return (int) _pwEntry?.IconId; + return -1; + } + set + { + HandleBackup(); + _pwEntry.IconId = (PwIcon)value; + } + } + + public DateTimeOffset ExpiryDate + { + get => new DateTimeOffset(_pwEntry.ExpiryTime.Date); + set + { + if (!HasExpirationDate) return; + HandleBackup(); + _pwEntry.ExpiryTime = value.DateTime; + } + } + + public TimeSpan ExpiryTime + { + get => _pwEntry.ExpiryTime.TimeOfDay; + set + { + if (!HasExpirationDate) return; + HandleBackup(); + _pwEntry.ExpiryTime = _pwEntry.ExpiryTime.Date.Add(value); + } + } + + public bool IsEditMode + { + get => IsSelected && _isEditMode; + set + { + _isEditMode = value; + NotifyPropertyChanged("IsEditMode"); + } + } + + public bool IsVisible + { + get => _isVisible; + set + { + _isVisible = value; + NotifyPropertyChanged("IsVisible"); + } + } + + public bool IsRevealPassword + { + get => _isRevealPassword; + set + { + _isRevealPassword = value; + NotifyPropertyChanged("IsRevealPassword"); + } + } + public bool HasExpirationDate + { + get => _pwEntry.Expires; + set + { + _pwEntry.Expires = value; + NotifyPropertyChanged("HasExpirationDate"); + } + } + + public IEnumerable History + { + get + { + var history = new Stack(); + foreach (var historyEntry in _pwEntry.History) + { + history.Push(new EntryVm(historyEntry, ParentGroup) {IsSelected = false}); + } + history.Push(this); + + return history; + } + } + + + public Color? BackgroundColor + { + get => _pwEntry?.BackgroundColor; + set + { + if (value != null) _pwEntry.BackgroundColor = (Color) value; + } + } + + public Color? ForegroundColor + { + get => _pwEntry?.ForegroundColor; + set + { + if (value != null) _pwEntry.ForegroundColor = (Color)value; + } + } + + public ICommand SaveCommand { get; } + public ICommand GeneratePasswordCommand { get; } + public ICommand UndoDeleteCommand { get; } + + public event PropertyChangedEventHandler PropertyChanged; + + private readonly PwEntry _pwEntry; + private readonly IDatabaseService _database; + private readonly IResourceService _resource; + private bool _isEditMode; + private bool _isDirty = true; + private bool _isRevealPassword; + private double _passwordLength = 25; + private bool _isVisible = true; + + private void NotifyPropertyChanged(string propertyName) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + public EntryVm() { } + + internal EntryVm(PwEntry entry, GroupVm parent) : this(entry, parent, DatabaseService.Instance, new ResourcesService()) { } + + public EntryVm(PwEntry entry, GroupVm parent, IDatabaseService database, IResourceService resource) + { + _database = database; + _resource = resource; + _pwEntry = entry; + ParentGroup = parent; + + SaveCommand = new RelayCommand(() => _database.Save()); + GeneratePasswordCommand = new RelayCommand(GeneratePassword); + UndoDeleteCommand = new RelayCommand(() => Move(PreviousGroup), () => PreviousGroup != null); + } + + public void GeneratePassword() + { + var pwProfile = new PwProfile + { + GeneratorType = PasswordGeneratorType.CharSet, + Length = (uint)PasswordLength, + CharSet = new PwCharSet() + }; + + if (UpperCasePatternSelected) pwProfile.CharSet.Add(PwCharSet.UpperCase); + if (LowerCasePatternSelected) pwProfile.CharSet.Add(PwCharSet.LowerCase); + if (DigitsPatternSelected) pwProfile.CharSet.Add(PwCharSet.Digits); + if (SpecialPatternSelected) pwProfile.CharSet.Add(PwCharSet.SpecialChars); + if (MinusPatternSelected) pwProfile.CharSet.Add('-'); + if (UnderscorePatternSelected) pwProfile.CharSet.Add('_'); + if (SpacePatternSelected) pwProfile.CharSet.Add(' '); + if (BracketsPatternSelected) pwProfile.CharSet.Add(PwCharSet.Brackets); + + pwProfile.CharSet.Add(CustomChars); + + ProtectedString password; + PwGenerator.Generate(out password, pwProfile, null, new CustomPwGeneratorPool()); + + SetEntryValue(PwDefs.PasswordField, password); + NotifyPropertyChanged("Password"); + NotifyPropertyChanged("IsRevealPasswordEnabled"); + NotifyPropertyChanged("PasswordComplexityIndicator"); + } + + + public void MarkForDelete(string recycleBinTitle) + { + if (_database.IsRecycleBinEnabled && _database.RecycleBin?.IdUuid == null) + _database.CreateRecycleBin(recycleBinTitle); + Move(_database.IsRecycleBinEnabled && !ParentGroup.IsSelected ? _database.RecycleBin : null); + } + + public void Move(GroupVm destination) + { + PreviousGroup = ParentGroup; + PreviousGroup.Entries.Remove(this); + if (destination == null) + { + _database.AddDeletedItem(IdUuid); + return; + } + ParentGroup = destination; + ParentGroup.Entries.Add(this); + } + + public void CommitDelete() + { + _pwEntry.ParentGroup.Entries.Remove(_pwEntry); + if (!_database.IsRecycleBinEnabled || PreviousGroup.IsSelected) _database.AddDeletedItem(IdUuid); + } + + public PwEntry GetPwEntry() + { + return _pwEntry; + } + public void Reset() + { + _isDirty = false; + } + + public override string ToString() + { + return IsSelected ? _resource.GetResourceValue("EntryCurrent") : _pwEntry.LastModificationTime.ToString("g"); + } + + private void HandleBackup() + { + if (_isDirty) return; + _pwEntry?.Touch(true); + _pwEntry?.CreateBackup(null); + _isDirty = true; + } + + private string GetEntryValue(string key) + { + return _pwEntry?.Strings.GetSafe(key).ReadString(); + } + + private void SetEntryValue(string key, ProtectedString newValue) + { + HandleBackup(); + _pwEntry?.Strings.Set(key, newValue); + } + } +} diff --git a/ModernKeePass10/ViewModels/Old/GroupVm.cs b/ModernKeePass10/ViewModels/Old/GroupVm.cs new file mode 100644 index 0000000..f3ba5c5 --- /dev/null +++ b/ModernKeePass10/ViewModels/Old/GroupVm.cs @@ -0,0 +1,257 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Input; +using ModernKeePass.Common; +using ModernKeePass.Interfaces; +using ModernKeePass.Services; +using ModernKeePassLib; + +namespace ModernKeePass.ViewModels +{ + public class GroupVm : NotifyPropertyChangedBase, IPwEntity, ISelectableModel + { + public GroupVm ParentGroup { get; private set; } + public GroupVm PreviousGroup { get; private set; } + + public ObservableCollection Entries + { + get => _entries; + private set => SetProperty(ref _entries, value); + } + + public IEnumerable SubEntries + { + get + { + var subEntries = new List(); + subEntries.AddRange(Entries); + foreach (var group in Groups) + { + subEntries.AddRange(group.SubEntries); + } + + return subEntries; + } + } + + public ObservableCollection Groups { get; set; } = new ObservableCollection(); + + public PwUuid IdUuid => _pwGroup?.Uuid; + public string Id => IdUuid?.ToHexString(); + public bool IsNotRoot => ParentGroup != null; + + public bool ShowRestore => IsNotRoot && ParentGroup.IsSelected; + + public bool IsRecycleOnDelete => _database.IsRecycleBinEnabled && !IsSelected && !ParentGroup.IsSelected; + + /// + /// Is the Group the database Recycle Bin? + /// + public bool IsSelected + { + get => _database != null && _database.IsRecycleBinEnabled && _database.RecycleBin?.Id == Id; + set + { + if (value && _pwGroup != null) _database.RecycleBin = this; + } + } + + public IOrderedEnumerable> EntriesZoomedOut => from e in Entries + group e by e.Name.ToUpper().FirstOrDefault() into grp + orderby grp.Key + select grp; + + public string Name + { + get => _pwGroup == null ? string.Empty : _pwGroup.Name; + set => _pwGroup.Name = value; + } + + public int IconId + { + get + { + if (_pwGroup?.IconId != null) return (int) _pwGroup?.IconId; + return -1; + } + set => _pwGroup.IconId = (PwIcon)value; + } + + public bool IsEditMode + { + get => _isEditMode; + set + { + SetProperty(ref _isEditMode, value); + ((RelayCommand)SortEntriesCommand).RaiseCanExecuteChanged(); + ((RelayCommand)SortGroupsCommand).RaiseCanExecuteChanged(); + } + } + + public bool IsMenuClosed + { + get => _isMenuClosed; + set => SetProperty(ref _isMenuClosed, value); + } + + public IEnumerable BreadCrumb + { + get + { + var groups = new Stack(); + var group = this; + while (group.ParentGroup != null) + { + group = group.ParentGroup; + groups.Push(group); + } + + return groups; + } + } + + public ICommand SaveCommand { get; } + public ICommand SortEntriesCommand { get; } + public ICommand SortGroupsCommand { get; } + public ICommand UndoDeleteCommand { get; } + + private readonly PwGroup _pwGroup; + private readonly IDatabaseService _database; + private bool _isEditMode; + private PwEntry _reorderedEntry; + private ObservableCollection _entries = new ObservableCollection(); + private bool _isMenuClosed = true; + + public GroupVm() {} + + internal GroupVm(PwGroup pwGroup, GroupVm parent, PwUuid recycleBinId = null) : this(pwGroup, parent, + DatabaseService.Instance, recycleBinId) + { } + + public GroupVm(PwGroup pwGroup, GroupVm parent, IDatabaseService database, PwUuid recycleBinId = null) + { + _pwGroup = pwGroup; + _database = database; + ParentGroup = parent; + + SaveCommand = new RelayCommand(() => _database.Save()); + SortEntriesCommand = new RelayCommand(async () => + await SortEntriesAsync().ConfigureAwait(false), () => IsEditMode); + SortGroupsCommand = new RelayCommand(async () => + await SortGroupsAsync().ConfigureAwait(false), () => IsEditMode); + UndoDeleteCommand = new RelayCommand(() => Move(PreviousGroup), () => PreviousGroup != null); + + if (recycleBinId != null && _pwGroup.Uuid.Equals(recycleBinId)) _database.RecycleBin = this; + Entries = new ObservableCollection(pwGroup.Entries.Select(e => new EntryVm(e, this))); + Entries.CollectionChanged += Entries_CollectionChanged; + Groups = new ObservableCollection(pwGroup.Groups.Select(g => new GroupVm(g, this, recycleBinId))); + } + + private void Entries_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Remove: + var oldIndex = (uint) e.OldStartingIndex; + _reorderedEntry = _pwGroup.Entries.GetAt(oldIndex); + _pwGroup.Entries.RemoveAt(oldIndex); + break; + case NotifyCollectionChangedAction.Add: + if (_reorderedEntry == null) _pwGroup.AddEntry(((EntryVm) e.NewItems[0]).GetPwEntry(), true); + else _pwGroup.Entries.Insert((uint)e.NewStartingIndex, _reorderedEntry); + break; + } + } + + public GroupVm AddNewGroup(string name = "") + { + var pwGroup = new PwGroup(true, true, name, PwIcon.Folder); + _pwGroup.AddGroup(pwGroup, true); + var newGroup = new GroupVm(pwGroup, this) {Name = name, IsEditMode = string.IsNullOrEmpty(name)}; + Groups.Add(newGroup); + return newGroup; + } + + public EntryVm AddNewEntry() + { + var pwEntry = new PwEntry(true, true); + var newEntry = new EntryVm(pwEntry, this) {IsEditMode = true}; + newEntry.GeneratePassword(); + Entries.Add(newEntry); + return newEntry; + } + + public void MarkForDelete(string recycleBinTitle) + { + if (_database.IsRecycleBinEnabled && _database.RecycleBin?.IdUuid == null) + _database.CreateRecycleBin(recycleBinTitle); + Move(_database.IsRecycleBinEnabled && !IsSelected ? _database.RecycleBin : null); + ((RelayCommand)UndoDeleteCommand).RaiseCanExecuteChanged(); + } + + public void UndoDelete() + { + Move(PreviousGroup); + } + + public void Move(GroupVm destination) + { + PreviousGroup = ParentGroup; + PreviousGroup.Groups.Remove(this); + PreviousGroup._pwGroup.Groups.Remove(_pwGroup); + if (destination == null) + { + _database.AddDeletedItem(IdUuid); + return; + } + ParentGroup = destination; + ParentGroup.Groups.Add(this); + ParentGroup._pwGroup.AddGroup(_pwGroup, true); + } + + public void CommitDelete() + { + _pwGroup.ParentGroup.Groups.Remove(_pwGroup); + if (_database.IsRecycleBinEnabled && !PreviousGroup.IsSelected) _database.RecycleBin._pwGroup.AddGroup(_pwGroup, true); + else _database.AddDeletedItem(IdUuid); + } + + public override string ToString() + { + return Name; + } + + private async Task SortEntriesAsync() + { + var comparer = new PwEntryComparer(PwDefs.TitleField, true, false); + try + { + _pwGroup.Entries.Sort(comparer); + Entries = new ObservableCollection(Entries.OrderBy(e => e.Name)); + } + catch (Exception e) + { + await MessageDialogHelper.ShowErrorDialog(e); + } + } + + private async Task SortGroupsAsync() + { + try + { + _pwGroup.SortSubGroups(false); + Groups = new ObservableCollection(Groups.OrderBy(g => g.Name).ThenBy(g => g._pwGroup == null)); + OnPropertyChanged("Groups"); + } + catch (Exception e) + { + await MessageDialogHelper.ShowErrorDialog(e); + } + } + + } +} diff --git a/ModernKeePass10/ViewModels/OpenViewModel.cs b/ModernKeePass10/ViewModels/OpenViewModel.cs new file mode 100644 index 0000000..87189bc --- /dev/null +++ b/ModernKeePass10/ViewModels/OpenViewModel.cs @@ -0,0 +1,44 @@ +using System.Threading.Tasks; +using Autofac; +using ModernKeePass.Domain.AOP; +using ModernKeePass.Domain.Dtos; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.ViewModels +{ + public class OpenViewModel: NotifyPropertyChangedBase + { + private readonly IRecentService _recentService; + private string _name; + private string _databaseFilePath; + + public bool IsFileSelected => !string.IsNullOrEmpty(DatabaseFilePath); + + public string Name + { + get => _name; + private set => SetProperty(ref _name, value); + } + + public string DatabaseFilePath + { + get => _databaseFilePath; + private set => SetProperty(ref _databaseFilePath, value); + } + + public OpenViewModel(): this(App.Container.Resolve()) + { } + public OpenViewModel(IRecentService recentService) + { + _recentService = recentService; + } + + public async Task OpenFile(FileInfo fileInfo) + { + Name = fileInfo.Name; + DatabaseFilePath = fileInfo.Path; + OnPropertyChanged(nameof(IsFileSelected)); + await _recentService.Add(fileInfo); + } + } +} diff --git a/ModernKeePass10/ViewModels/RecentViewModel.cs b/ModernKeePass10/ViewModels/RecentViewModel.cs new file mode 100644 index 0000000..bea32a6 --- /dev/null +++ b/ModernKeePass10/ViewModels/RecentViewModel.cs @@ -0,0 +1,69 @@ +using System.Collections.ObjectModel; +using System.Linq; +using System.Windows.Input; +using Autofac; +using ModernKeePass.Application.Common.Interfaces; +using ModernKeePass.Common; +using ModernKeePass.Domain.AOP; +using ModernKeePass.Domain.Interfaces; +using ModernKeePass.ViewModels.ListItems; + +namespace ModernKeePass.ViewModels +{ + public class RecentViewModel : NotifyPropertyChangedBase, IHasSelectableObject + { + private readonly IRecentService _recentService; + private ISelectableModel _selectedItem; + private ObservableCollection _recentItems = new ObservableCollection(); + + public ObservableCollection RecentItems + { + get => _recentItems; + set => SetProperty(ref _recentItems, value); + } + + public ISelectableModel SelectedItem + { + get => _selectedItem; + set + { + if (_selectedItem == value) return; + if (_selectedItem != null) + { + _selectedItem.IsSelected = false; + } + + SetProperty(ref _selectedItem, value); + + if (_selectedItem == null) return; + _selectedItem.IsSelected = true; + } + } + + public ICommand ClearAllCommand { get; } + + public RecentViewModel() : this (App.Container.Resolve()) + { } + + public RecentViewModel(IRecentService recentService) + { + _recentService = recentService; + ClearAllCommand = new RelayCommand(ClearAll); + + RecentItems = new ObservableCollection( + _recentService.GetAll().GetAwaiter().GetResult().Select(r => new RecentItemViewModel + { + Name = r.Name, + Token = r.Path + }) + ); + if (RecentItems.Count > 0) SelectedItem = RecentItems[0]; + } + + private void ClearAll() + { + _recentService.ClearAll(); + RecentItems.Clear(); + } + } +} diff --git a/ModernKeePass10/ViewModels/SaveViewModel.cs b/ModernKeePass10/ViewModels/SaveViewModel.cs new file mode 100644 index 0000000..21e7cba --- /dev/null +++ b/ModernKeePass10/ViewModels/SaveViewModel.cs @@ -0,0 +1,31 @@ +using Autofac; +using ModernKeePass.Domain.Dtos; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.ViewModels +{ + public class SaveViewModel + { + private readonly IDatabaseService _database; + public SaveViewModel() : this(App.Container.Resolve()) { } + + public SaveViewModel(IDatabaseService database) + { + _database = database; + } + + public void Save(bool close = true) + { + _database.Save(); + if (close) _database.Close(); + } + + public void Save(string token) + { + _database.SaveAs(new FileInfo + { + Path = token + }); + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/ViewModels/SettingsViewModel.cs b/ModernKeePass10/ViewModels/SettingsViewModel.cs new file mode 100644 index 0000000..dae2d66 --- /dev/null +++ b/ModernKeePass10/ViewModels/SettingsViewModel.cs @@ -0,0 +1,20 @@ +using Autofac; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.ViewModels +{ + public class SettingsViewModel + { + private readonly IDatabaseService _database; + + public bool IsDatabaseOpened => _database != null && _database.IsOpen; + + public SettingsViewModel() : this(App.Container.Resolve()) + { } + + public SettingsViewModel(IDatabaseService database) + { + _database = database; + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/ViewModels/UserControls/CredentialsViewModel.cs b/ModernKeePass10/ViewModels/UserControls/CredentialsViewModel.cs new file mode 100644 index 0000000..9c7927c --- /dev/null +++ b/ModernKeePass10/ViewModels/UserControls/CredentialsViewModel.cs @@ -0,0 +1,149 @@ +using System; +using System.Text; +using System.Threading.Tasks; +using Autofac; +using ModernKeePass.Domain.AOP; +using ModernKeePass.Domain.Dtos; +using ModernKeePass.Domain.Enums; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.ViewModels +{ + public class CredentialsViewModel: NotifyPropertyChangedBase + { + + private bool _hasPassword; + private bool _hasKeyFile; + private bool _hasUserAccount; + private bool _isOpening; + private string _password = string.Empty; + private string _status; + private CredentialStatusTypes _statusType; + private string _keyFilePath = string.Empty; + private string _keyFileText; + private readonly IResourceService _resourceService; + private readonly IDatabaseService _databaseService; + + public bool HasPassword + { + get => _hasPassword; + set + { + SetProperty(ref _hasPassword, value); + OnPropertyChanged(nameof(IsValid)); + } + } + + public bool HasKeyFile + { + get => _hasKeyFile; + set + { + SetProperty(ref _hasKeyFile, value); + OnPropertyChanged(nameof(IsValid)); + } + } + + public bool HasUserAccount + { + get => _hasUserAccount; + set + { + SetProperty(ref _hasUserAccount, value); + OnPropertyChanged(nameof(IsValid)); + } + } + + public bool IsValid => !_isOpening && (HasPassword || HasKeyFile && KeyFilePath != string.Empty || HasUserAccount); + + public string Status + { + get => _status; + set => SetProperty(ref _status, value); + } + + public int StatusType + { + get => (int)_statusType; + set => SetProperty(ref _statusType, (CredentialStatusTypes)value); + } + + public string Password + { + get => _password; + set + { + _password = value; + StatusType = (int)CredentialStatusTypes.Normal; + Status = string.Empty; + } + } + + public string KeyFilePath + { + get => _keyFilePath; + set + { + _keyFilePath = value; + OnPropertyChanged(nameof(IsValid)); + } + } + + public string KeyFileText + { + get => _keyFileText; + set => SetProperty(ref _keyFileText, value); + } + + + public CredentialsViewModel() : this(App.Container.Resolve(), App.Container.Resolve()) { } + + public CredentialsViewModel(IDatabaseService databaseService, IResourceService resourceService) + { + _databaseService = databaseService; + _resourceService = resourceService; + _keyFileText = _resourceService.GetResourceValue("CompositeKeyDefaultKeyFile"); + } + + public async Task OpenDatabase(FileInfo fileInfo) + { + try + { + _isOpening = true; + OnPropertyChanged(nameof(IsValid)); + var credentials = new Credentials + { + KeyFilePath = HasKeyFile ? KeyFilePath : string.Empty, + Password = HasPassword ? Password : string.Empty + }; + await Task.Run(() => _databaseService.Open(fileInfo, credentials)); + return true; + } + catch (ArgumentException) + { + var errorMessage = new StringBuilder($"{_resourceService.GetResourceValue("CompositeKeyErrorOpen")}\n"); + if (HasPassword) errorMessage.AppendLine(_resourceService.GetResourceValue("CompositeKeyErrorUserPassword")); + if (HasKeyFile) errorMessage.AppendLine(_resourceService.GetResourceValue("CompositeKeyErrorUserKeyFile")); + if (HasUserAccount) errorMessage.AppendLine(_resourceService.GetResourceValue("CompositeKeyErrorUserAccount")); + UpdateStatus(errorMessage.ToString(), CredentialStatusTypes.Error); + } + catch (Exception e) + { + var error = $"{_resourceService.GetResourceValue("CompositeKeyErrorOpen")}{e.Message}"; + UpdateStatus(error, CredentialStatusTypes.Error); + } + finally + { + _isOpening = false; + OnPropertyChanged(nameof(IsValid)); + } + return false; + } + + private void UpdateStatus(string text, CredentialStatusTypes type) + { + Status = text; + StatusType = (int)type; + } + } +} diff --git a/ModernKeePass10/ViewModels/UserControls/UpdateCredentialsViewModel.cs b/ModernKeePass10/ViewModels/UserControls/UpdateCredentialsViewModel.cs new file mode 100644 index 0000000..3ec7fbe --- /dev/null +++ b/ModernKeePass10/ViewModels/UserControls/UpdateCredentialsViewModel.cs @@ -0,0 +1,93 @@ +using Autofac; +using System; +using System.Threading.Tasks; +using ModernKeePass.Domain.AOP; +using ModernKeePass.Domain.Dtos; +using ModernKeePass.Domain.Enums; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.ViewModels +{ + public class UpdateCredentialsViewModel : NotifyPropertyChangedBase + { + private readonly ISecurityService _securityService; + private bool _hasPassword; + private bool _hasKeyFile; + private bool _hasUserAccount; + private string _confirmPassword; + private string _password; + private string _keyFileText; + private string _status; + private CredentialStatusTypes _statusType; + + public string Password + { + get => _password; + set + { + SetProperty(ref _password, value); + OnPropertyChanged(nameof(IsValid)); + } + } + + public string ConfirmPassword + { + get => _confirmPassword; + set => SetProperty(ref _confirmPassword, value); + } + + public string KeyFilePath { get; set; } + + public bool HasPassword + { + get => _hasPassword; + set => SetProperty(ref _hasPassword, value); + } + + public bool HasKeyFile + { + get => _hasKeyFile; + set => SetProperty(ref _hasKeyFile, value); + } + + public bool HasUserAccount + { + get => _hasUserAccount; + set => SetProperty(ref _hasUserAccount, value); + } + + public string KeyFileText + { + get => _keyFileText; + set => SetProperty(ref _keyFileText, value); + } + + public string Status + { + get => _status; + set => SetProperty(ref _status, value); + } + + public int StatusType + { + get => (int)_statusType; + set => SetProperty(ref _statusType, (CredentialStatusTypes)value); + } + + public double PasswordComplexityIndicator => _securityService.EstimatePasswordComplexity(Password); + + public bool IsValid => HasPassword && Password == ConfirmPassword || HasKeyFile && KeyFilePath != string.Empty || HasUserAccount; + + public UpdateCredentialsViewModel(): this(App.Container.Resolve()) { } + + public UpdateCredentialsViewModel(ISecurityService securityService) + { + _securityService = securityService; + } + + internal Task CreateDatabase(FileInfo fileInfo) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Views/BasePages/LayoutAwarePageBase.cs b/ModernKeePass10/Views/BasePages/LayoutAwarePageBase.cs new file mode 100644 index 0000000..080d09a --- /dev/null +++ b/ModernKeePass10/Views/BasePages/LayoutAwarePageBase.cs @@ -0,0 +1,206 @@ +using System; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Navigation; +using ModernKeePass.Application.Common.Interfaces; +using ModernKeePass.Common; +using ModernKeePass.Domain.Interfaces; + +namespace ModernKeePass.Views.BasePages +{ + public class LayoutAwarePageBase: Page + { + /// + /// NavigationHelper is used on each page to aid in navigation and + /// process lifetime management + /// + public NavigationHelper NavigationHelper { get; } + + public ListView ListView { get; set; } + public virtual CollectionViewSource ListViewSource { get; set; } + public virtual IHasSelectableObject Model { get; set; } + + public LayoutAwarePageBase() + { + // Setup the navigation helper + NavigationHelper = new NavigationHelper(this); + NavigationHelper.LoadState += navigationHelper_LoadState; + NavigationHelper.SaveState += navigationHelper_SaveState; + + // Setup the logical page navigation components that allow + // the page to only show one pane at a time. + NavigationHelper.GoBackCommand = new RelayCommand(GoBack, CanGoBack); + + // Start listening for Window size changes + // to change from showing two panes to showing a single pane + Window.Current.SizeChanged += Window_SizeChanged; + InvalidateVisualState(); + } + + protected void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + // Invalidate the view state when logical page navigation is in effect, as a change + // in selection may cause a corresponding change in the current logical page. When + // an item is selected this has the effect of changing from displaying the item list + // to showing the selected item's details. When the selection is cleared this has the + // opposite effect. + if (!UsingLogicalPageNavigation()) return; + NavigationHelper.GoBackCommand.RaiseCanExecuteChanged(); + InvalidateVisualState(); + } + + /// + /// Populates the page with content passed during navigation. Any saved state is also + /// provided when recreating a page from a prior session. + /// + /// + /// The source of the event; typically + /// + /// Event data that provides both the navigation parameter passed to + /// when this page was initially requested and + /// a dictionary of state preserved by this page during an earlier + /// session. The state will be null the first time a page is visited. + protected void navigationHelper_LoadState(object sender, LoadStateEventArgs e) + { + if (e.PageState == null) + { + // When this is a new page, select the first item automatically unless logical page + // navigation is being used (see the logical page navigation #region below.) + if (!UsingLogicalPageNavigation()) + { + ListViewSource.View?.MoveCurrentToFirst(); + } + } + else + { + // Restore the previously saved state associated with this page + if (e.PageState.ContainsKey("SelectedItem")) + { + ListViewSource.View?.MoveCurrentTo(e.PageState["SelectedItem"]); + } + } + } + + /// + /// Preserves state associated with this page in case the application is suspended or the + /// page is discarded from the navigation cache. Values must conform to the serialization + /// requirements of . + /// + /// The source of the event; typically + /// Event data that provides an empty dictionary to be populated with + /// serializable state. + protected void navigationHelper_SaveState(object sender, SaveStateEventArgs e) + { + if (ListViewSource.View != null) + { + e.PageState["SelectedItem"] = Model?.SelectedItem; + } + } + + #region Logical page navigation + + // The split page is designed so that when the Window does have enough space to show + // both the list and the details, only one pane will be shown at at time. + // + // This is all implemented with a single physical page that can represent two logical + // pages. The code below achieves this goal without making the user aware of the + // distinction. + + protected const int MinimumWidthForSupportingTwoPanes = 768; + + /// + /// Invoked to determine whether the page should act as one logical page or two. + /// + /// True if the window should show act as one logical page, false + /// otherwise. + protected bool UsingLogicalPageNavigation() + { + return Window.Current.Bounds.Width < MinimumWidthForSupportingTwoPanes; + } + + /// + /// Invoked with the Window changes size + /// + /// The current Window + /// Event data that describes the new size of the Window + protected void Window_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e) + { + InvalidateVisualState(); + } + + protected bool CanGoBack() + { + if (UsingLogicalPageNavigation() && ListView.SelectedItem != null) + { + return true; + } + return NavigationHelper.CanGoBack(); + } + protected void GoBack() + { + if (UsingLogicalPageNavigation() && ListView.SelectedItem != null) + { + // When logical page navigation is in effect and there's a selected item that + // item's details are currently displayed. Clearing the selection will return to + // the item list. From the user's point of view this is a logical backward + // navigation. + ListView.SelectedItem = null; + } + else + { + NavigationHelper.GoBack(); + } + } + + protected void InvalidateVisualState() + { + var visualState = DetermineVisualState(); + VisualStateManager.GoToState(this, visualState, false); + NavigationHelper.GoBackCommand.RaiseCanExecuteChanged(); + } + + /// + /// Invoked to determine the name of the visual state that corresponds to an application + /// view state. + /// + /// The name of the desired visual state. This is the same as the name of the + /// view state except when there is a selected item in portrait and snapped views where + /// this additional logical page is represented by adding a suffix of _Detail. + protected string DetermineVisualState() + { + if (!UsingLogicalPageNavigation()) + return "PrimaryView"; + + // Update the back button's enabled state when the view state changes + var logicalPageBack = UsingLogicalPageNavigation() && ListView?.SelectedItem != null; + + return logicalPageBack ? "SinglePane_Detail" : "SinglePane"; + } + + #endregion + + #region NavigationHelper registration + + /// The methods provided in this section are simply used to allow + /// NavigationHelper to respond to the page's navigation methods. + /// + /// Page specific logic should be placed in event handlers for the + /// + /// and . + /// The navigation parameter is available in the LoadState method + /// in addition to page state preserved during an earlier session. + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + NavigationHelper.OnNavigatedTo(e); + } + + protected override void OnNavigatedFrom(NavigationEventArgs e) + { + NavigationHelper.OnNavigatedFrom(e); + } + + #endregion + } +} diff --git a/ModernKeePass10/Views/EntriesPage.xaml b/ModernKeePass10/Views/EntriesPage.xaml new file mode 100644 index 0000000..8c84057 --- /dev/null +++ b/ModernKeePass10/Views/EntriesPage.xaml @@ -0,0 +1,266 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/EntriesPage.xaml.cs b/ModernKeePass10/Views/EntriesPage.xaml.cs new file mode 100644 index 0000000..65cb117 --- /dev/null +++ b/ModernKeePass10/Views/EntriesPage.xaml.cs @@ -0,0 +1,94 @@ +using System; +using Windows.System; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Navigation; +using Autofac; +using ModernKeePass.Domain.Interfaces; +using ModernKeePass.ViewModels; +using ModernKeePass.ViewModels.ListItems; + +// TODO: check https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlListView/cs/Samples/MasterDetailSelection +namespace ModernKeePass.Views +{ + public partial class EntriesPage + { + private readonly IDatabaseService _databaseService; + private readonly IResourceService _resourceService; + public EntriesViewModel ViewModel { get; set; } + + public EntriesPage(): this(App.Container.Resolve(), App.Container.Resolve()) + { } + + public EntriesPage(IDatabaseService databaseService, IResourceService resourceService) + { + _databaseService = databaseService; + _resourceService = resourceService; + InitializeComponent(); + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + if (e.Parameter is GroupItemViewModel group) ViewModel = new EntriesViewModel(group); + } + + private async void DeleteFlyoutItem_OnClick(object sender, RoutedEventArgs e) + { + if (sender is MenuFlyoutItem flyout) + { + var item = (EntryItemViewModel)flyout.DataContext; + + var deleteFileDialog = new ContentDialog + { + Title = $"{_resourceService.GetResourceValue("EntityDeleteActionButton")} {item.Name} ?", + Content = _databaseService.IsRecycleBinEnabled + ? _resourceService.GetResourceValue("EntryRecyclingConfirmation") + : _resourceService.GetResourceValue("EntryDeletingConfirmation"), + PrimaryButtonText = _resourceService.GetResourceValue("EntityDeleteActionButton"), + CloseButtonText = _resourceService.GetResourceValue("EntityDeleteCancelButton") + }; + + var result = await deleteFileDialog.ShowAsync(); + + // Delete the file if the user clicked the primary button. + // Otherwise, do nothing. + // TODO: move this logic to the service + if (result == ContentDialogResult.Primary) + { + ViewModel.Entries.Remove(item); + } + } + } + + private void NewEntryNameTextBox_OnKeyDown(object sender, KeyRoutedEventArgs e) + { + if (e.Key == VirtualKey.Enter) + { + e.Handled = true; + var text = NewEntryNameTextBox.Text; + if (string.IsNullOrEmpty(text)) return; + ViewModel.AddNewEntry(text); + AddEntryButton.IsChecked = false; + } + else if (e.Key == VirtualKey.Escape) + { + AddEntryButton.IsChecked = false; + } + } + + private void ColorPickerBackground_LostFocus(object sender, RoutedEventArgs e) + { + if (sender is ColorPicker colorPicker) ((EntryItemViewModel) colorPicker.DataContext).BackgroundColor = colorPicker.Color; + } + private void ColorPickerForeground_LostFocus(object sender, RoutedEventArgs e) + { + if (sender is ColorPicker colorPicker) ((EntryItemViewModel) colorPicker.DataContext).ForegroundColor = colorPicker.Color; + } + + private void HistoryListView_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Views/EntryPage.xaml b/ModernKeePass10/Views/EntryPage.xaml new file mode 100644 index 0000000..926c583 --- /dev/null +++ b/ModernKeePass10/Views/EntryPage.xaml @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/EntryPage.xaml.cs b/ModernKeePass10/Views/EntryPage.xaml.cs new file mode 100644 index 0000000..5be680f --- /dev/null +++ b/ModernKeePass10/Views/EntryPage.xaml.cs @@ -0,0 +1,21 @@ +using Windows.UI.Xaml.Navigation; +using ModernKeePass.ViewModels.ListItems; + +namespace ModernKeePass.Views +{ + public partial class EntryPage + { + public EntryItemViewModel ViewModel { get; set; } + + public EntryPage() + { + InitializeComponent(); + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + if (e.Parameter is EntryItemViewModel entry) ViewModel = entry; + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Views/GroupsPage.xaml b/ModernKeePass10/Views/GroupsPage.xaml new file mode 100644 index 0000000..3487413 --- /dev/null +++ b/ModernKeePass10/Views/GroupsPage.xaml @@ -0,0 +1,249 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/GroupsPage.xaml.cs b/ModernKeePass10/Views/GroupsPage.xaml.cs new file mode 100644 index 0000000..6958db3 --- /dev/null +++ b/ModernKeePass10/Views/GroupsPage.xaml.cs @@ -0,0 +1,194 @@ +using System; +using System.Linq; +using Windows.ApplicationModel.Core; +using Windows.System; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Navigation; +using Autofac; +using ModernKeePass.Domain.Entities; +using ModernKeePass.Domain.Interfaces; +using ModernKeePass.ViewModels.ListItems; +using ModernKeePass.ViewModels; + +namespace ModernKeePass.Views +{ + public partial class GroupsPage + { + private readonly IDatabaseService _databaseService; + private readonly IResourceService _resourceService; + + public GroupsViewModel ViewModel { get; set; } + + public GroupsPage(): this(App.Container.Resolve(), App.Container.Resolve()) + { } + + public GroupsPage(IDatabaseService databaseService, IResourceService resourceService) + { + InitializeComponent(); + SetTitleBar(); + _databaseService = databaseService; + _resourceService = resourceService; + } + + private void SetTitleBar() + { + var coreTitleBar = CoreApplication.GetCurrentView().TitleBar; + //coreTitleBar.LayoutMetricsChanged += CoreTitleBar_LayoutMetricsChanged; + //coreTitleBar.IsVisibleChanged += CoreTitleBar_IsVisibleChanged; + coreTitleBar.ExtendViewIntoTitleBar = false; + //UpdateTitleBarLayout(coreTitleBar); + + // Set XAML element as a draggable region. + //Window.Current.SetTitleBar(AppTitleBar); + } + + /*private void CoreTitleBar_IsVisibleChanged(CoreApplicationViewTitleBar sender, object args) => + AppTitleBar.Visibility = sender.IsVisible ? Visibility.Visible : Visibility.Collapsed; + + private void CoreTitleBar_LayoutMetricsChanged(CoreApplicationViewTitleBar coreTitleBar, object args) => UpdateTitleBarLayout(coreTitleBar); + + private void UpdateTitleBarLayout(CoreApplicationViewTitleBar coreTitleBar) + { + // Get the size of the caption controls area and back button + // (returned in logical pixels), and move your content around as necessary. + LeftPaddingColumn.Width = new GridLength(coreTitleBar.SystemOverlayLeftInset); + RightPaddingColumn.Width = new GridLength(coreTitleBar.SystemOverlayRightInset); + //BackBorder.Margin = new Thickness(0, 0, coreTitleBar.SystemOverlayLeftInset, 0); + AutoSuggestBox.Margin = new Thickness(0, 5, coreTitleBar.SystemOverlayRightInset, 5); + + // Update title bar control size as needed to account for system size changes. + //AppTitleBar.Height = coreTitleBar.Height; + AppTitleBar.Height = 44; + }*/ + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + if (!(e.Parameter is GroupEntity group)) group = _databaseService.RootGroupEntity; + ViewModel = new GroupsViewModel(group); + } + + private void HamburgerButton_OnClick(object sender, RoutedEventArgs e) + { + //SplitView.IsPaneOpen = !SplitView.IsPaneOpen; + switch (SplitView.DisplayMode) + { + case SplitViewDisplayMode.Inline: + SplitView.DisplayMode = SplitViewDisplayMode.CompactInline; + break; + case SplitViewDisplayMode.CompactInline: + SplitView.DisplayMode = SplitViewDisplayMode.Inline; + break; + } + } + + private void BackButton_OnClick(object sender, RoutedEventArgs e) + { + if (Frame.CanGoBack) + { + Frame.GoBack(); + } + } + + private void NavigationTree_OnItemInvoked(TreeView sender, TreeViewItemInvokedEventArgs args) + { + if (args.InvokedItem is GroupItemViewModel group) + { + ViewModel.Title = group.Text; + SplitViewFrame.Navigate(typeof(EntriesPage), group); + } + } + + private void RenameFlyoutItem_OnClick(object sender, RoutedEventArgs e) + { + if (sender is MenuFlyoutItem flyout) ((GroupItemViewModel)flyout.DataContext).IsEditMode = true; + } + + private async void DeleteFlyoutItem_OnClick(object sender, RoutedEventArgs e) + { + if (sender is MenuFlyoutItem flyout) + { + var item = (GroupItemViewModel) flyout.DataContext; + + var deleteFileDialog = new ContentDialog + { + Title = $"{_resourceService.GetResourceValue("EntityDeleteActionButton")} {item.Text} ?", + Content = _databaseService.IsRecycleBinEnabled + ? _resourceService.GetResourceValue("GroupRecyclingConfirmation") + : _resourceService.GetResourceValue("GroupDeletingConfirmation"), + PrimaryButtonText = _resourceService.GetResourceValue("EntityDeleteActionButton"), + CloseButtonText = _resourceService.GetResourceValue("EntityDeleteCancelButton") + }; + + var result = await deleteFileDialog.ShowAsync(); + + // Delete the file if the user clicked the primary button. + // Otherwise, do nothing. + // TODO: move this logic to the service + if (result == ContentDialogResult.Primary) + { + item.ParentViewModel.Children.Remove(item); + // TODO: refresh treeview + } + } + } + + private void GroupNameTextBox_KeyDown(object sender, KeyRoutedEventArgs e) + { + if (e.Key == VirtualKey.Enter) GroupNameTextBox_OnLostFocus(sender, null); + } + + private void GroupNameTextBox_OnLostFocus(object sender, RoutedEventArgs e) + { + if (sender is TextBox textBox) ((GroupItemViewModel)textBox.DataContext).IsEditMode = false; + } + + private void NewGroupNameTextBox_KeyDown(object sender, KeyRoutedEventArgs e) + { + if (e.Key == VirtualKey.Enter) + { + e.Handled = true; + var text = ((TextBox)sender).Text; + if (string.IsNullOrEmpty(text)) return; + ViewModel.AddNewGroup(text); + AddButton.IsEnabled = true; + NewGroupNameTextBox.Visibility = Visibility.Collapsed; + NewGroupNameTextBox.Text = string.Empty; + } + } + + private void AutoSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args) + { + // Only get results when it was a user typing, + // otherwise assume the value got filled in by TextMemberPath + // or the handler for SuggestionChosen. + if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput) + { + //Set the ItemsSource to be your filtered dataset + //sender.ItemsSource = dataset; + sender.ItemsSource = ViewModel.RootItemViewModel.SubEntries.Where(e => e.Name.IndexOf(sender.Text, StringComparison.OrdinalIgnoreCase) >= 0); + } + } + + private void AutoSuggestBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) + { + if (args.ChosenSuggestion != null) + { + // User selected an item from the suggestion list, take an action on it here. + } + else + { + // Use args.QueryText to determine what to do. + } + } + + private void NewGroupNameTextBox_LostFocus(object sender, RoutedEventArgs e) + { + if (string.IsNullOrEmpty(NewGroupNameTextBox.Text)) + { + NewGroupNameTextBox.Visibility = Visibility.Collapsed; + } + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Views/MainPage10.xaml b/ModernKeePass10/Views/MainPage10.xaml new file mode 100644 index 0000000..9497bee --- /dev/null +++ b/ModernKeePass10/Views/MainPage10.xaml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/MainPage10.xaml.cs b/ModernKeePass10/Views/MainPage10.xaml.cs new file mode 100644 index 0000000..6d7a10f --- /dev/null +++ b/ModernKeePass10/Views/MainPage10.xaml.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Windows.ApplicationModel.Core; +using Windows.Storage; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Navigation; +using MUXC = Microsoft.UI.Xaml.Controls; +using ModernKeePass.ViewModels; + +namespace ModernKeePass.Views +{ + public partial class MainPage10 + { + private MainViewModel ViewModel { get; } + + private readonly IList<(string Tag, Type Page)> _pages = new List<(string Tag, Type Page)> + { + ("welcome", typeof(WelcomePage)), + ("open", typeof(OpenDatabasePage)), + ("new", typeof(NewDatabasePage)), + ("save", typeof(SaveDatabasePage)), + ("recent", typeof(RecentDatabasesPage)), + ("about", typeof(AboutPage)), + ("donate", typeof(DonatePage)), + ("database", typeof(GroupsPage)) + }; + + public MainPage10() + { + InitializeComponent(); + ViewModel = new MainViewModel(); + SetTitleBar(); + } + + private void SetTitleBar() + { + var coreTitleBar = CoreApplication.GetCurrentView().TitleBar; + coreTitleBar.ExtendViewIntoTitleBar = true; + Window.Current.SetTitleBar(AppTitleBar); + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + ViewModel.File = e.Parameter as StorageFile; + } + + private void NavigationView_OnItemInvoked(MUXC.NavigationView navigationView, MUXC.NavigationViewItemInvokedEventArgs args) + { + if (args.IsSettingsInvoked) + Frame.Navigate(typeof(SettingsPage10)); + else + { + // Getting the Tag from Content (args.InvokedItem is the content of NavigationViewItem) + var navItem = NavigationView.MenuItems + .OfType() + .First(i => args.InvokedItem.Equals(i.Content)); + + NavigationView_Navigate(navItem); + } + } + + private void NavigationView_Navigate(MUXC.NavigationViewItem navItem, object parameter = null) + { + var (_, page) = _pages.First(p => p.Tag.Equals(navItem.Tag)); + NavigationView.Header = navItem.Content; + ContentFrame.Navigate(page, parameter); + } + + private void NavigationView_OnLoaded(object sender, RoutedEventArgs e) + { + object parameter = null; + if (ViewModel.IsDatabaseOpened) + { + NavigationView.SelectedItem = Save; + parameter = Frame; + } + else if (ViewModel.File != null) + { + NavigationView.SelectedItem = Open; + parameter = ViewModel.File; + } + else if (ViewModel.HasRecentItems) + { + NavigationView.SelectedItem = Recent; + } + else + { + NavigationView.SelectedItem = Welcome; + } + NavigationView_Navigate((MUXC.NavigationViewItem)NavigationView.SelectedItem, parameter); + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Views/MainPageFrames/AboutPage.xaml b/ModernKeePass10/Views/MainPageFrames/AboutPage.xaml new file mode 100644 index 0000000..6f11d7b --- /dev/null +++ b/ModernKeePass10/Views/MainPageFrames/AboutPage.xaml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/MainPageFrames/AboutPage.xaml.cs b/ModernKeePass10/Views/MainPageFrames/AboutPage.xaml.cs new file mode 100644 index 0000000..654e253 --- /dev/null +++ b/ModernKeePass10/Views/MainPageFrames/AboutPage.xaml.cs @@ -0,0 +1,15 @@ +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 + +namespace ModernKeePass.Views +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class AboutPage + { + public AboutPage() + { + InitializeComponent(); + } + } +} diff --git a/ModernKeePass10/Views/MainPageFrames/DonatePage.xaml b/ModernKeePass10/Views/MainPageFrames/DonatePage.xaml new file mode 100644 index 0000000..6af5daf --- /dev/null +++ b/ModernKeePass10/Views/MainPageFrames/DonatePage.xaml @@ -0,0 +1,20 @@ + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/MainPageFrames/DonatePage.xaml.cs b/ModernKeePass10/Views/MainPageFrames/DonatePage.xaml.cs new file mode 100644 index 0000000..849fdda --- /dev/null +++ b/ModernKeePass10/Views/MainPageFrames/DonatePage.xaml.cs @@ -0,0 +1,15 @@ +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 + +namespace ModernKeePass.Views +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class DonatePage + { + public DonatePage() + { + InitializeComponent(); + } + } +} diff --git a/ModernKeePass10/Views/MainPageFrames/ImportExportPage.xaml b/ModernKeePass10/Views/MainPageFrames/ImportExportPage.xaml new file mode 100644 index 0000000..91f5c35 --- /dev/null +++ b/ModernKeePass10/Views/MainPageFrames/ImportExportPage.xaml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + CSV + + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/MainPageFrames/NewDatabasePage.xaml.cs b/ModernKeePass10/Views/MainPageFrames/NewDatabasePage.xaml.cs new file mode 100644 index 0000000..815102c --- /dev/null +++ b/ModernKeePass10/Views/MainPageFrames/NewDatabasePage.xaml.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using Windows.Storage.AccessCache; +using Windows.Storage.Pickers; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Navigation; +using Autofac; +using ModernKeePass.Domain.Dtos; +using ModernKeePass.Domain.Enums; +using ModernKeePass.Domain.Interfaces; +using ModernKeePass.Events; +using ModernKeePass.ViewModels; + +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 + +namespace ModernKeePass.Views +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class NewDatabasePage + { + private Frame _mainFrame; + private readonly IResourceService _resourceService; + + public NewViewModel ViewModel { get; } + + public NewDatabasePage(): this(App.Container.Resolve()) + { } + + public NewDatabasePage(IResourceService resourceService) + { + InitializeComponent(); + ViewModel = new NewViewModel(); + _resourceService = resourceService; + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + _mainFrame = e.Parameter as Frame; + } + + private async void CreateDatabaseButton_OnClick(object sender, RoutedEventArgs e) + { + var savePicker = new FileSavePicker + { + SuggestedStartLocation = PickerLocationId.DocumentsLibrary, + SuggestedFileName = "New Database" + }; + savePicker.FileTypeChoices.Add("KeePass 2.x database", new List { ".kdbx" }); + + var file = await savePicker.PickSaveFileAsync(); + if (file == null) return; + + var token = StorageApplicationPermissions.FutureAccessList.Add(file); + var fileInfo = new FileInfo + { + Path = token, + Name = file.DisplayName + }; + await ViewModel.OpenFile(fileInfo); + } + + private void ImportFormatComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + var comboBox = sender as ComboBox; + switch (comboBox?.SelectedIndex) + { + case 0: + ViewModel.ImportFormat = ImportFormat.CSV; + ViewModel.ImportFileExtensionFilter = ".csv"; + ViewModel.ImportFormatHelp = _resourceService.GetResourceValue("NewImportFormatHelpCSV"); + break; + } + } + + private async void ImportFileButton_OnClick(object sender, RoutedEventArgs e) + { + var picker = + new FileOpenPicker + { + ViewMode = PickerViewMode.List, + SuggestedStartLocation = PickerLocationId.DocumentsLibrary + }; + if (!string.IsNullOrEmpty(ViewModel.ImportFileExtensionFilter)) + picker.FileTypeFilter.Add(ViewModel.ImportFileExtensionFilter); + + // Application now has read/write access to the picked file + ViewModel.ImportFile = await picker.PickSingleFileAsync(); + if (ViewModel.ImportFile != null) ImportFileLink.Content = ViewModel.ImportFile.Name; + } + + private void CompositeKeyUserControl_OnValidationChecked(object sender, EventArgs e) + { + ViewModel.PopulateInitialData(); + _mainFrame.Navigate(typeof(GroupsPage)); + } + } +} diff --git a/ModernKeePass10/Views/MainPageFrames/OpenDatabasePage.xaml b/ModernKeePass10/Views/MainPageFrames/OpenDatabasePage.xaml new file mode 100644 index 0000000..9eaacd3 --- /dev/null +++ b/ModernKeePass10/Views/MainPageFrames/OpenDatabasePage.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ModernKeePass10/Views/MainPageFrames/OpenDatabasePage.xaml.cs b/ModernKeePass10/Views/MainPageFrames/OpenDatabasePage.xaml.cs new file mode 100644 index 0000000..8c7d220 --- /dev/null +++ b/ModernKeePass10/Views/MainPageFrames/OpenDatabasePage.xaml.cs @@ -0,0 +1,58 @@ +using System; +using Windows.Storage.Pickers; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Navigation; +using ModernKeePass.ViewModels; +using Windows.Storage.AccessCache; +using ModernKeePass.Domain.Dtos; + +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 + +namespace ModernKeePass.Views +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class OpenDatabasePage + { + public OpenViewModel ViewModel { get; } + + public OpenDatabasePage() + { + InitializeComponent(); + ViewModel = new OpenViewModel(); + } + + protected override async void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + if (e.Parameter is FileInfo fileInfo) + { + await ViewModel.OpenFile(fileInfo); + } + } + + private async void ButtonBase_OnClick(object sender, RoutedEventArgs e) + { + var picker = + new FileOpenPicker + { + ViewMode = PickerViewMode.List, + SuggestedStartLocation = PickerLocationId.DocumentsLibrary + }; + picker.FileTypeFilter.Add(".kdbx"); + + // Application now has read/write access to the picked file + var file = await picker.PickSingleFileAsync(); + if (file == null) return; + + var token = StorageApplicationPermissions.FutureAccessList.Add(file); + var fileInfo = new FileInfo + { + Path = token, + Name = file.DisplayName + }; + await ViewModel.OpenFile(fileInfo); + } + } +} diff --git a/ModernKeePass10/Views/MainPageFrames/RecentDatabasesPage.xaml b/ModernKeePass10/Views/MainPageFrames/RecentDatabasesPage.xaml new file mode 100644 index 0000000..36747ae --- /dev/null +++ b/ModernKeePass10/Views/MainPageFrames/RecentDatabasesPage.xaml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ModernKeePass10/Views/MainPageFrames/RecentDatabasesPage.xaml.cs b/ModernKeePass10/Views/MainPageFrames/RecentDatabasesPage.xaml.cs new file mode 100644 index 0000000..323a9a2 --- /dev/null +++ b/ModernKeePass10/Views/MainPageFrames/RecentDatabasesPage.xaml.cs @@ -0,0 +1,20 @@ +// Pour en savoir plus sur le modèle d'élément Page vierge, consultez la page http://go.microsoft.com/fwlink/?LinkId=234238 + +using ModernKeePass.ViewModels; + +namespace ModernKeePass.Views +{ + /// + /// Une page vide peut être utilisée seule ou constituer une page de destination au sein d'un frame. + /// + public sealed partial class RecentDatabasesPage + { + private RecentViewModel ViewModel { get; } + + public RecentDatabasesPage() + { + InitializeComponent(); + ViewModel = new RecentViewModel(); + } + } +} diff --git a/ModernKeePass10/Views/MainPageFrames/SaveDatabasePage.xaml b/ModernKeePass10/Views/MainPageFrames/SaveDatabasePage.xaml new file mode 100644 index 0000000..83c983f --- /dev/null +++ b/ModernKeePass10/Views/MainPageFrames/SaveDatabasePage.xaml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/ModernKeePass10/Views/MainPageFrames/SaveDatabasePage.xaml.cs b/ModernKeePass10/Views/MainPageFrames/SaveDatabasePage.xaml.cs new file mode 100644 index 0000000..46efe4e --- /dev/null +++ b/ModernKeePass10/Views/MainPageFrames/SaveDatabasePage.xaml.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using Windows.Storage.AccessCache; +using Windows.Storage.Pickers; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Navigation; +using ModernKeePass.ViewModels; + +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 + +namespace ModernKeePass.Views +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class SaveDatabasePage + { + private Frame _mainFrame; + public SaveViewModel ViewModel { get; } + public SaveDatabasePage() + { + InitializeComponent(); + ViewModel = new SaveViewModel(); + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + _mainFrame = e.Parameter as Frame; + } + + private void SaveButton_OnClick(object sender, RoutedEventArgs e) + { + ViewModel.Save(); + _mainFrame.Navigate(typeof(MainPage10)); + } + + private async void SaveAsButton_OnClick(object sender, RoutedEventArgs e) + { + var savePicker = new FileSavePicker + { + SuggestedStartLocation = PickerLocationId.DocumentsLibrary, + SuggestedFileName = "New Database" + }; + savePicker.FileTypeChoices.Add("KeePass 2.x database", new List { ".kdbx" }); + + var file = await savePicker.PickSaveFileAsync(); + if (file == null) return; + + var token = StorageApplicationPermissions.FutureAccessList.Add(file); + ViewModel.Save(token); + + _mainFrame.Navigate(typeof(MainPage10)); + } + } +} diff --git a/ModernKeePass10/Views/MainPageFrames/WelcomePage.xaml b/ModernKeePass10/Views/MainPageFrames/WelcomePage.xaml new file mode 100644 index 0000000..89a4831 --- /dev/null +++ b/ModernKeePass10/Views/MainPageFrames/WelcomePage.xaml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/MainPageFrames/WelcomePage.xaml.cs b/ModernKeePass10/Views/MainPageFrames/WelcomePage.xaml.cs new file mode 100644 index 0000000..9f19a53 --- /dev/null +++ b/ModernKeePass10/Views/MainPageFrames/WelcomePage.xaml.cs @@ -0,0 +1,15 @@ +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 + +namespace ModernKeePass.Views +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class WelcomePage + { + public WelcomePage() + { + InitializeComponent(); + } + } +} diff --git a/ModernKeePass10/Views/Old/EntryDetailPage.xaml b/ModernKeePass10/Views/Old/EntryDetailPage.xaml new file mode 100644 index 0000000..1a536ec --- /dev/null +++ b/ModernKeePass10/Views/Old/EntryDetailPage.xaml @@ -0,0 +1,572 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Visible + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ModernKeePass10/Views/Old/EntryDetailPage.xaml.cs b/ModernKeePass10/Views/Old/EntryDetailPage.xaml.cs new file mode 100644 index 0000000..65abfff --- /dev/null +++ b/ModernKeePass10/Views/Old/EntryDetailPage.xaml.cs @@ -0,0 +1,78 @@ +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Navigation; +using ModernKeePass.Common; +using ModernKeePass.ViewModels; + +// Pour en savoir plus sur le modèle d'élément Page Détail de l'élément, consultez la page http://go.microsoft.com/fwlink/?LinkId=234232 + +namespace ModernKeePass.Views +{ + /// + /// Page affichant les détails d'un élément au sein d'un groupe, offrant la possibilité de + /// consulter les autres éléments qui appartiennent au même groupe. + /// + public sealed partial class EntryDetailPage + { + public EntryVm Model => (EntryVm) DataContext; + + /// + /// NavigationHelper est utilisé sur chaque page pour faciliter la navigation et + /// gestion de la durée de vie des processus + /// + public NavigationHelper NavigationHelper { get; } + + public EntryDetailPage() + { + InitializeComponent(); + NavigationHelper = new NavigationHelper(this); + } + + #region Inscription de NavigationHelper + + /// Les méthodes fournies dans cette section sont utilisées simplement pour permettre + /// NavigationHelper pour répondre aux méthodes de navigation de la page. + /// + /// La logique spécifique à la page doit être placée dans les gestionnaires d'événements pour + /// + /// et . + /// Le paramètre de navigation est disponible dans la méthode LoadState + /// en plus de l'état de page conservé durant une session antérieure. + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + NavigationHelper.OnNavigatedTo(e); + if (!(e.Parameter is EntryVm)) return; + DataContext = (EntryVm)e.Parameter; + } + + protected override void OnNavigatedFrom(NavigationEventArgs e) + { + NavigationHelper.OnNavigatedFrom(e); + Model.Reset(); + } + + #endregion + + private void EntryDetailPage_OnSizeChanged(object sender, SizeChangedEventArgs e) + { + VisualStateManager.GoToState(this, e.NewSize.Width < 700 ? "Small" : "Large", true); + VisualStateManager.GoToState(TopMenu, e.NewSize.Width < 800 ? "Collapsed" : "Overflowed", true); + } + + private void HamburgerMenuUserControl_OnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + var listView = sender as ListView; + switch (listView?.SelectedIndex) + { + case -1: + return; + default: + var entry = listView?.SelectedItem as EntryVm; + StackPanel.DataContext = entry; + TopGrid.DataContext = entry; + break; + } + } + } +} diff --git a/ModernKeePass10/Views/Old/GroupDetailPage.xaml b/ModernKeePass10/Views/Old/GroupDetailPage.xaml new file mode 100644 index 0000000..220d9e7 --- /dev/null +++ b/ModernKeePass10/Views/Old/GroupDetailPage.xaml @@ -0,0 +1,326 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ModernKeePass10/Views/Old/GroupDetailPage.xaml.cs b/ModernKeePass10/Views/Old/GroupDetailPage.xaml.cs new file mode 100644 index 0000000..6431cd7 --- /dev/null +++ b/ModernKeePass10/Views/Old/GroupDetailPage.xaml.cs @@ -0,0 +1,142 @@ +using System; +using System.Linq; +using Windows.ApplicationModel.DataTransfer; +using Windows.Storage.Streams; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Navigation; +using ModernKeePass.Common; +using ModernKeePass.Events; +using ModernKeePass.ViewModels; + +// The Group Detail Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234229 + +namespace ModernKeePass.Views +{ + /// + /// A page that displays an overview of a single group, including a preview of the items + /// within the group. + /// + public sealed partial class GroupDetailPage + { + /// + /// NavigationHelper is used on each page to aid in navigation and + /// process lifetime management + /// + public NavigationHelper NavigationHelper { get; } + public GroupVm Model => (GroupVm)DataContext; + + public GroupDetailPage() + { + InitializeComponent(); + NavigationHelper = new NavigationHelper(this); + } + + #region NavigationHelper registration + + /// The methods provided in this section are simply used to allow + /// NavigationHelper to respond to the page's navigation methods. + /// + /// Page specific logic should be placed in event handlers for the + /// + /// and . + /// The navigation parameter is available in the LoadState method + /// in addition to page state preserved during an earlier session. + /// + protected override void OnNavigatedTo(NavigationEventArgs e) + { + NavigationHelper.OnNavigatedTo(e); + + if (e.Parameter is PasswordEventArgs args) + DataContext = args.RootGroup; + else + { + if (e.Parameter is GroupVm vm) + DataContext = vm; + } + } + + protected override void OnNavigatedFrom(NavigationEventArgs e) + { + NavigationHelper.OnNavigatedFrom(e); + } + + #endregion + + #region Event Handlers + + private void groups_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + var listView = sender as ListView; + switch (listView?.SelectedIndex) + { + case -1: + return; + default: + var group = listView?.SelectedItem as GroupVm; + Frame.Navigate(typeof(GroupDetailPage), group); + break; + } + } + + private void entries_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + switch (GridView.SelectedIndex) + { + case -1: + return; + default: + var entry = GridView.SelectedItem as EntryVm; + Frame.Navigate(typeof(EntryDetailPage), entry); + break; + } + } + + private void SemanticZoom_ViewChangeStarted(object sender, SemanticZoomViewChangedEventArgs e) + { + // We need to synchronize the two lists (zoomed-in and zoomed-out) because the source is different + if (!e.IsSourceZoomedInView) + { + e.DestinationItem.Item = e.SourceItem.Item; + } + } + private void CreateEntry_ButtonClick(object sender, RoutedEventArgs e) + { + Frame.Navigate(typeof(EntryDetailPage), Model.AddNewEntry()); + } + private void CreateGroup_ButtonClick(object sender, RoutedEventArgs e) + { + Frame.Navigate(typeof(GroupDetailPage), Model.AddNewGroup()); + } + + private void GridView_DragItemsStarting(object sender, DragItemsStartingEventArgs e) + { + e.Cancel = !Model.IsEditMode; + e.Data.RequestedOperation = DataPackageOperation.Move; + } + + private void SearchBox_OnSuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args) + { + var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appdata://Assets/ModernKeePass-SmallLogo.scale-80.png")); + var results = Model.SubEntries.Where(e => e.Name.IndexOf(args.QueryText, StringComparison.OrdinalIgnoreCase) >= 0).Take(5); + foreach (var result in results) + { + args.Request.SearchSuggestionCollection.AppendResultSuggestion(result.Name, result.ParentGroup.Name, result.Id, imageUri, string.Empty); + } + } + + private void SearchBox_OnResultSuggestionChosen(SearchBox sender, SearchBoxResultSuggestionChosenEventArgs args) + { + var entry = Model.SubEntries.FirstOrDefault(e => e.Id == args.Tag); + Frame.Navigate(typeof(EntryDetailPage), entry); + } + + private void GroupDetailPage_OnSizeChanged(object sender, SizeChangedEventArgs e) + { + VisualStateManager.GoToState(this, e.NewSize.Width < 800 ? "Small" : "Large", true); + VisualStateManager.GoToState(TopMenu, e.NewSize.Width < 800 ? "Collapsed" : "Overflowed", true); + } + + #endregion + } +} diff --git a/ModernKeePass10/Views/Old/MainPage.xaml b/ModernKeePass10/Views/Old/MainPage.xaml new file mode 100644 index 0000000..6afd265 --- /dev/null +++ b/ModernKeePass10/Views/Old/MainPage.xaml @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ModernKeePass10/Views/Old/MainPage.xaml.cs b/ModernKeePass10/Views/Old/MainPage.xaml.cs new file mode 100644 index 0000000..481c9c1 --- /dev/null +++ b/ModernKeePass10/Views/Old/MainPage.xaml.cs @@ -0,0 +1,40 @@ +using Windows.Storage; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Navigation; +using ModernKeePass.ViewModels; +using ModernKeePass.ViewModels.ListItems; + +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 + +namespace ModernKeePass.Views +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class MainPage + { + public new MainVm Model => (MainVm)DataContext; + + public MainPage() + { + InitializeComponent(); + ListView = MenuListView; + ListViewSource = MenuItemsSource; + } + + private new void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + base.ListView_SelectionChanged(sender, e); + + if (!(Model.SelectedItem is MainMenuItemViewModel selectedItem)) MenuFrame.Navigate(typeof(WelcomePage)); + else selectedItem.Destination.Navigate(selectedItem.PageType, selectedItem.Parameter); + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + var file = e.Parameter as StorageFile; + DataContext = new MainVm(Frame, MenuFrame, file); + } + } +} diff --git a/ModernKeePass10/Views/Old/SettingsPage.xaml b/ModernKeePass10/Views/Old/SettingsPage.xaml new file mode 100644 index 0000000..18de4ff --- /dev/null +++ b/ModernKeePass10/Views/Old/SettingsPage.xaml @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/Old/SettingsPage.xaml.cs b/ModernKeePass10/Views/Old/SettingsPage.xaml.cs new file mode 100644 index 0000000..effae3b --- /dev/null +++ b/ModernKeePass10/Views/Old/SettingsPage.xaml.cs @@ -0,0 +1,31 @@ +using Windows.UI.Xaml.Controls; +using ModernKeePass.ViewModels; +using ModernKeePass.ViewModels.ListItems; + +// The Split Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234234 + +namespace ModernKeePass.Views +{ + /// + /// A page that displays a group title, a list of items within the group, and details for + /// the currently selected item. + /// + public sealed partial class SettingsPage + { + public new SettingsViewModel Model => (SettingsViewModel)DataContext; + + public SettingsPage() + { + InitializeComponent(); + ListView = MenuListView; + ListViewSource = MenuItemsSource; + } + + private new void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + base.ListView_SelectionChanged(sender, e); + var selectedItem = Model.SelectedItem as ListMenuItemViewModel; + MenuFrame?.Navigate(selectedItem == null ? typeof(SettingsWelcomePage) : selectedItem.PageType); + } + } +} diff --git a/ModernKeePass10/Views/SettingsPage10.xaml b/ModernKeePass10/Views/SettingsPage10.xaml new file mode 100644 index 0000000..90e3ee3 --- /dev/null +++ b/ModernKeePass10/Views/SettingsPage10.xaml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/SettingsPage10.xaml.cs b/ModernKeePass10/Views/SettingsPage10.xaml.cs new file mode 100644 index 0000000..87beccf --- /dev/null +++ b/ModernKeePass10/Views/SettingsPage10.xaml.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.ApplicationModel.Core; +using ModernKeePass.ViewModels; +using ModernKeePass.Views.SettingsPageFrames; + +namespace ModernKeePass.Views +{ + public partial class SettingsPage10 + { + private SettingsViewModel ViewModel { get; } + + private readonly IList<(string Tag, Type Page)> _pages = new List<(string Tag, Type Page)> + { + ("welcome", typeof(SettingsWelcomePage)), + ("new", typeof(SettingsNewDatabasePage)), + ("save", typeof(SettingsSavePage)), + ("general", typeof(SettingsDatabasePage)), + ("security", typeof(SettingsSecurityPage)) + }; + + public SettingsPage10() + { + InitializeComponent(); + ViewModel = new SettingsViewModel(); + SetTitleBar(); + } + + private void SetTitleBar() + { + var coreTitleBar = CoreApplication.GetCurrentView().TitleBar; + coreTitleBar.ExtendViewIntoTitleBar = true; + Window.Current.SetTitleBar(AppTitleBar); + } + + private void NavigationView_OnItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args) + { + // Getting the Tag from Content (args.InvokedItem is the content of NavigationViewItem) + var navItem = NavigationView.MenuItems + .OfType() + .First(i => args.InvokedItem.Equals(i.Content)); + + NavigationView_Navigate(navItem); + } + + private void NavigationView_Navigate(NavigationViewItem navItem) + { + var item = _pages.First(p => p.Tag.Equals(navItem.Tag)); + NavigationView.Header = navItem.Content; + ContentFrame.Navigate(item.Page); + } + + private void NavigationView_OnLoaded(object sender, RoutedEventArgs e) + { + NavigationView_Navigate(Welcome); + NavigationView.IsBackEnabled = Frame.CanGoBack; + } + + private void NavigationView_OnBackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args) + { + Frame.GoBack(); + } + } +} \ No newline at end of file diff --git a/ModernKeePass10/Views/SettingsPageFrames/SettingsDatabasePage.xaml b/ModernKeePass10/Views/SettingsPageFrames/SettingsDatabasePage.xaml new file mode 100644 index 0000000..d00dea1 --- /dev/null +++ b/ModernKeePass10/Views/SettingsPageFrames/SettingsDatabasePage.xaml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/SettingsPageFrames/SettingsDatabasePage.xaml.cs b/ModernKeePass10/Views/SettingsPageFrames/SettingsDatabasePage.xaml.cs new file mode 100644 index 0000000..7fcfb83 --- /dev/null +++ b/ModernKeePass10/Views/SettingsPageFrames/SettingsDatabasePage.xaml.cs @@ -0,0 +1,20 @@ +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 + +using ModernKeePass.ViewModels.ListItems; + +namespace ModernKeePass.Views.SettingsPageFrames +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class SettingsDatabasePage + { + public SettingsDatabaseViewModel ViewModel { get; } + + public SettingsDatabasePage() + { + InitializeComponent(); + ViewModel = new SettingsDatabaseViewModel(); + } + } +} diff --git a/ModernKeePass10/Views/SettingsPageFrames/SettingsNewDatabasePage.xaml b/ModernKeePass10/Views/SettingsPageFrames/SettingsNewDatabasePage.xaml new file mode 100644 index 0000000..5384edf --- /dev/null +++ b/ModernKeePass10/Views/SettingsPageFrames/SettingsNewDatabasePage.xaml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/SettingsPageFrames/SettingsNewDatabasePage.xaml.cs b/ModernKeePass10/Views/SettingsPageFrames/SettingsNewDatabasePage.xaml.cs new file mode 100644 index 0000000..dd58c4f --- /dev/null +++ b/ModernKeePass10/Views/SettingsPageFrames/SettingsNewDatabasePage.xaml.cs @@ -0,0 +1,20 @@ +// Pour en savoir plus sur le modèle d'élément Page vierge, consultez la page http://go.microsoft.com/fwlink/?LinkId=234238 + +using ModernKeePass.ViewModels.ListItems; + +namespace ModernKeePass.Views.SettingsPageFrames +{ + /// + /// Une page vide peut être utilisée seule ou constituer une page de destination au sein d'un frame. + /// + public sealed partial class SettingsNewDatabasePage + { + private SettingsNewViewModel ViewModel { get; } + + public SettingsNewDatabasePage() + { + InitializeComponent(); + ViewModel = new SettingsNewViewModel(); + } + } +} diff --git a/ModernKeePass10/Views/SettingsPageFrames/SettingsSavePage.xaml b/ModernKeePass10/Views/SettingsPageFrames/SettingsSavePage.xaml new file mode 100644 index 0000000..fa73b26 --- /dev/null +++ b/ModernKeePass10/Views/SettingsPageFrames/SettingsSavePage.xaml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/ModernKeePass10/Views/SettingsPageFrames/SettingsSavePage.xaml.cs b/ModernKeePass10/Views/SettingsPageFrames/SettingsSavePage.xaml.cs new file mode 100644 index 0000000..2dafac4 --- /dev/null +++ b/ModernKeePass10/Views/SettingsPageFrames/SettingsSavePage.xaml.cs @@ -0,0 +1,19 @@ +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 + +using ModernKeePass.ViewModels.ListItems; + +namespace ModernKeePass.Views.SettingsPageFrames +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class SettingsSavePage + { + private SettingsSaveViewModel ViewModel { get; } + public SettingsSavePage() + { + InitializeComponent(); + ViewModel = new SettingsSaveViewModel(); + } + } +} diff --git a/ModernKeePass10/Views/SettingsPageFrames/SettingsSecurityPage.xaml b/ModernKeePass10/Views/SettingsPageFrames/SettingsSecurityPage.xaml new file mode 100644 index 0000000..76f468d --- /dev/null +++ b/ModernKeePass10/Views/SettingsPageFrames/SettingsSecurityPage.xaml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/SettingsPageFrames/SettingsSecurityPage.xaml.cs b/ModernKeePass10/Views/SettingsPageFrames/SettingsSecurityPage.xaml.cs new file mode 100644 index 0000000..ee45395 --- /dev/null +++ b/ModernKeePass10/Views/SettingsPageFrames/SettingsSecurityPage.xaml.cs @@ -0,0 +1,15 @@ +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 + +namespace ModernKeePass.Views.SettingsPageFrames +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class SettingsSecurityPage + { + public SettingsSecurityPage() + { + InitializeComponent(); + } + } +} diff --git a/ModernKeePass10/Views/SettingsPageFrames/SettingsWelcomePage.xaml b/ModernKeePass10/Views/SettingsPageFrames/SettingsWelcomePage.xaml new file mode 100644 index 0000000..1bbcefa --- /dev/null +++ b/ModernKeePass10/Views/SettingsPageFrames/SettingsWelcomePage.xaml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/ModernKeePass10/Views/SettingsPageFrames/SettingsWelcomePage.xaml.cs b/ModernKeePass10/Views/SettingsPageFrames/SettingsWelcomePage.xaml.cs new file mode 100644 index 0000000..93ccf89 --- /dev/null +++ b/ModernKeePass10/Views/SettingsPageFrames/SettingsWelcomePage.xaml.cs @@ -0,0 +1,15 @@ +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 + +namespace ModernKeePass.Views.SettingsPageFrames +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class SettingsWelcomePage + { + public SettingsWelcomePage() + { + InitializeComponent(); + } + } +} diff --git a/ModernKeePass10/Views/UserControls/BreadCrumbUserControl.xaml b/ModernKeePass10/Views/UserControls/BreadCrumbUserControl.xaml new file mode 100644 index 0000000..f1247ff --- /dev/null +++ b/ModernKeePass10/Views/UserControls/BreadCrumbUserControl.xaml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/UserControls/BreadCrumbUserControl.xaml.cs b/ModernKeePass10/Views/UserControls/BreadCrumbUserControl.xaml.cs new file mode 100644 index 0000000..2d88786 --- /dev/null +++ b/ModernKeePass10/Views/UserControls/BreadCrumbUserControl.xaml.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using Windows.UI.Xaml; +using ModernKeePass.Domain.Entities; + +// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236 + +namespace ModernKeePass.Views.UserControls +{ + public sealed partial class BreadCrumbUserControl + { + public BreadCrumbUserControl() + { + InitializeComponent(); + } + + public IEnumerable ItemsSource + { + get => (IEnumerable)GetValue(ItemsSourceProperty); + set => SetValue(ItemsSourceProperty, value); + } + + public static readonly DependencyProperty ItemsSourceProperty = + DependencyProperty.Register( + "ItemsSource", + typeof(IEnumerable), + typeof(BreadCrumbUserControl), + new PropertyMetadata(new Stack(), (o, args) => { })); + } +} diff --git a/ModernKeePass10/Views/UserControls/ColorPickerUserControl.xaml b/ModernKeePass10/Views/UserControls/ColorPickerUserControl.xaml new file mode 100644 index 0000000..634b79a --- /dev/null +++ b/ModernKeePass10/Views/UserControls/ColorPickerUserControl.xaml @@ -0,0 +1,24 @@ + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/UserControls/ColorPickerUserControl.xaml.cs b/ModernKeePass10/Views/UserControls/ColorPickerUserControl.xaml.cs new file mode 100644 index 0000000..7356803 --- /dev/null +++ b/ModernKeePass10/Views/UserControls/ColorPickerUserControl.xaml.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media; + +// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236 + +namespace ModernKeePass.Views.UserControls +{ + public sealed partial class ColorPickerUserControl + { + public struct Color + { + public string ColorName { get; set; } + public SolidColorBrush ColorBrush { get; set; } + } + + public List Colors { get; } + + public SolidColorBrush SelectedColor + { + get => (SolidColorBrush)GetValue(SelectedColorProperty); + set => SetValue(SelectedColorProperty, value); + } + public static readonly DependencyProperty SelectedColorProperty = + DependencyProperty.Register( + "SelectedColor", + typeof(SolidColorBrush), + typeof(ColorPickerUserControl), + new PropertyMetadata(new SolidColorBrush(), (o, args) => { })); + + public ColorPickerUserControl() + { + InitializeComponent(); + Colors = new List(); + var type = typeof(Windows.UI.Colors); + var properties = type.GetRuntimeProperties().ToArray(); + foreach (var propertyInfo in properties) + { + Colors.Add(new Color + { + ColorName = propertyInfo.Name, + ColorBrush = new SolidColorBrush((Windows.UI.Color)propertyInfo.GetValue(null, null)) + }); + } + } + + private void ComboBox_Loaded(object sender, RoutedEventArgs e) + { + ComboBox.SelectedItem = Colors.Find(c => c.ColorBrush.Color.Equals(SelectedColor.Color)); + } + + private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + var selectedItem = ComboBox.SelectedItem as Color? ?? new Color(); + SelectedColor = selectedItem.ColorBrush; + } + } +} diff --git a/ModernKeePass10/Views/UserControls/CredentialsUserControl.xaml b/ModernKeePass10/Views/UserControls/CredentialsUserControl.xaml new file mode 100644 index 0000000..88511b9 --- /dev/null +++ b/ModernKeePass10/Views/UserControls/CredentialsUserControl.xaml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/UserControls/HamburgerMenuUserControl.xaml.cs b/ModernKeePass10/Views/UserControls/HamburgerMenuUserControl.xaml.cs new file mode 100644 index 0000000..b6e6429 --- /dev/null +++ b/ModernKeePass10/Views/UserControls/HamburgerMenuUserControl.xaml.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using ModernKeePass.Domain.Entities; + +// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236 + +namespace ModernKeePass.Views.UserControls +{ + public sealed partial class HamburgerMenuUserControl + { + public HamburgerMenuUserControl() + { + InitializeComponent(); + } + + public string HeaderLabel + { + get => (string)GetValue(HeaderLabelProperty); + set => SetValue(HeaderLabelProperty, value); + } + public static readonly DependencyProperty HeaderLabelProperty = + DependencyProperty.Register( + "HeaderLabel", + typeof(string), + typeof(HamburgerMenuUserControl), + new PropertyMetadata("Header", (o, args) => { })); + + public string ButtonLabel + { + get => (string)GetValue(ButtonLabelProperty); + set => SetValue(ButtonLabelProperty, value); + } + public static readonly DependencyProperty ButtonLabelProperty = + DependencyProperty.Register( + "ButtonLabel", + typeof(string), + typeof(HamburgerMenuUserControl), + new PropertyMetadata("Button", (o, args) => { })); + + public string DisplayMemberPath + { + get => (string)GetValue(DisplayMemberPathProperty); + set => SetValue(DisplayMemberPathProperty, value); + } + public static readonly DependencyProperty DisplayMemberPathProperty = + DependencyProperty.Register( + "DisplayMemberPath", + typeof(string), + typeof(HamburgerMenuUserControl), + new PropertyMetadata("Title", (o, args) => { })); + + public object ResizeTarget + { + get => GetValue(ResizeTargetProperty); + set => SetValue(ResizeTargetProperty, value); + } + public static readonly DependencyProperty ResizeTargetProperty = + DependencyProperty.Register( + "ResizeTarget", + typeof(object), + typeof(HamburgerMenuUserControl), + new PropertyMetadata(null, (o, args) => { })); + + public Visibility IsButtonVisible + { + get => (Visibility)GetValue(IsButtonVisibleProperty); + set => SetValue(IsButtonVisibleProperty, value); + } + public static readonly DependencyProperty IsButtonVisibleProperty = + DependencyProperty.Register( + "IsButtonVisible", + typeof(Visibility), + typeof(HamburgerMenuUserControl), + new PropertyMetadata(Visibility.Collapsed, (o, args) => { })); + + public IEnumerable ItemsSource + { + get => (IEnumerable)GetValue(ItemsSourceProperty); + set => SetValue(ItemsSourceProperty, value); + } + + public static readonly DependencyProperty ItemsSourceProperty = + DependencyProperty.Register( + "ItemsSource", + typeof(IEnumerable), + typeof(HamburgerMenuUserControl), + new PropertyMetadata(new List(), (o, args) => { })); + + public object SelectedItem + { + get => GetValue(SelectedItemProperty); + set => SetValue(SelectedItemProperty, value); + } + public static readonly DependencyProperty SelectedItemProperty = + DependencyProperty.Register( + "SelectedItem", + typeof(object), + typeof(HamburgerMenuUserControl), + new PropertyMetadata(null, (o, args) => { })); + + public event EventHandler SelectionChanged; + private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + SelectionChanged?.Invoke(sender, e); + } + + public event EventHandler ButtonClicked; + private void ButtonBase_OnClick(object sender, RoutedEventArgs e) + { + ButtonClicked?.Invoke(sender, e); + } + } +} diff --git a/ModernKeePass10/Views/UserControls/SymbolPickerUserControl.xaml b/ModernKeePass10/Views/UserControls/SymbolPickerUserControl.xaml new file mode 100644 index 0000000..5c426a9 --- /dev/null +++ b/ModernKeePass10/Views/UserControls/SymbolPickerUserControl.xaml @@ -0,0 +1,24 @@ + + + + + + + + + + + diff --git a/ModernKeePass10/Views/UserControls/SymbolPickerUserControl.xaml.cs b/ModernKeePass10/Views/UserControls/SymbolPickerUserControl.xaml.cs new file mode 100644 index 0000000..e90631a --- /dev/null +++ b/ModernKeePass10/Views/UserControls/SymbolPickerUserControl.xaml.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using ModernKeePass.Converters; + +// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236 + +namespace ModernKeePass.Views.UserControls +{ + public sealed partial class SymbolPickerUserControl + { + public IEnumerable Symbols { get; } + + public Symbol SelectedSymbol + { + get => (Symbol)GetValue(SelectedSymbolProperty); + set => SetValue(SelectedSymbolProperty, value); + } + public static readonly DependencyProperty SelectedSymbolProperty = + DependencyProperty.Register( + "SelectedSymbol", + typeof(Symbol), + typeof(SymbolPickerUserControl), + new PropertyMetadata(Symbol.Stop, (o, args) => { })); + + public SymbolPickerUserControl() + { + InitializeComponent(); + var converter = new IconToSymbolConverter(); + Symbols = Enum.GetValues(typeof(Symbol)).Cast().Where(s => (int)converter.ConvertBack(s, null, null, string.Empty) != -1); + } + + private void ComboBox_OnLoaded(object sender, RoutedEventArgs e) + { + ComboBox.SelectedItem = Symbols.FirstOrDefault(s => s == SelectedSymbol); + } + } +} diff --git a/ModernKeePass10/Views/UserControls/TopMenuUserControl.xaml b/ModernKeePass10/Views/UserControls/TopMenuUserControl.xaml new file mode 100644 index 0000000..8976a85 --- /dev/null +++ b/ModernKeePass10/Views/UserControls/TopMenuUserControl.xaml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ModernKeePass10/Views/UserControls/TopMenuUserControl.xaml.cs b/ModernKeePass10/Views/UserControls/TopMenuUserControl.xaml.cs new file mode 100644 index 0000000..88942aa --- /dev/null +++ b/ModernKeePass10/Views/UserControls/TopMenuUserControl.xaml.cs @@ -0,0 +1,195 @@ +using System; +using System.Windows.Input; +using Windows.UI.Xaml; + +// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236 + +namespace ModernKeePass.Views.UserControls +{ + public sealed partial class TopMenuUserControl + { + public ICommand SaveCommand + { + get => (ICommand)GetValue(SaveCommandProperty); + set => SetValue(SaveCommandProperty, value); + } + public static readonly DependencyProperty SaveCommandProperty = + DependencyProperty.Register( + "SaveCommand", + typeof(ICommand), + typeof(TopMenuUserControl), + new PropertyMetadata(null, (o, args) => { })); + + public ICommand EditCommand + { + get => (ICommand)GetValue(EditCommandProperty); + set => SetValue(EditCommandProperty, value); + } + public static readonly DependencyProperty EditCommandProperty = + DependencyProperty.Register( + "EditCommand", + typeof(ICommand), + typeof(TopMenuUserControl), + new PropertyMetadata(null, (o, args) => { })); + + public ICommand DeleteCommand + { + get => (ICommand)GetValue(DeleteCommandProperty); + set => SetValue(DeleteCommandProperty, value); + } + public static readonly DependencyProperty DeleteCommandProperty = + DependencyProperty.Register( + "DeleteCommand", + typeof(ICommand), + typeof(TopMenuUserControl), + new PropertyMetadata(null, (o, args) => { })); + + public ICommand RestoreCommand + { + get => (ICommand)GetValue(RestoreCommandProperty); + set => SetValue(RestoreCommandProperty, value); + } + public static readonly DependencyProperty RestoreCommandProperty = + DependencyProperty.Register( + "RestoreCommand", + typeof(ICommand), + typeof(TopMenuUserControl), + new PropertyMetadata(null, (o, args) => { })); + + public ICommand SortEntriesCommand + { + get => (ICommand)GetValue(SortEntriesCommandProperty); + set => SetValue(SortEntriesCommandProperty, value); + } + public static readonly DependencyProperty SortEntriesCommandProperty = + DependencyProperty.Register( + "SortEntriesCommand", + typeof(ICommand), + typeof(TopMenuUserControl), + new PropertyMetadata(null, (o, args) => { })); + + public ICommand SortGroupsCommand + { + get => (ICommand)GetValue(SortGroupsCommandProperty); + set => SetValue(SortGroupsCommandProperty, value); + } + public static readonly DependencyProperty SortGroupsCommandProperty = + DependencyProperty.Register( + "SortGroupsCommand", + typeof(ICommand), + typeof(TopMenuUserControl), + new PropertyMetadata(null, (o, args) => { })); + + public Visibility RestoreButtonVisibility + { + get => (Visibility)GetValue(RestoreButtonVisibilityProperty); + set => SetValue(RestoreButtonVisibilityProperty, value); + } + public static readonly DependencyProperty RestoreButtonVisibilityProperty = + DependencyProperty.Register( + "RestoreButtonVisibility", + typeof(Visibility), + typeof(TopMenuUserControl), + new PropertyMetadata(Visibility.Collapsed, (o, args) => { })); + + public Visibility DeleteButtonVisibility + { + get => (Visibility)GetValue(DeleteButtonVisibilityProperty); + set => SetValue(DeleteButtonVisibilityProperty, value); + } + public static readonly DependencyProperty DeleteButtonVisibilityProperty = + DependencyProperty.Register( + "DeleteButtonVisibility", + typeof(Visibility), + typeof(TopMenuUserControl), + new PropertyMetadata(Visibility.Collapsed, (o, args) => { })); + + public Visibility SortButtonVisibility + { + get => (Visibility)GetValue(SortButtonVisibilityProperty); + set => SetValue(SortButtonVisibilityProperty, value); + } + public static readonly DependencyProperty SortButtonVisibilityProperty = + DependencyProperty.Register( + "SortButtonVisibility", + typeof(Visibility), + typeof(TopMenuUserControl), + new PropertyMetadata(Visibility.Collapsed, (o, args) => { })); + + public bool IsDeleteButtonEnabled + { + get => (bool)GetValue(IsDeleteButtonEnabledProperty); + set => SetValue(IsDeleteButtonEnabledProperty, value); + } + public static readonly DependencyProperty IsDeleteButtonEnabledProperty = + DependencyProperty.Register( + "IsDeleteButtonEnabled", + typeof(bool), + typeof(TopMenuUserControl), + new PropertyMetadata(true, (o, args) => { })); + + public bool IsEditButtonChecked + { + get => (bool)GetValue(IsEditButtonCheckedProperty); + set => SetValue(IsEditButtonCheckedProperty, value); + } + public static readonly DependencyProperty IsEditButtonCheckedProperty = + DependencyProperty.Register( + "IsEditButtonChecked", + typeof(bool), + typeof(TopMenuUserControl), + new PropertyMetadata(false, (o, args) => { })); + + public event EventHandler EditButtonClick; + public event EventHandler DeleteButtonClick; + public event EventHandler RestoreButtonClick; + + public TopMenuUserControl() + { + InitializeComponent(); + EditFlyout.Click += EditFlyout_Click; + } + + private void EditFlyout_Click(object sender, RoutedEventArgs e) + { + IsEditButtonChecked = EditFlyout.IsChecked; + EditButton_Click(sender, e); + } + + private void EditButton_Click(object sender, RoutedEventArgs e) + { + EditButtonClick?.Invoke(sender, e); + } + + private void DeleteButton_Click(object sender, RoutedEventArgs e) + { + DeleteButtonClick?.Invoke(sender, e); + } + + private void RestoreButton_Click(object sender, RoutedEventArgs e) + { + RestoreButtonClick?.Invoke(sender, e); + } + + private void OverflowFlyout_OnOpening(object sender, object e) + { + DeleteFlyout.IsEnabled = IsDeleteButtonEnabled; + DeleteFlyout.Visibility = DeleteButtonVisibility; + + EditFlyout.IsChecked = IsEditButtonChecked; + + RestoreFlyout.Visibility = RestoreButtonVisibility; + + SortEntriesFlyout.Visibility = SortButtonVisibility; + SortGroupsFlyout.Visibility = SortButtonVisibility; + SortEntriesFlyout.Command = SortEntriesCommand; + SortGroupsFlyout.Command = SortGroupsCommand; + } + + private void SortFlyout_OnOpening(object sender, object e) + { + SortEntriesButtonFlyout.Command = SortEntriesCommand; + SortGroupsButtonFlyout.Command = SortGroupsCommand; + } + } +} diff --git a/ModernKeePass10/Views/UserControls/UpdateCredentialsUserControl.xaml b/ModernKeePass10/Views/UserControls/UpdateCredentialsUserControl.xaml new file mode 100644 index 0000000..633127a --- /dev/null +++ b/ModernKeePass10/Views/UserControls/UpdateCredentialsUserControl.xaml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +