Compare commits
78 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4aefbcb8b9 | ||
![]() |
56129253d9 | ||
![]() |
7613629d87 | ||
![]() |
fb0eab00c2 | ||
![]() |
5b8c3b9b11 | ||
![]() |
700f76679a | ||
![]() |
e7d731bb04 | ||
![]() |
49637fcc3b | ||
![]() |
fc25d7ea93 | ||
![]() |
cca6579274 | ||
![]() |
7dbf93fe7b | ||
![]() |
b46ab8db51 | ||
![]() |
a19519fa73 | ||
![]() |
4a3f36d38b | ||
![]() |
4ae02fc07b | ||
![]() |
047fca32bf | ||
![]() |
abbff449c0 | ||
![]() |
fba668860b | ||
![]() |
acb196d9c2 | ||
![]() |
dfa3a21e6b | ||
![]() |
7ff6bccbc4 | ||
![]() |
88e5b80778 | ||
![]() |
d127431396 | ||
![]() |
588703ecd6 | ||
![]() |
223c9b641a | ||
![]() |
7db34d6517 | ||
![]() |
13901d17ab | ||
![]() |
19bc9005e9 | ||
![]() |
7c86a325d9 | ||
![]() |
d203b521c1 | ||
![]() |
0afa59fb66 | ||
![]() |
470a08f4bc | ||
![]() |
50c5940a0a | ||
![]() |
35f64eec1b | ||
![]() |
e25f9f4aae | ||
![]() |
a86dbf9dac | ||
![]() |
026bfcba78 | ||
![]() |
3b66824c58 | ||
![]() |
898a9a0935 | ||
![]() |
7aa342cf9c | ||
![]() |
f173283a66 | ||
![]() |
4f69b5cdcc | ||
![]() |
744858df81 | ||
![]() |
f172e31250 | ||
![]() |
7530cf8006 | ||
![]() |
33223934e3 | ||
![]() |
f2731c49dd | ||
![]() |
227bc30dde | ||
![]() |
7b39fe79c8 | ||
![]() |
fcbda1e33d | ||
![]() |
42ac04b02c | ||
![]() |
7cd05cb1d8 | ||
![]() |
1b2d25e171 | ||
![]() |
675a718107 | ||
![]() |
a8f5897364 | ||
![]() |
5120c8177b | ||
![]() |
f2d97b4e7e | ||
![]() |
197e061bc5 | ||
![]() |
d1a6b418d5 | ||
![]() |
e9c79b192b | ||
![]() |
52c56757ca | ||
![]() |
559af0ddd8 | ||
![]() |
cd1b3ce1ed | ||
![]() |
5273a25385 | ||
![]() |
3089609c19 | ||
![]() |
e1f62342d9 | ||
![]() |
9313ac1abf | ||
7a632c8f80 | |||
7f9a0e5b1e | |||
![]() |
b0a3f796cb | ||
![]() |
97521f174a | ||
432d5e49d5 | |||
b2c8f2e0f4 | |||
23011568b7 | |||
078f9535cf | |||
![]() |
ea481187d5 | ||
![]() |
810caaf8e2 | ||
![]() |
d290d9b4e3 |
@@ -9,6 +9,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePassLib", "ModernK
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePassLib.Test", "ModernKeePassLib.Test\ModernKeePassLib.Test.csproj", "{0A4279CF-2A67-4868-9906-052E50C25F3B}"
|
||||
EndProject
|
||||
Project("{F5034706-568F-408A-B7B3-4D38C6DB8A32}") = "Scripts", "Scripts\Scripts.pssproj", "{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePassApp.Test", "ModernKeePassApp.Test\ModernKeePassApp.Test.csproj", "{7E80F5E7-724A-4668-9333-B10F5D75C6D0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -85,6 +89,46 @@ Global
|
||||
{0A4279CF-2A67-4868-9906-052E50C25F3B}.Release|x86.ActiveCfg = Release|x86
|
||||
{0A4279CF-2A67-4868-9906-052E50C25F3B}.Release|x86.Build.0 = Release|x86
|
||||
{0A4279CF-2A67-4868-9906-052E50C25F3B}.Release|x86.Deploy.0 = Release|x86
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|x86.Build.0 = Release|Any CPU
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|x64.Build.0 = Debug|x64
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|x86.Build.0 = Debug|x86
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|ARM.Build.0 = Release|ARM
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|x64.ActiveCfg = Release|x64
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|x64.Build.0 = Release|x64
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|x64.Deploy.0 = Release|x64
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|x86.ActiveCfg = Release|x86
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|x86.Build.0 = Release|x86
|
||||
{7E80F5E7-724A-4668-9333-B10F5D75C6D0}.Release|x86.Deploy.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
33
ModernKeePass/Actions/NavigateToUrlAction.cs
Normal file
@@ -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 { return (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);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
14
ModernKeePass/Aop/DatabaseChanged.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using ModernKeePass.Services;
|
||||
|
||||
namespace ModernKeePass.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class DatabaseChangedAttribute: Attribute
|
||||
{
|
||||
public DatabaseChangedAttribute()
|
||||
{
|
||||
DatabaseService.Instance.HasChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
26
ModernKeePass/Aop/DatabaseChangedProxy.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.Reflection;
|
||||
using ModernKeePass.Interfaces;
|
||||
|
||||
namespace ModernKeePass.Aop
|
||||
{
|
||||
public class DatabaseChangedProxy<T>: IProxyInvocationHandler
|
||||
{
|
||||
private readonly T _decorated;
|
||||
private readonly IDatabaseService _databaseService;
|
||||
|
||||
public DatabaseChangedProxy(T decorated, IDatabaseService databaseService)
|
||||
{
|
||||
_decorated = decorated;
|
||||
_databaseService = databaseService;
|
||||
}
|
||||
|
||||
public object Invoke(object proxy, MethodInfo method, object[] parameters)
|
||||
{
|
||||
object retVal = null;
|
||||
retVal = method.Invoke(proxy, parameters);
|
||||
_databaseService.HasChanged = true;
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
}
|
@@ -10,8 +10,8 @@
|
||||
<ResourceDictionary Source="Styles/HamburgerButtonStyle.xaml" />
|
||||
<ResourceDictionary Source="Styles/ListViewLeftIndicatorStyle.xaml" />
|
||||
<ResourceDictionary Source="Styles/NoBorderButtonStyle.xaml" />
|
||||
<ResourceDictionary Source="Styles/TextBlockStyles.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
|
||||
</Application>
|
||||
|
@@ -1,14 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
using Windows.Data.Json;
|
||||
using Windows.Storage;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
using Microsoft.AppCenter;
|
||||
using Microsoft.AppCenter.Analytics;
|
||||
using Microsoft.AppCenter.Push;
|
||||
using ModernKeePass.Common;
|
||||
using ModernKeePass.Interfaces;
|
||||
using ModernKeePass.Exceptions;
|
||||
using ModernKeePass.Services;
|
||||
using ModernKeePass.Views;
|
||||
|
||||
// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227
|
||||
|
||||
@@ -19,19 +23,44 @@ namespace ModernKeePass
|
||||
/// </summary>
|
||||
sealed partial class App
|
||||
{
|
||||
public DatabaseHelper Database { get; set; } = new DatabaseHelper();
|
||||
|
||||
/// <summary>
|
||||
/// 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().
|
||||
/// </summary>
|
||||
public App()
|
||||
{
|
||||
AppCenter.Start("79d23520-a486-4f63-af81-8d90bf4e1bea", typeof(Analytics), typeof(Push));
|
||||
InitializeComponent();
|
||||
Suspending += OnSuspending;
|
||||
Resuming += OnResuming;
|
||||
UnhandledException += OnUnhandledException;
|
||||
}
|
||||
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
private 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;
|
||||
|
||||
if (realException is SaveException)
|
||||
{
|
||||
unhandledExceptionEventArgs.Handled = true;
|
||||
MessageDialogHelper.SaveErrorDialog(realException as SaveException, DatabaseService.Instance);
|
||||
}
|
||||
else if (realException is DatabaseOpenedException)
|
||||
{
|
||||
unhandledExceptionEventArgs.Handled = true;
|
||||
MessageDialogHelper.SaveUnchangedDialog(realException as DatabaseOpenedException, DatabaseService.Instance);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
@@ -71,7 +100,10 @@ namespace ModernKeePass
|
||||
|
||||
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
|
||||
{
|
||||
//TODO: Load state from previously suspended application
|
||||
//TODO: Load state from previously terminated application
|
||||
#if DEBUG
|
||||
MessageDialogHelper.ShowNotificationDialog("App terminated", "Windows or an error made the app terminate");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Place the frame in the current Window
|
||||
@@ -86,7 +118,7 @@ namespace ModernKeePass
|
||||
// When the navigation stack isn't restored navigate to the first page,
|
||||
// configuring the new page by passing required information as a navigation
|
||||
// parameter
|
||||
rootFrame.Navigate(typeof(Pages.MainPage), lauchActivatedEventArgs.Arguments);
|
||||
rootFrame.Navigate(typeof(MainPage), lauchActivatedEventArgs.Arguments);
|
||||
}
|
||||
/*else
|
||||
{
|
||||
@@ -106,6 +138,31 @@ namespace ModernKeePass
|
||||
Window.Current.Activate();
|
||||
}
|
||||
|
||||
private async void OnResuming(object sender, object e)
|
||||
{
|
||||
var currentFrame = Window.Current.Content as Frame;
|
||||
var database = DatabaseService.Instance;
|
||||
if (database.DatabaseFile == null)
|
||||
{
|
||||
#if DEBUG
|
||||
ToastNotificationHelper.ShowGenericToast("App suspended", "Nothing to do, no previous database opened");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
if (database.CompositeKey != null) await database.ReOpen();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
currentFrame?.Navigate(typeof(MainPage));
|
||||
#if DEBUG
|
||||
MessageDialogHelper.ShowErrorDialog(ex);
|
||||
#endif
|
||||
ToastNotificationHelper.ShowGenericToast("App suspended", "Database was closed (changes were saved)");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when Navigation to a certain page fails
|
||||
/// </summary>
|
||||
@@ -123,10 +180,21 @@ namespace ModernKeePass
|
||||
/// </summary>
|
||||
/// <param name="sender">The source of the suspend request.</param>
|
||||
/// <param name="e">Details about the suspend request.</param>
|
||||
private void OnSuspending(object sender, SuspendingEventArgs e)
|
||||
private async void OnSuspending(object sender, SuspendingEventArgs e)
|
||||
{
|
||||
var deferral = e.SuspendingOperation.GetDeferral();
|
||||
Database.Save();
|
||||
var database = DatabaseService.Instance;
|
||||
try
|
||||
{
|
||||
if (SettingsService.Instance.GetSetting("SaveSuspend", true)) database.Save();
|
||||
await database.Close(false);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
#if DEBUG
|
||||
ToastNotificationHelper.ShowErrorToast(exception);
|
||||
#endif
|
||||
}
|
||||
deferral.Complete();
|
||||
}
|
||||
|
||||
@@ -138,11 +206,12 @@ namespace ModernKeePass
|
||||
{
|
||||
base.OnFileActivated(args);
|
||||
var rootFrame = new Frame();
|
||||
Database.DatabaseFile = args.Files[0] as StorageFile;
|
||||
rootFrame.Navigate(typeof(Pages.MainPage), args);
|
||||
DatabaseService.Instance.DatabaseFile = args.Files[0] as StorageFile;
|
||||
rootFrame.Navigate(typeof(MainPage), args);
|
||||
Window.Current.Content = rootFrame;
|
||||
Window.Current.Activate();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 700 B |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 907 B |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1020 B After Width: | Height: | Size: 607 B |
BIN
ModernKeePass/Assets/ModernKeePass-SmallLogo.targetsize-16.png
Normal file
After Width: | Height: | Size: 463 B |
BIN
ModernKeePass/Assets/ModernKeePass-SmallLogo.targetsize-256.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
ModernKeePass/Assets/ModernKeePass-SmallLogo.targetsize-32.png
Normal file
After Width: | Height: | Size: 736 B |
BIN
ModernKeePass/Assets/ModernKeePass-SmallLogo.targetsize-48.png
Normal file
After Width: | Height: | Size: 980 B |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 700 B |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 907 B |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1020 B After Width: | Height: | Size: 607 B |
BIN
ModernKeePass/Assets/SmallLogo.targetsize-16.png
Normal file
After Width: | Height: | Size: 463 B |
BIN
ModernKeePass/Assets/SmallLogo.targetsize-256.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
ModernKeePass/Assets/SmallLogo.targetsize-32.png
Normal file
After Width: | Height: | Size: 736 B |
BIN
ModernKeePass/Assets/SmallLogo.targetsize-48.png
Normal file
After Width: | Height: | Size: 980 B |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 728 B |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 961 B |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -1,163 +0,0 @@
|
||||
using System;
|
||||
using Windows.Storage;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using ModernKeePass.ViewModels;
|
||||
using ModernKeePassLib;
|
||||
using ModernKeePassLib.Cryptography.KeyDerivation;
|
||||
using ModernKeePassLib.Interfaces;
|
||||
using ModernKeePassLib.Keys;
|
||||
using ModernKeePassLib.Serialization;
|
||||
|
||||
namespace ModernKeePass.Common
|
||||
{
|
||||
public class DatabaseHelper
|
||||
{
|
||||
public enum DatabaseStatus
|
||||
{
|
||||
Error = -3,
|
||||
NoCompositeKey = -2,
|
||||
CompositeKeyError = -1,
|
||||
Closed = 0,
|
||||
Opening = 1,
|
||||
Opened = 2
|
||||
}
|
||||
private readonly PwDatabase _pwDatabase = new PwDatabase();
|
||||
private StorageFile _databaseFile;
|
||||
private GroupVm _recycleBin;
|
||||
|
||||
public GroupVm RootGroup { get; set; }
|
||||
|
||||
public GroupVm RecycleBin
|
||||
{
|
||||
get { return _recycleBin; }
|
||||
set
|
||||
{
|
||||
_recycleBin = value;
|
||||
_pwDatabase.RecycleBinUuid = _recycleBin.IdUuid;
|
||||
}
|
||||
}
|
||||
|
||||
public DatabaseStatus Status { get; private set; } = DatabaseStatus.Closed;
|
||||
public string Name => DatabaseFile?.Name;
|
||||
|
||||
public bool RecycleBinEnabled
|
||||
{
|
||||
get { return _pwDatabase.RecycleBinEnabled; }
|
||||
set { _pwDatabase.RecycleBinEnabled = value; }
|
||||
}
|
||||
|
||||
public StorageFile DatabaseFile
|
||||
{
|
||||
get { return _databaseFile; }
|
||||
set
|
||||
{
|
||||
_databaseFile = value;
|
||||
Status = DatabaseStatus.Opening;
|
||||
}
|
||||
}
|
||||
|
||||
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; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open a KeePass database
|
||||
/// </summary>
|
||||
/// <param name="key">The database composite key</param>
|
||||
/// <param name="createNew">True to create a new database before opening it</param>
|
||||
/// <returns>An error message, if any</returns>
|
||||
public void Open(CompositeKey key, bool createNew = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (key == null) Status = DatabaseStatus.NoCompositeKey;
|
||||
var ioConnection = IOConnectionInfo.FromFile(DatabaseFile);
|
||||
if (createNew) _pwDatabase.New(ioConnection, key);
|
||||
else _pwDatabase.Open(ioConnection, key, new NullStatusLogger());
|
||||
|
||||
if (_pwDatabase.IsOpen)
|
||||
{
|
||||
Status = DatabaseStatus.Opened;
|
||||
RootGroup = new GroupVm(_pwDatabase.RootGroup, null, RecycleBinEnabled ? _pwDatabase.RecycleBinUuid : null);
|
||||
}
|
||||
}
|
||||
catch (InvalidCompositeKeyException)
|
||||
{
|
||||
Status = DatabaseStatus.CompositeKeyError;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Status = DatabaseStatus.Error;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the current database to another file and open it
|
||||
/// </summary>
|
||||
/// <param name="file">The new database file</param>
|
||||
internal void Save(StorageFile file)
|
||||
{
|
||||
DatabaseFile = file;
|
||||
_pwDatabase.SaveAs(IOConnectionInfo.FromFile(DatabaseFile), true, new NullStatusLogger());
|
||||
Status = DatabaseStatus.Opened;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Commit the changes to the currently opened database to file
|
||||
/// </summary>
|
||||
public bool Save()
|
||||
{
|
||||
if (_pwDatabase == null || !_pwDatabase.IsOpen) return false;
|
||||
try
|
||||
{
|
||||
_pwDatabase.Save(new NullStatusLogger());
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageDialogHelper.ShowErrorDialog(ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close the currently opened database
|
||||
/// </summary>
|
||||
public void Close()
|
||||
{
|
||||
_pwDatabase?.Close();
|
||||
Status = DatabaseStatus.Closed;
|
||||
}
|
||||
|
||||
public void AddDeletedItem(PwUuid id)
|
||||
{
|
||||
_pwDatabase.DeletedObjects.Add(new PwDeletedObject(id, DateTime.UtcNow));
|
||||
}
|
||||
|
||||
public void CreateRecycleBin()
|
||||
{
|
||||
RecycleBin = RootGroup.AddNewGroup("Recycle bin");
|
||||
RecycleBin.IsSelected = true;
|
||||
RecycleBin.IconSymbol = Symbol.Delete;
|
||||
}
|
||||
|
||||
public void UpdateCompositeKey(CompositeKey key)
|
||||
{
|
||||
_pwDatabase.MasterKey = key;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,18 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Windows.Storage.Pickers;
|
||||
using Windows.UI.Popups;
|
||||
using ModernKeePass.Exceptions;
|
||||
using ModernKeePass.Interfaces;
|
||||
|
||||
namespace ModernKeePass.Common
|
||||
{
|
||||
public static class MessageDialogHelper
|
||||
{
|
||||
public static async void ShowDeleteConfirmationDialog(string actionText, string contentText, UICommandInvokedHandler action)
|
||||
// TODO: include resources
|
||||
public static async void ShowActionDialog(string title, string contentText, string actionButtonText, string cancelButtonText, UICommandInvokedHandler actionCommand, UICommandInvokedHandler cancelCommand)
|
||||
{
|
||||
// Create the message dialog and set its content
|
||||
var messageDialog = new MessageDialog(contentText);
|
||||
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(actionText, action));
|
||||
messageDialog.Commands.Add(new UICommand("Cancel"));
|
||||
messageDialog.Commands.Add(new UICommand(actionButtonText, actionCommand));
|
||||
|
||||
// Show the message dialog
|
||||
await messageDialog.ShowAsync();
|
||||
}
|
||||
|
||||
public static void SaveErrorDialog(SaveException exception, IDatabaseService database)
|
||||
{
|
||||
ShowActionDialog("Save error", exception.InnerException.Message, "Save as", "Discard", async command =>
|
||||
{
|
||||
var savePicker = new FileSavePicker
|
||||
{
|
||||
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
|
||||
SuggestedFileName = $"{database.DatabaseFile.DisplayName} - copy"
|
||||
};
|
||||
savePicker.FileTypeChoices.Add("KeePass 2.x database", new List<string> { ".kdbx" });
|
||||
|
||||
var file = await savePicker.PickSaveFileAsync();
|
||||
if (file != null) database.Save(file);
|
||||
}, null);
|
||||
}
|
||||
|
||||
public static void SaveUnchangedDialog(DatabaseOpenedException exception, IDatabaseService database)
|
||||
{
|
||||
ShowActionDialog("Opened database", $"Database {database.Name} is currently opened. What to you wish to do?", "Save changes", "Discard", command =>
|
||||
{
|
||||
database.Save();
|
||||
database.Close();
|
||||
},
|
||||
command =>
|
||||
{
|
||||
database.Close();
|
||||
});
|
||||
}
|
||||
|
||||
public static async void ShowErrorDialog(Exception exception)
|
||||
{
|
||||
if (exception == null) return;
|
||||
// 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 void 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;
|
||||
@@ -20,20 +83,7 @@ namespace ModernKeePass.Common
|
||||
// Set the command to be invoked when escape is pressed
|
||||
messageDialog.CancelCommandIndex = 1;
|
||||
|
||||
// Show the message dialog
|
||||
await messageDialog.ShowAsync();
|
||||
}
|
||||
|
||||
public static async void ShowErrorDialog(Exception exception)
|
||||
{
|
||||
// Create the message dialog and set its content
|
||||
var messageDialog = new MessageDialog(exception.Message, "Error occured");
|
||||
|
||||
// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
|
||||
messageDialog.Commands.Add(new UICommand("OK"));
|
||||
|
||||
// Show the message dialog
|
||||
await messageDialog.ShowAsync();
|
||||
return messageDialog;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -32,5 +32,23 @@ namespace ModernKeePass.Common
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -6,18 +6,6 @@ namespace ModernKeePass.Controls
|
||||
{
|
||||
public class TextBoxWithButton : TextBox
|
||||
{
|
||||
/*public Symbol ButtonSymbol
|
||||
{
|
||||
get { return (Symbol)GetValue(ButtonSymbolProperty); }
|
||||
set { SetValue(ButtonSymbolProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty ButtonSymbolProperty =
|
||||
DependencyProperty.Register(
|
||||
"ButtonSymbol",
|
||||
typeof(Symbol),
|
||||
typeof(TextBoxWithButton),
|
||||
new PropertyMetadata(Symbol.Delete, (o, args) => { }));*/
|
||||
|
||||
public string ButtonSymbol
|
||||
{
|
||||
get { return (string)GetValue(ButtonSymbolProperty); }
|
||||
@@ -31,6 +19,31 @@ namespace ModernKeePass.Controls
|
||||
new PropertyMetadata("", (o, args) => { }));
|
||||
public event EventHandler<RoutedEventArgs> ButtonClick;
|
||||
|
||||
public string ButtonTooltip
|
||||
{
|
||||
get { return (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 { return (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();
|
||||
|
@@ -1,15 +1,15 @@
|
||||
using System;
|
||||
using Windows.UI.Text;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Data;
|
||||
|
||||
namespace ModernKeePass.Converters
|
||||
{
|
||||
public class BooleanToFontStyleConverter : IValueConverter
|
||||
class EmptyStringToVisibilityConverter: IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
var boolean = value is bool ? (bool)value : false;
|
||||
return boolean ? FontStyle.Italic : FontStyle.Normal;
|
||||
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)
|
9
ModernKeePass/Exceptions/DatabaseOpenedException.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace ModernKeePass.Exceptions
|
||||
{
|
||||
public class DatabaseOpenedException: Exception
|
||||
{
|
||||
|
||||
}
|
||||
}
|
14
ModernKeePass/Exceptions/SaveException.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace ModernKeePass.Exceptions
|
||||
{
|
||||
public class SaveException : Exception
|
||||
{
|
||||
public new Exception InnerException { get; }
|
||||
|
||||
public SaveException(Exception exception)
|
||||
{
|
||||
InnerException = exception;
|
||||
}
|
||||
}
|
||||
}
|
32
ModernKeePass/Extensions/DispatcherTaskExtensions.cs
Normal file
@@ -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<T> RunTaskAsync<T>(this CoreDispatcher dispatcher,
|
||||
Func<Task<T>> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal)
|
||||
{
|
||||
var taskCompletionSource = new TaskCompletionSource<T>();
|
||||
await dispatcher.RunAsync(priority, async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
taskCompletionSource.SetResult(await func());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
taskCompletionSource.SetException(ex);
|
||||
}
|
||||
});
|
||||
return await taskCompletionSource.Task;
|
||||
}
|
||||
|
||||
// There is no TaskCompletionSource<void> so we use a bool that we throw away.
|
||||
public static async Task RunTaskAsync(this CoreDispatcher dispatcher,
|
||||
Func<Task> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) =>
|
||||
await RunTaskAsync(dispatcher, async () => { await func(); return false; }, priority);
|
||||
}
|
||||
}
|
35
ModernKeePass/Interfaces/IDatabaseService.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using ModernKeePass.ViewModels;
|
||||
using ModernKeePassLib;
|
||||
using ModernKeePassLib.Cryptography.KeyDerivation;
|
||||
using ModernKeePassLib.Keys;
|
||||
|
||||
namespace ModernKeePass.Interfaces
|
||||
{
|
||||
public interface IDatabaseService
|
||||
{
|
||||
string Name { get; }
|
||||
bool RecycleBinEnabled { get; set; }
|
||||
//int Status { get; set; }
|
||||
GroupVm RootGroup { get; set; }
|
||||
GroupVm RecycleBin { get; set; }
|
||||
StorageFile DatabaseFile { get; set; }
|
||||
CompositeKey CompositeKey { get; set; }
|
||||
PwUuid DataCipher { get; set; }
|
||||
PwCompressionAlgorithm CompressionAlgorithm { get; set; }
|
||||
KdfParameters KeyDerivation { get; set; }
|
||||
bool IsOpen { get; }
|
||||
bool IsFileOpen { get; }
|
||||
bool IsClosed { get; }
|
||||
bool HasChanged { get; set; }
|
||||
|
||||
Task Open(CompositeKey key, bool createNew = false);
|
||||
Task ReOpen();
|
||||
void Save();
|
||||
void Save(StorageFile file);
|
||||
void CreateRecycleBin(string title);
|
||||
void AddDeletedItem(PwUuid id);
|
||||
Task Close(bool releaseFile = true);
|
||||
}
|
||||
}
|
12
ModernKeePass/Interfaces/ILicenseService.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel.Store;
|
||||
|
||||
namespace ModernKeePass.Interfaces
|
||||
{
|
||||
public interface ILicenseService
|
||||
{
|
||||
IReadOnlyDictionary<string, ProductListing> Products { get; }
|
||||
Task<int> Purchase(string addOn);
|
||||
}
|
||||
}
|
9
ModernKeePass/Interfaces/IProxyInvocationHandler.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace ModernKeePass.Interfaces
|
||||
{
|
||||
public interface IProxyInvocationHandler
|
||||
{
|
||||
object Invoke(object proxy, MethodInfo method, object[] parameters);
|
||||
}
|
||||
}
|
@@ -12,6 +12,7 @@ namespace ModernKeePass.Interfaces
|
||||
string Name { get; set; }
|
||||
string Path { get; }
|
||||
bool IsEditMode { get; }
|
||||
bool IsRecycleOnDelete { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Move a entity to the destination group
|
||||
@@ -33,6 +34,6 @@ namespace ModernKeePass.Interfaces
|
||||
/// <summary>
|
||||
/// Delete from ViewModel
|
||||
/// </summary>
|
||||
void MarkForDelete();
|
||||
void MarkForDelete(string recycleBinTitle);
|
||||
}
|
||||
}
|
11
ModernKeePass/Interfaces/IRecentItem.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Windows.Storage;
|
||||
|
||||
namespace ModernKeePass.Interfaces
|
||||
{
|
||||
public interface IRecentItem
|
||||
{
|
||||
StorageFile DatabaseFile { get; }
|
||||
string Token { get; }
|
||||
string Name { get; }
|
||||
}
|
||||
}
|
15
ModernKeePass/Interfaces/IRecentService.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
|
||||
namespace ModernKeePass.Interfaces
|
||||
{
|
||||
public interface IRecentService
|
||||
{
|
||||
int EntryCount { get; }
|
||||
Task<IStorageItem> GetFileAsync(string token);
|
||||
ObservableCollection<IRecentItem> GetAllFiles(bool removeIfNonExistant = true);
|
||||
void Add(IStorageItem file, string metadata);
|
||||
void ClearAll();
|
||||
}
|
||||
}
|
7
ModernKeePass/Interfaces/IResourceService.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace ModernKeePass.Interfaces
|
||||
{
|
||||
public interface IResourceService
|
||||
{
|
||||
string GetResourceValue(string key);
|
||||
}
|
||||
}
|
8
ModernKeePass/Interfaces/ISettingsService.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace ModernKeePass.Interfaces
|
||||
{
|
||||
public interface ISettingsService
|
||||
{
|
||||
T GetSetting<T>(string property, T defaultValue = default(T));
|
||||
void PutSetting<T>(string property, T value);
|
||||
}
|
||||
}
|
@@ -109,32 +109,65 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Actions\ClipboardAction.cs" />
|
||||
<Compile Include="Actions\NavigateToUrlAction.cs" />
|
||||
<Compile Include="Actions\SetupFocusAction.cs" />
|
||||
<Compile Include="Aop\DatabaseChangedProxy.cs" />
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Common\DatabaseHelper.cs" />
|
||||
<Compile Include="Aop\DatabaseChanged.cs" />
|
||||
<Compile Include="Exceptions\DatabaseOpenedException.cs" />
|
||||
<Compile Include="Interfaces\ILicenseService.cs" />
|
||||
<Compile Include="Interfaces\IProxyInvocationHandler.cs" />
|
||||
<Compile Include="Interfaces\IRecentService.cs" />
|
||||
<Compile Include="Interfaces\IRecentItem.cs" />
|
||||
<Compile Include="Interfaces\IResourceService.cs" />
|
||||
<Compile Include="Services\SingletonServiceBase.cs" />
|
||||
<Compile Include="TemplateSelectors\SelectableDataTemplateSelector.cs" />
|
||||
<Compile Include="ViewModels\Items\SettingsSaveVm.cs" />
|
||||
<Compile Include="Views\MainPageFrames\DonatePage.xaml.cs">
|
||||
<DependentUpon>DonatePage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Services\DatabaseService.cs" />
|
||||
<Compile Include="Interfaces\ISettingsService.cs" />
|
||||
<Compile Include="Common\MessageDialogHelper.cs" />
|
||||
<Compile Include="Common\NavigationHelper.cs" />
|
||||
<Compile Include="Common\NotifyPropertyChangedBase.cs" />
|
||||
<Compile Include="Common\ObservableDictionary.cs" />
|
||||
<Compile Include="Common\RelayCommand.cs" />
|
||||
<Compile Include="Common\SuspensionManager.cs" />
|
||||
<Compile Include="Services\LicenseService.cs" />
|
||||
<Compile Include="Services\RecentService.cs" />
|
||||
<Compile Include="Services\ResourcesService.cs" />
|
||||
<Compile Include="Services\SettingsService.cs" />
|
||||
<Compile Include="Common\ToastNotificationHelper.cs" />
|
||||
<Compile Include="Converters\DiscreteIntToSolidColorBrushConverter.cs" />
|
||||
<Compile Include="Converters\EmptyStringToVisibilityConverter.cs" />
|
||||
<Compile Include="Converters\NullToBooleanConverter.cs" />
|
||||
<Compile Include="Exceptions\SaveException.cs" />
|
||||
<Compile Include="Extensions\DispatcherTaskExtensions.cs" />
|
||||
<Compile Include="Interfaces\IDatabaseService.cs" />
|
||||
<Compile Include="Interfaces\IHasSelectableObject.cs" />
|
||||
<Compile Include="Interfaces\ISelectableModel.cs" />
|
||||
<Compile Include="Pages\BasePages\LayoutAwarePageBase.cs" />
|
||||
<Compile Include="Pages\SettingsPageFrames\SettingsDatabasePage.xaml.cs">
|
||||
<Compile Include="Views\BasePages\LayoutAwarePageBase.cs" />
|
||||
<Compile Include="Views\SettingsPageFrames\SettingsDatabasePage.xaml.cs">
|
||||
<DependentUpon>SettingsDatabasePage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\SettingsPageFrames\SettingsSecurityPage.xaml.cs">
|
||||
<Compile Include="Views\SettingsPageFrames\SettingsNewDatabasePage.xaml.cs">
|
||||
<DependentUpon>SettingsNewDatabasePage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsPageFrames\SettingsSavePage.xaml.cs">
|
||||
<DependentUpon>SettingsSavePage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsPageFrames\SettingsSecurityPage.xaml.cs">
|
||||
<DependentUpon>SettingsSecurityPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsPageFrames\SettingsWelcomePage.xaml.cs">
|
||||
<DependentUpon>SettingsWelcomePage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="TemplateSelectors\FirstItemDataTemplateSelector.cs" />
|
||||
<Compile Include="Controls\ListViewWithDisable.cs" />
|
||||
<Compile Include="Controls\CompositeKeyUserControl.xaml.cs">
|
||||
<Compile Include="Views\UserControls\CompositeKeyUserControl.xaml.cs">
|
||||
<DependentUpon>CompositeKeyUserControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TextBoxWithButton.cs" />
|
||||
@@ -142,27 +175,26 @@
|
||||
<Compile Include="Converters\ColorToBrushConverter.cs" />
|
||||
<Compile Include="Converters\DoubleToSolidColorBrushConverter.cs" />
|
||||
<Compile Include="Converters\InverseBooleanToVisibilityConverter.cs" />
|
||||
<Compile Include="Converters\BooleanToFontStyleConverter.cs" />
|
||||
<Compile Include="Converters\PluralizationConverter.cs" />
|
||||
<Compile Include="Converters\ProgressBarLegalValuesConverter.cs" />
|
||||
<Compile Include="Converters\TextToWidthConverter.cs" />
|
||||
<Compile Include="Events\PasswordEventArgs.cs" />
|
||||
<Compile Include="Interfaces\IIsEnabled.cs" />
|
||||
<Compile Include="Interfaces\IPwEntity.cs" />
|
||||
<Compile Include="Pages\MainPage.xaml.cs">
|
||||
<Compile Include="Views\MainPage.xaml.cs">
|
||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Mappings\PwIconToSegoeMapping.cs" />
|
||||
<Compile Include="Pages\MainPageFrames\AboutPage.xaml.cs">
|
||||
<Compile Include="Views\MainPageFrames\AboutPage.xaml.cs">
|
||||
<DependentUpon>AboutPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\MainPageFrames\NewDatabasePage.xaml.cs">
|
||||
<Compile Include="Views\MainPageFrames\NewDatabasePage.xaml.cs">
|
||||
<DependentUpon>NewDatabasePage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\SettingsPage.xaml.cs">
|
||||
<Compile Include="Views\SettingsPage.xaml.cs">
|
||||
<DependentUpon>SettingsPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\MainPageFrames\WelcomePage.xaml.cs">
|
||||
<Compile Include="Views\MainPageFrames\WelcomePage.xaml.cs">
|
||||
<DependentUpon>WelcomePage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ViewModels\AboutVm.cs" />
|
||||
@@ -170,24 +202,25 @@
|
||||
<Compile Include="ViewModels\Items\ListMenuItemVm.cs" />
|
||||
<Compile Include="ViewModels\Items\MainMenuItemVm.cs" />
|
||||
<Compile Include="ViewModels\Items\RecentItemVm.cs" />
|
||||
<Compile Include="Pages\EntryDetailPage.xaml.cs">
|
||||
<Compile Include="Views\EntryDetailPage.xaml.cs">
|
||||
<DependentUpon>EntryDetailPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\GroupDetailPage.xaml.cs">
|
||||
<Compile Include="Views\GroupDetailPage.xaml.cs">
|
||||
<DependentUpon>GroupDetailPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\MainPageFrames\OpenDatabasePage.xaml.cs">
|
||||
<Compile Include="Views\MainPageFrames\OpenDatabasePage.xaml.cs">
|
||||
<DependentUpon>OpenDatabasePage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\MainPageFrames\RecentDatabasesPage.xaml.cs">
|
||||
<Compile Include="Views\MainPageFrames\RecentDatabasesPage.xaml.cs">
|
||||
<DependentUpon>RecentDatabasesPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\MainPageFrames\SaveDatabasePage.xaml.cs">
|
||||
<Compile Include="Views\MainPageFrames\SaveDatabasePage.xaml.cs">
|
||||
<DependentUpon>SaveDatabasePage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ViewModels\EntryVm.cs" />
|
||||
<Compile Include="ViewModels\GroupVm.cs" />
|
||||
<Compile Include="ViewModels\Items\SettingsNewVm.cs" />
|
||||
<Compile Include="ViewModels\SettingsVm.cs" />
|
||||
<Compile Include="ViewModels\MainVm.cs" />
|
||||
<Compile Include="ViewModels\NewVm.cs" />
|
||||
@@ -200,11 +233,13 @@
|
||||
<AppxManifest Include="Package.appxmanifest">
|
||||
<SubType>Designer</SubType>
|
||||
</AppxManifest>
|
||||
<None Include="ModernKeePass_StoreKey.pfx" />
|
||||
<None Include="ModernKeePass_TemporaryKey.pfx" />
|
||||
<None Include="packages.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<PRIResource Include="Strings\fr-FR\Resources.resw" />
|
||||
<PRIResource Include="Strings\fr-FR\CodeBehind.resw" />
|
||||
<PRIResource Include="Strings\en-US\CodeBehind.resw" />
|
||||
<PRIResource Include="Strings\en-US\Resources.resw" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Package.StoreAssociation.xml" />
|
||||
@@ -214,55 +249,71 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="Controls\CompositeKeyUserControl.xaml">
|
||||
<Page Include="Views\SettingsPageFrames\SettingsSavePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\MainPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Pages\MainPageFrames\AboutPage.xaml">
|
||||
<Page Include="Views\UserControls\CompositeKeyUserControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\EntryDetailPage.xaml">
|
||||
<Page Include="Views\MainPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views\MainPageFrames\AboutPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\GroupDetailPage.xaml">
|
||||
<Page Include="Views\EntryDetailPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\MainPageFrames\NewDatabasePage.xaml">
|
||||
<Page Include="Views\GroupDetailPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\MainPageFrames\OpenDatabasePage.xaml">
|
||||
<Page Include="Views\MainPageFrames\DonatePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\MainPageFrames\RecentDatabasesPage.xaml">
|
||||
<Page Include="Views\MainPageFrames\NewDatabasePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\MainPageFrames\SaveDatabasePage.xaml">
|
||||
<Page Include="Views\MainPageFrames\OpenDatabasePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\SettingsPage.xaml">
|
||||
<Page Include="Views\MainPageFrames\RecentDatabasesPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\MainPageFrames\WelcomePage.xaml">
|
||||
<Page Include="Views\MainPageFrames\SaveDatabasePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\SettingsPageFrames\SettingsDatabasePage.xaml">
|
||||
<Page Include="Views\SettingsPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\SettingsPageFrames\SettingsSecurityPage.xaml">
|
||||
<Page Include="Views\MainPageFrames\WelcomePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsPageFrames\SettingsDatabasePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsPageFrames\SettingsNewDatabasePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsPageFrames\SettingsSecurityPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsPageFrames\SettingsWelcomePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
@@ -281,6 +332,11 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Page>
|
||||
<Page Include="Styles\TextBlockStyles.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Page>
|
||||
<Page Include="Styles\TextBoxWithButtonStyle.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
@@ -292,12 +348,24 @@
|
||||
<HintPath>..\packages\Portable.BouncyCastle.1.8.1.3\lib\netstandard1.0\BouncyCastle.Crypto.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AppCenter, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AppCenter.1.5.0\lib\portable-net45+win8+wpa81+wp8\Microsoft.AppCenter.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AppCenter.Analytics, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AppCenter.Analytics.1.5.0\lib\portable-net45+win8+wpa81+wp8\Microsoft.AppCenter.Analytics.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AppCenter.Push, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AppCenter.Push.1.5.0\lib\portable-net45+win8+wpa81+wp8\Microsoft.AppCenter.Push.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Toolkit.Uwp.Notifications, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Toolkit.Uwp.Notifications.2.0.0\lib\dotnet\Microsoft.Toolkit.Uwp.Notifications.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="ModernKeePassLib, Version=2.37.0.2000, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ModernKeePassLib.2.37.6000\lib\netstandard1.2\ModernKeePassLib.dll</HintPath>
|
||||
<HintPath>..\packages\ModernKeePassLib.2.38.2\lib\netstandard1.2\ModernKeePassLib.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
@@ -319,31 +387,63 @@
|
||||
</SDKReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="appMetadata\en-us\baselisting\description.txt" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\description.Entry.txt" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\description.Filter.txt" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\description.Group.txt" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\description.New.txt" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\description.Open.txt" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\description.Recent.txt" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\description.Semantic.txt" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\description.Settings.txt" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\Entry.png" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\Filter.png" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\Group.png" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\New.png" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\Open.png" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\Recent.png" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\Semantic.png" />
|
||||
<Content Include="appMetadata\en-us\baselisting\images\Screenshot\Settings.png" />
|
||||
<Content Include="appMetadata\en-us\baselisting\keywords.txt" />
|
||||
<Content Include="appMetadata\en-us\baselisting\privacyPolicy.txt" />
|
||||
<Content Include="appMetadata\en-us\baselisting\releaseNotes.txt" />
|
||||
<Content Include="appMetadata\en-us\baselisting\websiteUrl.txt" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\description.txt" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\description.Entry.txt" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\description.Filter.txt" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\description.Group.txt" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\description.New.txt" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\description.Open.txt" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\description.Recent.txt" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\description.Semantic.txt" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\description.Settings.txt" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\Entry.png" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\Filter.png" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\Group.png" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\New.png" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\Open.png" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\Recent.png" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\Semantic.png" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\images\Screenshot\Settings.png" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\keywords.txt" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\privacyPolicy.txt" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\releaseNotes.txt" />
|
||||
<Content Include="appMetadata\fr-fr\baselisting\websiteUrl.txt" />
|
||||
<Content Include="Assets\Logo.scale-100.png" />
|
||||
<Content Include="Assets\Logo.scale-140.png" />
|
||||
<Content Include="Assets\Logo.scale-180.png" />
|
||||
<Content Include="Assets\Logo.scale-80.png" />
|
||||
<Content Include="Assets\ModernKeePass-Logo.scale-100.png" />
|
||||
<Content Include="Assets\ModernKeePass-Logo.scale-140.png" />
|
||||
<Content Include="Assets\ModernKeePass-Logo.scale-180.png" />
|
||||
<Content Include="Assets\ModernKeePass-Logo.scale-80.png" />
|
||||
<Content Include="Assets\ModernKeePass-SmallLogo.scale-100.png" />
|
||||
<Content Include="Assets\ModernKeePass-SmallLogo.scale-140.png" />
|
||||
<Content Include="Assets\ModernKeePass-SmallLogo.scale-180.png" />
|
||||
<Content Include="Assets\ModernKeePass-SmallLogo.scale-80.png" />
|
||||
<Content Include="Assets\ModernKeePass-SmallLogo.targetsize-16.png" />
|
||||
<Content Include="Assets\ModernKeePass-SmallLogo.targetsize-256.png" />
|
||||
<Content Include="Assets\ModernKeePass-SmallLogo.targetsize-32.png" />
|
||||
<Content Include="Assets\ModernKeePass-SmallLogo.targetsize-48.png" />
|
||||
<Content Include="Assets\ModernKeePass-SplashScreen.scale-100.png" />
|
||||
<Content Include="Assets\ModernKeePass-SplashScreen.scale-140.png" />
|
||||
<Content Include="Assets\ModernKeePass-SplashScreen.scale-180.png" />
|
||||
<Content Include="Assets\ModernKeePass-StoreLogo.scale-100.png" />
|
||||
<Content Include="Assets\ModernKeePass-StoreLogo.scale-140.png" />
|
||||
<Content Include="Assets\ModernKeePass-StoreLogo.scale-180.png" />
|
||||
<Content Include="Assets\SmallLogo.scale-100.png" />
|
||||
<Content Include="Assets\SmallLogo.scale-140.png" />
|
||||
<Content Include="Assets\SmallLogo.scale-180.png" />
|
||||
<Content Include="Assets\SmallLogo.scale-80.png" />
|
||||
<Content Include="Assets\SplashScreen.scale-100.png" />
|
||||
<Content Include="Assets\SplashScreen.scale-140.png" />
|
||||
<Content Include="Assets\SplashScreen.scale-180.png" />
|
||||
<Content Include="Assets\Square310x310Logo.scale-100.png" />
|
||||
<Content Include="Assets\Square310x310Logo.scale-140.png" />
|
||||
<Content Include="Assets\Square310x310Logo.scale-180.png" />
|
||||
|
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest">
|
||||
<Identity Name="wismna.ModernKeePass" Publisher="CN=0719A91A-C322-4EE0-A257-E60733EECF06" Version="1.8.0.28" />
|
||||
<Identity Name="wismna.ModernKeePass" Publisher="CN=0719A91A-C322-4EE0-A257-E60733EECF06" Version="1.13.0.32" />
|
||||
<Properties>
|
||||
<DisplayName>ModernKeePass</DisplayName>
|
||||
<PublisherDisplayName>wismna</PublisherDisplayName>
|
||||
<Logo>Assets\ModernKeePass-StoreLogo.png</Logo>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
<Prerequisites>
|
||||
<OSMinVersion>6.3.0</OSMinVersion>
|
||||
@@ -15,10 +15,10 @@
|
||||
</Resources>
|
||||
<Applications>
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="ModernKeePass.App">
|
||||
<m2:VisualElements DisplayName="ModernKeePass" Square150x150Logo="Assets\ModernKeePass-Logo.png" Square30x30Logo="Assets\ModernKeePass-SmallLogo.png" Description="A port of the KeePass application for the Windows store. You can create, open and edit KeePass 2.x password databases in a modern fashion." ForegroundText="light" BackgroundColor="#464646" ToastCapable="true">
|
||||
<m2:VisualElements DisplayName="ModernKeePass" Square150x150Logo="Assets\Logo.png" Square30x30Logo="Assets\ModernKeePass-SmallLogo.png" Description="A port of the KeePass application for the Windows store. You can create, open and edit KeePass 2.x password databases in a modern fashion." ForegroundText="light" BackgroundColor="#7755c4" ToastCapable="true">
|
||||
<m2:DefaultTile Square310x310Logo="Assets\Square310x310Logo.png" Wide310x150Logo="Assets\Wide310x150Logo.png" Square70x70Logo="Assets\Square70x70Logo.png">
|
||||
</m2:DefaultTile>
|
||||
<m2:SplashScreen Image="Assets\ModernKeePass-SplashScreen.png" />
|
||||
<m2:SplashScreen Image="Assets\ModernKeePass-SplashScreen.png" BackgroundColor="#7755c4" />
|
||||
</m2:VisualElements>
|
||||
<Extensions>
|
||||
<Extension Category="windows.fileOpenPicker">
|
||||
|
@@ -1,304 +0,0 @@
|
||||
<Page
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
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:actions="using:ModernKeePass.Actions"
|
||||
xmlns:templateSelectors="using:ModernKeePass.TemplateSelectors"
|
||||
x:Name="PageRoot"
|
||||
x:Class="ModernKeePass.Pages.GroupDetailPage"
|
||||
mc:Ignorable="d" >
|
||||
<Page.Resources>
|
||||
<SolidColorBrush x:Key="Transparent" Color="Transparent"/>
|
||||
<SolidColorBrush x:Key="SystemColor" Color="{StaticResource SystemColorButtonFaceColor}" />
|
||||
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
|
||||
<converters:BooleanToFontStyleConverter x:Key="BooleanToFontStyleConverter"/>
|
||||
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||
<converters:NullToBooleanConverter x:Key="NullToBooleanConverter"/>
|
||||
</Page.Resources>
|
||||
<Page.DataContext>
|
||||
<viewModels:GroupVm />
|
||||
</Page.DataContext>
|
||||
<Page.BottomAppBar>
|
||||
<CommandBar x:Name="CommandBar" VerticalAlignment="Center">
|
||||
<CommandBar.SecondaryCommands>
|
||||
<AppBarButton Icon="Save" Label="Save">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<core:EventTriggerBehavior EventName="Click">
|
||||
<core:CallMethodAction TargetObject="{Binding}" MethodName="Save"/>
|
||||
<core:ChangePropertyAction TargetObject="{Binding ElementName=CommandBar}" PropertyName="IsOpen" Value="False" />
|
||||
</core:EventTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</AppBarButton>
|
||||
<AppBarButton Icon="Setting" Label="Settings">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<core:EventTriggerBehavior EventName="Click">
|
||||
<core:NavigateToPageAction TargetPage="ModernKeePass.Pages.SettingsPage" />
|
||||
</core:EventTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</AppBarButton>
|
||||
</CommandBar.SecondaryCommands>
|
||||
<AppBarToggleButton Icon="Edit" Label="Edit" IsChecked="{Binding IsEditMode, Mode=TwoWay}">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<core:EventTriggerBehavior EventName="Click">
|
||||
<core:ChangePropertyAction TargetObject="{Binding ElementName=CommandBar}" PropertyName="IsOpen" Value="False" />
|
||||
</core:EventTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</AppBarToggleButton>
|
||||
<AppBarButton Icon="Undo" Label="Restore" Visibility="{Binding ShowRestore, Converter={StaticResource BooleanToVisibilityConverter}}" IsEnabled="{Binding PreviousGroup, Converter={StaticResource NullToBooleanConverter}}" Click="RestoreButton_Click">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<core:EventTriggerBehavior EventName="Click">
|
||||
<core:CallMethodAction MethodName="UndoDelete" TargetObject="{Binding}" />
|
||||
</core:EventTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</AppBarButton>
|
||||
<AppBarButton Icon="Delete" Label="Delete" IsEnabled="{Binding IsNotRoot}" Click="DeleteButton_Click" />
|
||||
</CommandBar>
|
||||
</Page.BottomAppBar>
|
||||
<Grid>
|
||||
<Grid.Resources>
|
||||
<CollectionViewSource
|
||||
x:Name="GroupsViewSource"
|
||||
Source="{Binding Groups}" />
|
||||
<CollectionViewSource
|
||||
x:Name="EntriesViewSource"
|
||||
Source="{Binding Entries}" />
|
||||
<CollectionViewSource
|
||||
x:Name="EntriesZoomedOutViewSource"
|
||||
Source="{Binding EntriesZoomedOut}" IsSourceGrouped="True"/>
|
||||
</Grid.Resources>
|
||||
<Grid.Background>
|
||||
<StaticResource ResourceKey="ApplicationPageBackgroundThemeBrush"/>
|
||||
</Grid.Background>
|
||||
<Grid.ChildrenTransitions>
|
||||
<TransitionCollection>
|
||||
<EntranceThemeTransition/>
|
||||
</TransitionCollection>
|
||||
</Grid.ChildrenTransitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="50"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ListView
|
||||
Grid.Column="0"
|
||||
x:Name="LeftListView"
|
||||
Margin="0,0,0,-10"
|
||||
SelectionChanged="groups_SelectionChanged"
|
||||
IsSwipeEnabled="false"
|
||||
IsSynchronizedWithCurrentItem="False"
|
||||
DataContext="{Binding DataContext, ElementName=PageRoot}"
|
||||
RequestedTheme="Dark"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
||||
Foreground="{ThemeResource DefaultTextForegroundThemeBrush}">
|
||||
<ListView.Resources>
|
||||
<DataTemplate x:Name="Collapsed">
|
||||
<SymbolIcon Symbol="{Binding IconSymbol}" Margin="8,0,0,0">
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip Content="{Binding Name}" />
|
||||
</ToolTipService.ToolTip>
|
||||
</SymbolIcon>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Name="Expanded">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<SymbolIcon Symbol="{Binding IconSymbol}" Margin="8,0,0,0" />
|
||||
<TextBlock Text="{Binding Name}" FontWeight="{Binding FontWeight}" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="30,0,20,0" FontStyle="{Binding IsSelected, Converter={StaticResource BooleanToFontStyleConverter}}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListView.Resources>
|
||||
<ListView.ItemsSource>
|
||||
<Binding Source="{StaticResource GroupsViewSource}"/>
|
||||
</ListView.ItemsSource>
|
||||
<ListView.ItemContainerStyle>
|
||||
<Style TargetType="ListViewItem">
|
||||
<Setter Property="VerticalContentAlignment" Value="Stretch" />
|
||||
<!--<Setter Property="HorizontalContentAlignment" Value="Center" />-->
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="Margin" Value="0"/>
|
||||
</Style>
|
||||
</ListView.ItemContainerStyle>
|
||||
<ListView.HeaderTemplate>
|
||||
<DataTemplate>
|
||||
<ToggleButton Style="{StaticResource HamburgerToggleButton}">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<core:EventTriggerBehavior EventName="Loaded">
|
||||
<core:ChangePropertyAction PropertyName="ItemTemplate" Value="{StaticResource Collapsed}" TargetObject="{Binding ElementName=LeftListView}"/>
|
||||
</core:EventTriggerBehavior>
|
||||
<core:EventTriggerBehavior EventName="Checked">
|
||||
<core:ChangePropertyAction PropertyName="ItemTemplate" Value="{StaticResource Expanded}" TargetObject="{Binding ElementName=LeftListView}"/>
|
||||
</core:EventTriggerBehavior>
|
||||
<core:EventTriggerBehavior EventName="Unchecked">
|
||||
<core:ChangePropertyAction PropertyName="ItemTemplate" Value="{StaticResource Collapsed}" TargetObject="{Binding ElementName=LeftListView}"/>
|
||||
</core:EventTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</ToggleButton>
|
||||
</DataTemplate>
|
||||
</ListView.HeaderTemplate>
|
||||
</ListView>
|
||||
<!-- Horizontal scrolling grid -->
|
||||
<SemanticZoom Grid.Column="1" ViewChangeStarted="SemanticZoom_ViewChangeStarted" Margin="0,30,0,0">
|
||||
<SemanticZoom.ZoomedInView>
|
||||
<GridView
|
||||
x:Name="GridView"
|
||||
AutomationProperties.AutomationId="ItemGridView"
|
||||
AutomationProperties.Name="Entries"
|
||||
TabIndex="1"
|
||||
SelectionChanged="entries_SelectionChanged"
|
||||
IsSynchronizedWithCurrentItem="False">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="False">
|
||||
<actions:SetupFocusAction TargetObject="{Binding ElementName=GridView}" />
|
||||
</core:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
<GridView.Resources>
|
||||
<DataTemplate x:Name="GroupFirstItem">
|
||||
<Border
|
||||
BorderThickness="2"
|
||||
BorderBrush="{StaticResource SystemColor}"
|
||||
Background="{StaticResource HubSectionHeaderPressedForegroundThemeBrush}">
|
||||
<Grid Height="110" Width="480">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<SymbolIcon Grid.Column="0" Symbol="{Binding IconSymbol}" Width="100" Height="100" RenderTransformOrigin="0.5,0.5" Foreground="{ThemeResource TextBoxBackgroundThemeBrush}" >
|
||||
<SymbolIcon.RenderTransform>
|
||||
<CompositeTransform ScaleX="2" TranslateX="0" TranslateY="0" ScaleY="2"/>
|
||||
</SymbolIcon.RenderTransform>
|
||||
</SymbolIcon>
|
||||
<TextBlock Grid.Column="1" Text="{Binding Name}" FontWeight="Bold" Style="{ThemeResource TitleTextBlockStyle}" Foreground="{ThemeResource TextBoxBackgroundThemeBrush}" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="13,0,0,5"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Name="GroupOtherItem">
|
||||
<Grid Height="110" Width="480" x:Name="EntryGrid" >
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border
|
||||
Grid.Column="0"
|
||||
BorderThickness="2"
|
||||
BorderBrush="{StaticResource SystemColor}"
|
||||
Background="{Binding BackgroundColor, ConverterParameter={StaticResource Transparent}, Converter={StaticResource ColorToBrushConverter}}">
|
||||
<SymbolIcon Symbol="{Binding IconSymbol}" Width="100" Height="100" RenderTransformOrigin="0.5,0.5" >
|
||||
<SymbolIcon.RenderTransform>
|
||||
<CompositeTransform ScaleX="2" TranslateX="0" TranslateY="0" ScaleY="2"/>
|
||||
</SymbolIcon.RenderTransform>
|
||||
</SymbolIcon>
|
||||
</Border>
|
||||
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,10,0,0" >
|
||||
<TextBlock x:Name="NameTextBlock" Text="{Binding Name}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" Foreground="{Binding ForegroundColor, ConverterParameter={StaticResource TextBoxForegroundThemeBrush}, Converter={StaticResource ColorToBrushConverter}}"/>
|
||||
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
|
||||
<TextBlock Text="{Binding UserName}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
|
||||
<TextBlock Text="{Binding Url}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</GridView.Resources>
|
||||
<GridView.ItemsSource>
|
||||
<Binding Source="{StaticResource EntriesViewSource}"/>
|
||||
</GridView.ItemsSource>
|
||||
<GridView.DataContext>
|
||||
<viewModels:EntryVm/>
|
||||
</GridView.DataContext>
|
||||
<GridView.ItemTemplateSelector>
|
||||
<templateSelectors:FirstItemDataTemplateSelector
|
||||
FirstItem="{StaticResource GroupFirstItem}"
|
||||
OtherItem="{StaticResource GroupOtherItem}" />
|
||||
</GridView.ItemTemplateSelector>
|
||||
<GridView.ItemContainerStyle>
|
||||
<Style TargetType="FrameworkElement">
|
||||
<Setter Property="Margin" Value="52,0,0,2"/>
|
||||
</Style>
|
||||
</GridView.ItemContainerStyle>
|
||||
</GridView>
|
||||
</SemanticZoom.ZoomedInView>
|
||||
|
||||
<SemanticZoom.ZoomedOutView>
|
||||
<ListView
|
||||
x:Name="SemanticListView"
|
||||
ItemsSource="{Binding Source={StaticResource EntriesZoomedOutViewSource}}"
|
||||
IsSwipeEnabled="false"
|
||||
SelectionChanged="groups_SelectionChanged"
|
||||
IsSynchronizedWithCurrentItem="False">
|
||||
<ListView.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListView.ItemsPanel>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock Text="{Binding Name}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
<ListView.GroupStyle>
|
||||
<GroupStyle HidesIfEmpty="True">
|
||||
<GroupStyle.HeaderTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Background="LightGray" Margin="0,0,10,0" HorizontalAlignment="Left">
|
||||
<TextBlock Text="{Binding Key}" Width="40" Foreground="Black" Margin="30" Style="{StaticResource HeaderTextBlockStyle}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</GroupStyle.HeaderTemplate>
|
||||
</GroupStyle>
|
||||
</ListView.GroupStyle>
|
||||
</ListView>
|
||||
</SemanticZoom.ZoomedOutView>
|
||||
</SemanticZoom>
|
||||
|
||||
</Grid>
|
||||
<!-- Back button and page title -->
|
||||
<Grid Grid.Row="0" Background="{ThemeResource AppBarBackgroundThemeBrush}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="60"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="400"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="0"
|
||||
x:Name="BackButton"
|
||||
Command="{Binding NavigationHelper.GoBackCommand, ElementName=PageRoot}"
|
||||
Height="50"
|
||||
Width="50"
|
||||
VerticalAlignment="Center"
|
||||
AutomationProperties.Name="Back"
|
||||
AutomationProperties.AutomationId="BackButton"
|
||||
AutomationProperties.ItemType="Navigation Button"
|
||||
Style="{StaticResource NoBorderButtonStyle}">
|
||||
<SymbolIcon Symbol="Back" />
|
||||
</Button>
|
||||
<StackPanel Grid.Column="1" >
|
||||
<TextBox
|
||||
x:Name="TitleTextBox"
|
||||
Text="{Binding Name, Mode=TwoWay}"
|
||||
Foreground="{ThemeResource DefaultTextForegroundThemeBrush}"
|
||||
Background="Transparent"
|
||||
IsHitTestVisible="{Binding IsEditMode}"
|
||||
BorderThickness="0"
|
||||
FontSize="20"
|
||||
FontWeight="SemiBold"
|
||||
TextWrapping="NoWrap"
|
||||
VerticalAlignment="Center"
|
||||
PlaceholderText="New group name...">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="True">
|
||||
<actions:SetupFocusAction TargetObject="{Binding ElementName=TitleTextBox}" />
|
||||
</core:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</TextBox>
|
||||
<TextBlock FontSize="12" Text="{Binding Path}" />
|
||||
</StackPanel>
|
||||
<SearchBox Grid.Column="2" PlaceholderText="Search..." Width="350" Background="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" BorderThickness="0" FontSize="18" SuggestionsRequested="SearchBox_OnSuggestionsRequested" SearchHistoryEnabled="False" ResultSuggestionChosen="SearchBox_OnResultSuggestionChosen" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Page>
|
@@ -1,48 +0,0 @@
|
||||
<Page
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="using:ModernKeePass.ViewModels"
|
||||
xmlns:local="using:ModernKeePass.Controls"
|
||||
xmlns:converters="using:ModernKeePass.Converters"
|
||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
|
||||
x:Class="ModernKeePass.Pages.RecentDatabasesPage"
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||
<CollectionViewSource x:Name="RecentItemsSource" Source="{Binding RecentItems}" />
|
||||
</Page.Resources>
|
||||
<Page.DataContext>
|
||||
<viewModels:RecentVm/>
|
||||
</Page.DataContext>
|
||||
<ListView Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
|
||||
ItemsSource="{Binding Source={StaticResource RecentItemsSource}}"
|
||||
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
|
||||
ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Margin="10,0,10,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Row="0" Text="{Binding Name}" Padding="5,0,0,0" />
|
||||
<TextBlock Grid.Row="1" Text="{Binding Path}" Padding="5,0,0,0" FontSize="10" />
|
||||
<local:CompositeKeyUserControl Grid.Row="2" x:Name="DatabaseUserControl" HorizontalAlignment="Stretch" MinWidth="400" Margin="0,10,0,0" Visibility="{Binding IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}" ValidationChecking="OpenDatabaseUserControl_OnValidationChecking">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<core:EventTriggerBehavior EventName="ValidationChecked">
|
||||
<core:NavigateToPageAction TargetPage="ModernKeePass.Pages.GroupDetailPage" />
|
||||
</core:EventTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</local:CompositeKeyUserControl>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</Page>
|
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
|
||||
|
||||
namespace ModernKeePass.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public sealed partial class WelcomePage : Page
|
||||
{
|
||||
public WelcomePage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,29 +0,0 @@
|
||||
<Page
|
||||
x:Class="ModernKeePass.Pages.SettingsDatabasePage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="using:ModernKeePass.ViewModels"
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
<CollectionViewSource x:Name="RecycleBinGroups" Source="{Binding Groups}" />
|
||||
<CollectionViewSource x:Name="Ciphers" Source="{Binding Ciphers}" />
|
||||
<CollectionViewSource x:Name="Compressions" Source="{Binding Compressions}" />
|
||||
<CollectionViewSource x:Name="KeyDerivations" Source="{Binding KeyDerivations}" />
|
||||
</Page.Resources>
|
||||
<Page.DataContext>
|
||||
<viewModels:SettingsDatabaseVm />
|
||||
</Page.DataContext>
|
||||
|
||||
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<ToggleSwitch Header="Recycle bin" OffContent="Disabled" OnContent="Enabled" IsOn="{Binding HasRecycleBin, Mode=TwoWay}" />
|
||||
<ComboBox ItemsSource="{Binding Source={StaticResource RecycleBinGroups}}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" IsEnabled="{Binding HasRecycleBin}" />
|
||||
<TextBlock Text="Encryption Algorithm" FontSize="14" Margin="5,20,0,10" />
|
||||
<ComboBox ItemsSource="{Binding Source={StaticResource Ciphers}}" SelectedIndex="{Binding CipherIndex, Mode=TwoWay}" />
|
||||
<TextBlock Text="Compression Algorithm" FontSize="14" Margin="5,20,0,10" />
|
||||
<ComboBox ItemsSource="{Binding Source={StaticResource Compressions}}" SelectedItem="{Binding CompressionName, Mode=TwoWay}" />
|
||||
<TextBlock Text="Key Derivation Algorithm" FontSize="14" Margin="5,20,0,10" />
|
||||
<ComboBox ItemsSource="{Binding Source={StaticResource KeyDerivations}}" SelectedItem="{Binding KeyDerivationName, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</Page>
|
@@ -1,14 +0,0 @@
|
||||
<Page
|
||||
x:Class="ModernKeePass.Pages.SettingsSecurityPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:ModernKeePass.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<TextBlock Text="Change database security options" />
|
||||
<local:CompositeKeyUserControl UpdateKey="True" />
|
||||
</StackPanel>
|
||||
</Page>
|
@@ -24,6 +24,6 @@ using System.Runtime.InteropServices;
|
||||
// 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.8.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.8.0.0")]
|
||||
[assembly: AssemblyVersion("1.13.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.13.0.0")]
|
||||
[assembly: ComVisible(false)]
|
260
ModernKeePass/Services/DatabaseService.cs
Normal file
@@ -0,0 +1,260 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using ModernKeePass.Exceptions;
|
||||
using ModernKeePass.Interfaces;
|
||||
using ModernKeePass.ViewModels;
|
||||
using ModernKeePassLib;
|
||||
using ModernKeePassLib.Collections;
|
||||
using ModernKeePassLib.Cryptography.KeyDerivation;
|
||||
using ModernKeePassLib.Interfaces;
|
||||
using ModernKeePassLib.Keys;
|
||||
using ModernKeePassLib.Security;
|
||||
using ModernKeePassLib.Serialization;
|
||||
|
||||
namespace ModernKeePass.Services
|
||||
{
|
||||
public class DatabaseService: SingletonServiceBase<DatabaseService>, IDatabaseService
|
||||
{
|
||||
private readonly PwDatabase _pwDatabase = new PwDatabase();
|
||||
private readonly ISettingsService _settings;
|
||||
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?.IdUuid;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name => DatabaseFile?.Name;
|
||||
|
||||
public bool RecycleBinEnabled
|
||||
{
|
||||
get { return _pwDatabase.RecycleBinEnabled; }
|
||||
set { _pwDatabase.RecycleBinEnabled = value; }
|
||||
}
|
||||
|
||||
public StorageFile DatabaseFile
|
||||
{
|
||||
get { return _databaseFile; }
|
||||
set
|
||||
{
|
||||
if (IsOpen && HasChanged)
|
||||
{
|
||||
throw new DatabaseOpenedException();
|
||||
}
|
||||
_databaseFile = value;
|
||||
}
|
||||
}
|
||||
|
||||
public CompositeKey CompositeKey
|
||||
{
|
||||
get { return _compositeKey; }
|
||||
set { _compositeKey = 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;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Open a KeePass database
|
||||
/// </summary>
|
||||
/// <param name="key">The database composite key</param>
|
||||
/// <param name="createNew">True to create a new database before opening it</param>
|
||||
/// <returns>An error message, if any</returns>
|
||||
public async Task Open(CompositeKey key, bool createNew = false)
|
||||
{
|
||||
// TODO: Check if there is an existing backup file
|
||||
try
|
||||
{
|
||||
if (key == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(key));
|
||||
}
|
||||
|
||||
_compositeKey = key;
|
||||
var ioConnection = IOConnectionInfo.FromFile(DatabaseFile);
|
||||
if (createNew)
|
||||
{
|
||||
_pwDatabase.New(ioConnection, key);
|
||||
|
||||
//Get settings default values
|
||||
if (_settings.GetSetting<bool>("Sample")) CreateSampleData();
|
||||
var fileFormat = _settings.GetSetting<string>("DefaultFileFormat");
|
||||
switch (fileFormat)
|
||||
{
|
||||
case "4":
|
||||
KeyDerivation = KdfPool.Get("Argon2").GetDefaultParameters();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else _pwDatabase.Open(ioConnection, key, new NullStatusLogger());
|
||||
|
||||
//if (!_pwDatabase.IsOpen) return;
|
||||
|
||||
// Copy database in temp directory and use this file for operations
|
||||
if (_settings.GetSetting<bool>("AntiCorruption"))
|
||||
{
|
||||
_realDatabaseFile = _databaseFile;
|
||||
var backupFile =
|
||||
await ApplicationData.Current.RoamingFolder.CreateFileAsync(Name,
|
||||
CreationCollisionOption.FailIfExists);
|
||||
Save(backupFile);
|
||||
}
|
||||
|
||||
RootGroup = new GroupVm(_pwDatabase.RootGroup, null, RecycleBinEnabled ? _pwDatabase.RecycleBinUuid : null);
|
||||
}
|
||||
catch (InvalidCompositeKeyException ex)
|
||||
{
|
||||
throw new ArgumentException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ReOpen()
|
||||
{
|
||||
await Open(_compositeKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Commit the changes to the currently opened database to file
|
||||
/// </summary>
|
||||
public void Save()
|
||||
{
|
||||
if (!IsOpen) return;
|
||||
try
|
||||
{
|
||||
_pwDatabase.Save(new NullStatusLogger());
|
||||
|
||||
// Test if save worked correctly
|
||||
if (_settings.GetSetting<bool>("AntiCorruption"))
|
||||
{
|
||||
_pwDatabase.Open(_pwDatabase.IOConnectionInfo, _pwDatabase.MasterKey, new NullStatusLogger());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new SaveException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the current database to another file and open it
|
||||
/// </summary>
|
||||
/// <param name="file">The new database file</param>
|
||||
public void Save(StorageFile file)
|
||||
{
|
||||
var oldFile = DatabaseFile;
|
||||
DatabaseFile = file;
|
||||
try
|
||||
{
|
||||
_pwDatabase.SaveAs(IOConnectionInfo.FromFile(DatabaseFile), true, new NullStatusLogger());
|
||||
}
|
||||
catch
|
||||
{
|
||||
DatabaseFile = oldFile;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close the currently opened database
|
||||
/// </summary>
|
||||
public async Task Close(bool releaseFile = true)
|
||||
{
|
||||
_pwDatabase?.Close();
|
||||
|
||||
// Restore the backup DB to the original one
|
||||
if (_settings.GetSetting<bool>("AntiCorruption"))
|
||||
{
|
||||
if (_pwDatabase != null && _pwDatabase.Modified)
|
||||
Save(_realDatabaseFile);
|
||||
await DatabaseFile.DeleteAsync();
|
||||
}
|
||||
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.IconSymbol = Symbol.Delete;
|
||||
}
|
||||
|
||||
private void CreateSampleData()
|
||||
{
|
||||
_pwDatabase.RootGroup.AddGroup(new PwGroup(true, true, "Banking", PwIcon.Count), true);
|
||||
_pwDatabase.RootGroup.AddGroup(new PwGroup(true, true, "Email", PwIcon.EMail), true);
|
||||
_pwDatabase.RootGroup.AddGroup(new PwGroup(true, true, "Internet", PwIcon.World), true);
|
||||
|
||||
var pe = new PwEntry(true, true);
|
||||
pe.Strings.Set(PwDefs.TitleField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectTitle,
|
||||
"Sample Entry"));
|
||||
pe.Strings.Set(PwDefs.UserNameField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectUserName,
|
||||
"Username"));
|
||||
pe.Strings.Set(PwDefs.UrlField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectUrl,
|
||||
PwDefs.HomepageUrl));
|
||||
pe.Strings.Set(PwDefs.PasswordField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectPassword,
|
||||
"Password"));
|
||||
pe.Strings.Set(PwDefs.NotesField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectNotes,
|
||||
"You may safely delete this sample"));
|
||||
_pwDatabase.RootGroup.AddEntry(pe, true);
|
||||
|
||||
pe = new PwEntry(true, true);
|
||||
pe.Strings.Set(PwDefs.TitleField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectTitle,
|
||||
"Sample Entry #2"));
|
||||
pe.Strings.Set(PwDefs.UserNameField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectUserName,
|
||||
"Michael321"));
|
||||
pe.Strings.Set(PwDefs.UrlField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectUrl,
|
||||
PwDefs.HelpUrl + "kb/testform.html"));
|
||||
pe.Strings.Set(PwDefs.PasswordField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectPassword,
|
||||
"12345"));
|
||||
pe.AutoType.Add(new AutoTypeAssociation("*Test Form - KeePass*", string.Empty));
|
||||
_pwDatabase.RootGroup.AddEntry(pe, true);
|
||||
}
|
||||
}
|
||||
}
|
74
ModernKeePass/Services/LicenseService.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel.Store;
|
||||
using ModernKeePass.Interfaces;
|
||||
|
||||
namespace ModernKeePass.Services
|
||||
{
|
||||
public class LicenseService : SingletonServiceBase<LicenseService>, ILicenseService
|
||||
{
|
||||
public enum PurchaseResult
|
||||
{
|
||||
Succeeded,
|
||||
NothingToFulfill,
|
||||
PurchasePending,
|
||||
PurchaseReverted,
|
||||
ServerError,
|
||||
NotPurchased,
|
||||
AlreadyPurchased
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<string, ProductListing> Products { get; }
|
||||
|
||||
//private LicenseInformation _licenseInformation;
|
||||
private readonly HashSet<Guid> _consumedTransactionIds = new HashSet<Guid>();
|
||||
|
||||
public LicenseService()
|
||||
{
|
||||
var listing = CurrentApp.LoadListingInformationAsync().GetAwaiter().GetResult();
|
||||
Products = listing.ProductListings;
|
||||
}
|
||||
|
||||
public async Task<int> Purchase(string addOn)
|
||||
{
|
||||
var purchaseResults = await CurrentApp.RequestProductPurchaseAsync(addOn);
|
||||
switch (purchaseResults.Status)
|
||||
{
|
||||
case ProductPurchaseStatus.Succeeded:
|
||||
GrantFeatureLocally(purchaseResults.TransactionId);
|
||||
return (int) await ReportFulfillmentAsync(purchaseResults.TransactionId, addOn);
|
||||
case ProductPurchaseStatus.NotFulfilled:
|
||||
// The purchase failed because we haven't confirmed fulfillment of a previous purchase.
|
||||
// Fulfill it now.
|
||||
if (!IsLocallyFulfilled(purchaseResults.TransactionId))
|
||||
{
|
||||
GrantFeatureLocally(purchaseResults.TransactionId);
|
||||
}
|
||||
return (int) await ReportFulfillmentAsync(purchaseResults.TransactionId, addOn);
|
||||
case ProductPurchaseStatus.NotPurchased:
|
||||
return (int) PurchaseResult.NotPurchased;
|
||||
case ProductPurchaseStatus.AlreadyPurchased:
|
||||
return (int) PurchaseResult.AlreadyPurchased;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<PurchaseResult> ReportFulfillmentAsync(Guid transactionId, string productName)
|
||||
{
|
||||
var result = await CurrentApp.ReportConsumableFulfillmentAsync(productName, transactionId);
|
||||
return (PurchaseResult) result;
|
||||
}
|
||||
|
||||
private void GrantFeatureLocally(Guid transactionId)
|
||||
{
|
||||
_consumedTransactionIds.Add(transactionId);
|
||||
}
|
||||
|
||||
private bool IsLocallyFulfilled(Guid transactionId)
|
||||
{
|
||||
return _consumedTransactionIds.Contains(transactionId);
|
||||
}
|
||||
}
|
||||
}
|
50
ModernKeePass/Services/RecentService.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
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<RecentService>, IRecentService
|
||||
{
|
||||
private readonly StorageItemMostRecentlyUsedList _mru = StorageApplicationPermissions.MostRecentlyUsedList;
|
||||
|
||||
public int EntryCount => _mru.Entries.Count;
|
||||
|
||||
public ObservableCollection<IRecentItem> GetAllFiles(bool removeIfNonExistant = true)
|
||||
{
|
||||
var result = new ObservableCollection<IRecentItem>();
|
||||
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<IStorageItem> GetFileAsync(string token)
|
||||
{
|
||||
return await _mru.GetFileAsync(token);
|
||||
}
|
||||
}
|
||||
}
|
17
ModernKeePass/Services/ResourcesService.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Windows.ApplicationModel.Resources;
|
||||
using ModernKeePass.Interfaces;
|
||||
|
||||
namespace ModernKeePass.Services
|
||||
{
|
||||
public class ResourcesService: IResourceService
|
||||
{
|
||||
private const string ResourceFileName = "CodeBehind";
|
||||
private readonly ResourceLoader _resourceLoader = ResourceLoader.GetForCurrentView();
|
||||
|
||||
public string GetResourceValue(string key)
|
||||
{
|
||||
var resource = _resourceLoader.GetString($"/{ResourceFileName}/{key}");
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
}
|
31
ModernKeePass/Services/SettingsService.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.Storage;
|
||||
using ModernKeePass.Interfaces;
|
||||
|
||||
namespace ModernKeePass.Services
|
||||
{
|
||||
public class SettingsService : SingletonServiceBase<SettingsService>, ISettingsService
|
||||
{
|
||||
private readonly IPropertySet _values = ApplicationData.Current.LocalSettings.Values;
|
||||
|
||||
public T GetSetting<T>(string property, T defaultValue = default(T))
|
||||
{
|
||||
try
|
||||
{
|
||||
return (T)Convert.ChangeType(_values[property], typeof(T));
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void PutSetting<T>(string property, T value)
|
||||
{
|
||||
if (_values.ContainsKey(property))
|
||||
_values[property] = value;
|
||||
else _values.Add(property, value);
|
||||
}
|
||||
}
|
||||
}
|
12
ModernKeePass/Services/SingletonServiceBase.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace ModernKeePass.Services
|
||||
{
|
||||
public abstract class SingletonServiceBase<T> where T : new()
|
||||
{
|
||||
private static readonly Lazy<T> LazyInstance =
|
||||
new Lazy<T>(() => new T());
|
||||
|
||||
public static T Instance => LazyInstance.Value;
|
||||
}
|
||||
}
|
276
ModernKeePass/Strings/en-US/CodeBehind.resw
Normal file
@@ -0,0 +1,276 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="CompositeKeyDefaultKeyFile" xml:space="preserve">
|
||||
<value>Select key file from disk...</value>
|
||||
</data>
|
||||
<data name="CompositeKeyErrorOpen" xml:space="preserve">
|
||||
<value>Error</value>
|
||||
</data>
|
||||
<data name="CompositeKeyErrorUserKeyFile" xml:space="preserve">
|
||||
<value>key file</value>
|
||||
</data>
|
||||
<data name="CompositeKeyErrorUserOr" xml:space="preserve">
|
||||
<value> or </value>
|
||||
</data>
|
||||
<data name="CompositeKeyErrorUserPassword" xml:space="preserve">
|
||||
<value>password</value>
|
||||
</data>
|
||||
<data name="CompositeKeyErrorUserStart" xml:space="preserve">
|
||||
<value>Error: wrong </value>
|
||||
</data>
|
||||
<data name="CompositeKeyOpening" xml:space="preserve">
|
||||
<value>Opening...</value>
|
||||
</data>
|
||||
<data name="CompositeKeyUpdated" xml:space="preserve">
|
||||
<value>Database composite key updated.</value>
|
||||
</data>
|
||||
<data name="DonateAlreadyPurchasedMessage" xml:space="preserve">
|
||||
<value>Your product has already been purchased.</value>
|
||||
</data>
|
||||
<data name="DonateAlreadyPurchasedTitle" xml:space="preserve">
|
||||
<value>Purchase</value>
|
||||
</data>
|
||||
<data name="DonateNothingToFulfillMessage" xml:space="preserve">
|
||||
<value>No purchased product to fulfill</value>
|
||||
</data>
|
||||
<data name="DonateNothingToFulfillTitle" xml:space="preserve">
|
||||
<value>Fulfillment</value>
|
||||
</data>
|
||||
<data name="DonateNotPurchasedMessage" xml:space="preserve">
|
||||
<value>The purchase failed because we haven't confirmed fulfillment of a previous purchase.</value>
|
||||
</data>
|
||||
<data name="DonateNotPurchasedTitle" xml:space="preserve">
|
||||
<value>Purchase</value>
|
||||
</data>
|
||||
<data name="DonatePurchasePendingMessage" xml:space="preserve">
|
||||
<value>The purchase is pending so we cannot fulfill the product.</value>
|
||||
</data>
|
||||
<data name="DonatePurchasePendingTitle" xml:space="preserve">
|
||||
<value>Purchase</value>
|
||||
</data>
|
||||
<data name="DonatePurchaseRevertedMessage" xml:space="preserve">
|
||||
<value>Your purchase has been reverted.</value>
|
||||
</data>
|
||||
<data name="DonatePurchaseRevertedTitle" xml:space="preserve">
|
||||
<value>Purchase</value>
|
||||
</data>
|
||||
<data name="DonateServerErrorMessage" xml:space="preserve">
|
||||
<value>Impossible to contact the Windows Store, there was an error when fulfilling.</value>
|
||||
</data>
|
||||
<data name="DonateServerErrorTitle" xml:space="preserve">
|
||||
<value>Error</value>
|
||||
</data>
|
||||
<data name="DonateSucceededMessage" xml:space="preserve">
|
||||
<value>Your donation was successful.</value>
|
||||
</data>
|
||||
<data name="DonateSucceededTitle" xml:space="preserve">
|
||||
<value>Thank you!</value>
|
||||
</data>
|
||||
<data name="EntityDeleteActionButton" xml:space="preserve">
|
||||
<value>Delete</value>
|
||||
</data>
|
||||
<data name="EntityDeleteCancelButton" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="EntityDeleteTitle" xml:space="preserve">
|
||||
<value>Warning</value>
|
||||
</data>
|
||||
<data name="EntityDeleting" xml:space="preserve">
|
||||
<value>Deleting</value>
|
||||
</data>
|
||||
<data name="EntityRestoredTitle" xml:space="preserve">
|
||||
<value>Restored</value>
|
||||
</data>
|
||||
<data name="EntryDeleted" xml:space="preserve">
|
||||
<value>Entry permanently removed</value>
|
||||
</data>
|
||||
<data name="EntryDeletingConfirmation" xml:space="preserve">
|
||||
<value>Are you sure you want to delete this entry?</value>
|
||||
</data>
|
||||
<data name="EntryRecycled" xml:space="preserve">
|
||||
<value>Entry moved to the Recycle bin</value>
|
||||
</data>
|
||||
<data name="EntryRecyclingConfirmation" xml:space="preserve">
|
||||
<value>Are you sure you want to send this entry to the recycle bin?</value>
|
||||
</data>
|
||||
<data name="EntryRestored" xml:space="preserve">
|
||||
<value>Entry returned to its original group</value>
|
||||
</data>
|
||||
<data name="GroupDeleted" xml:space="preserve">
|
||||
<value>Group permanently removed</value>
|
||||
</data>
|
||||
<data name="GroupDeletingConfirmation" xml:space="preserve">
|
||||
<value>Are you sure you want to delete the whole group and all its entries?</value>
|
||||
</data>
|
||||
<data name="GroupRecycled" xml:space="preserve">
|
||||
<value>Group moved to the Recycle bin</value>
|
||||
</data>
|
||||
<data name="GroupRecyclingConfirmation" xml:space="preserve">
|
||||
<value>Are you sure you want to send the whole group and all its entries to the recycle bin?</value>
|
||||
</data>
|
||||
<data name="GroupRestored" xml:space="preserve">
|
||||
<value>Group returned to its original group</value>
|
||||
</data>
|
||||
<data name="MainMenuItemAbout" xml:space="preserve">
|
||||
<value>About</value>
|
||||
</data>
|
||||
<data name="MainMenuItemDonate" xml:space="preserve">
|
||||
<value>Donate</value>
|
||||
</data>
|
||||
<data name="MainMenuItemNew" xml:space="preserve">
|
||||
<value>New</value>
|
||||
</data>
|
||||
<data name="MainMenuItemOpen" xml:space="preserve">
|
||||
<value>Open</value>
|
||||
</data>
|
||||
<data name="MainMenuItemRecent" xml:space="preserve">
|
||||
<value>Recent</value>
|
||||
</data>
|
||||
<data name="MainMenuItemSave" xml:space="preserve">
|
||||
<value>Save</value>
|
||||
</data>
|
||||
<data name="MainMenuItemSettings" xml:space="preserve">
|
||||
<value>Settings</value>
|
||||
</data>
|
||||
<data name="SettingsMenuGroupApplication" xml:space="preserve">
|
||||
<value>Application</value>
|
||||
</data>
|
||||
<data name="SettingsMenuGroupDatabase" xml:space="preserve">
|
||||
<value>Database</value>
|
||||
</data>
|
||||
<data name="SettingsMenuItemGeneral" xml:space="preserve">
|
||||
<value>General</value>
|
||||
</data>
|
||||
<data name="SettingsMenuItemNew" xml:space="preserve">
|
||||
<value>New</value>
|
||||
</data>
|
||||
<data name="SettingsMenuItemSecurity" xml:space="preserve">
|
||||
<value>Security</value>
|
||||
</data>
|
||||
<data name="CompositeKeyErrorUserAccount" xml:space="preserve">
|
||||
<value>user account</value>
|
||||
</data>
|
||||
<data name="SettingsMenuItemSave" xml:space="preserve">
|
||||
<value>Saving</value>
|
||||
</data>
|
||||
<data name="RecycleBinTitle" xml:space="preserve">
|
||||
<value>Recycle Bin</value>
|
||||
</data>
|
||||
</root>
|
387
ModernKeePass/Strings/en-US/Resources.resw
Normal file
@@ -0,0 +1,387 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="AboutCredits1.Text" xml:space="preserve">
|
||||
<value>Dominik Reichl for the KeePass application and file format</value>
|
||||
</data>
|
||||
<data name="AboutCredits2.Text" xml:space="preserve">
|
||||
<value>David Lechner for his PCL adapatation of the KeePass Library and his correlated tests</value>
|
||||
</data>
|
||||
<data name="AboutCreditsLabel.Text" xml:space="preserve">
|
||||
<value>Credits</value>
|
||||
</data>
|
||||
<data name="AboutDesc.Text" xml:space="preserve">
|
||||
<value>A modern password manager for the Windows Store</value>
|
||||
</data>
|
||||
<data name="AboutHomepage.Text" xml:space="preserve">
|
||||
<value>Homepage:</value>
|
||||
</data>
|
||||
<data name="AppBarDelete.Label" xml:space="preserve">
|
||||
<value>Delete</value>
|
||||
</data>
|
||||
<data name="AppBarEdit.Label" xml:space="preserve">
|
||||
<value>Edit</value>
|
||||
</data>
|
||||
<data name="AppBarHome.Label" xml:space="preserve">
|
||||
<value>Home</value>
|
||||
</data>
|
||||
<data name="AppBarRestore.Label" xml:space="preserve">
|
||||
<value>Restore</value>
|
||||
</data>
|
||||
<data name="AppBarSave.Label" xml:space="preserve">
|
||||
<value>Save</value>
|
||||
</data>
|
||||
<data name="AppBarSettings.Label" xml:space="preserve">
|
||||
<value>Settings</value>
|
||||
</data>
|
||||
<data name="AppBarSort.Label" xml:space="preserve">
|
||||
<value>Sort</value>
|
||||
</data>
|
||||
<data name="AppBarSortEntries.Text" xml:space="preserve">
|
||||
<value>Entries</value>
|
||||
</data>
|
||||
<data name="AppBarSortGroups.Text" xml:space="preserve">
|
||||
<value>Groups</value>
|
||||
</data>
|
||||
<data name="CompositeKeyNewButton.ButtonLabel" xml:space="preserve">
|
||||
<value>Create</value>
|
||||
</data>
|
||||
<data name="CompositeKeyNewKeyFileTooltip.Content" xml:space="preserve">
|
||||
<value>Create new key file</value>
|
||||
</data>
|
||||
<data name="CompositeKeyOpenButton.ButtonLabel" xml:space="preserve">
|
||||
<value>Open</value>
|
||||
</data>
|
||||
<data name="CompositeKeyPassword.PlaceholderText" xml:space="preserve">
|
||||
<value>Password</value>
|
||||
</data>
|
||||
<data name="CompositeKeyUserAccount.Text" xml:space="preserve">
|
||||
<value>Windows User Account</value>
|
||||
</data>
|
||||
<data name="DonateButton.Content" xml:space="preserve">
|
||||
<value>Donate</value>
|
||||
</data>
|
||||
<data name="DonateDesc.Text" xml:space="preserve">
|
||||
<value>Like this app? Why not make a small donation to support my work and help me keep it ad-free :) ?</value>
|
||||
</data>
|
||||
<data name="EntryExpirationDate.Content" xml:space="preserve">
|
||||
<value>Expiration date</value>
|
||||
</data>
|
||||
<data name="EntryExpirationTooltip.Content" xml:space="preserve">
|
||||
<value>Password has expired</value>
|
||||
</data>
|
||||
<data name="EntryItemCopyLogin.Text" xml:space="preserve">
|
||||
<value>Copy login</value>
|
||||
</data>
|
||||
<data name="EntryItemCopyPassword.Text" xml:space="preserve">
|
||||
<value>Copy password</value>
|
||||
</data>
|
||||
<data name="EntryItemCopyUrl.Text" xml:space="preserve">
|
||||
<value>Navigate to URL</value>
|
||||
</data>
|
||||
<data name="EntryLogin.Text" xml:space="preserve">
|
||||
<value>User name or login</value>
|
||||
</data>
|
||||
<data name="EntryNotes.Text" xml:space="preserve">
|
||||
<value>Notes</value>
|
||||
</data>
|
||||
<data name="EntryPassword.Text" xml:space="preserve">
|
||||
<value>Password</value>
|
||||
</data>
|
||||
<data name="EntryShowPassword.Content" xml:space="preserve">
|
||||
<value>Show password</value>
|
||||
</data>
|
||||
<data name="GroupCreateEntry.Text" xml:space="preserve">
|
||||
<value>Create new entry</value>
|
||||
</data>
|
||||
<data name="GroupFilter.PlaceholderText" xml:space="preserve">
|
||||
<value>Filter...</value>
|
||||
</data>
|
||||
<data name="GroupNewItemTextBox.Text" xml:space="preserve">
|
||||
<value>New group</value>
|
||||
</data>
|
||||
<data name="GroupNewItemTooltip.Content" xml:space="preserve">
|
||||
<value>New group</value>
|
||||
</data>
|
||||
<data name="GroupSearch.PlaceholderText" xml:space="preserve">
|
||||
<value>Search...</value>
|
||||
</data>
|
||||
<data name="GroupTitle.PlaceholderText" xml:space="preserve">
|
||||
<value>New group name...</value>
|
||||
</data>
|
||||
<data name="NewCreateButton.Content" xml:space="preserve">
|
||||
<value>Create new...</value>
|
||||
</data>
|
||||
<data name="NewCreateDesc.Text" xml:space="preserve">
|
||||
<value>Create a new password database to the location of your chosing.</value>
|
||||
</data>
|
||||
<data name="OpenBrowseButton.Content" xml:space="preserve">
|
||||
<value>Browse files...</value>
|
||||
</data>
|
||||
<data name="OpenBrowseDesc.Text" xml:space="preserve">
|
||||
<value>Open an existing password database from your PC.</value>
|
||||
</data>
|
||||
<data name="OpenUrlButton.Content" xml:space="preserve">
|
||||
<value>From Url...</value>
|
||||
</data>
|
||||
<data name="OpenUrlDesc.Text" xml:space="preserve">
|
||||
<value>Open an existing password database from an Internet location (not yet implemented).</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorAlso.Text" xml:space="preserve">
|
||||
<value>Also add these characters:</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorBrackets.Content" xml:space="preserve">
|
||||
<value>Brackets ([], {}, (), ...)</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorButton.Content" xml:space="preserve">
|
||||
<value>Generate</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorDigits.Content" xml:space="preserve">
|
||||
<value>Digits (0, 1, 2, ...)</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorLength.Text" xml:space="preserve">
|
||||
<value>Password Length:</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorLower.Content" xml:space="preserve">
|
||||
<value>Lower case (a, b, c, ...)</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorMinus.Content" xml:space="preserve">
|
||||
<value>Minus (-)</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorSpace.Content" xml:space="preserve">
|
||||
<value>Space ( )</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorSpecial.Content" xml:space="preserve">
|
||||
<value>Special (!, $, %, ...)</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorTooltip.Content" xml:space="preserve">
|
||||
<value>Generate password</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorUnderscore.Content" xml:space="preserve">
|
||||
<value>Underscore (_)</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorUpper.Content" xml:space="preserve">
|
||||
<value>Upper case (A, B, C, ...)</value>
|
||||
</data>
|
||||
<data name="RecentClear.Text" xml:space="preserve">
|
||||
<value>Clear all</value>
|
||||
</data>
|
||||
<data name="ReorderEntriesLabel.Text" xml:space="preserve">
|
||||
<value>Drag and drop entries to reorder them</value>
|
||||
</data>
|
||||
<data name="SaveAsButton.Content" xml:space="preserve">
|
||||
<value>Save as...</value>
|
||||
</data>
|
||||
<data name="SaveAsDesc.Text" xml:space="preserve">
|
||||
<value>This will save the currently opened database as a new file and leave it open.</value>
|
||||
</data>
|
||||
<data name="SaveButton.Content" xml:space="preserve">
|
||||
<value>Save and close</value>
|
||||
</data>
|
||||
<data name="SaveDesc.Text" xml:space="preserve">
|
||||
<value>This will save and close the currently opened database.</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseCompression.Text" xml:space="preserve">
|
||||
<value>Compression Algorithm</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseEncryption.Text" xml:space="preserve">
|
||||
<value>Encryption Algorithm</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseKdf.Text" xml:space="preserve">
|
||||
<value>Key Derivation Algorithm</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseRecycleBin.Header" xml:space="preserve">
|
||||
<value>Recycle bin</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseRecycleBin.OffContent" xml:space="preserve">
|
||||
<value>Disabled</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseRecycleBin.OnContent" xml:space="preserve">
|
||||
<value>Enabled</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseRecycleBinCreate.Content" xml:space="preserve">
|
||||
<value>Create a new group</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseRecycleBinExisting.Content" xml:space="preserve">
|
||||
<value>Use an existing group</value>
|
||||
</data>
|
||||
<data name="SettingsNewDatabaseDesc.Text" xml:space="preserve">
|
||||
<value>Here, you can change some default options when creating a database.</value>
|
||||
</data>
|
||||
<data name="SettingsNewDatabaseKdf.Text" xml:space="preserve">
|
||||
<value>KDBX database file version</value>
|
||||
</data>
|
||||
<data name="SettingsNewDatabaseKdfMoreInfo.Text" xml:space="preserve">
|
||||
<value>Higher is better, but there may be compatibility issues with older applications</value>
|
||||
</data>
|
||||
<data name="SettingsNewDatabaseSample.Header" xml:space="preserve">
|
||||
<value>Create sample data</value>
|
||||
</data>
|
||||
<data name="SettingsNewDatabaseSample.OffContent" xml:space="preserve">
|
||||
<value>No</value>
|
||||
</data>
|
||||
<data name="SettingsNewDatabaseSample.OnContent" xml:space="preserve">
|
||||
<value>Yes</value>
|
||||
</data>
|
||||
<data name="SettingsSaveDatabaseSuspend.OffContent" xml:space="preserve">
|
||||
<value>Don't save</value>
|
||||
</data>
|
||||
<data name="SettingsSaveDatabaseSuspend.OnContent" xml:space="preserve">
|
||||
<value>Save</value>
|
||||
</data>
|
||||
<data name="SettingsSaveDatabaseSuspendDesc.Text" xml:space="preserve">
|
||||
<value>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.</value>
|
||||
</data>
|
||||
<data name="SettingsSaveDatabaseSuspendTitle.Text" xml:space="preserve">
|
||||
<value>Auto-save on suspend?</value>
|
||||
</data>
|
||||
<data name="SettingsSecurityDesc1.Text" xml:space="preserve">
|
||||
<value>Here, you may change your database password, key file, or both. Just click on on</value>
|
||||
</data>
|
||||
<data name="SettingsSecurityDesc2.Text" xml:space="preserve">
|
||||
<value>Update master key</value>
|
||||
</data>
|
||||
<data name="SettingsSecurityDesc3.Text" xml:space="preserve">
|
||||
<value>when you're done. Please make sure to remember the password you choose here!</value>
|
||||
</data>
|
||||
<data name="SettingsSecurityTitle.Text" xml:space="preserve">
|
||||
<value>Change database security options</value>
|
||||
</data>
|
||||
<data name="SettingsSecurityUpdateButton.ButtonLabel" xml:space="preserve">
|
||||
<value>Update master key</value>
|
||||
</data>
|
||||
<data name="SettingsTitle.Text" xml:space="preserve">
|
||||
<value>Settings</value>
|
||||
</data>
|
||||
<data name="SettingsWelcomeDesc.Text" xml:space="preserve">
|
||||
<value>Here, you may change the application or the database settings.</value>
|
||||
</data>
|
||||
<data name="SettingsWelcomeHowto.Text" xml:space="preserve">
|
||||
<value>Select a setting pane on the left to access the options.</value>
|
||||
</data>
|
||||
<data name="SettingsWelcomeTitle.Text" xml:space="preserve">
|
||||
<value>Settings</value>
|
||||
</data>
|
||||
<data name="WelcomeNew.Text" xml:space="preserve">
|
||||
<value>Want to create a new password database? Do it here.</value>
|
||||
</data>
|
||||
<data name="WelcomeOpen.Text" xml:space="preserve">
|
||||
<value>Have an existing password database? Open it here.</value>
|
||||
</data>
|
||||
</root>
|
276
ModernKeePass/Strings/fr-FR/CodeBehind.resw
Normal file
@@ -0,0 +1,276 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="CompositeKeyDefaultKeyFile" xml:space="preserve">
|
||||
<value>Choisissez un fichier...</value>
|
||||
</data>
|
||||
<data name="CompositeKeyErrorOpen" xml:space="preserve">
|
||||
<value>Erreur</value>
|
||||
</data>
|
||||
<data name="CompositeKeyErrorUserKeyFile" xml:space="preserve">
|
||||
<value>fichier de clé</value>
|
||||
</data>
|
||||
<data name="CompositeKeyErrorUserOr" xml:space="preserve">
|
||||
<value> ou </value>
|
||||
</data>
|
||||
<data name="CompositeKeyErrorUserPassword" xml:space="preserve">
|
||||
<value>mot de passe</value>
|
||||
</data>
|
||||
<data name="CompositeKeyErrorUserStart" xml:space="preserve">
|
||||
<value>Erreur: mauvais </value>
|
||||
</data>
|
||||
<data name="CompositeKeyOpening" xml:space="preserve">
|
||||
<value>Ouverture...</value>
|
||||
</data>
|
||||
<data name="CompositeKeyUpdated" xml:space="preserve">
|
||||
<value>Clé composite de la base de données mise à jour.</value>
|
||||
</data>
|
||||
<data name="DonateAlreadyPurchasedMessage" xml:space="preserve">
|
||||
<value>Vous avez déjà acheté ce produit.</value>
|
||||
</data>
|
||||
<data name="DonateAlreadyPurchasedTitle" xml:space="preserve">
|
||||
<value>Achat</value>
|
||||
</data>
|
||||
<data name="DonateNothingToFulfillMessage" xml:space="preserve">
|
||||
<value>Il n'y a aucun produit acheté à valider.</value>
|
||||
</data>
|
||||
<data name="DonateNothingToFulfillTitle" xml:space="preserve">
|
||||
<value>Validation</value>
|
||||
</data>
|
||||
<data name="DonateNotPurchasedMessage" xml:space="preserve">
|
||||
<value>L'achat a échoué parce que nous n'avons pas pu valider un achat précédent.</value>
|
||||
</data>
|
||||
<data name="DonateNotPurchasedTitle" xml:space="preserve">
|
||||
<value>Achat</value>
|
||||
</data>
|
||||
<data name="DonatePurchasePendingMessage" xml:space="preserve">
|
||||
<value>Un achat est en cours donc nous ne pouvons le valider.</value>
|
||||
</data>
|
||||
<data name="DonatePurchasePendingTitle" xml:space="preserve">
|
||||
<value>Achat</value>
|
||||
</data>
|
||||
<data name="DonatePurchaseRevertedMessage" xml:space="preserve">
|
||||
<value>Votre achat a été annulé.</value>
|
||||
</data>
|
||||
<data name="DonatePurchaseRevertedTitle" xml:space="preserve">
|
||||
<value>Achat</value>
|
||||
</data>
|
||||
<data name="DonateServerErrorMessage" xml:space="preserve">
|
||||
<value>Impossible de contacter le Windows Store, l'achat n'a pas été réalisé.</value>
|
||||
</data>
|
||||
<data name="DonateServerErrorTitle" xml:space="preserve">
|
||||
<value>Erreur</value>
|
||||
</data>
|
||||
<data name="DonateSucceededMessage" xml:space="preserve">
|
||||
<value>Votre don a été enregistré.</value>
|
||||
</data>
|
||||
<data name="DonateSucceededTitle" xml:space="preserve">
|
||||
<value>Merci!</value>
|
||||
</data>
|
||||
<data name="EntityDeleteActionButton" xml:space="preserve">
|
||||
<value>Supprimer</value>
|
||||
</data>
|
||||
<data name="EntityDeleteCancelButton" xml:space="preserve">
|
||||
<value>Annuler</value>
|
||||
</data>
|
||||
<data name="EntityDeleteTitle" xml:space="preserve">
|
||||
<value>Attention</value>
|
||||
</data>
|
||||
<data name="EntityDeleting" xml:space="preserve">
|
||||
<value>Suprression</value>
|
||||
</data>
|
||||
<data name="EntityRestoredTitle" xml:space="preserve">
|
||||
<value>Restauré</value>
|
||||
</data>
|
||||
<data name="EntryDeleted" xml:space="preserve">
|
||||
<value>Entrée supprimée définitivement</value>
|
||||
</data>
|
||||
<data name="EntryDeletingConfirmation" xml:space="preserve">
|
||||
<value>Êtes-vous sûr de vouloir supprimer cette entrée ?</value>
|
||||
</data>
|
||||
<data name="EntryRecycled" xml:space="preserve">
|
||||
<value>Entrée placée dans la Corbeille</value>
|
||||
</data>
|
||||
<data name="EntryRecyclingConfirmation" xml:space="preserve">
|
||||
<value>Êtes-vous sûr de vouloir placer cette entrée dans la Corbeille ?</value>
|
||||
</data>
|
||||
<data name="EntryRestored" xml:space="preserve">
|
||||
<value>Entrée replacée dans son groupe d'origine</value>
|
||||
</data>
|
||||
<data name="GroupDeleted" xml:space="preserve">
|
||||
<value>Groupe supprimé défnitivement</value>
|
||||
</data>
|
||||
<data name="GroupDeletingConfirmation" xml:space="preserve">
|
||||
<value>Êtes-vous sûr de vouloir supprimer ce group et toutes ses entrées ?</value>
|
||||
</data>
|
||||
<data name="GroupRecycled" xml:space="preserve">
|
||||
<value>Groupe placé dans la Corbeille</value>
|
||||
</data>
|
||||
<data name="GroupRecyclingConfirmation" xml:space="preserve">
|
||||
<value>Êtes-vous sûr de vouloir envoyer ce groupe et toutes ses entrées vers la Corbeille ?</value>
|
||||
</data>
|
||||
<data name="GroupRestored" xml:space="preserve">
|
||||
<value>Groupe replacé à sa place originelle</value>
|
||||
</data>
|
||||
<data name="MainMenuItemAbout" xml:space="preserve">
|
||||
<value>A propos</value>
|
||||
</data>
|
||||
<data name="MainMenuItemDonate" xml:space="preserve">
|
||||
<value>Donation</value>
|
||||
</data>
|
||||
<data name="MainMenuItemNew" xml:space="preserve">
|
||||
<value>Nouveau</value>
|
||||
</data>
|
||||
<data name="MainMenuItemOpen" xml:space="preserve">
|
||||
<value>Ouvrir</value>
|
||||
</data>
|
||||
<data name="MainMenuItemRecent" xml:space="preserve">
|
||||
<value>Récents</value>
|
||||
</data>
|
||||
<data name="MainMenuItemSave" xml:space="preserve">
|
||||
<value>Sauvegarder</value>
|
||||
</data>
|
||||
<data name="MainMenuItemSettings" xml:space="preserve">
|
||||
<value>Paramètres</value>
|
||||
</data>
|
||||
<data name="SettingsMenuGroupApplication" xml:space="preserve">
|
||||
<value>Application</value>
|
||||
</data>
|
||||
<data name="SettingsMenuGroupDatabase" xml:space="preserve">
|
||||
<value>Base de données</value>
|
||||
</data>
|
||||
<data name="SettingsMenuItemGeneral" xml:space="preserve">
|
||||
<value>Général</value>
|
||||
</data>
|
||||
<data name="SettingsMenuItemNew" xml:space="preserve">
|
||||
<value>Nouveau</value>
|
||||
</data>
|
||||
<data name="SettingsMenuItemSecurity" xml:space="preserve">
|
||||
<value>Sécurité</value>
|
||||
</data>
|
||||
<data name="CompositeKeyErrorUserAccount" xml:space="preserve">
|
||||
<value>compte utilisateur</value>
|
||||
</data>
|
||||
<data name="SettingsMenuItemSave" xml:space="preserve">
|
||||
<value>Sauvegardes</value>
|
||||
</data>
|
||||
<data name="RecycleBinTitle" xml:space="preserve">
|
||||
<value>Corbeille</value>
|
||||
</data>
|
||||
</root>
|
387
ModernKeePass/Strings/fr-FR/Resources.resw
Normal file
@@ -0,0 +1,387 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="AboutCredits1.Text" xml:space="preserve">
|
||||
<value>Dominik Reichl pour l'application KeePass et le format de fichier</value>
|
||||
</data>
|
||||
<data name="AboutCredits2.Text" xml:space="preserve">
|
||||
<value>David Lechner pour son adaptation PCL de la blibliothèque KeePass et ses tests associés</value>
|
||||
</data>
|
||||
<data name="AboutCreditsLabel.Text" xml:space="preserve">
|
||||
<value>Crédits</value>
|
||||
</data>
|
||||
<data name="AboutDesc.Text" xml:space="preserve">
|
||||
<value>Un gestionnaire de mot de passes moderne pour le Windows Store</value>
|
||||
</data>
|
||||
<data name="AboutHomepage.Text" xml:space="preserve">
|
||||
<value>Page d'accueil :</value>
|
||||
</data>
|
||||
<data name="AppBarDelete.Label" xml:space="preserve">
|
||||
<value>Supprimer</value>
|
||||
</data>
|
||||
<data name="AppBarEdit.Label" xml:space="preserve">
|
||||
<value>Editer</value>
|
||||
</data>
|
||||
<data name="AppBarHome.Label" xml:space="preserve">
|
||||
<value>Accueil</value>
|
||||
</data>
|
||||
<data name="AppBarRestore.Label" xml:space="preserve">
|
||||
<value>Restaurer</value>
|
||||
</data>
|
||||
<data name="AppBarSave.Label" xml:space="preserve">
|
||||
<value>Sauvegarder</value>
|
||||
</data>
|
||||
<data name="AppBarSettings.Label" xml:space="preserve">
|
||||
<value>Paramètres</value>
|
||||
</data>
|
||||
<data name="AppBarSort.Label" xml:space="preserve">
|
||||
<value>Trier</value>
|
||||
</data>
|
||||
<data name="AppBarSortEntries.Text" xml:space="preserve">
|
||||
<value>Entrées</value>
|
||||
</data>
|
||||
<data name="AppBarSortGroups.Text" xml:space="preserve">
|
||||
<value>Groupes</value>
|
||||
</data>
|
||||
<data name="CompositeKeyNewButton.ButtonLabel" xml:space="preserve">
|
||||
<value>Créer</value>
|
||||
</data>
|
||||
<data name="CompositeKeyNewKeyFileTooltip.Content" xml:space="preserve">
|
||||
<value>Créer un nouveau fichier de clé</value>
|
||||
</data>
|
||||
<data name="CompositeKeyOpenButton.ButtonLabel" xml:space="preserve">
|
||||
<value>Ouvrir</value>
|
||||
</data>
|
||||
<data name="CompositeKeyPassword.PlaceholderText" xml:space="preserve">
|
||||
<value>Mot de passe</value>
|
||||
</data>
|
||||
<data name="CompositeKeyUserAccount.Text" xml:space="preserve">
|
||||
<value>Compte Utilisateur Windows</value>
|
||||
</data>
|
||||
<data name="DonateButton.Content" xml:space="preserve">
|
||||
<value>Donner</value>
|
||||
</data>
|
||||
<data name="DonateDesc.Text" xml:space="preserve">
|
||||
<value>Vous aimez cette app? Pourquoi ne pas faire un petit don afin de m'encourager et d'éviter le recours aux publicités :) ?</value>
|
||||
</data>
|
||||
<data name="EntryExpirationDate.Content" xml:space="preserve">
|
||||
<value>Date d'expiration</value>
|
||||
</data>
|
||||
<data name="EntryExpirationTooltip.Content" xml:space="preserve">
|
||||
<value>Le mot de passe a expiré</value>
|
||||
</data>
|
||||
<data name="EntryItemCopyLogin.Text" xml:space="preserve">
|
||||
<value>Copier le login</value>
|
||||
</data>
|
||||
<data name="EntryItemCopyPassword.Text" xml:space="preserve">
|
||||
<value>Copier le mot de passe</value>
|
||||
</data>
|
||||
<data name="EntryItemCopyUrl.Text" xml:space="preserve">
|
||||
<value>Naviguer vers l'URL</value>
|
||||
</data>
|
||||
<data name="EntryLogin.Text" xml:space="preserve">
|
||||
<value>Nom d'utilisateur ou login</value>
|
||||
</data>
|
||||
<data name="EntryNotes.Text" xml:space="preserve">
|
||||
<value>Notes</value>
|
||||
</data>
|
||||
<data name="EntryPassword.Text" xml:space="preserve">
|
||||
<value>Mot de passe</value>
|
||||
</data>
|
||||
<data name="EntryShowPassword.Content" xml:space="preserve">
|
||||
<value>Afficher le mot de passe</value>
|
||||
</data>
|
||||
<data name="GroupCreateEntry.Text" xml:space="preserve">
|
||||
<value>Créer une nouvelle entrée</value>
|
||||
</data>
|
||||
<data name="GroupFilter.PlaceholderText" xml:space="preserve">
|
||||
<value>Filtrer...</value>
|
||||
</data>
|
||||
<data name="GroupNewItemTextBox.Text" xml:space="preserve">
|
||||
<value>Nouveau groupe</value>
|
||||
</data>
|
||||
<data name="GroupNewItemTooltip.Content" xml:space="preserve">
|
||||
<value>Nouveau groupe</value>
|
||||
</data>
|
||||
<data name="GroupSearch.PlaceholderText" xml:space="preserve">
|
||||
<value>Rechercher...</value>
|
||||
</data>
|
||||
<data name="GroupTitle.PlaceholderText" xml:space="preserve">
|
||||
<value>Nom du nouveau groupe...</value>
|
||||
</data>
|
||||
<data name="NewCreateButton.Content" xml:space="preserve">
|
||||
<value>Créer une nouvelle...</value>
|
||||
</data>
|
||||
<data name="NewCreateDesc.Text" xml:space="preserve">
|
||||
<value>Créer une nouvelle base de données de mots de passe à l'endroit de votre choix.</value>
|
||||
</data>
|
||||
<data name="OpenBrowseButton.Content" xml:space="preserve">
|
||||
<value>Parcourir les fichiers...</value>
|
||||
</data>
|
||||
<data name="OpenBrowseDesc.Text" xml:space="preserve">
|
||||
<value>Ouvrir une base de données de mots de passe existante sur votre PC.</value>
|
||||
</data>
|
||||
<data name="OpenUrlButton.Content" xml:space="preserve">
|
||||
<value>Depuis une URL...</value>
|
||||
</data>
|
||||
<data name="OpenUrlDesc.Text" xml:space="preserve">
|
||||
<value>Ouvrir une base de données de mots de passe depuis Internet (pas encore implementé).</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorAlso.Text" xml:space="preserve">
|
||||
<value>Ajouter aussi ces caractères :</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorBrackets.Content" xml:space="preserve">
|
||||
<value>Parenthèses ([], {}, (), ...)</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorButton.Content" xml:space="preserve">
|
||||
<value>Générer</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorDigits.Content" xml:space="preserve">
|
||||
<value>Chiffres (0, 1, 2, ...)</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorLength.Text" xml:space="preserve">
|
||||
<value>Longueur de mot de passe :</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorLower.Content" xml:space="preserve">
|
||||
<value>Minuscules (a, b, c, ...)</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorMinus.Content" xml:space="preserve">
|
||||
<value>Moins (-)</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorSpace.Content" xml:space="preserve">
|
||||
<value>Espace ( )</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorSpecial.Content" xml:space="preserve">
|
||||
<value>Spéciaux (!, $, %, ...)</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorTooltip.Content" xml:space="preserve">
|
||||
<value>Générer le mot de passe</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorUnderscore.Content" xml:space="preserve">
|
||||
<value>Underscore (_)</value>
|
||||
</data>
|
||||
<data name="PasswordGeneratorUpper.Content" xml:space="preserve">
|
||||
<value>Majuscules (A, B, C, ...)</value>
|
||||
</data>
|
||||
<data name="RecentClear.Text" xml:space="preserve">
|
||||
<value>Supprimer tout</value>
|
||||
</data>
|
||||
<data name="ReorderEntriesLabel.Text" xml:space="preserve">
|
||||
<value>Glissez-déposez les entrées pour les réorganiser</value>
|
||||
</data>
|
||||
<data name="SaveAsButton.Content" xml:space="preserve">
|
||||
<value>Sauvegarder sous...</value>
|
||||
</data>
|
||||
<data name="SaveAsDesc.Text" xml:space="preserve">
|
||||
<value>Cela va sauvegarder la base de données dans un nouveau fichier et l'ouvrir.</value>
|
||||
</data>
|
||||
<data name="SaveButton.Content" xml:space="preserve">
|
||||
<value>Sauvegarder et fermer</value>
|
||||
</data>
|
||||
<data name="SaveDesc.Text" xml:space="preserve">
|
||||
<value>Cela va sauvegarder et fermer la base de données.</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseCompression.Text" xml:space="preserve">
|
||||
<value>Algorithme de compression</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseEncryption.Text" xml:space="preserve">
|
||||
<value>Algorithme de chiffrement</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseKdf.Text" xml:space="preserve">
|
||||
<value>Algorithme de dérivation de clé</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseRecycleBin.Header" xml:space="preserve">
|
||||
<value>Corbeille</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseRecycleBin.OffContent" xml:space="preserve">
|
||||
<value>Désactivé</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseRecycleBin.OnContent" xml:space="preserve">
|
||||
<value>Activé</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseRecycleBinCreate.Content" xml:space="preserve">
|
||||
<value>Créer un nouveau groupe</value>
|
||||
</data>
|
||||
<data name="SettingsDatabaseRecycleBinExisting.Content" xml:space="preserve">
|
||||
<value>Utiliser un groupe existant</value>
|
||||
</data>
|
||||
<data name="SettingsNewDatabaseDesc.Text" xml:space="preserve">
|
||||
<value>Ici, vous pouvez changer certains options lors de la création d'une nouvelle base de données</value>
|
||||
</data>
|
||||
<data name="SettingsNewDatabaseKdf.Text" xml:space="preserve">
|
||||
<value>Version de fichier KDBX</value>
|
||||
</data>
|
||||
<data name="SettingsNewDatabaseKdfMoreInfo.Text" xml:space="preserve">
|
||||
<value>Le plus élévé est le mieux, mais vous pourriez rencontrer des problèmes de compatibilité avec des application plus anciennes</value>
|
||||
</data>
|
||||
<data name="SettingsNewDatabaseSample.Header" xml:space="preserve">
|
||||
<value>Créer des données d'exemple</value>
|
||||
</data>
|
||||
<data name="SettingsNewDatabaseSample.OffContent" xml:space="preserve">
|
||||
<value>Non</value>
|
||||
</data>
|
||||
<data name="SettingsNewDatabaseSample.OnContent" xml:space="preserve">
|
||||
<value>Oui</value>
|
||||
</data>
|
||||
<data name="SettingsSaveDatabaseSuspend.OffContent" xml:space="preserve">
|
||||
<value>Ne pas sauvegarder</value>
|
||||
</data>
|
||||
<data name="SettingsSaveDatabaseSuspend.OnContent" xml:space="preserve">
|
||||
<value>Sauvegarder</value>
|
||||
</data>
|
||||
<data name="SettingsSaveDatabaseSuspendDesc.Text" xml:space="preserve">
|
||||
<value>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.</value>
|
||||
</data>
|
||||
<data name="SettingsSaveDatabaseSuspendTitle.Text" xml:space="preserve">
|
||||
<value>Sauvegarder automatiquement lors de la suspension ?</value>
|
||||
</data>
|
||||
<data name="SettingsSecurityDesc1.Text" xml:space="preserve">
|
||||
<value>Ici, vous pouvez changer le mot de passe maître, le fichier de clé, ou les deux. Cliquez simplement sur</value>
|
||||
</data>
|
||||
<data name="SettingsSecurityDesc2.Text" xml:space="preserve">
|
||||
<value>Mettre à jour la clé maître</value>
|
||||
</data>
|
||||
<data name="SettingsSecurityDesc3.Text" xml:space="preserve">
|
||||
<value>quand vous avez fini. Retenez bien le mot de passe que vous utilisez !</value>
|
||||
</data>
|
||||
<data name="SettingsSecurityTitle.Text" xml:space="preserve">
|
||||
<value>Changer les options de sécurité de la base de données</value>
|
||||
</data>
|
||||
<data name="SettingsSecurityUpdateButton.ButtonLabel" xml:space="preserve">
|
||||
<value>Mettre à jour la clé maître</value>
|
||||
</data>
|
||||
<data name="SettingsTitle.Text" xml:space="preserve">
|
||||
<value>Paramètres</value>
|
||||
</data>
|
||||
<data name="SettingsWelcomeDesc.Text" xml:space="preserve">
|
||||
<value>Ici, vous pouvez changer les options de l'application ou de la base de données.</value>
|
||||
</data>
|
||||
<data name="SettingsWelcomeHowto.Text" xml:space="preserve">
|
||||
<value>Choisissez un élément dans le menu de gauche.</value>
|
||||
</data>
|
||||
<data name="SettingsWelcomeTitle.Text" xml:space="preserve">
|
||||
<value>Paramètres</value>
|
||||
</data>
|
||||
<data name="WelcomeNew.Text" xml:space="preserve">
|
||||
<value>Pour créer une nouvelle base de données de mots de passe, c'est ici.</value>
|
||||
</data>
|
||||
<data name="WelcomeOpen.Text" xml:space="preserve">
|
||||
<value>Pour ouvrir une base de données existante, c'est ici.</value>
|
||||
</data>
|
||||
</root>
|
9
ModernKeePass/Styles/TextBlockStyles.xaml
Normal file
@@ -0,0 +1,9 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Style TargetType="TextBlock" x:Name="TextBlockSettingsHeaderStyle" >
|
||||
<Setter Property="FontFamily" Value="Segoe UI" />
|
||||
<Setter Property="FontSize" Value="14.667" />
|
||||
<Setter Property="FontWeight" Value="SemiLight" />
|
||||
</Style>
|
||||
</ResourceDictionary>
|
@@ -62,7 +62,7 @@
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Disabled">
|
||||
<!--<VisualState x:Name="Disabled">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
@@ -73,7 +73,7 @@
|
||||
To="0"
|
||||
Duration="0" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualState>-->
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<Border x:Name="BorderElement"
|
||||
@@ -89,6 +89,7 @@
|
||||
HorizontalAlignment="Center"
|
||||
FontStyle="Normal"
|
||||
Text="{TemplateBinding Content}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
AutomationProperties.AccessibilityView="Raw"/>
|
||||
</Border>
|
||||
@@ -142,9 +143,28 @@
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
Duration="0"
|
||||
To="{ThemeResource TextControlPointerOverBorderThemeOpacity}" />
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton"
|
||||
Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0">
|
||||
<DiscreteObjectKeyFrame.Value>
|
||||
<Visibility>Visible</Visibility>
|
||||
</DiscreteObjectKeyFrame.Value>
|
||||
</DiscreteObjectKeyFrame>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Focused">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton"
|
||||
Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0">
|
||||
<DiscreteObjectKeyFrame.Value>
|
||||
<Visibility>Visible</Visibility>
|
||||
</DiscreteObjectKeyFrame.Value>
|
||||
</DiscreteObjectKeyFrame>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Focused" />
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="ButtonStates">
|
||||
<VisualState x:Name="ButtonVisible">
|
||||
@@ -199,6 +219,7 @@
|
||||
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
|
||||
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
|
||||
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Margin="{TemplateBinding BorderThickness}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
IsTabStop="False"
|
||||
@@ -209,6 +230,7 @@
|
||||
Foreground="{ThemeResource TextBoxPlaceholderTextThemeBrush}"
|
||||
Margin="{TemplateBinding BorderThickness}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
IsTabStop="False"
|
||||
Grid.ColumnSpan="2"
|
||||
Content="{TemplateBinding PlaceholderText}"
|
||||
@@ -222,7 +244,12 @@
|
||||
Visibility="Collapsed"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
Content="{TemplateBinding ButtonSymbol}"
|
||||
VerticalAlignment="Stretch"/>
|
||||
IsEnabled="{TemplateBinding IsButtonEnabled}"
|
||||
VerticalAlignment="Stretch">
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip Content="{TemplateBinding ButtonTooltip}" />
|
||||
</ToolTipService.ToolTip>
|
||||
</Button>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
|
@@ -0,0 +1,18 @@
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using ModernKeePass.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)
|
||||
{
|
||||
var isSelectableItem = item as ISelectableModel;
|
||||
return isSelectableItem != null && isSelectableItem.IsSelected ? TrueItem : FalseItem;
|
||||
}
|
||||
}
|
||||
}
|
@@ -4,17 +4,24 @@ namespace ModernKeePass.ViewModels
|
||||
{
|
||||
public class AboutVm
|
||||
{
|
||||
public string Name { get; } = Package.Current.DisplayName;
|
||||
private readonly Package _package;
|
||||
|
||||
public string Name => _package.DisplayName;
|
||||
|
||||
public string Version
|
||||
{
|
||||
get
|
||||
{
|
||||
var package = Package.Current;
|
||||
var version = package.Id.Version;
|
||||
|
||||
var version = _package.Id.Version;
|
||||
return $"{version.Major}.{version.Minor}";
|
||||
}
|
||||
}
|
||||
|
||||
public AboutVm() : this(Package.Current) { }
|
||||
|
||||
public AboutVm(Package package)
|
||||
{
|
||||
_package = package;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,10 @@
|
||||
using System.Text;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using Windows.UI.Xaml;
|
||||
using ModernKeePass.Common;
|
||||
using ModernKeePass.Interfaces;
|
||||
using ModernKeePass.Services;
|
||||
using ModernKeePassLib.Cryptography;
|
||||
using ModernKeePassLib.Keys;
|
||||
using ModernKeePassLib.Serialization;
|
||||
@@ -18,14 +21,7 @@ namespace ModernKeePass.ViewModels
|
||||
Success = 5
|
||||
}
|
||||
|
||||
private readonly App _app = Application.Current as App;
|
||||
private bool _hasPassword;
|
||||
private bool _hasKeyFile;
|
||||
private string _password = string.Empty;
|
||||
private string _status;
|
||||
private StatusTypes _statusType;
|
||||
private StorageFile _keyFile;
|
||||
private string _keyFileText = "Select key file from disk...";
|
||||
public IDatabaseService Database { get; set; }
|
||||
|
||||
public bool HasPassword
|
||||
{
|
||||
@@ -47,7 +43,17 @@ namespace ModernKeePass.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsValid => HasPassword || HasKeyFile && KeyFile != null;
|
||||
public bool HasUserAccount
|
||||
{
|
||||
get { return _hasUserAccount; }
|
||||
set
|
||||
{
|
||||
SetProperty(ref _hasUserAccount, value);
|
||||
OnPropertyChanged("IsValid");
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsValid => !_isOpening && (HasPassword || HasKeyFile && KeyFile != null || HasUserAccount);
|
||||
|
||||
public string Status
|
||||
{
|
||||
@@ -69,6 +75,7 @@ namespace ModernKeePass.ViewModels
|
||||
_password = value;
|
||||
OnPropertyChanged("PasswordComplexityIndicator");
|
||||
StatusType = (int)StatusTypes.Normal;
|
||||
Status = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,31 +97,71 @@ namespace ModernKeePass.ViewModels
|
||||
}
|
||||
|
||||
public GroupVm RootGroup { get; set; }
|
||||
|
||||
public double PasswordComplexityIndicator => QualityEstimation.EstimatePasswordBits(Password?.ToCharArray());
|
||||
|
||||
public bool OpenDatabase(bool createNew)
|
||||
|
||||
private bool _hasPassword;
|
||||
private bool _hasKeyFile;
|
||||
private bool _hasUserAccount;
|
||||
private bool _isOpening;
|
||||
private string _password = string.Empty;
|
||||
private string _status;
|
||||
private StatusTypes _statusType;
|
||||
private StorageFile _keyFile;
|
||||
private string _keyFileText;
|
||||
private readonly IResourceService _resource;
|
||||
|
||||
public CompositeKeyVm() : this(DatabaseService.Instance, new ResourcesService()) { }
|
||||
|
||||
public CompositeKeyVm(IDatabaseService database, IResourceService resource)
|
||||
{
|
||||
_app.Database.Open(CreateCompositeKey(), createNew);
|
||||
switch (_app.Database.Status)
|
||||
_resource = resource;
|
||||
_keyFileText = _resource.GetResourceValue("CompositeKeyDefaultKeyFile");
|
||||
Database = database;
|
||||
}
|
||||
|
||||
public async Task<bool> OpenDatabase(bool createNew)
|
||||
{
|
||||
case DatabaseHelper.DatabaseStatus.Opened:
|
||||
RootGroup = _app.Database.RootGroup;
|
||||
try
|
||||
{
|
||||
_isOpening = true;
|
||||
await Database.Open(CreateCompositeKey(), createNew);
|
||||
await Task.Run(() => RootGroup = Database.RootGroup);
|
||||
return true;
|
||||
case DatabaseHelper.DatabaseStatus.CompositeKeyError:
|
||||
var errorMessage = new StringBuilder("Error: wrong ");
|
||||
if (HasPassword) errorMessage.Append("password");
|
||||
if (HasPassword && HasKeyFile) errorMessage.Append(" or ");
|
||||
if (HasKeyFile) errorMessage.Append("key file");
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
var errorMessage = new StringBuilder(_resource.GetResourceValue("CompositeKeyErrorUserStart"));
|
||||
if (HasPassword) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserPassword"));
|
||||
if (HasPassword && HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserOr"));
|
||||
if (HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserKeyFile"));
|
||||
if (HasUserAccount) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserAccount"));
|
||||
UpdateStatus(errorMessage.ToString(), StatusTypes.Error);
|
||||
break;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var error = $"{_resource.GetResourceValue("CompositeKeyErrorOpen")}: {e.Message}";
|
||||
UpdateStatus(error, StatusTypes.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isOpening = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void UpdateKey()
|
||||
{
|
||||
_app.Database.UpdateCompositeKey(CreateCompositeKey());
|
||||
UpdateStatus("Database composite key updated.", StatusTypes.Success);
|
||||
Database.CompositeKey = CreateCompositeKey();
|
||||
UpdateStatus(_resource.GetResourceValue("CompositeKeyUpdated"), StatusTypes.Success);
|
||||
}
|
||||
|
||||
public void CreateKeyFile(StorageFile file)
|
||||
{
|
||||
// TODO: implement entropy generator
|
||||
KcpKeyFile.Create(file, null);
|
||||
KeyFile = file;
|
||||
}
|
||||
|
||||
private void UpdateStatus(string text, StatusTypes type)
|
||||
@@ -127,7 +174,8 @@ namespace ModernKeePass.ViewModels
|
||||
{
|
||||
var compositeKey = new CompositeKey();
|
||||
if (HasPassword) compositeKey.AddUserKey(new KcpPassword(Password));
|
||||
if (HasKeyFile) compositeKey.AddUserKey(new KcpKeyFile(IOConnectionInfo.FromFile(KeyFile)));
|
||||
if (HasKeyFile && KeyFile != null) compositeKey.AddUserKey(new KcpKeyFile(IOConnectionInfo.FromFile(KeyFile)));
|
||||
if (HasUserAccount) compositeKey.AddUserKey(new KcpUserAccount());
|
||||
return compositeKey;
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Text;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using ModernKeePass.Attributes;
|
||||
using ModernKeePass.Interfaces;
|
||||
using ModernKeePass.Mappings;
|
||||
using ModernKeePass.Services;
|
||||
using ModernKeePassLib;
|
||||
using ModernKeePassLib.Cryptography.PasswordGenerator;
|
||||
using ModernKeePassLib.Security;
|
||||
@@ -15,17 +16,13 @@ namespace ModernKeePass.ViewModels
|
||||
public class EntryVm : INotifyPropertyChanged, IPwEntity
|
||||
{
|
||||
public GroupVm ParentGroup { get; private set; }
|
||||
|
||||
public GroupVm PreviousGroup { get; private set; }
|
||||
|
||||
public System.Drawing.Color? BackgroundColor => _pwEntry?.BackgroundColor;
|
||||
public System.Drawing.Color? ForegroundColor => _pwEntry?.ForegroundColor;
|
||||
public bool IsRevealPasswordEnabled => !string.IsNullOrEmpty(Password);
|
||||
public bool HasExpired => HasExpirationDate && _pwEntry.ExpiryTime < DateTime.Now;
|
||||
public double PasswordComplexityIndicator => QualityEstimation.EstimatePasswordBits(Password.ToCharArray());
|
||||
public bool IsFirstItem => _pwEntry == null;
|
||||
|
||||
|
||||
public bool UpperCasePatternSelected { get; set; } = true;
|
||||
public bool LowerCasePatternSelected { get; set; } = true;
|
||||
public bool DigitsPatternSelected { get; set; } = true;
|
||||
@@ -36,6 +33,7 @@ namespace ModernKeePass.ViewModels
|
||||
public bool BracketsPatternSelected { get; set; }
|
||||
public string CustomChars { get; set; } = string.Empty;
|
||||
public PwUuid IdUuid => _pwEntry?.Uuid;
|
||||
public string Id => _pwEntry?.Uuid.ToHexString();
|
||||
|
||||
public double PasswordLength
|
||||
{
|
||||
@@ -46,17 +44,13 @@ namespace ModernKeePass.ViewModels
|
||||
NotifyPropertyChanged("PasswordLength");
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
var title = GetEntryValue(PwDefs.TitleField);
|
||||
return title == null ? "< New entry >" : title;
|
||||
}
|
||||
get { return GetEntryValue(PwDefs.TitleField); }
|
||||
set { SetEntryValue(PwDefs.TitleField, value); }
|
||||
}
|
||||
|
||||
public string Id => _pwEntry?.Uuid.ToHexString();
|
||||
|
||||
public string UserName
|
||||
{
|
||||
@@ -74,6 +68,7 @@ namespace ModernKeePass.ViewModels
|
||||
NotifyPropertyChanged("PasswordComplexityIndicator");
|
||||
}
|
||||
}
|
||||
|
||||
public string Url
|
||||
{
|
||||
get { return GetEntryValue(PwDefs.UrlField); }
|
||||
@@ -118,6 +113,18 @@ namespace ModernKeePass.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsVisible
|
||||
{
|
||||
get { return _isVisible; }
|
||||
set
|
||||
{
|
||||
_isVisible = value;
|
||||
NotifyPropertyChanged("IsVisible");
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsRecycleOnDelete => _database.RecycleBinEnabled && !ParentGroup.IsSelected;
|
||||
|
||||
public bool IsRevealPassword
|
||||
{
|
||||
get { return _isRevealPassword; }
|
||||
@@ -150,10 +157,11 @@ namespace ModernKeePass.ViewModels
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
private readonly PwEntry _pwEntry;
|
||||
private readonly App _app = Application.Current as App;
|
||||
private readonly IDatabaseService _database;
|
||||
private bool _isEditMode;
|
||||
private bool _isRevealPassword;
|
||||
private double _passwordLength = 25;
|
||||
private bool _isVisible = true;
|
||||
|
||||
private void NotifyPropertyChanged(string propertyName)
|
||||
{
|
||||
@@ -161,15 +169,19 @@ namespace ModernKeePass.ViewModels
|
||||
}
|
||||
|
||||
public EntryVm() { }
|
||||
public EntryVm(PwEntry entry, GroupVm parent)
|
||||
|
||||
internal EntryVm(PwEntry entry, GroupVm parent) : this(entry, parent, DatabaseService.Instance) { }
|
||||
|
||||
public EntryVm(PwEntry entry, GroupVm parent, IDatabaseService database)
|
||||
{
|
||||
_database = database;
|
||||
_pwEntry = entry;
|
||||
ParentGroup = parent;
|
||||
}
|
||||
|
||||
public void GeneratePassword()
|
||||
{
|
||||
var pwProfile = new PwProfile()
|
||||
var pwProfile = new PwProfile
|
||||
{
|
||||
GeneratorType = PasswordGeneratorType.CharSet,
|
||||
Length = (uint)PasswordLength,
|
||||
@@ -201,16 +213,17 @@ namespace ModernKeePass.ViewModels
|
||||
return _pwEntry?.Strings.GetSafe(key).ReadString();
|
||||
}
|
||||
|
||||
[DatabaseChanged]
|
||||
private void SetEntryValue(string key, string newValue)
|
||||
{
|
||||
_pwEntry?.Strings.Set(key, new ProtectedString(true, newValue));
|
||||
}
|
||||
|
||||
public void MarkForDelete()
|
||||
public void MarkForDelete(string recycleBinTitle)
|
||||
{
|
||||
if (_app.Database.RecycleBinEnabled && _app.Database.RecycleBin?.IdUuid == null)
|
||||
_app.Database.CreateRecycleBin();
|
||||
Move(_app.Database.RecycleBinEnabled && !ParentGroup.IsSelected ? _app.Database.RecycleBin : null);
|
||||
if (_database.RecycleBinEnabled && _database.RecycleBin?.IdUuid == null)
|
||||
_database.CreateRecycleBin(recycleBinTitle);
|
||||
Move(_database.RecycleBinEnabled && !ParentGroup.IsSelected ? _database.RecycleBin : null);
|
||||
}
|
||||
|
||||
public void UndoDelete()
|
||||
@@ -222,27 +235,29 @@ namespace ModernKeePass.ViewModels
|
||||
{
|
||||
PreviousGroup = ParentGroup;
|
||||
PreviousGroup.Entries.Remove(this);
|
||||
PreviousGroup.RemovePwEntry(_pwEntry);
|
||||
if (destination == null)
|
||||
{
|
||||
_app.Database.AddDeletedItem(IdUuid);
|
||||
_database.AddDeletedItem(IdUuid);
|
||||
return;
|
||||
}
|
||||
ParentGroup = destination;
|
||||
ParentGroup.Entries.Add(this);
|
||||
ParentGroup.AddPwEntry(_pwEntry);
|
||||
}
|
||||
|
||||
public void CommitDelete()
|
||||
{
|
||||
_pwEntry.ParentGroup.Entries.Remove(_pwEntry);
|
||||
if (_app.Database.RecycleBinEnabled && !PreviousGroup.IsSelected) _app.Database.RecycleBin.AddPwEntry(_pwEntry);
|
||||
else _app.Database.AddDeletedItem(IdUuid);
|
||||
if (!_database.RecycleBinEnabled || PreviousGroup.IsSelected) _database.AddDeletedItem(IdUuid);
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
_app.Database.Save();
|
||||
_database.Save();
|
||||
}
|
||||
|
||||
public PwEntry GetPwEntry()
|
||||
{
|
||||
return _pwEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,12 +1,14 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Windows.UI.Text;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using ModernKeePass.Attributes;
|
||||
using ModernKeePass.Common;
|
||||
using ModernKeePass.Interfaces;
|
||||
using ModernKeePass.Mappings;
|
||||
using ModernKeePass.Services;
|
||||
using ModernKeePassLib;
|
||||
|
||||
namespace ModernKeePass.ViewModels
|
||||
@@ -15,33 +17,32 @@ namespace ModernKeePass.ViewModels
|
||||
{
|
||||
public GroupVm ParentGroup { get; private set; }
|
||||
public GroupVm PreviousGroup { get; private set; }
|
||||
public ObservableCollection<EntryVm> Entries { get; set; } = new ObservableCollection<EntryVm>();
|
||||
|
||||
public ObservableCollection<EntryVm> Entries
|
||||
{
|
||||
get { return _entries; }
|
||||
set { SetProperty(ref _entries, value); }
|
||||
}
|
||||
|
||||
public ObservableCollection<GroupVm> Groups { get; set; } = new ObservableCollection<GroupVm>();
|
||||
|
||||
public int EntryCount => Entries.Count() - 1;
|
||||
public FontWeight FontWeight => _pwGroup == null ? FontWeights.Bold : FontWeights.Normal;
|
||||
public int GroupCount => Groups.Count - 1;
|
||||
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.RecycleBinEnabled && !IsSelected && !ParentGroup.IsSelected;
|
||||
/// <summary>
|
||||
/// Is the Group the database Recycle Bin?
|
||||
/// </summary>
|
||||
public bool IsSelected
|
||||
{
|
||||
get { return _app.Database.RecycleBinEnabled && _app.Database.RecycleBin?.Id == Id; }
|
||||
get { return _database != null && _database.RecycleBinEnabled && _database.RecycleBin?.Id == Id; }
|
||||
set
|
||||
{
|
||||
if (value && _pwGroup != null) _app.Database.RecycleBin = this;
|
||||
/*else if (value && _pwGroup == null)
|
||||
{
|
||||
var recycleBin = _app.Database.RootGroup.AddNewGroup("Recycle bin");
|
||||
recycleBin.IsSelected = true;
|
||||
recycleBin.IconSymbol = Symbol.Delete;
|
||||
}*/
|
||||
if (value && _pwGroup != null) _database.RecycleBin = this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +54,8 @@ namespace ModernKeePass.ViewModels
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return _pwGroup == null ? "< New group >" : _pwGroup.Name; }
|
||||
get { return _pwGroup == null ? string.Empty : _pwGroup.Name; }
|
||||
[DatabaseChanged]
|
||||
set { _pwGroup.Name = value; }
|
||||
}
|
||||
|
||||
@@ -61,7 +63,6 @@ namespace ModernKeePass.ViewModels
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_pwGroup == null) return Symbol.Add;
|
||||
var result = PwIconToSegoeMapping.GetSymbolFromIcon(_pwGroup.IconId);
|
||||
return result == Symbol.More ? Symbol.Folder : result;
|
||||
}
|
||||
@@ -74,6 +75,12 @@ namespace ModernKeePass.ViewModels
|
||||
set { SetProperty(ref _isEditMode, value); }
|
||||
}
|
||||
|
||||
public bool IsMenuClosed
|
||||
{
|
||||
get { return _isMenuClosed; }
|
||||
set { SetProperty(ref _isMenuClosed, value); }
|
||||
}
|
||||
|
||||
public string Path
|
||||
{
|
||||
get
|
||||
@@ -86,23 +93,48 @@ namespace ModernKeePass.ViewModels
|
||||
}
|
||||
|
||||
private readonly PwGroup _pwGroup;
|
||||
private readonly App _app = Application.Current as App;
|
||||
private readonly IDatabaseService _database;
|
||||
private bool _isEditMode;
|
||||
private PwEntry _reorderedEntry;
|
||||
private ObservableCollection<EntryVm> _entries = new ObservableCollection<EntryVm>();
|
||||
private bool _isMenuClosed = true;
|
||||
|
||||
public GroupVm() {}
|
||||
|
||||
public GroupVm(PwGroup pwGroup, GroupVm parent, PwUuid recycleBinId = null)
|
||||
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;
|
||||
|
||||
if (recycleBinId != null && _pwGroup.Uuid.Equals(recycleBinId)) _app.Database.RecycleBin = this;
|
||||
Entries = new ObservableCollection<EntryVm>(pwGroup.Entries.Select(e => new EntryVm(e, this)).OrderBy(e => e.Name));
|
||||
Entries.Insert(0, new EntryVm ());
|
||||
Groups = new ObservableCollection<GroupVm>(pwGroup.Groups.Select(g => new GroupVm(g, this, recycleBinId)).OrderBy(g => g.Name));
|
||||
Groups.Insert(0, new GroupVm ());
|
||||
if (recycleBinId != null && _pwGroup.Uuid.Equals(recycleBinId)) _database.RecycleBin = this;
|
||||
Entries = new ObservableCollection<EntryVm>(pwGroup.Entries.Select(e => new EntryVm(e, this)));
|
||||
Entries.CollectionChanged += Entries_CollectionChanged;
|
||||
Groups = new ObservableCollection<GroupVm>(pwGroup.Groups.Select(g => new GroupVm(g, this, recycleBinId)));
|
||||
}
|
||||
|
||||
[DatabaseChanged]
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
[DatabaseChanged]
|
||||
public GroupVm AddNewGroup(string name = "")
|
||||
{
|
||||
var pwGroup = new PwGroup(true, true, name, PwIcon.Folder);
|
||||
@@ -115,35 +147,25 @@ namespace ModernKeePass.ViewModels
|
||||
public EntryVm AddNewEntry()
|
||||
{
|
||||
var pwEntry = new PwEntry(true, true);
|
||||
_pwGroup.AddEntry(pwEntry, true);
|
||||
var newEntry = new EntryVm(pwEntry, this) {IsEditMode = true};
|
||||
newEntry.GeneratePassword();
|
||||
Entries.Add(newEntry);
|
||||
return newEntry;
|
||||
}
|
||||
|
||||
public void AddPwEntry(PwEntry entry)
|
||||
public void MarkForDelete(string recycleBinTitle)
|
||||
{
|
||||
_pwGroup.AddEntry(entry, true);
|
||||
if (_database.RecycleBinEnabled && _database.RecycleBin?.IdUuid == null)
|
||||
_database.CreateRecycleBin(recycleBinTitle);
|
||||
Move(_database.RecycleBinEnabled && !IsSelected ? _database.RecycleBin : null);
|
||||
}
|
||||
|
||||
public void RemovePwEntry(PwEntry entry)
|
||||
{
|
||||
_pwGroup.Entries.Remove(entry);
|
||||
}
|
||||
|
||||
public void MarkForDelete()
|
||||
{
|
||||
if (_app.Database.RecycleBinEnabled && _app.Database.RecycleBin?.IdUuid == null)
|
||||
_app.Database.CreateRecycleBin();
|
||||
Move(_app.Database.RecycleBinEnabled && !IsSelected ? _app.Database.RecycleBin : null);
|
||||
}
|
||||
|
||||
|
||||
public void UndoDelete()
|
||||
{
|
||||
Move(PreviousGroup);
|
||||
}
|
||||
|
||||
[DatabaseChanged]
|
||||
public void Move(GroupVm destination)
|
||||
{
|
||||
PreviousGroup = ParentGroup;
|
||||
@@ -151,7 +173,7 @@ namespace ModernKeePass.ViewModels
|
||||
PreviousGroup._pwGroup.Groups.Remove(_pwGroup);
|
||||
if (destination == null)
|
||||
{
|
||||
_app.Database.AddDeletedItem(IdUuid);
|
||||
_database.AddDeletedItem(IdUuid);
|
||||
return;
|
||||
}
|
||||
ParentGroup = destination;
|
||||
@@ -162,13 +184,43 @@ namespace ModernKeePass.ViewModels
|
||||
public void CommitDelete()
|
||||
{
|
||||
_pwGroup.ParentGroup.Groups.Remove(_pwGroup);
|
||||
if (_app.Database.RecycleBinEnabled && !PreviousGroup.IsSelected) _app.Database.RecycleBin._pwGroup.AddGroup(_pwGroup, true);
|
||||
else _app.Database.AddDeletedItem(IdUuid);
|
||||
if (_database.RecycleBinEnabled && !PreviousGroup.IsSelected) _database.RecycleBin._pwGroup.AddGroup(_pwGroup, true);
|
||||
else _database.AddDeletedItem(IdUuid);
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
_app.Database.Save();
|
||||
_database.Save();
|
||||
}
|
||||
|
||||
[DatabaseChanged]
|
||||
public void SortEntries()
|
||||
{
|
||||
var comparer = new PwEntryComparer(PwDefs.TitleField, true, false);
|
||||
try
|
||||
{
|
||||
_pwGroup.Entries.Sort(comparer);
|
||||
Entries = new ObservableCollection<EntryVm>(Entries.OrderBy(e => e.Name));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageDialogHelper.ShowErrorDialog(e);
|
||||
}
|
||||
}
|
||||
|
||||
[DatabaseChanged]
|
||||
public void SortGroups()
|
||||
{
|
||||
try
|
||||
{
|
||||
_pwGroup.SortSubGroups(false);
|
||||
Groups = new ObservableCollection<GroupVm>(Groups.OrderBy(g => g.Name).ThenBy(g => g._pwGroup == null));
|
||||
OnPropertyChanged("Groups");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageDialogHelper.ShowErrorDialog(e);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
@@ -11,7 +11,7 @@ namespace ModernKeePass.ViewModels
|
||||
|
||||
public string Title { get; set; }
|
||||
|
||||
public int Group { get; set; } = 0;
|
||||
public string Group { get; set; } = "_";
|
||||
public Type PageType { get; set; }
|
||||
public Symbol SymbolIcon { get; set; }
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
|
@@ -1,22 +1,14 @@
|
||||
using Windows.Storage;
|
||||
using ModernKeePass.Common;
|
||||
using Windows.Storage.AccessCache;
|
||||
using ModernKeePass.Interfaces;
|
||||
using ModernKeePass.Services;
|
||||
|
||||
namespace ModernKeePass.ViewModels
|
||||
{
|
||||
public class RecentItemVm: NotifyPropertyChangedBase, ISelectableModel
|
||||
public class RecentItemVm: NotifyPropertyChangedBase, ISelectableModel, IRecentItem
|
||||
{
|
||||
private bool _isSelected;
|
||||
|
||||
public RecentItemVm() {}
|
||||
public RecentItemVm(AccessListEntry entry, StorageFile file)
|
||||
{
|
||||
Token = entry.Token;
|
||||
Name = entry.Metadata;
|
||||
DatabaseFile = file;
|
||||
}
|
||||
|
||||
public StorageFile DatabaseFile { get; }
|
||||
public string Token { get; }
|
||||
public string Name { get; }
|
||||
@@ -27,5 +19,33 @@ namespace ModernKeePass.ViewModels
|
||||
get { return _isSelected; }
|
||||
set { SetProperty(ref _isSelected, value); }
|
||||
}
|
||||
|
||||
public RecentItemVm() {}
|
||||
public RecentItemVm(string token, string metadata, IStorageItem file)
|
||||
{
|
||||
Token = token;
|
||||
Name = metadata;
|
||||
DatabaseFile = file as StorageFile;
|
||||
}
|
||||
|
||||
public void OpenDatabaseFile()
|
||||
{
|
||||
OpenDatabaseFile(DatabaseService.Instance);
|
||||
}
|
||||
|
||||
public void OpenDatabaseFile(IDatabaseService database)
|
||||
{
|
||||
database.DatabaseFile = DatabaseFile;
|
||||
}
|
||||
|
||||
public void UpdateAccessTime()
|
||||
{
|
||||
UpdateAccessTime(RecentService.Instance);
|
||||
}
|
||||
|
||||
public async void UpdateAccessTime(IRecentService recent)
|
||||
{
|
||||
await recent.GetFileAsync(Token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,29 +2,37 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Windows.Storage;
|
||||
using Windows.UI.Xaml;
|
||||
using ModernKeePass.Common;
|
||||
using ModernKeePass.Interfaces;
|
||||
using ModernKeePass.Services;
|
||||
using ModernKeePassLib;
|
||||
using ModernKeePassLib.Cryptography.Cipher;
|
||||
using ModernKeePassLib.Cryptography.KeyDerivation;
|
||||
|
||||
namespace ModernKeePass.ViewModels
|
||||
{
|
||||
// TODO: implement Kdf settings
|
||||
public class SettingsDatabaseVm: NotifyPropertyChangedBase, IHasSelectableObject
|
||||
{
|
||||
private readonly App _app = Application.Current as App;
|
||||
private readonly ApplicationDataContainer _localSettings = ApplicationData.Current.LocalSettings;
|
||||
private readonly IDatabaseService _database;
|
||||
private GroupVm _selectedItem;
|
||||
|
||||
public bool HasRecycleBin
|
||||
{
|
||||
get { return _app.Database.RecycleBinEnabled; }
|
||||
get { return _database.RecycleBinEnabled; }
|
||||
set
|
||||
{
|
||||
_app.Database.RecycleBinEnabled = value;
|
||||
OnPropertyChanged();
|
||||
_database.RecycleBinEnabled = value;
|
||||
OnPropertyChanged("HasRecycleBin");
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsNewRecycleBin
|
||||
{
|
||||
get { return _database.RecycleBin == null; }
|
||||
set
|
||||
{
|
||||
if (value) _database.RecycleBin = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,26 +55,26 @@ namespace ModernKeePass.ViewModels
|
||||
{
|
||||
for (var inx = 0; inx < CipherPool.GlobalPool.EngineCount; ++inx)
|
||||
{
|
||||
if (CipherPool.GlobalPool[inx].CipherUuid.Equals(_app.Database.DataCipher)) return inx;
|
||||
if (CipherPool.GlobalPool[inx].CipherUuid.Equals(_database.DataCipher)) return inx;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
set { _app.Database.DataCipher = CipherPool.GlobalPool[value].CipherUuid; }
|
||||
set { _database.DataCipher = CipherPool.GlobalPool[value].CipherUuid; }
|
||||
}
|
||||
|
||||
public IEnumerable<string> Compressions => Enum.GetNames(typeof(PwCompressionAlgorithm)).Take((int)PwCompressionAlgorithm.Count);
|
||||
|
||||
public string CompressionName
|
||||
{
|
||||
get { return Enum.GetName(typeof(PwCompressionAlgorithm), _app.Database.CompressionAlgorithm); }
|
||||
set { _app.Database.CompressionAlgorithm = (PwCompressionAlgorithm)Enum.Parse(typeof(PwCompressionAlgorithm), value); }
|
||||
get { return Enum.GetName(typeof(PwCompressionAlgorithm), _database.CompressionAlgorithm); }
|
||||
set { _database.CompressionAlgorithm = (PwCompressionAlgorithm)Enum.Parse(typeof(PwCompressionAlgorithm), value); }
|
||||
}
|
||||
public IEnumerable<string> KeyDerivations => KdfPool.Engines.Select(e => e.Name);
|
||||
|
||||
public string KeyDerivationName
|
||||
{
|
||||
get { return KdfPool.Get(_app.Database.KeyDerivation.KdfUuid).Name; }
|
||||
set { _app.Database.KeyDerivation = KdfPool.Engines.FirstOrDefault(e => e.Name == value)?.GetDefaultParameters(); }
|
||||
get { return KdfPool.Get(_database.KeyDerivation.KdfUuid).Name; }
|
||||
set { _database.KeyDerivation = KdfPool.Engines.FirstOrDefault(e => e.Name == value)?.GetDefaultParameters(); }
|
||||
}
|
||||
|
||||
public ISelectableModel SelectedItem
|
||||
@@ -74,7 +82,7 @@ namespace ModernKeePass.ViewModels
|
||||
get { return Groups.FirstOrDefault(g => g.IsSelected); }
|
||||
set
|
||||
{
|
||||
if (_selectedItem == value) return;
|
||||
if (_selectedItem == value || IsNewRecycleBin) return;
|
||||
if (_selectedItem != null)
|
||||
{
|
||||
_selectedItem.IsSelected = false;
|
||||
@@ -89,22 +97,12 @@ namespace ModernKeePass.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public SettingsDatabaseVm()
|
||||
{
|
||||
Groups = _app?.Database.RootGroup.Groups;
|
||||
}
|
||||
public SettingsDatabaseVm() : this(DatabaseService.Instance) { }
|
||||
|
||||
// TODO: Move to another setting class (or a static class)
|
||||
private T GetSetting<T>(string property)
|
||||
public SettingsDatabaseVm(IDatabaseService database)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (T) Convert.ChangeType(_localSettings.Values[property], typeof(T));
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
_database = database;
|
||||
Groups = _database?.RootGroup.Groups;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
33
ModernKeePass/ViewModels/Items/SettingsNewVm.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
using ModernKeePass.Interfaces;
|
||||
using ModernKeePass.Services;
|
||||
|
||||
namespace ModernKeePass.ViewModels
|
||||
{
|
||||
public class SettingsNewVm
|
||||
{
|
||||
private readonly ISettingsService _settings;
|
||||
|
||||
public SettingsNewVm() : this(SettingsService.Instance)
|
||||
{ }
|
||||
|
||||
public SettingsNewVm(ISettingsService settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public bool IsCreateSample
|
||||
{
|
||||
get { return _settings.GetSetting<bool>("Sample"); }
|
||||
set { _settings.PutSetting("Sample", value); }
|
||||
}
|
||||
|
||||
public IEnumerable<string> FileFormats => new []{"2", "4"};
|
||||
|
||||
public string FileFormatVersion
|
||||
{
|
||||
get { return _settings.GetSetting<string>("DefaultFileFormat"); }
|
||||
set { _settings.PutSetting("DefaultFileFormat", value); }
|
||||
}
|
||||
}
|
||||
}
|