Compare commits
74 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
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 | ||
![]() |
abb12accc7 | ||
2779e5b7c7 | |||
3970d485f6 | |||
![]() |
7b888cc4a2 | ||
![]() |
117513d6bf | ||
97511ab290 | |||
3131eca8a1 | |||
91a5507217 | |||
7d904b7120 | |||
![]() |
be72fc4f7e |
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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,15 @@
|
||||
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 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,7 +20,7 @@ namespace ModernKeePass
|
||||
/// </summary>
|
||||
sealed partial class App
|
||||
{
|
||||
public DatabaseHelper Database { get; set; } = new DatabaseHelper();
|
||||
public DatabaseService Database { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the singleton application object. This is the first line of authored code
|
||||
@@ -29,9 +30,27 @@ namespace ModernKeePass
|
||||
{
|
||||
InitializeComponent();
|
||||
Suspending += OnSuspending;
|
||||
UnhandledException += OnUnhandledException;
|
||||
Database = new DatabaseService();
|
||||
}
|
||||
|
||||
#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)) return;
|
||||
unhandledExceptionEventArgs.Handled = true;
|
||||
MessageDialogHelper.SaveErrorDialog(realException as SaveException, Database);
|
||||
}
|
||||
|
||||
/// <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.
|
||||
@@ -86,7 +105,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
|
||||
{
|
||||
@@ -126,6 +145,7 @@ namespace ModernKeePass
|
||||
private void OnSuspending(object sender, SuspendingEventArgs e)
|
||||
{
|
||||
var deferral = e.SuspendingOperation.GetDeferral();
|
||||
UnhandledException -= OnUnhandledException;
|
||||
Database.Save();
|
||||
deferral.Complete();
|
||||
}
|
||||
@@ -139,10 +159,11 @@ namespace ModernKeePass
|
||||
base.OnFileActivated(args);
|
||||
var rootFrame = new Frame();
|
||||
Database.DatabaseFile = args.Files[0] as StorageFile;
|
||||
rootFrame.Navigate(typeof(Pages.MainPage), args);
|
||||
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,157 +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
|
||||
{
|
||||
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 string Open(CompositeKey key, bool createNew = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (key == null) return "No composite key";
|
||||
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 (ArgumentNullException)
|
||||
{
|
||||
return "Password cannot be empty";
|
||||
}
|
||||
catch (InvalidCompositeKeyException)
|
||||
{
|
||||
return "Wrong password";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ex.Message;
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <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 void Save()
|
||||
{
|
||||
// TODO: Save is disabled for now for Argon2Kdf because it corrupts DB (read works)
|
||||
if (_pwDatabase == null || !_pwDatabase.IsOpen /*|| KdfPool.Get(KeyDerivation.KdfUuid) is Argon2Kdf*/) return;
|
||||
_pwDatabase.Save(new NullStatusLogger());
|
||||
}
|
||||
|
||||
/// <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,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Windows.Storage.Pickers;
|
||||
using Windows.UI.Popups;
|
||||
using Windows.UI.Xaml.Media.Animation;
|
||||
using ModernKeePass.Exceptions;
|
||||
using ModernKeePass.Interfaces;
|
||||
|
||||
namespace ModernKeePass.Common
|
||||
{
|
||||
public static class MessageDialogHelper
|
||||
{
|
||||
public static async void ShowDeleteConfirmationDialog(string actionText, string contentText, UICommandInvokedHandler action)
|
||||
public static async void ShowActionDialog(string title, string contentText, string actionButtonText, string cancelButtonText, UICommandInvokedHandler action)
|
||||
{
|
||||
// Create the message dialog and set its content
|
||||
var messageDialog = new MessageDialog(contentText);
|
||||
var messageDialog = CreateBasicDialog(title, contentText, cancelButtonText);
|
||||
|
||||
// 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, action));
|
||||
|
||||
// Show the message dialog
|
||||
await messageDialog.ShowAsync();
|
||||
}
|
||||
|
||||
public static void SaveErrorDialog(SaveException exception, IDatabase 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);
|
||||
});
|
||||
}
|
||||
|
||||
public static async void ShowErrorDialog(Exception exception)
|
||||
{
|
||||
if (exception == null) return;
|
||||
// Create the message dialog and set its content
|
||||
var messageDialog = CreateBasicDialog("Error occured", exception.Message, "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)
|
||||
{
|
||||
// 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));
|
||||
|
||||
// Set the command that will be invoked by default
|
||||
messageDialog.DefaultCommandIndex = 1;
|
||||
@@ -20,8 +70,7 @@ namespace ModernKeePass.Common
|
||||
// Set the command to be invoked when escape is pressed
|
||||
messageDialog.CancelCommandIndex = 1;
|
||||
|
||||
// Show the message dialog
|
||||
await messageDialog.ShowAsync();
|
||||
return messageDialog;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -32,5 +32,18 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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)
|
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);
|
||||
}
|
||||
}
|
29
ModernKeePass/Interfaces/IDatabase.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Windows.Storage;
|
||||
using ModernKeePass.ViewModels;
|
||||
using ModernKeePassLib;
|
||||
using ModernKeePassLib.Cryptography.KeyDerivation;
|
||||
using ModernKeePassLib.Keys;
|
||||
|
||||
namespace ModernKeePass.Interfaces
|
||||
{
|
||||
public interface IDatabase
|
||||
{
|
||||
string Name { get; }
|
||||
bool RecycleBinEnabled { get; set; }
|
||||
int Status { get; set; }
|
||||
GroupVm RootGroup { get; set; }
|
||||
GroupVm RecycleBin { get; set; }
|
||||
StorageFile DatabaseFile { get; set; }
|
||||
PwUuid DataCipher { get; set; }
|
||||
PwCompressionAlgorithm CompressionAlgorithm { get; set; }
|
||||
KdfParameters KeyDerivation { get; set; }
|
||||
|
||||
void Open(CompositeKey key, bool createNew);
|
||||
void UpdateCompositeKey(CompositeKey key);
|
||||
void Save();
|
||||
void Save(StorageFile file);
|
||||
void CreateRecycleBin();
|
||||
void AddDeletedItem(PwUuid id);
|
||||
void Close();
|
||||
}
|
||||
}
|
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);
|
||||
}
|
||||
}
|
@@ -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
|
||||
|
15
ModernKeePass/Interfaces/IRecent.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
|
||||
namespace ModernKeePass.Interfaces
|
||||
{
|
||||
public interface IRecent
|
||||
{
|
||||
int EntryCount { get; }
|
||||
Task<IStorageItem> GetFileAsync(string token);
|
||||
ObservableCollection<IRecentItem> GetAllFiles(bool removeIfNonExistant = true);
|
||||
void Add(IStorageItem file, string metadata);
|
||||
void ClearAll();
|
||||
}
|
||||
}
|
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; }
|
||||
}
|
||||
}
|
7
ModernKeePass/Interfaces/IResource.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace ModernKeePass.Interfaces
|
||||
{
|
||||
public interface IResource
|
||||
{
|
||||
string GetResourceValue(string key);
|
||||
}
|
||||
}
|
8
ModernKeePass/Interfaces/ISettings.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace ModernKeePass.Interfaces
|
||||
{
|
||||
public interface ISettings
|
||||
{
|
||||
T GetSetting<T>(string property);
|
||||
void PutSetting<T>(string property, T value);
|
||||
}
|
||||
}
|
@@ -109,32 +109,57 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Actions\ClipboardAction.cs" />
|
||||
<Compile Include="Actions\NavigateToUrlAction.cs" />
|
||||
<Compile Include="Actions\SetupFocusAction.cs" />
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Common\DatabaseHelper.cs" />
|
||||
<Compile Include="Interfaces\ILicenseService.cs" />
|
||||
<Compile Include="Interfaces\IRecent.cs" />
|
||||
<Compile Include="Interfaces\IRecentItem.cs" />
|
||||
<Compile Include="Interfaces\IResource.cs" />
|
||||
<Compile Include="TemplateSelectors\SelectableDataTemplateSelector.cs" />
|
||||
<Compile Include="ViewModels\DonateVm.cs" />
|
||||
<Compile Include="Views\MainPageFrames\DonatePage.xaml.cs">
|
||||
<DependentUpon>DonatePage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Services\DatabaseService.cs" />
|
||||
<Compile Include="Interfaces\ISettings.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\IDatabase.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\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 +167,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 +194,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 +225,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 +241,67 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="Controls\CompositeKeyUserControl.xaml">
|
||||
<Page Include="Views\UserControls\CompositeKeyUserControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\MainPage.xaml">
|
||||
<Page Include="Views\MainPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Pages\MainPageFrames\AboutPage.xaml">
|
||||
<Page Include="Views\MainPageFrames\AboutPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\EntryDetailPage.xaml">
|
||||
<Page Include="Views\EntryDetailPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\GroupDetailPage.xaml">
|
||||
<Page Include="Views\GroupDetailPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\MainPageFrames\NewDatabasePage.xaml">
|
||||
<Page Include="Views\MainPageFrames\DonatePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\MainPageFrames\OpenDatabasePage.xaml">
|
||||
<Page Include="Views\MainPageFrames\NewDatabasePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\MainPageFrames\RecentDatabasesPage.xaml">
|
||||
<Page Include="Views\MainPageFrames\OpenDatabasePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\MainPageFrames\SaveDatabasePage.xaml">
|
||||
<Page Include="Views\MainPageFrames\RecentDatabasesPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\SettingsPage.xaml">
|
||||
<Page Include="Views\MainPageFrames\SaveDatabasePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\MainPageFrames\WelcomePage.xaml">
|
||||
<Page Include="Views\SettingsPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\SettingsPageFrames\SettingsDatabasePage.xaml">
|
||||
<Page Include="Views\MainPageFrames\WelcomePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\SettingsPageFrames\SettingsSecurityPage.xaml">
|
||||
<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 +320,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>
|
||||
@@ -297,7 +341,7 @@
|
||||
<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.37.8000\lib\netstandard1.2\ModernKeePassLib.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
@@ -319,31 +363,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.7.0.28" />
|
||||
<Identity Name="wismna.ModernKeePass" Publisher="CN=0719A91A-C322-4EE0-A257-E60733EECF06" Version="1.12.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,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.7.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.7.0.0")]
|
||||
[assembly: AssemblyVersion("1.12.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.12.0.0")]
|
||||
[assembly: ComVisible(false)]
|
234
ModernKeePass/Services/DatabaseService.cs
Normal file
@@ -0,0 +1,234 @@
|
||||
using System;
|
||||
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: IDatabase
|
||||
{
|
||||
public enum DatabaseStatus
|
||||
{
|
||||
Error = -3,
|
||||
NoCompositeKey = -2,
|
||||
CompositeKeyError = -1,
|
||||
Closed = 0,
|
||||
Opening = 1,
|
||||
Opened = 2
|
||||
}
|
||||
private readonly PwDatabase _pwDatabase = new PwDatabase();
|
||||
private readonly ISettings _settings;
|
||||
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 int Status { get; set; } = (int)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 = (int)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; }
|
||||
}
|
||||
|
||||
public DatabaseService() : this(new SettingsService())
|
||||
{ }
|
||||
|
||||
public DatabaseService(ISettings 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 void Open(CompositeKey key, bool createNew = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (key == null)
|
||||
{
|
||||
Status = (int)DatabaseStatus.NoCompositeKey;
|
||||
return;
|
||||
}
|
||||
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;
|
||||
Status = (int)DatabaseStatus.Opened;
|
||||
RootGroup = new GroupVm(_pwDatabase.RootGroup, null, RecycleBinEnabled ? _pwDatabase.RecycleBinUuid : null);
|
||||
}
|
||||
catch (InvalidCompositeKeyException)
|
||||
{
|
||||
Status = (int)DatabaseStatus.CompositeKeyError;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Status = (int)DatabaseStatus.Error;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Status = (int)DatabaseStatus.Opened;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Commit the changes to the currently opened database to file
|
||||
/// </summary>
|
||||
public void Save()
|
||||
{
|
||||
if (_pwDatabase == null || !_pwDatabase.IsOpen) return;
|
||||
try
|
||||
{
|
||||
_pwDatabase.Save(new NullStatusLogger());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new SaveException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close the currently opened database
|
||||
/// </summary>
|
||||
public void Close()
|
||||
{
|
||||
_pwDatabase?.Close();
|
||||
Status = (int)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;
|
||||
}
|
||||
|
||||
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 : 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 : IRecent
|
||||
{
|
||||
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: IResource
|
||||
{
|
||||
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 : ISettings
|
||||
{
|
||||
private readonly IPropertySet _values = ApplicationData.Current.LocalSettings.Values;
|
||||
|
||||
public T GetSetting<T>(string property)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (T)Convert.ChangeType(_values[property], typeof(T));
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
|
||||
public void PutSetting<T>(string property, T value)
|
||||
{
|
||||
if (_values.ContainsKey(property))
|
||||
_values[property] = value;
|
||||
else _values.Add(property, 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="EntryNew" xml:space="preserve">
|
||||
<value>< New 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="GroupNew" xml:space="preserve">
|
||||
<value>< New group ></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>
|
||||
</root>
|
369
ModernKeePass/Strings/en-US/Resources.resw
Normal file
@@ -0,0 +1,369 @@
|
||||
<?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="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="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>
|
277
ModernKeePass/Strings/fr-FR/CodeBehind.resw
Normal file
@@ -0,0 +1,277 @@
|
||||
<?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="EntryNew" xml:space="preserve">
|
||||
<value>< Nouvelle entrée ></value>
|
||||
<comment>Unused</comment>
|
||||
</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="GroupNew" xml:space="preserve">
|
||||
<value>< Nouveau groupe ></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>
|
||||
</root>
|
369
ModernKeePass/Strings/fr-FR/Resources.resw
Normal file
@@ -0,0 +1,369 @@
|
||||
<?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>Restorer</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="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="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"
|
||||
@@ -83,14 +83,15 @@
|
||||
Background="{ThemeResource TextBoxButtonBackgroundThemeBrush}"
|
||||
Margin="{TemplateBinding BorderThickness}">
|
||||
<TextBlock x:Name="GlyphElement"
|
||||
Foreground="{ThemeResource TextBoxButtonForegroundThemeBrush}"
|
||||
Padding="4,0,4,0"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
FontStyle="Normal"
|
||||
Text="{TemplateBinding Content}"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
AutomationProperties.AccessibilityView="Raw"/>
|
||||
Foreground="{ThemeResource TextBoxButtonForegroundThemeBrush}"
|
||||
Padding="4,0,4,0"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
FontStyle="Normal"
|
||||
Text="{TemplateBinding Content}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
AutomationProperties.AccessibilityView="Raw"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
@@ -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,6 +1,11 @@
|
||||
using Windows.Storage;
|
||||
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;
|
||||
@@ -17,13 +22,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;
|
||||
public IDatabase Database { get; set; }
|
||||
|
||||
public bool HasPassword
|
||||
{
|
||||
@@ -45,7 +44,17 @@ namespace ModernKeePass.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsValid => HasPassword || HasKeyFile;
|
||||
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
|
||||
{
|
||||
@@ -67,6 +76,7 @@ namespace ModernKeePass.ViewModels
|
||||
_password = value;
|
||||
OnPropertyChanged("PasswordComplexityIndicator");
|
||||
StatusType = (int)StatusTypes.Normal;
|
||||
Status = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,24 +86,89 @@ namespace ModernKeePass.ViewModels
|
||||
set
|
||||
{
|
||||
_keyFile = value;
|
||||
UpdateStatus($"Key file: {value.Name}", StatusTypes.Normal);
|
||||
KeyFileText = value?.Name;
|
||||
OnPropertyChanged("IsValid");
|
||||
}
|
||||
}
|
||||
|
||||
public string KeyFileText
|
||||
{
|
||||
get { return _keyFileText; }
|
||||
set { SetProperty(ref _keyFileText, value); }
|
||||
}
|
||||
|
||||
public GroupVm RootGroup { get; set; }
|
||||
|
||||
public double PasswordComplexityIndicator => QualityEstimation.EstimatePasswordBits(Password?.ToCharArray());
|
||||
|
||||
public DatabaseHelper.DatabaseStatus 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 IResource _resource;
|
||||
|
||||
public CompositeKeyVm() : this((Application.Current as App)?.Database, new ResourcesService()) { }
|
||||
|
||||
public CompositeKeyVm(IDatabase database, IResource resource)
|
||||
{
|
||||
UpdateStatus(_app.Database.Open(CreateCompositeKey(), createNew), StatusTypes.Error);
|
||||
RootGroup = _app.Database.RootGroup;
|
||||
return _app.Database.Status;
|
||||
_resource = resource;
|
||||
_keyFileText = _resource.GetResourceValue("CompositeKeyDefaultKeyFile");
|
||||
Database = database;
|
||||
}
|
||||
|
||||
public async Task<bool> OpenDatabase(bool createNew)
|
||||
{
|
||||
var error = string.Empty;
|
||||
try
|
||||
{
|
||||
_isOpening = true;
|
||||
Database.Open(CreateCompositeKey(), createNew);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
error = $"{_resource.GetResourceValue("CompositeKeyErrorOpen")}: {e.Message}";
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isOpening = false;
|
||||
}
|
||||
switch ((DatabaseService.DatabaseStatus)Database.Status)
|
||||
{
|
||||
case DatabaseService.DatabaseStatus.Opened:
|
||||
await Task.Run(() => RootGroup = Database.RootGroup);
|
||||
return true;
|
||||
case DatabaseService.DatabaseStatus.CompositeKeyError:
|
||||
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 (HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserAccount"));
|
||||
UpdateStatus(errorMessage.ToString(), StatusTypes.Error);
|
||||
break;
|
||||
case DatabaseService.DatabaseStatus.Error:
|
||||
UpdateStatus(error, StatusTypes.Error);
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void UpdateKey()
|
||||
{
|
||||
_app.Database.UpdateCompositeKey(CreateCompositeKey());
|
||||
UpdateStatus("Database composite key updated.", StatusTypes.Success);
|
||||
Database.UpdateCompositeKey(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)
|
||||
@@ -106,7 +181,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;
|
||||
}
|
||||
}
|
||||
|
44
ModernKeePass/ViewModels/DonateVm.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel.Store;
|
||||
using ModernKeePass.Common;
|
||||
using ModernKeePass.Interfaces;
|
||||
using ModernKeePass.Services;
|
||||
|
||||
namespace ModernKeePass.ViewModels
|
||||
{
|
||||
public class DonateVm: NotifyPropertyChangedBase
|
||||
{
|
||||
public ObservableCollection<ProductListing> Donations { get; }
|
||||
|
||||
public ProductListing SelectedItem
|
||||
{
|
||||
get { return _selectedItem; }
|
||||
set { SetProperty(ref _selectedItem, value); }
|
||||
}
|
||||
|
||||
private readonly ILicenseService _license;
|
||||
private ProductListing _selectedItem;
|
||||
|
||||
public DonateVm() : this (new LicenseService()) { }
|
||||
|
||||
public DonateVm(ILicenseService license)
|
||||
{
|
||||
// TODO: find a nice way to order products
|
||||
_license = license;
|
||||
Donations = new ObservableCollection<ProductListing>(
|
||||
_license.Products.Values
|
||||
/*.OrderBy(p => decimal.Parse(p.FormattedPrice.Replace('\u00A0', ' '), NumberStyles.Currency,
|
||||
CultureInfo.CurrentCulture.NumberFormat))*/
|
||||
);
|
||||
}
|
||||
|
||||
public async Task<int> Purchase()
|
||||
{
|
||||
return await _license.Purchase(SelectedItem.ProductId);
|
||||
}
|
||||
}
|
||||
}
|
@@ -15,17 +15,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 +32,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 +43,18 @@ namespace ModernKeePass.ViewModels
|
||||
NotifyPropertyChanged("PasswordLength");
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
var title = GetEntryValue(PwDefs.TitleField);
|
||||
return title == null ? "< New entry >" : title;
|
||||
/*var title = GetEntryValue(PwDefs.TitleField);
|
||||
return title == null ? _resource.GetResourceValue("EntryNew") : title;*/
|
||||
return GetEntryValue(PwDefs.TitleField);
|
||||
}
|
||||
set { SetEntryValue(PwDefs.TitleField, value); }
|
||||
}
|
||||
|
||||
public string Id => _pwEntry?.Uuid.ToHexString();
|
||||
|
||||
public string UserName
|
||||
{
|
||||
@@ -118,6 +116,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 +160,11 @@ namespace ModernKeePass.ViewModels
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
private readonly PwEntry _pwEntry;
|
||||
private readonly App _app = Application.Current as App;
|
||||
private readonly IDatabase _database;
|
||||
private bool _isEditMode;
|
||||
private bool _isRevealPassword;
|
||||
private double _passwordLength = 25;
|
||||
private bool _isVisible = true;
|
||||
|
||||
private void NotifyPropertyChanged(string propertyName)
|
||||
{
|
||||
@@ -161,15 +172,19 @@ namespace ModernKeePass.ViewModels
|
||||
}
|
||||
|
||||
public EntryVm() { }
|
||||
public EntryVm(PwEntry entry, GroupVm parent)
|
||||
|
||||
internal EntryVm(PwEntry entry, GroupVm parent) : this(entry, parent, (Application.Current as App)?.Database) { }
|
||||
|
||||
public EntryVm(PwEntry entry, GroupVm parent, IDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
_pwEntry = entry;
|
||||
ParentGroup = parent;
|
||||
}
|
||||
|
||||
public void GeneratePassword()
|
||||
{
|
||||
var pwProfile = new PwProfile()
|
||||
var pwProfile = new PwProfile
|
||||
{
|
||||
GeneratorType = PasswordGeneratorType.CharSet,
|
||||
Length = (uint)PasswordLength,
|
||||
@@ -208,9 +223,9 @@ namespace ModernKeePass.ViewModels
|
||||
|
||||
public void MarkForDelete()
|
||||
{
|
||||
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();
|
||||
Move(_database.RecycleBinEnabled && !ParentGroup.IsSelected ? _database.RecycleBin : null);
|
||||
}
|
||||
|
||||
public void UndoDelete()
|
||||
@@ -222,27 +237,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,7 +1,8 @@
|
||||
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.Common;
|
||||
@@ -15,33 +16,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 +53,7 @@ namespace ModernKeePass.ViewModels
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return _pwGroup == null ? "< New group >" : _pwGroup.Name; }
|
||||
get { return _pwGroup == null ? string.Empty : _pwGroup.Name; }
|
||||
set { _pwGroup.Name = value; }
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace ModernKeePass.ViewModels
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_pwGroup == null) return Symbol.Add;
|
||||
//if (_pwGroup == null) return Symbol.Add;
|
||||
var result = PwIconToSegoeMapping.GetSymbolFromIcon(_pwGroup.IconId);
|
||||
return result == Symbol.More ? Symbol.Folder : result;
|
||||
}
|
||||
@@ -74,6 +74,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,21 +92,44 @@ namespace ModernKeePass.ViewModels
|
||||
}
|
||||
|
||||
private readonly PwGroup _pwGroup;
|
||||
private readonly App _app = Application.Current as App;
|
||||
private readonly IDatabase _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,
|
||||
(Application.Current as App)?.Database, recycleBinId)
|
||||
{ }
|
||||
|
||||
public GroupVm(PwGroup pwGroup, GroupVm parent, IDatabase 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)));
|
||||
}
|
||||
|
||||
private void Entries_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
switch (e.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
var oldIndex = (uint) e.OldStartingIndex;
|
||||
_reorderedEntry = _pwGroup.Entries.GetAt(oldIndex);
|
||||
_pwGroup.Entries.RemoveAt(oldIndex);
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
if (_reorderedEntry == null) _pwGroup.AddEntry(((EntryVm) e.NewItems[0]).GetPwEntry(), true);
|
||||
else _pwGroup.Entries.Insert((uint)e.NewStartingIndex, _reorderedEntry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public GroupVm AddNewGroup(string name = "")
|
||||
@@ -115,30 +144,19 @@ 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)
|
||||
{
|
||||
_pwGroup.AddEntry(entry, true);
|
||||
}
|
||||
|
||||
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);
|
||||
if (_database.RecycleBinEnabled && _database.RecycleBin?.IdUuid == null)
|
||||
_database.CreateRecycleBin();
|
||||
Move(_database.RecycleBinEnabled && !IsSelected ? _database.RecycleBin : null);
|
||||
}
|
||||
|
||||
|
||||
public void UndoDelete()
|
||||
{
|
||||
Move(PreviousGroup);
|
||||
@@ -151,7 +169,7 @@ namespace ModernKeePass.ViewModels
|
||||
PreviousGroup._pwGroup.Groups.Remove(_pwGroup);
|
||||
if (destination == null)
|
||||
{
|
||||
_app.Database.AddDeletedItem(IdUuid);
|
||||
_database.AddDeletedItem(IdUuid);
|
||||
return;
|
||||
}
|
||||
ParentGroup = destination;
|
||||
@@ -162,13 +180,41 @@ 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();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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,15 @@
|
||||
using Windows.Storage;
|
||||
using ModernKeePass.Common;
|
||||
using Windows.Storage.AccessCache;
|
||||
using Windows.UI.Xaml;
|
||||
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 +20,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((Application.Current as App)?.Database);
|
||||
}
|
||||
|
||||
public void OpenDatabaseFile(IDatabase database)
|
||||
{
|
||||
database.DatabaseFile = DatabaseFile;
|
||||
}
|
||||
|
||||
public void UpdateAccessTime()
|
||||
{
|
||||
UpdateAccessTime(new RecentService());
|
||||
}
|
||||
|
||||
public async void UpdateAccessTime(IRecent recent)
|
||||
{
|
||||
await recent.GetFileAsync(Token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Windows.Storage;
|
||||
using Windows.UI.Xaml;
|
||||
using ModernKeePass.Common;
|
||||
using ModernKeePass.Interfaces;
|
||||
@@ -12,19 +11,19 @@ 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 IDatabase _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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,26 +46,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
|
||||
@@ -89,22 +88,13 @@ namespace ModernKeePass.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public SettingsDatabaseVm()
|
||||
{
|
||||
Groups = _app.Database.RootGroup.Groups;
|
||||
}
|
||||
public SettingsDatabaseVm() : this((Application.Current as App)?.Database) { }
|
||||
|
||||
// TODO: Move to another setting class (or a static class)
|
||||
private T GetSetting<T>(string property)
|
||||
public SettingsDatabaseVm(IDatabase database)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (T) Convert.ChangeType(_localSettings.Values[property], typeof(T));
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
_database = database;
|
||||
Groups = _database?.RootGroup.Groups;
|
||||
Groups?.Insert(0, new GroupVm());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
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 ISettings _settings;
|
||||
|
||||
public SettingsNewVm() : this(new SettingsService())
|
||||
{ }
|
||||
|
||||
public SettingsNewVm(ISettings 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); }
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,23 +1,23 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.Storage.AccessCache;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using ModernKeePass.Common;
|
||||
using ModernKeePass.Interfaces;
|
||||
using ModernKeePass.Pages;
|
||||
using ModernKeePass.Services;
|
||||
using ModernKeePass.Views;
|
||||
|
||||
namespace ModernKeePass.ViewModels
|
||||
{
|
||||
public class MainVm : NotifyPropertyChangedBase, IHasSelectableObject
|
||||
{
|
||||
private IOrderedEnumerable<IGrouping<int, MainMenuItemVm>> _mainMenuItems;
|
||||
private IOrderedEnumerable<IGrouping<string, MainMenuItemVm>> _mainMenuItems;
|
||||
private MainMenuItemVm _selectedItem;
|
||||
|
||||
public string Name { get; } = Package.Current.DisplayName;
|
||||
|
||||
public IOrderedEnumerable<IGrouping<int, MainMenuItemVm>> MainMenuItems
|
||||
public IOrderedEnumerable<IGrouping<string, MainMenuItemVm>> MainMenuItems
|
||||
{
|
||||
get { return _mainMenuItems; }
|
||||
set { SetProperty(ref _mainMenuItems, value); }
|
||||
@@ -45,47 +45,89 @@ namespace ModernKeePass.ViewModels
|
||||
|
||||
public MainVm() {}
|
||||
|
||||
public MainVm(Frame referenceFrame, Frame destinationFrame)
|
||||
internal MainVm(Frame referenceFrame, Frame destinationFrame) : this(referenceFrame, destinationFrame,
|
||||
(Application.Current as App)?.Database, new ResourcesService(), new RecentService())
|
||||
{ }
|
||||
|
||||
public MainVm(Frame referenceFrame, Frame destinationFrame, IDatabase database, IResource resource, IRecent recent)
|
||||
{
|
||||
var app = (App)Application.Current;
|
||||
var mru = StorageApplicationPermissions.MostRecentlyUsedList;
|
||||
var isDatabaseOpen = app.Database != null && app.Database.Status == DatabaseHelper.DatabaseStatus.Opened;
|
||||
var isDatabaseOpen = database != null && database.Status == (int) DatabaseService.DatabaseStatus.Opened;
|
||||
|
||||
var mainMenuItems = new ObservableCollection<MainMenuItemVm>
|
||||
{
|
||||
new MainMenuItemVm
|
||||
{
|
||||
Title = "Open", PageType = typeof(OpenDatabasePage), Destination = destinationFrame, Parameter = referenceFrame, SymbolIcon = Symbol.Page2,
|
||||
IsSelected = app.Database.Status == DatabaseHelper.DatabaseStatus.Opening
|
||||
Title = resource.GetResourceValue("MainMenuItemOpen"),
|
||||
PageType = typeof(OpenDatabasePage),
|
||||
Destination = destinationFrame,
|
||||
Parameter = referenceFrame,
|
||||
SymbolIcon = Symbol.Page2,
|
||||
IsSelected = database != null && database.Status == (int) DatabaseService.DatabaseStatus.Opening
|
||||
},
|
||||
new MainMenuItemVm
|
||||
{
|
||||
Title = "New" , PageType = typeof(NewDatabasePage), Destination = destinationFrame, Parameter = referenceFrame, SymbolIcon = Symbol.Add
|
||||
Title = resource.GetResourceValue("MainMenuItemNew"),
|
||||
PageType = typeof(NewDatabasePage),
|
||||
Destination = destinationFrame,
|
||||
Parameter = referenceFrame,
|
||||
SymbolIcon = Symbol.Add
|
||||
},
|
||||
new MainMenuItemVm
|
||||
{
|
||||
Title = "Save" , PageType = typeof(SaveDatabasePage), Destination = destinationFrame, Parameter = referenceFrame, SymbolIcon = Symbol.Save,
|
||||
IsSelected = isDatabaseOpen, IsEnabled = isDatabaseOpen
|
||||
},
|
||||
new MainMenuItemVm {
|
||||
Title = "Recent" , PageType = typeof(RecentDatabasesPage), Destination = destinationFrame, Parameter = referenceFrame, SymbolIcon = Symbol.Copy,
|
||||
IsSelected = (app.Database == null || app.Database.Status == DatabaseHelper.DatabaseStatus.Closed) && mru.Entries.Count > 0, IsEnabled = mru.Entries.Count > 0
|
||||
Title = resource.GetResourceValue("MainMenuItemSave"),
|
||||
PageType = typeof(SaveDatabasePage),
|
||||
Destination = destinationFrame,
|
||||
Parameter = referenceFrame,
|
||||
SymbolIcon = Symbol.Save,
|
||||
IsSelected = isDatabaseOpen,
|
||||
IsEnabled = isDatabaseOpen
|
||||
},
|
||||
new MainMenuItemVm
|
||||
{
|
||||
Title = "About" , PageType = typeof(AboutPage), Destination = destinationFrame, SymbolIcon = Symbol.Help
|
||||
}
|
||||
Title = resource.GetResourceValue("MainMenuItemRecent"),
|
||||
PageType = typeof(RecentDatabasesPage),
|
||||
Destination = destinationFrame,
|
||||
Parameter = referenceFrame,
|
||||
SymbolIcon = Symbol.Copy,
|
||||
IsSelected =
|
||||
(database == null || database.Status == (int) DatabaseService.DatabaseStatus.Closed) &&
|
||||
recent.EntryCount > 0,
|
||||
IsEnabled = recent.EntryCount > 0
|
||||
},
|
||||
new MainMenuItemVm
|
||||
{
|
||||
Title = resource.GetResourceValue("MainMenuItemSettings"),
|
||||
PageType = typeof(SettingsPage),
|
||||
Destination = referenceFrame,
|
||||
SymbolIcon = Symbol.Setting
|
||||
},
|
||||
new MainMenuItemVm
|
||||
{
|
||||
Title = resource.GetResourceValue("MainMenuItemAbout"),
|
||||
PageType = typeof(AboutPage),
|
||||
Destination = destinationFrame,
|
||||
SymbolIcon = Symbol.Help
|
||||
}/*,
|
||||
new MainMenuItemVm
|
||||
{
|
||||
Title = resource.GetResourceValue("MainMenuItemDonate"),
|
||||
PageType = typeof(DonatePage),
|
||||
Destination = destinationFrame,
|
||||
SymbolIcon = Symbol.Shop
|
||||
}*/
|
||||
};
|
||||
// Auto-select the Recent Items menu item if the conditions are met
|
||||
SelectedItem = mainMenuItems.FirstOrDefault(m => m.IsSelected);
|
||||
if (app.Database != null && app.Database.Status == DatabaseHelper.DatabaseStatus.Opened)
|
||||
|
||||
// Add currently opened database to the menu
|
||||
if (database != null && database.Status == (int) DatabaseService.DatabaseStatus.Opened)
|
||||
mainMenuItems.Add(new MainMenuItemVm
|
||||
{
|
||||
Title = app.Database.Name,
|
||||
Title = database.Name,
|
||||
PageType = typeof(GroupDetailPage),
|
||||
Destination = referenceFrame,
|
||||
Parameter = app.Database.RootGroup,
|
||||
Group = 1,
|
||||
Parameter = database.RootGroup,
|
||||
Group = "Databases",
|
||||
SymbolIcon = Symbol.ProtectedDocument
|
||||
});
|
||||
|
||||
|
@@ -1,50 +1,44 @@
|
||||
using System.ComponentModel;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.AccessCache;
|
||||
using Windows.Storage;
|
||||
using Windows.UI.Xaml;
|
||||
using ModernKeePass.Common;
|
||||
using ModernKeePass.Interfaces;
|
||||
using ModernKeePass.Services;
|
||||
|
||||
namespace ModernKeePass.ViewModels
|
||||
{
|
||||
public class OpenVm: INotifyPropertyChanged
|
||||
public class OpenVm: NotifyPropertyChangedBase
|
||||
{
|
||||
public bool ShowPasswordBox
|
||||
{
|
||||
get { return ((App)Application.Current).Database.Status == DatabaseHelper.DatabaseStatus.Opening; }
|
||||
}
|
||||
public bool ShowPasswordBox => _database?.Status == (int) DatabaseService.DatabaseStatus.Opening;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return ((App)Application.Current).Database.Name; }
|
||||
}
|
||||
public string Name => _database?.Name;
|
||||
|
||||
public OpenVm()
|
||||
{
|
||||
var app = Application.Current as App;
|
||||
if (app?.Database == null || app.Database.Status != DatabaseHelper.DatabaseStatus.Opening) return;
|
||||
OpenFile(app.Database.DatabaseFile);
|
||||
}
|
||||
private readonly IDatabase _database;
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
public OpenVm() : this((Application.Current as App)?.Database) { }
|
||||
|
||||
protected void NotifyPropertyChanged(string propertyName)
|
||||
public OpenVm(IDatabase database)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
_database = database;
|
||||
if (database == null || database.Status != (int) DatabaseService.DatabaseStatus.Opening) return;
|
||||
OpenFile(database.DatabaseFile);
|
||||
}
|
||||
|
||||
public void OpenFile(StorageFile file)
|
||||
{
|
||||
var database = ((App)Application.Current).Database;
|
||||
database.DatabaseFile = file;
|
||||
NotifyPropertyChanged("Name");
|
||||
NotifyPropertyChanged("ShowPasswordBox");
|
||||
AddToRecentList(file);
|
||||
OpenFile(file, new RecentService());
|
||||
}
|
||||
|
||||
private void AddToRecentList(StorageFile file)
|
||||
public void OpenFile(StorageFile file, IRecent recent)
|
||||
{
|
||||
var mru = StorageApplicationPermissions.MostRecentlyUsedList;
|
||||
mru.Add(file, file.DisplayName);
|
||||
_database.DatabaseFile = file;
|
||||
OnPropertyChanged("Name");
|
||||
OnPropertyChanged("ShowPasswordBox");
|
||||
AddToRecentList(file, recent);
|
||||
}
|
||||
|
||||
private void AddToRecentList(StorageFile file, IRecent recent)
|
||||
{
|
||||
recent.Add(file, file.DisplayName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,17 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using Windows.Storage.AccessCache;
|
||||
using System.Collections.ObjectModel;
|
||||
using ModernKeePass.Common;
|
||||
using ModernKeePass.Interfaces;
|
||||
using ModernKeePass.Services;
|
||||
|
||||
namespace ModernKeePass.ViewModels
|
||||
{
|
||||
public class RecentVm : NotifyPropertyChangedBase, IHasSelectableObject
|
||||
{
|
||||
private readonly IRecent _recent;
|
||||
private ISelectableModel _selectedItem;
|
||||
private ObservableCollection<RecentItemVm> _recentItems = new ObservableCollection<RecentItemVm>();
|
||||
private ObservableCollection<IRecentItem> _recentItems = new ObservableCollection<IRecentItem>();
|
||||
|
||||
public ObservableCollection<RecentItemVm> RecentItems
|
||||
public ObservableCollection<IRecentItem> RecentItems
|
||||
{
|
||||
get { return _recentItems; }
|
||||
set { SetProperty(ref _recentItems, value); }
|
||||
@@ -35,25 +35,21 @@ namespace ModernKeePass.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public RecentVm()
|
||||
public RecentVm() : this (new RecentService())
|
||||
{ }
|
||||
|
||||
public RecentVm(IRecent recent)
|
||||
{
|
||||
// TODO: opening the files actually changes the MRU order
|
||||
var mru = StorageApplicationPermissions.MostRecentlyUsedList;
|
||||
foreach (var entry in mru.Entries)
|
||||
{
|
||||
try
|
||||
{
|
||||
var file = mru.GetFileAsync(entry.Token).GetAwaiter().GetResult();
|
||||
RecentItems.Add(new RecentItemVm(entry, file));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
mru.Remove(entry.Token);
|
||||
}
|
||||
}
|
||||
_recent = recent;
|
||||
RecentItems = _recent.GetAllFiles();
|
||||
if (RecentItems.Count > 0)
|
||||
SelectedItem = RecentItems[0];
|
||||
SelectedItem = RecentItems[0] as RecentItemVm;
|
||||
}
|
||||
|
||||
public void ClearAll()
|
||||
{
|
||||
_recent.ClearAll();
|
||||
RecentItems.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,22 +1,28 @@
|
||||
using Windows.Storage;
|
||||
using Windows.UI.Xaml;
|
||||
using ModernKeePass.Interfaces;
|
||||
|
||||
namespace ModernKeePass.ViewModels
|
||||
{
|
||||
public class SaveVm
|
||||
{
|
||||
public void Save(bool close = true)
|
||||
private readonly IDatabase _database;
|
||||
public SaveVm() : this((Application.Current as App)?.Database) { }
|
||||
|
||||
public SaveVm(IDatabase database)
|
||||
{
|
||||
var app = (App)Application.Current;
|
||||
app.Database.Save();
|
||||
if (!close) return;
|
||||
app.Database.Close();
|
||||
_database = database;
|
||||
}
|
||||
|
||||
internal void Save(StorageFile file)
|
||||
public void Save(bool close = true)
|
||||
{
|
||||
var app = (App)Application.Current;
|
||||
app.Database.Save(file);
|
||||
_database.Save();
|
||||
if (close) _database.Close();
|
||||
}
|
||||
|
||||
public void Save(StorageFile file)
|
||||
{
|
||||
_database.Save(file);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,17 +1,26 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using ModernKeePass.Common;
|
||||
using ModernKeePass.Interfaces;
|
||||
using ModernKeePass.Pages;
|
||||
using ModernKeePass.Views;
|
||||
using ModernKeePass.Services;
|
||||
|
||||
namespace ModernKeePass.ViewModels
|
||||
{
|
||||
public class SettingsVM : NotifyPropertyChangedBase, IHasSelectableObject
|
||||
public class SettingsVm : NotifyPropertyChangedBase, IHasSelectableObject
|
||||
{
|
||||
private ListMenuItemVm _selectedItem;
|
||||
|
||||
public ObservableCollection<ListMenuItemVm> MenuItems { get; set; }
|
||||
private IOrderedEnumerable<IGrouping<string, ListMenuItemVm>> _menuItems;
|
||||
|
||||
public IOrderedEnumerable<IGrouping<string, ListMenuItemVm>> MenuItems
|
||||
{
|
||||
get { return _menuItems; }
|
||||
set { SetProperty(ref _menuItems, value); }
|
||||
}
|
||||
|
||||
public ISelectableModel SelectedItem
|
||||
{
|
||||
get { return _selectedItem; }
|
||||
@@ -32,15 +41,40 @@ namespace ModernKeePass.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public SettingsVM()
|
||||
public SettingsVm() : this((Application.Current as App)?.Database, new ResourcesService()) { }
|
||||
|
||||
public SettingsVm(IDatabase database, IResource resource)
|
||||
{
|
||||
MenuItems = new ObservableCollection<ListMenuItemVm>
|
||||
var menuItems = new ObservableCollection<ListMenuItemVm>
|
||||
{
|
||||
new ListMenuItemVm { Title = "Database", SymbolIcon = Symbol.Setting, PageType = typeof(SettingsDatabasePage), IsSelected = true },
|
||||
new ListMenuItemVm { Title = "Security", SymbolIcon = Symbol.Permissions, PageType = typeof(SettingsSecurityPage) },
|
||||
//new ListMenuItemVm { Title = "General", SymbolIcon = Symbol.Edit, PageType = typeof(SettingsGeneralPage) }
|
||||
new ListMenuItemVm
|
||||
{
|
||||
Title = resource.GetResourceValue("SettingsMenuItemNew"),
|
||||
Group = resource.GetResourceValue("SettingsMenuGroupApplication"),
|
||||
SymbolIcon = Symbol.Add,
|
||||
PageType = typeof(SettingsNewDatabasePage),
|
||||
IsSelected = true
|
||||
},
|
||||
new ListMenuItemVm
|
||||
{
|
||||
Title = resource.GetResourceValue("SettingsMenuItemGeneral"),
|
||||
Group = resource.GetResourceValue("SettingsMenuGroupDatabase"),
|
||||
SymbolIcon = Symbol.Setting,
|
||||
PageType = typeof(SettingsDatabasePage),
|
||||
IsEnabled = database?.Status == 2
|
||||
},
|
||||
new ListMenuItemVm
|
||||
{
|
||||
Title = resource.GetResourceValue("SettingsMenuItemSecurity"),
|
||||
Group = resource.GetResourceValue("SettingsMenuGroupDatabase"),
|
||||
SymbolIcon = Symbol.Permissions,
|
||||
PageType = typeof(SettingsSecurityPage),
|
||||
IsEnabled = database?.Status == 2
|
||||
}
|
||||
};
|
||||
SelectedItem = MenuItems.FirstOrDefault(m => m.IsSelected);
|
||||
SelectedItem = menuItems.FirstOrDefault(m => m.IsSelected);
|
||||
|
||||
MenuItems = from item in menuItems group item by item.Group into grp orderby grp.Key select grp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|