mirror of
https://github.com/wismna/ModernKeePass.git
synced 2025-10-04 08:00:16 -04:00
Compare commits
101 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fa3d38db18 | ||
dd1e128e17 | |||
d247aa8334 | |||
5f995a10c1 | |||
![]() |
b89998c053 | ||
d10f617910 | |||
1b439a4960 | |||
![]() |
5cf4ff3012 | ||
46c8429cde | |||
8cd3801897 | |||
b47d7fb69b | |||
52e08d8c98 | |||
ad0d8d6c97 | |||
5b31d3ff72 | |||
2bbd931b1a | |||
8c09d266e8 | |||
a11d209280 | |||
![]() |
e95e62f184 | ||
![]() |
84e7afc819 | ||
![]() |
c82d6d001d | ||
d5b7845242 | |||
9de9ae54da | |||
6548d1d9c1 | |||
54ad395d13 | |||
6bb37d9e70 | |||
66fd87124b | |||
7bb78fd374 | |||
dc62cedb74 | |||
![]() |
bc6e7d0097 | ||
01ed1bc9c1 | |||
![]() |
19008cdad2 | ||
8a312bec71 | |||
2b8d37057c | |||
5497e6fc00 | |||
86064af3a2 | |||
3265244f06 | |||
2698070328 | |||
5638b59fda | |||
9f94dd55c2 | |||
0ded991673 | |||
cddda7adcd | |||
69a63f4b2e | |||
10b6330ac6 | |||
676365460c | |||
acb5bcc230 | |||
![]() |
f1737ca9f7 | ||
2f1355104e | |||
97b1475100 | |||
454e074c44 | |||
951172e36f | |||
f5fd3effaf | |||
ec4f2e7d88 | |||
98ecb0b8a1 | |||
![]() |
f2794f8055 | ||
![]() |
dfb5ec9683 | ||
3d033417ad | |||
f22ca4c46f | |||
11fb82573b | |||
4aa3b17398 | |||
c611f5a8a2 | |||
013108f2ec | |||
616d922145 | |||
![]() |
95771878fc | ||
267d9f25c2 | |||
2bcc4fde60 | |||
30838d0e00 | |||
![]() |
6d69dd4d15 | ||
![]() |
324553c58c | ||
![]() |
1ca3f29da0 | ||
817f25e8a8 | |||
![]() |
056e1624be | ||
b5c04d524d | |||
1582060466 | |||
caaf34918e | |||
![]() |
3a045dbb16 | ||
40256be135 | |||
26e9b78b3b | |||
a76b0ff350 | |||
7e0f21f88f | |||
d78e75f449 | |||
93be4cf01c | |||
ec037b97fd | |||
2b469d764d | |||
cfd61a87e8 | |||
1faa26473d | |||
27aaa8023a | |||
22ea657885 | |||
34996da19d | |||
![]() |
3bf8015280 | ||
![]() |
32e629231c | ||
![]() |
9d78d59a15 | ||
668afbe817 | |||
a43bc20eb3 | |||
![]() |
baba70e56d | ||
c4ac244270 | |||
668ffcb107 | |||
a7cdd248c9 | |||
f976a2cc86 | |||
![]() |
5d271d4133 | ||
![]() |
25d1564a8d | ||
00897307a4 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -33,4 +33,7 @@ _ReSharper*/
|
|||||||
Translation/TrlUtil.vshost.exe.manifest
|
Translation/TrlUtil.vshost.exe.manifest
|
||||||
*.nupkg
|
*.nupkg
|
||||||
.vs/
|
.vs/
|
||||||
/UpgradeLog.htm
|
/UpgradeLog*.htm
|
||||||
|
packages/
|
||||||
|
project.lock.json
|
||||||
|
AppPackages/
|
@@ -5,7 +5,12 @@ VisualStudioVersion = 14.0.25420.1
|
|||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePass", "ModernKeePass\ModernKeePass.csproj", "{A0CFC681-769B-405A-8482-0CDEE595A91F}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePass", "ModernKeePass\ModernKeePass.csproj", "{A0CFC681-769B-405A-8482-0CDEE595A91F}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePassLib", "ModernKeePassLib\ModernKeePassLib.csproj", "{A207789D-9020-401B-9D0A-D0D2CFF721BD}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePassLib", "ModernKeePassLib\ModernKeePassLib.csproj", "{2E710089-9559-4967-846C-E763DD1F3ACB}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePassLib.Test", "ModernKeePassLib.Test\ModernKeePassLib.Test.csproj", "{067456C0-086C-46A8-B37F-1405717B7BFC}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{2E710089-9559-4967-846C-E763DD1F3ACB} = {2E710089-9559-4967-846C-E763DD1F3ACB}
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -43,22 +48,38 @@ Global
|
|||||||
{A0CFC681-769B-405A-8482-0CDEE595A91F}.Release|x86.ActiveCfg = Release|x86
|
{A0CFC681-769B-405A-8482-0CDEE595A91F}.Release|x86.ActiveCfg = Release|x86
|
||||||
{A0CFC681-769B-405A-8482-0CDEE595A91F}.Release|x86.Build.0 = Release|x86
|
{A0CFC681-769B-405A-8482-0CDEE595A91F}.Release|x86.Build.0 = Release|x86
|
||||||
{A0CFC681-769B-405A-8482-0CDEE595A91F}.Release|x86.Deploy.0 = Release|x86
|
{A0CFC681-769B-405A-8482-0CDEE595A91F}.Release|x86.Deploy.0 = Release|x86
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|ARM.ActiveCfg = Debug|ARM
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|ARM.Build.0 = Debug|ARM
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|x64.ActiveCfg = Debug|x64
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|x64.Build.0 = Debug|x64
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|x86.ActiveCfg = Debug|x86
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|x86.Build.0 = Debug|x86
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|Any CPU.Build.0 = Release|Any CPU
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|ARM.ActiveCfg = Release|ARM
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|ARM.Build.0 = Release|ARM
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|x64.ActiveCfg = Release|x64
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|x64.Build.0 = Release|x64
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|x86.ActiveCfg = Release|x86
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|x86.Build.0 = Release|x86
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
27
ModernKeePass/Actions/SetupFocusAction.cs
Normal file
27
ModernKeePass/Actions/SetupFocusAction.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Windows.UI.Core;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Microsoft.Xaml.Interactivity;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Actions
|
||||||
|
{
|
||||||
|
public class SetupFocusAction : DependencyObject, IAction
|
||||||
|
{
|
||||||
|
public Control TargetObject
|
||||||
|
{
|
||||||
|
get { return (Control)GetValue(TargetObjectProperty); }
|
||||||
|
set { SetValue(TargetObjectProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly DependencyProperty TargetObjectProperty =
|
||||||
|
DependencyProperty.Register("TargetObject", typeof(Control), typeof(SetupFocusAction), new PropertyMetadata(null));
|
||||||
|
|
||||||
|
public object Execute(object sender, object parameter)
|
||||||
|
{
|
||||||
|
return Task.Factory.StartNew(
|
||||||
|
() => Dispatcher.RunAsync(CoreDispatcherPriority.Low,
|
||||||
|
() => TargetObject?.Focus(FocusState.Programmatic)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -2,6 +2,16 @@
|
|||||||
x:Class="ModernKeePass.App"
|
x:Class="ModernKeePass.App"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="using:ModernKeePass">
|
RequestedTheme="Light">
|
||||||
|
<Application.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="Styles/TextBoxWithButtonStyle.xaml" />
|
||||||
|
<ResourceDictionary Source="Styles/HamburgerButtonStyle.xaml" />
|
||||||
|
<ResourceDictionary Source="Styles/ListViewLeftIndicatorStyle.xaml" />
|
||||||
|
<ResourceDictionary Source="Styles/NoBorderButtonStyle.xaml" />
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Application.Resources>
|
||||||
|
|
||||||
</Application>
|
</Application>
|
||||||
|
@@ -1,19 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using Windows.ApplicationModel;
|
using Windows.ApplicationModel;
|
||||||
using Windows.ApplicationModel.Activation;
|
using Windows.ApplicationModel.Activation;
|
||||||
using Windows.Foundation;
|
using Windows.Data.Json;
|
||||||
using Windows.Foundation.Collections;
|
using Windows.Storage;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
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;
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
using ModernKeePass.Interfaces;
|
||||||
|
|
||||||
// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227
|
// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227
|
||||||
|
|
||||||
@@ -22,18 +17,22 @@ namespace ModernKeePass
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides application-specific behavior to supplement the default Application class.
|
/// Provides application-specific behavior to supplement the default Application class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
sealed partial class App : Application
|
sealed partial class App
|
||||||
{
|
{
|
||||||
|
public DatabaseHelper Database { get; set; } = new DatabaseHelper();
|
||||||
|
public Dictionary<string, IPwEntity> PendingDeleteEntities = new Dictionary<string, IPwEntity>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the singleton application object. This is the first line of authored code
|
/// Initializes the singleton application object. This is the first line of authored code
|
||||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public App()
|
public App()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
this.Suspending += OnSuspending;
|
Suspending += OnSuspending;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Event Handlers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoked when the application is launched normally by the end user. Other entry points
|
/// 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.
|
/// will be used such as when the application is launched to open a specific file.
|
||||||
@@ -41,24 +40,33 @@ namespace ModernKeePass
|
|||||||
/// <param name="e">Details about the launch request and process.</param>
|
/// <param name="e">Details about the launch request and process.</param>
|
||||||
protected override void OnLaunched(LaunchActivatedEventArgs e)
|
protected override void OnLaunched(LaunchActivatedEventArgs e)
|
||||||
{
|
{
|
||||||
|
OnLaunchOrActivated(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnActivated(IActivatedEventArgs args)
|
||||||
|
{
|
||||||
|
OnLaunchOrActivated(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLaunchOrActivated(IActivatedEventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (System.Diagnostics.Debugger.IsAttached)
|
if (System.Diagnostics.Debugger.IsAttached)
|
||||||
{
|
{
|
||||||
this.DebugSettings.EnableFrameRateCounter = true;
|
//DebugSettings.EnableFrameRateCounter = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Frame rootFrame = Window.Current.Content as Frame;
|
var rootFrame = Window.Current.Content as Frame;
|
||||||
|
|
||||||
// Do not repeat app initialization when the Window already has content,
|
// Do not repeat app initialization when the Window already has content,
|
||||||
// just ensure that the window is active
|
// just ensure that the window is active
|
||||||
if (rootFrame == null)
|
if (rootFrame == null)
|
||||||
{
|
{
|
||||||
// Create a Frame to act as the navigation context and navigate to the first page
|
// Create a Frame to act as the navigation context and navigate to the first page
|
||||||
rootFrame = new Frame();
|
rootFrame = new Frame {Language = Windows.Globalization.ApplicationLanguages.Languages[0]};
|
||||||
// Set the default language
|
// Set the default language
|
||||||
rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];
|
|
||||||
|
|
||||||
rootFrame.NavigationFailed += OnNavigationFailed;
|
rootFrame.NavigationFailed += OnNavigationFailed;
|
||||||
|
|
||||||
@@ -71,13 +79,30 @@ namespace ModernKeePass
|
|||||||
Window.Current.Content = rootFrame;
|
Window.Current.Content = rootFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e is LaunchActivatedEventArgs)
|
||||||
|
{
|
||||||
|
var lauchActivatedEventArgs = (LaunchActivatedEventArgs) e;
|
||||||
if (rootFrame.Content == null)
|
if (rootFrame.Content == null)
|
||||||
{
|
{
|
||||||
// When the navigation stack isn't restored navigate to the first page,
|
// When the navigation stack isn't restored navigate to the first page,
|
||||||
// configuring the new page by passing required information as a navigation
|
// configuring the new page by passing required information as a navigation
|
||||||
// parameter
|
// parameter
|
||||||
rootFrame.Navigate(typeof(MainPage), e.Arguments);
|
rootFrame.Navigate(typeof(Pages.MainPage), lauchActivatedEventArgs.Arguments);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// App is "launched" via the Toast Activation event
|
||||||
|
UndoEntityDelete(lauchActivatedEventArgs.Arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// This is only available on Windows 10...
|
||||||
|
/*else if (e is ToastNotificationActivatedEventArgs)
|
||||||
|
{
|
||||||
|
var toastActivationArgs = e as ToastNotificationActivatedEventArgs;
|
||||||
|
|
||||||
|
// Parse the query string (using QueryString.NET)
|
||||||
|
UndoEntityDelete(QueryString.Parse(toastActivationArgs.Argument));
|
||||||
|
}*/
|
||||||
// Ensure the current window is active
|
// Ensure the current window is active
|
||||||
Window.Current.Activate();
|
Window.Current.Activate();
|
||||||
}
|
}
|
||||||
@@ -102,8 +127,32 @@ namespace ModernKeePass
|
|||||||
private void OnSuspending(object sender, SuspendingEventArgs e)
|
private void OnSuspending(object sender, SuspendingEventArgs e)
|
||||||
{
|
{
|
||||||
var deferral = e.SuspendingOperation.GetDeferral();
|
var deferral = e.SuspendingOperation.GetDeferral();
|
||||||
//TODO: Save application state and stop any background activity
|
Database.Save();
|
||||||
deferral.Complete();
|
deferral.Complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when application is launched from opening a file in Windows Explorer
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">Details about the file being opened</param>
|
||||||
|
protected override void OnFileActivated(FileActivatedEventArgs args)
|
||||||
|
{
|
||||||
|
base.OnFileActivated(args);
|
||||||
|
var rootFrame = new Frame();
|
||||||
|
Database.DatabaseFile = args.Files[0] as StorageFile;
|
||||||
|
rootFrame.Navigate(typeof(Pages.MainPage), args);
|
||||||
|
Window.Current.Content = rootFrame;
|
||||||
|
Window.Current.Activate();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void UndoEntityDelete(string arguments)
|
||||||
|
{
|
||||||
|
if (arguments == null) return;
|
||||||
|
var args = JsonObject.Parse(arguments);
|
||||||
|
var entity = PendingDeleteEntities[args["entityId"].GetString()];
|
||||||
|
PendingDeleteEntities.Remove(args["entityId"].GetString());
|
||||||
|
entity.UndoDelete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
4
ModernKeePass/BundleArtifacts/neutral.txt
Normal file
4
ModernKeePass/BundleArtifacts/neutral.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
MainPackage=C:\Users\bg45\source\repos\ModernKeePass\ModernKeePass\bin\Release\ModernKeePass_1.5.0.25_AnyCPU.appx
|
||||||
|
SymbolPackage=C:\Users\bg45\source\repos\ModernKeePass\ModernKeePass\AppPackages\ModernKeePass_1.5.0.25_Test\ModernKeePass_1.5.0.25_AnyCPU.appxsym
|
||||||
|
ResourcePack=C:\Users\bg45\source\repos\ModernKeePass\ModernKeePass\bin\Release\ModernKeePass_1.5.0.25_scale-140.appx
|
||||||
|
ResourcePack=C:\Users\bg45\source\repos\ModernKeePass\ModernKeePass\bin\Release\ModernKeePass_1.5.0.25_scale-180.appx
|
102
ModernKeePass/Common/DatabaseHelper.cs
Normal file
102
ModernKeePass/Common/DatabaseHelper.cs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.Storage;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
using ModernKeePassLib;
|
||||||
|
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 PwDatabase _pwDatabase = new PwDatabase();
|
||||||
|
private StorageFile _databaseFile;
|
||||||
|
|
||||||
|
public GroupVm RootGroup { get; set; }
|
||||||
|
public DatabaseStatus Status { get; private set; } = DatabaseStatus.Closed;
|
||||||
|
public string Name => DatabaseFile?.Name;
|
||||||
|
|
||||||
|
public StorageFile DatabaseFile
|
||||||
|
{
|
||||||
|
get { return _databaseFile; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_databaseFile = value;
|
||||||
|
Status = DatabaseStatus.Opening;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Open a KeePass database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="password">The database password</param>
|
||||||
|
/// <param name="createNew">True to create a new database before opening it</param>
|
||||||
|
/// <returns>An error message, if any</returns>
|
||||||
|
public string Open(string password, bool createNew = false)
|
||||||
|
{
|
||||||
|
var key = new CompositeKey();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
key.AddUserKey(new KcpPassword(password));
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
if (_pwDatabase != null && _pwDatabase.IsOpen)
|
||||||
|
_pwDatabase.Save(new NullStatusLogger());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Close the currently opened database
|
||||||
|
/// </summary>
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
_pwDatabase?.Close();
|
||||||
|
Status = DatabaseStatus.Closed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
ModernKeePass/Common/MessageDialogHelper.cs
Normal file
35
ModernKeePass/Common/MessageDialogHelper.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Popups;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using ModernKeePass.Interfaces;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Common
|
||||||
|
{
|
||||||
|
public static class MessageDialogHelper
|
||||||
|
{
|
||||||
|
public static async void ShowDeleteConfirmationDialog(string text, IPwEntity model, Frame backFrame)
|
||||||
|
{
|
||||||
|
// Create the message dialog and set its content
|
||||||
|
var messageDialog = new MessageDialog(text);
|
||||||
|
|
||||||
|
// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
|
||||||
|
messageDialog.Commands.Add(new UICommand("Delete", delete =>
|
||||||
|
{
|
||||||
|
ToastNotificationHelper.ShowUndoToast(model);
|
||||||
|
model.MarkForDelete();
|
||||||
|
if (backFrame.CanGoBack) backFrame.GoBack();
|
||||||
|
}));
|
||||||
|
messageDialog.Commands.Add(new UICommand("Cancel"));
|
||||||
|
|
||||||
|
// Set the command that will be invoked by default
|
||||||
|
messageDialog.DefaultCommandIndex = 1;
|
||||||
|
|
||||||
|
// Set the command to be invoked when escape is pressed
|
||||||
|
messageDialog.CancelCommandIndex = 1;
|
||||||
|
|
||||||
|
// Show the message dialog
|
||||||
|
await messageDialog.ShowAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
ModernKeePass/Common/NotifyPropertyChangedBase.cs
Normal file
28
ModernKeePass/Common/NotifyPropertyChangedBase.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Common
|
||||||
|
{
|
||||||
|
public class NotifyPropertyChangedBase : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool SetProperty<T>(ref T property, T value, [CallerMemberName] string propertyName = "")
|
||||||
|
{
|
||||||
|
if (EqualityComparer<T>.Default.Equals(property, value))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
property = value;
|
||||||
|
OnPropertyChanged(propertyName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -46,6 +46,14 @@ namespace ModernKeePass.Common
|
|||||||
this.Add(item.Key, item.Value);
|
this.Add(item.Key, item.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddRange(IEnumerable<KeyValuePair<string, object>> values)
|
||||||
|
{
|
||||||
|
foreach (var value in values)
|
||||||
|
{
|
||||||
|
Add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool Remove(string key)
|
public bool Remove(string key)
|
||||||
{
|
{
|
||||||
if (this._dictionary.Remove(key))
|
if (this._dictionary.Remove(key))
|
||||||
|
102
ModernKeePass/Common/ToastNotificationHelper.cs
Normal file
102
ModernKeePass/Common/ToastNotificationHelper.cs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.Data.Json;
|
||||||
|
using Windows.Data.Xml.Dom;
|
||||||
|
using Windows.UI.Notifications;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using ModernKeePass.Interfaces;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Common
|
||||||
|
{
|
||||||
|
public static class ToastNotificationHelper
|
||||||
|
{
|
||||||
|
public static /*async*/ void ShowUndoToast(IPwEntity entity)
|
||||||
|
{
|
||||||
|
// This is for Windows 10
|
||||||
|
// Construct the visuals of the toast
|
||||||
|
/*var visual = new ToastVisual
|
||||||
|
{
|
||||||
|
BindingGeneric = new ToastBindingGeneric
|
||||||
|
{
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new AdaptiveText
|
||||||
|
{
|
||||||
|
Text = $"{entityType} {entity.Name} deleted."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Construct the actions for the toast (inputs and buttons)
|
||||||
|
var actions = new ToastActionsCustom
|
||||||
|
{
|
||||||
|
Buttons =
|
||||||
|
{
|
||||||
|
new ToastButton("Undo", new QueryString
|
||||||
|
{
|
||||||
|
{ "action", "undo" },
|
||||||
|
{ "entityType", entityType },
|
||||||
|
{ "entityId", entity.Id }
|
||||||
|
|
||||||
|
}.ToString())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Now we can construct the final toast content
|
||||||
|
var toastContent = new ToastContent
|
||||||
|
{
|
||||||
|
Visual = visual,
|
||||||
|
Actions = actions,
|
||||||
|
// Arguments when the user taps body of toast
|
||||||
|
Launch = new QueryString()
|
||||||
|
{
|
||||||
|
{ "action", "undo" },
|
||||||
|
{ "entityType", "group" },
|
||||||
|
{ "entityId", entity.Id }
|
||||||
|
|
||||||
|
}.ToString()
|
||||||
|
};
|
||||||
|
|
||||||
|
// And create the toast notification
|
||||||
|
var toastXml = new XmlDocument();
|
||||||
|
toastXml.LoadXml(toastContent.GetContent());
|
||||||
|
|
||||||
|
var toast = new ToastNotification(toastXml) {ExpirationTime = DateTime.Now.AddSeconds(5)};
|
||||||
|
toast.Dismissed += Toast_Dismissed;
|
||||||
|
*/
|
||||||
|
|
||||||
|
var entityType = entity is GroupVm ? "Group" : "Entry";
|
||||||
|
var notificationXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
|
||||||
|
var toastElements = notificationXml.GetElementsByTagName("text");
|
||||||
|
toastElements[0].AppendChild(notificationXml.CreateTextNode($"{entityType} {entity.Name} deleted"));
|
||||||
|
toastElements[1].AppendChild(notificationXml.CreateTextNode("Click me to undo"));
|
||||||
|
var toastNode = notificationXml.SelectSingleNode("/toast");
|
||||||
|
|
||||||
|
var launch = new JsonObject
|
||||||
|
{
|
||||||
|
{"entityType", JsonValue.CreateStringValue(entityType)},
|
||||||
|
{"entityId", JsonValue.CreateStringValue(entity.Id)}
|
||||||
|
};
|
||||||
|
((XmlElement)toastNode)?.SetAttribute("launch", launch.Stringify());
|
||||||
|
|
||||||
|
var toast = new ToastNotification(notificationXml)
|
||||||
|
{
|
||||||
|
ExpirationTime = DateTime.Now.AddSeconds(5)
|
||||||
|
};
|
||||||
|
toast.Dismissed += Toast_Dismissed;
|
||||||
|
ToastNotificationManager.CreateToastNotifier().Show(toast);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Toast_Dismissed(ToastNotification sender, ToastDismissedEventArgs args)
|
||||||
|
{
|
||||||
|
var toastNode = sender.Content.SelectSingleNode("/toast");
|
||||||
|
if (toastNode == null) return;
|
||||||
|
var launchArguments = JsonObject.Parse(((XmlElement)toastNode).GetAttribute("launch"));
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
var entity = app.PendingDeleteEntities[launchArguments["entityId"].GetString()];
|
||||||
|
app.PendingDeleteEntities.Remove(launchArguments["entityId"].GetString());
|
||||||
|
entity.CommitDelete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
ModernKeePass/Controls/ListViewWithDisable.cs
Normal file
20
ModernKeePass/Controls/ListViewWithDisable.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using ModernKeePass.Interfaces;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Controls
|
||||||
|
{
|
||||||
|
public class ListViewWithDisable: ListView
|
||||||
|
{
|
||||||
|
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
|
||||||
|
{
|
||||||
|
base.PrepareContainerForItemOverride(element, item);
|
||||||
|
|
||||||
|
var container = element as ListViewItem;
|
||||||
|
var binaryItem = item as IIsEnabled;
|
||||||
|
if (container == null || binaryItem == null) return;
|
||||||
|
container.IsEnabled = binaryItem.IsEnabled;
|
||||||
|
container.IsHitTestVisible = binaryItem.IsEnabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
349
ModernKeePass/Controls/OpenDatabaseUserControl.xaml
Normal file
349
ModernKeePass/Controls/OpenDatabaseUserControl.xaml
Normal file
@@ -0,0 +1,349 @@
|
|||||||
|
<UserControl x:Name="UserControl"
|
||||||
|
x:Class="ModernKeePass.Controls.OpenDatabaseUserControl"
|
||||||
|
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:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||||
|
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
|
||||||
|
xmlns:actions="using:ModernKeePass.Actions"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="60"
|
||||||
|
d:DesignWidth="550" >
|
||||||
|
<UserControl.Resources>
|
||||||
|
<SolidColorBrush x:Key="ErrorColorBrush" Color="Red"/>
|
||||||
|
<Style TargetType="PasswordBox" x:Name="PasswordBoxWithButtonStyle">
|
||||||
|
<Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
|
||||||
|
<Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
|
||||||
|
<Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}" />
|
||||||
|
<Setter Property="Background" Value="{ThemeResource TextBoxBackgroundThemeBrush}" />
|
||||||
|
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextSelectionHighlightColorThemeBrush}" />
|
||||||
|
<Setter Property="BorderBrush" Value="{ThemeResource TextBoxBorderThemeBrush}" />
|
||||||
|
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
|
||||||
|
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||||
|
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
|
||||||
|
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
|
||||||
|
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
|
||||||
|
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="PasswordBox">
|
||||||
|
<Grid>
|
||||||
|
<Grid.Resources>
|
||||||
|
<Style x:Name="RevealButtonStyle" TargetType="Button">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Grid>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Pressed">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
<Border x:Name="BorderElement"
|
||||||
|
BorderBrush="{ThemeResource TextBoxButtonBorderThemeBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"/>
|
||||||
|
<Border x:Name="BackgroundElement"
|
||||||
|
Background="{ThemeResource TextBoxButtonBackgroundThemeBrush}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}">
|
||||||
|
<TextBlock x:Name="GlyphElement"
|
||||||
|
Foreground="{ThemeResource TextBoxButtonForegroundThemeBrush}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
FontStyle="Normal"
|
||||||
|
Text=""
|
||||||
|
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"/>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style x:Name="GotoButtonStyle" TargetType="Button">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Grid>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" >
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Pressed">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
<Border x:Name="BorderElement"
|
||||||
|
BorderBrush="{ThemeResource TextBoxButtonBorderThemeBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"/>
|
||||||
|
<Border x:Name="BackgroundElement"
|
||||||
|
Background="{ThemeResource TextBoxButtonBackgroundThemeBrush}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}">
|
||||||
|
<TextBlock x:Name="GlyphElement"
|
||||||
|
Foreground="{ThemeResource TextBoxButtonForegroundThemeBrush}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
FontStyle="Normal"
|
||||||
|
Text=""
|
||||||
|
Padding="4,0,4,0"
|
||||||
|
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"/>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</Grid.Resources>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Normal">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlBackgroundThemeOpacity}" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlBorderThemeOpacity}" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlPointerOverBackgroundThemeOpacity}" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlPointerOverBorderThemeOpacity}" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Error">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ErrorColorBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Focused" />
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="ButtonStates">
|
||||||
|
<VisualState x:Name="ButtonVisible">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RevealButton"
|
||||||
|
Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0">
|
||||||
|
<DiscreteObjectKeyFrame.Value>
|
||||||
|
<Visibility>Visible</Visibility>
|
||||||
|
</DiscreteObjectKeyFrame.Value>
|
||||||
|
</DiscreteObjectKeyFrame>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="ButtonCollapsed" />
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Border x:Name="BackgroundElement"
|
||||||
|
Grid.Row="1"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}"
|
||||||
|
Grid.ColumnSpan="3"
|
||||||
|
Grid.RowSpan="1"/>
|
||||||
|
<Border x:Name="BorderElement"
|
||||||
|
Grid.Row="1"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
Grid.ColumnSpan="3"
|
||||||
|
Grid.RowSpan="1"/>
|
||||||
|
<ContentPresenter x:Name="HeaderContentPresenter"
|
||||||
|
Grid.Row="0"
|
||||||
|
Foreground="{ThemeResource TextBoxForegroundHeaderThemeBrush}"
|
||||||
|
Margin="0,4,0,4"
|
||||||
|
Grid.ColumnSpan="3"
|
||||||
|
Content="{TemplateBinding Header}"
|
||||||
|
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||||
|
FontWeight="Semilight" />
|
||||||
|
<ScrollViewer x:Name="ContentElement"
|
||||||
|
Grid.Row="1"
|
||||||
|
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
|
||||||
|
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
|
||||||
|
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
|
||||||
|
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
|
||||||
|
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
|
||||||
|
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}"
|
||||||
|
Padding="{TemplateBinding Padding}"
|
||||||
|
IsTabStop="False"
|
||||||
|
ZoomMode="Disabled"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"/>
|
||||||
|
<ContentControl x:Name="PlaceholderTextContentPresenter"
|
||||||
|
Grid.Row="1"
|
||||||
|
Foreground="{ThemeResource TextBoxPlaceholderTextThemeBrush}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}"
|
||||||
|
Padding="{TemplateBinding Padding}"
|
||||||
|
IsTabStop="False"
|
||||||
|
Grid.ColumnSpan="3"
|
||||||
|
Content="{TemplateBinding PlaceholderText}"
|
||||||
|
IsHitTestVisible="False"/>
|
||||||
|
<Button x:Name="RevealButton"
|
||||||
|
Grid.Row="1"
|
||||||
|
Style="{StaticResource RevealButtonStyle}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
IsTabStop="False"
|
||||||
|
Grid.Column="1"
|
||||||
|
Visibility="Collapsed"
|
||||||
|
FontSize="{TemplateBinding FontSize}"
|
||||||
|
VerticalAlignment="Stretch"/>
|
||||||
|
<Button x:Name="GotoButton"
|
||||||
|
Grid.Row="1"
|
||||||
|
Style="{StaticResource GotoButtonStyle}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
IsTabStop="False"
|
||||||
|
Grid.Column="2"
|
||||||
|
Visibility="Visible"
|
||||||
|
FontSize="{TemplateBinding FontSize}"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
Click="OpenButton_OnClick" />
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</UserControl.Resources>
|
||||||
|
<StackPanel>
|
||||||
|
<PasswordBox x:Name="PasswordBox" Password="{Binding Password, ElementName=UserControl, Mode=TwoWay}" IsPasswordRevealButtonEnabled="True" KeyDown="PasswordBox_KeyDown" PlaceholderText="Password" Style="{StaticResource PasswordBoxWithButtonStyle}">
|
||||||
|
<interactivity:Interaction.Behaviors>
|
||||||
|
<core:DataTriggerBehavior Binding="{Binding Visibility, ElementName=UserControl}" Value="Visible">
|
||||||
|
<actions:SetupFocusAction TargetObject="{Binding ElementName=PasswordBox}" />
|
||||||
|
</core:DataTriggerBehavior>
|
||||||
|
</interactivity:Interaction.Behaviors>
|
||||||
|
</PasswordBox>
|
||||||
|
<TextBlock x:Name="StatusTextBlock" Height="28" Foreground="{ThemeResource ErrorColorBrush}" FontSize="14" FontWeight="Light" TextWrapping="WrapWholeWords" />
|
||||||
|
</StackPanel>
|
||||||
|
</UserControl>
|
73
ModernKeePass/Controls/OpenDatabaseUserControl.xaml.cs
Normal file
73
ModernKeePass/Controls/OpenDatabaseUserControl.xaml.cs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.System;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Input;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
using ModernKeePass.Events;
|
||||||
|
|
||||||
|
// Pour en savoir plus sur le modèle d'élément Contrôle utilisateur, consultez la page http://go.microsoft.com/fwlink/?LinkId=234236
|
||||||
|
|
||||||
|
namespace ModernKeePass.Controls
|
||||||
|
{
|
||||||
|
public sealed partial class OpenDatabaseUserControl
|
||||||
|
{
|
||||||
|
public bool CreateNew
|
||||||
|
{
|
||||||
|
get { return (bool)GetValue(CreateNewProperty); }
|
||||||
|
set { SetValue(CreateNewProperty, value); }
|
||||||
|
}
|
||||||
|
public static readonly DependencyProperty CreateNewProperty =
|
||||||
|
DependencyProperty.Register(
|
||||||
|
"CreateNew",
|
||||||
|
typeof(bool),
|
||||||
|
typeof(OpenDatabaseUserControl),
|
||||||
|
new PropertyMetadata(false, (o, args) => { }));
|
||||||
|
|
||||||
|
public string Password
|
||||||
|
{
|
||||||
|
get { return (string)GetValue(PasswordProperty); }
|
||||||
|
set { SetValue(PasswordProperty, value); }
|
||||||
|
}
|
||||||
|
public static readonly DependencyProperty PasswordProperty =
|
||||||
|
DependencyProperty.Register(
|
||||||
|
"Password",
|
||||||
|
typeof(string),
|
||||||
|
typeof(OpenDatabaseUserControl),
|
||||||
|
new PropertyMetadata(string.Empty, (o, args) => { }));
|
||||||
|
|
||||||
|
public OpenDatabaseUserControl()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public event PasswordCheckingEventHandler ValidationChecking;
|
||||||
|
public delegate void PasswordCheckingEventHandler(object sender, EventArgs e);
|
||||||
|
public event PasswordCheckedEventHandler ValidationChecked;
|
||||||
|
public delegate void PasswordCheckedEventHandler(object sender, PasswordEventArgs e);
|
||||||
|
|
||||||
|
private void OpenButton_OnClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
ValidationChecking?.Invoke(this, new EventArgs());
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
StatusTextBlock.Text = app.Database.Open(PasswordBox.Password, CreateNew);
|
||||||
|
if (app.Database.Status == DatabaseHelper.DatabaseStatus.Opened)
|
||||||
|
{
|
||||||
|
ValidationChecked?.Invoke(this, new PasswordEventArgs(app.Database.RootGroup));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(PasswordBox, "Error", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PasswordBox_KeyDown(object sender, KeyRoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Key == VirtualKey.Enter) OpenButton_OnClick(null, null);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(PasswordBox, "Normal", true);
|
||||||
|
StatusTextBlock.Text = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
ModernKeePass/Controls/TextBoxWithButton.cs
Normal file
21
ModernKeePass/Controls/TextBoxWithButton.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Controls
|
||||||
|
{
|
||||||
|
public class TextBoxWithButton : TextBox
|
||||||
|
{
|
||||||
|
public event EventHandler<RoutedEventArgs> GotoClick;
|
||||||
|
|
||||||
|
protected override void OnApplyTemplate()
|
||||||
|
{
|
||||||
|
base.OnApplyTemplate();
|
||||||
|
var extraButton = GetTemplateChild("GotoButton") as Button;
|
||||||
|
if (extraButton != null)
|
||||||
|
{
|
||||||
|
extraButton.Click += (sender, e) => GotoClick?.Invoke(sender, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
ModernKeePass/Converters/BooleanToVisibilityConverter.cs
Normal file
28
ModernKeePass/Converters/BooleanToVisibilityConverter.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Converters
|
||||||
|
{
|
||||||
|
public class BooleanToVisibilityConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
var boolean = value is bool ? (bool) value : false;
|
||||||
|
return boolean ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to implement this
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
var visibility = value is Visibility ? (Visibility) value : Visibility.Visible;
|
||||||
|
switch (visibility)
|
||||||
|
{
|
||||||
|
case Visibility.Visible: return true;
|
||||||
|
case Visibility.Collapsed: return false;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
ModernKeePass/Converters/ColorToBrushConverter.cs
Normal file
26
ModernKeePass/Converters/ColorToBrushConverter.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
using Windows.UI.Xaml.Media;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Converters
|
||||||
|
{
|
||||||
|
public class ColorToBrushConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
var color = value is Color ? (Color?) value : Color.Empty;
|
||||||
|
if (color == Color.Empty && parameter is SolidColorBrush) return (SolidColorBrush) parameter;
|
||||||
|
return new SolidColorBrush(Windows.UI.Color.FromArgb(
|
||||||
|
color.Value.A,
|
||||||
|
color.Value.R,
|
||||||
|
color.Value.G,
|
||||||
|
color.Value.B));
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
using Windows.UI.Xaml.Media;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Converters
|
||||||
|
{
|
||||||
|
public class DoubleToForegroungBrushComplexityConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var currentValue = (double) value;
|
||||||
|
var maxValue = double.Parse(parameter as string);
|
||||||
|
var green = System.Convert.ToByte(currentValue / maxValue * byte.MaxValue);
|
||||||
|
var red = (byte) (byte.MaxValue - green);
|
||||||
|
return new SolidColorBrush(Color.FromArgb(255, red, green, 0));
|
||||||
|
}
|
||||||
|
catch (OverflowException)
|
||||||
|
{
|
||||||
|
return new SolidColorBrush(Color.FromArgb(255, 0, byte.MaxValue, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Converters
|
||||||
|
{
|
||||||
|
public class InverseBooleanToVisibilityConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
var boolean = value is bool ? (bool)value : false;
|
||||||
|
return boolean ? Visibility.Collapsed : Visibility.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to implement this
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
var visibility = value is Visibility ? (Visibility)value : Visibility.Visible;
|
||||||
|
switch (visibility)
|
||||||
|
{
|
||||||
|
case Visibility.Visible: return false;
|
||||||
|
case Visibility.Collapsed: return true;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
ModernKeePass/Converters/PluralizationConverter.cs
Normal file
24
ModernKeePass/Converters/PluralizationConverter.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Converters
|
||||||
|
{
|
||||||
|
public class PluralizationConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
var pluralizationOptionString = parameter as string;
|
||||||
|
var pluralizationOptions = pluralizationOptionString?.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
if (pluralizationOptions == null || pluralizationOptions.Length != 2) return string.Empty;
|
||||||
|
var count = value is int ? (int) value : 0;
|
||||||
|
var text = count == 1 ? pluralizationOptions[0] : pluralizationOptions[1];
|
||||||
|
return $"{count} {text}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to implement this
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
ModernKeePass/Converters/ProgressBarLegalValuesConverter.cs
Normal file
27
ModernKeePass/Converters/ProgressBarLegalValuesConverter.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Converters
|
||||||
|
{
|
||||||
|
public class ProgressBarLegalValuesConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
var legalValuesOptionString = parameter as string;
|
||||||
|
var legalValuesOptions = legalValuesOptionString?.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
if (legalValuesOptions == null || legalValuesOptions.Length != 2) return 0;
|
||||||
|
|
||||||
|
var minValue = double.Parse(legalValuesOptions[0]);
|
||||||
|
var maxValue = double.Parse(legalValuesOptions[1]);
|
||||||
|
var count = value is double ? (double)value : 0;
|
||||||
|
if (count > maxValue) return maxValue;
|
||||||
|
if (count < minValue) return minValue;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
ModernKeePass/Converters/TextToFontStyleConverter.cs
Normal file
24
ModernKeePass/Converters/TextToFontStyleConverter.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices.WindowsRuntime;
|
||||||
|
using Windows.UI.Text;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Converters
|
||||||
|
{
|
||||||
|
public class TextToFontStyleConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
var compareValue = parameter as string;
|
||||||
|
var text = value as string;
|
||||||
|
return string.Compare(text, compareValue, StringComparison.OrdinalIgnoreCase) == 0
|
||||||
|
? FontStyle.Italic
|
||||||
|
: FontStyle.Normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
ModernKeePass/Converters/TextToWidthConverter.cs
Normal file
20
ModernKeePass/Converters/TextToWidthConverter.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Converters
|
||||||
|
{
|
||||||
|
public class TextToWidthConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
var fontSize = double.Parse(parameter as string);
|
||||||
|
var text = value as string;
|
||||||
|
return text?.Length * fontSize ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
ModernKeePass/Events/PasswordEventArgs.cs
Normal file
15
ModernKeePass/Events/PasswordEventArgs.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Events
|
||||||
|
{
|
||||||
|
public class PasswordEventArgs: EventArgs
|
||||||
|
{
|
||||||
|
public GroupVm RootGroup { get; set; }
|
||||||
|
|
||||||
|
public PasswordEventArgs(GroupVm groupVm)
|
||||||
|
{
|
||||||
|
RootGroup = groupVm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
ModernKeePass/Interfaces/IHasSelectableObject.cs
Normal file
7
ModernKeePass/Interfaces/IHasSelectableObject.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace ModernKeePass.Interfaces
|
||||||
|
{
|
||||||
|
public interface IHasSelectableObject
|
||||||
|
{
|
||||||
|
ISelectableModel SelectedItem { get; set; }
|
||||||
|
}
|
||||||
|
}
|
7
ModernKeePass/Interfaces/IIsEnabled.cs
Normal file
7
ModernKeePass/Interfaces/IIsEnabled.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace ModernKeePass.Interfaces
|
||||||
|
{
|
||||||
|
public interface IIsEnabled
|
||||||
|
{
|
||||||
|
bool IsEnabled { get; }
|
||||||
|
}
|
||||||
|
}
|
19
ModernKeePass/Interfaces/IPwEntity.cs
Normal file
19
ModernKeePass/Interfaces/IPwEntity.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Interfaces
|
||||||
|
{
|
||||||
|
public interface IPwEntity
|
||||||
|
{
|
||||||
|
GroupVm ParentGroup { get; }
|
||||||
|
Symbol IconSymbol { get; }
|
||||||
|
string Id { get; }
|
||||||
|
string Name { get; set; }
|
||||||
|
bool IsEditMode { get; }
|
||||||
|
|
||||||
|
void CommitDelete();
|
||||||
|
void UndoDelete();
|
||||||
|
void Save();
|
||||||
|
void MarkForDelete();
|
||||||
|
}
|
||||||
|
}
|
7
ModernKeePass/Interfaces/ISelectableModel.cs
Normal file
7
ModernKeePass/Interfaces/ISelectableModel.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace ModernKeePass.Interfaces
|
||||||
|
{
|
||||||
|
public interface ISelectableModel
|
||||||
|
{
|
||||||
|
bool IsSelected { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@@ -1,41 +0,0 @@
|
|||||||
<Page
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:local="using:ModernKeePass"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:ViewModels="using:ModernKeePass.ViewModels"
|
|
||||||
x:Class="ModernKeePass.MainPage"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
|
|
||||||
<Page.DataContext>
|
|
||||||
<ViewModels:DatabaseVm/>
|
|
||||||
</Page.DataContext>
|
|
||||||
|
|
||||||
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="250" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="50" />
|
|
||||||
<RowDefinition Height="*" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<Button Grid.Column="0" Grid.Row="0" x:Name="selectButton" Content="Select password database" Click="Button_Click" HorizontalAlignment="Center" />
|
|
||||||
<Grid Grid.Column="0" Grid.Row="2" HorizontalAlignment="Center" Height="auto" VerticalAlignment="Top" Width="auto" Visibility="{Binding Visibility}" >
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="100" />
|
|
||||||
<ColumnDefinition Width="150" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="*" />
|
|
||||||
<RowDefinition Height="*" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<TextBlock Grid.Column="0" Grid.Row="0" x:Name="passwordTextBlock" HorizontalAlignment="Left" TextWrapping="Wrap" Text="Password" VerticalAlignment="Center" Height="auto" Width="auto" FontSize="16" Margin="10,7,0,6" />
|
|
||||||
<PasswordBox Grid.Column="1" Grid.Row="0" x:Name="passwordBox" VerticalAlignment="Top" HorizontalAlignment="Right" Width="130" Password="{Binding Password, Mode=TwoWay}" IsPasswordRevealButtonEnabled="True" Margin="0,0,10,0"/>
|
|
||||||
<Button Grid.Column="1" Grid.Row="1" x:Name="openBbutton" Content="Open" HorizontalAlignment="Right" VerticalAlignment="Top" Click="openBbutton_Click" Margin="0,0,7,0" Width="auto"/>
|
|
||||||
<TextBlock Grid.Column="1" Grid.Row="2" x:Name="errorTextBlock" TextWrapping="Wrap" Text="{Binding ErrorMessage}" HorizontalAlignment="Right" Height="auto" Width="auto" Foreground="#FF9E0909" Margin="0,0,10,0"/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Page>
|
|
@@ -1,49 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Windows.UI.Xaml.Controls;
|
|
||||||
using Windows.UI.Xaml.Input;
|
|
||||||
|
|
||||||
using ModernKeePass.Pages;
|
|
||||||
using ModernKeePass.ViewModels;
|
|
||||||
|
|
||||||
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
|
|
||||||
|
|
||||||
namespace ModernKeePass
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
|
||||||
/// </summary>
|
|
||||||
public sealed partial class MainPage : Page
|
|
||||||
{
|
|
||||||
public MainPage()
|
|
||||||
{
|
|
||||||
this.InitializeComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void Button_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
var picker = new Windows.Storage.Pickers.FileOpenPicker();
|
|
||||||
picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.List;
|
|
||||||
picker.SuggestedStartLocation =
|
|
||||||
Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary;
|
|
||||||
picker.FileTypeFilter.Add(".kdbx");
|
|
||||||
|
|
||||||
var file = await picker.PickSingleFileAsync();
|
|
||||||
if (file != null)
|
|
||||||
{
|
|
||||||
// Application now has read/write access to the picked file
|
|
||||||
DataContext = new DatabaseVm(file);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void openBbutton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
var database = DataContext as DatabaseVm;
|
|
||||||
database.Open();
|
|
||||||
if (database.IsOpen)
|
|
||||||
Frame.Navigate(typeof(GroupDetailPage), database.RootGroup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
82
ModernKeePass/Mappings/PwIconToSegoeMapping.cs
Normal file
82
ModernKeePass/Mappings/PwIconToSegoeMapping.cs
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using ModernKeePassLib;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Mappings
|
||||||
|
{
|
||||||
|
public static class PwIconToSegoeMapping
|
||||||
|
{
|
||||||
|
public static Symbol GetSymbolFromIcon(PwIcon icon)
|
||||||
|
{
|
||||||
|
switch (icon)
|
||||||
|
{
|
||||||
|
case PwIcon.Key: return Symbol.Permissions;
|
||||||
|
case PwIcon.WorldSocket:
|
||||||
|
case PwIcon.World: return Symbol.World;
|
||||||
|
case PwIcon.Warning: return Symbol.Important;
|
||||||
|
case PwIcon.WorldComputer:
|
||||||
|
case PwIcon.Drive:
|
||||||
|
case PwIcon.DriveWindows:
|
||||||
|
case PwIcon.NetworkServer: return Symbol.MapDrive;
|
||||||
|
case PwIcon.MarkedDirectory: return Symbol.Map;
|
||||||
|
case PwIcon.UserCommunication: return Symbol.ContactInfo;
|
||||||
|
case PwIcon.Parts: return Symbol.ViewAll;
|
||||||
|
case PwIcon.Notepad: return Symbol.Document;
|
||||||
|
case PwIcon.Identity: return Symbol.Contact2;
|
||||||
|
case PwIcon.PaperReady: return Symbol.SyncFolder;
|
||||||
|
case PwIcon.Digicam: return Symbol.Camera;
|
||||||
|
case PwIcon.IRCommunication: return Symbol.View;
|
||||||
|
case PwIcon.Energy: return Symbol.ZeroBars;
|
||||||
|
case PwIcon.Scanner: return Symbol.Scan;
|
||||||
|
case PwIcon.CDRom: return Symbol.Rotate;
|
||||||
|
case PwIcon.Monitor: return Symbol.Caption;
|
||||||
|
case PwIcon.EMailBox:
|
||||||
|
case PwIcon.EMail: return Symbol.Mail;
|
||||||
|
case PwIcon.Configuration: return Symbol.Setting;
|
||||||
|
case PwIcon.ClipboardReady: return Symbol.Paste;
|
||||||
|
case PwIcon.PaperNew: return Symbol.Page2;
|
||||||
|
case PwIcon.Screen: return Symbol.GoToStart;
|
||||||
|
case PwIcon.EnergyCareful: return Symbol.FourBars;
|
||||||
|
case PwIcon.Disk: return Symbol.Save;
|
||||||
|
//case PwIcon.PaperQ: return Symbol.;
|
||||||
|
//case PwIcon.TerminalEncrypted: return Symbol.;
|
||||||
|
case PwIcon.Console: return Symbol.SlideShow;
|
||||||
|
case PwIcon.Printer: return Symbol.Scan;
|
||||||
|
case PwIcon.ProgramIcons: return Symbol.GoToStart;
|
||||||
|
//case PwIcon.Run: return Symbol.;
|
||||||
|
case PwIcon.Settings:
|
||||||
|
case PwIcon.Tool: return Symbol.Repair;
|
||||||
|
case PwIcon.Archive: return Symbol.Crop;
|
||||||
|
case PwIcon.Count: return Symbol.Calculator;
|
||||||
|
case PwIcon.Clock: return Symbol.Clock;
|
||||||
|
case PwIcon.EMailSearch: return Symbol.Find;
|
||||||
|
case PwIcon.PaperFlag: return Symbol.Flag;
|
||||||
|
//case PwIcon.Memory: return Symbol.;
|
||||||
|
case PwIcon.TrashBin: return Symbol.Delete;
|
||||||
|
case PwIcon.Expired: return Symbol.Cancel;
|
||||||
|
case PwIcon.Info: return Symbol.Help;
|
||||||
|
//case PwIcon.Package: return Symbol.;
|
||||||
|
case PwIcon.Folder:
|
||||||
|
case PwIcon.FolderOpen:
|
||||||
|
case PwIcon.FolderPackage: return Symbol.Folder;
|
||||||
|
//case PwIcon.LockOpen: return Symbol.;
|
||||||
|
case PwIcon.PaperLocked: return Symbol.ProtectedDocument;
|
||||||
|
case PwIcon.Checked: return Symbol.Accept;
|
||||||
|
case PwIcon.Pen: return Symbol.Edit;
|
||||||
|
case PwIcon.Thumbnail: return Symbol.BrowsePhotos;
|
||||||
|
case PwIcon.Book: return Symbol.Library;
|
||||||
|
case PwIcon.List: return Symbol.List;
|
||||||
|
case PwIcon.UserKey: return Symbol.ContactPresence;
|
||||||
|
case PwIcon.Home: return Symbol.Home;
|
||||||
|
case PwIcon.Star: return Symbol.OutlineStar;
|
||||||
|
//case PwIcon.Tux: return Symbol.;
|
||||||
|
//case PwIcon.Feather: return Symbol.;
|
||||||
|
//case PwIcon.Apple: return Symbol.;
|
||||||
|
//case PwIcon.Wiki: return Symbol.;
|
||||||
|
case PwIcon.Money: return Symbol.Shop;
|
||||||
|
case PwIcon.Certificate: return Symbol.PreviewLink;
|
||||||
|
case PwIcon.BlackBerry: return Symbol.CellPhone;
|
||||||
|
default: return Symbol.Stop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -20,6 +20,7 @@
|
|||||||
<PackageCertificateThumbprint>ED3AA34F46D03498F989901C5DB2742B65D72F60</PackageCertificateThumbprint>
|
<PackageCertificateThumbprint>ED3AA34F46D03498F989901C5DB2742B65D72F60</PackageCertificateThumbprint>
|
||||||
<AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
|
<AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
|
||||||
<AppxBundlePlatforms>neutral</AppxBundlePlatforms>
|
<AppxBundlePlatforms>neutral</AppxBundlePlatforms>
|
||||||
|
<AppxBundle>Always</AppxBundle>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
@@ -107,26 +108,80 @@
|
|||||||
<Prefer32Bit>true</Prefer32Bit>
|
<Prefer32Bit>true</Prefer32Bit>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Actions\SetupFocusAction.cs" />
|
||||||
<Compile Include="App.xaml.cs">
|
<Compile Include="App.xaml.cs">
|
||||||
<DependentUpon>App.xaml</DependentUpon>
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Common\DatabaseHelper.cs" />
|
||||||
|
<Compile Include="Common\MessageDialogHelper.cs" />
|
||||||
<Compile Include="Common\NavigationHelper.cs" />
|
<Compile Include="Common\NavigationHelper.cs" />
|
||||||
|
<Compile Include="Common\NotifyPropertyChangedBase.cs" />
|
||||||
<Compile Include="Common\ObservableDictionary.cs" />
|
<Compile Include="Common\ObservableDictionary.cs" />
|
||||||
<Compile Include="Common\RelayCommand.cs" />
|
<Compile Include="Common\RelayCommand.cs" />
|
||||||
<Compile Include="Common\SuspensionManager.cs" />
|
<Compile Include="Common\SuspensionManager.cs" />
|
||||||
<Compile Include="MainPage.xaml.cs">
|
<Compile Include="Common\ToastNotificationHelper.cs" />
|
||||||
|
<Compile Include="Interfaces\IHasSelectableObject.cs" />
|
||||||
|
<Compile Include="Interfaces\ISelectableModel.cs" />
|
||||||
|
<Compile Include="Pages\BasePages\LayoutAwarePageBase.cs" />
|
||||||
|
<Compile Include="TemplateSelectors\FirstItemDataTemplateSelector.cs" />
|
||||||
|
<Compile Include="Controls\ListViewWithDisable.cs" />
|
||||||
|
<Compile Include="Controls\OpenDatabaseUserControl.xaml.cs">
|
||||||
|
<DependentUpon>OpenDatabaseUserControl.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Controls\TextBoxWithButton.cs" />
|
||||||
|
<Compile Include="Converters\BooleanToVisibilityConverter.cs" />
|
||||||
|
<Compile Include="Converters\ColorToBrushConverter.cs" />
|
||||||
|
<Compile Include="Converters\DoubleToForegroungBrushComplexityConverter.cs" />
|
||||||
|
<Compile Include="Converters\InverseBooleanToVisibilityConverter.cs" />
|
||||||
|
<Compile Include="Converters\TextToFontStyleConverter.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">
|
||||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Mappings\PwIconToSegoeMapping.cs" />
|
||||||
|
<Compile Include="Pages\MainPageFrames\AboutPage.xaml.cs">
|
||||||
|
<DependentUpon>AboutPage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Pages\MainPageFrames\NewDatabasePage.xaml.cs">
|
||||||
|
<DependentUpon>NewDatabasePage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Pages\SettingsPage.xaml.cs">
|
||||||
|
<DependentUpon>SettingsPage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Pages\MainPageFrames\WelcomePage.xaml.cs">
|
||||||
|
<DependentUpon>WelcomePage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="ViewModels\AboutVm.cs" />
|
||||||
|
<Compile Include="ViewModels\Items\MainMenuItemVm.cs" />
|
||||||
|
<Compile Include="ViewModels\Items\RecentItemVm.cs" />
|
||||||
<Compile Include="Pages\EntryDetailPage.xaml.cs">
|
<Compile Include="Pages\EntryDetailPage.xaml.cs">
|
||||||
<DependentUpon>EntryDetailPage.xaml</DependentUpon>
|
<DependentUpon>EntryDetailPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Pages\GroupDetailPage.xaml.cs">
|
<Compile Include="Pages\GroupDetailPage.xaml.cs">
|
||||||
<DependentUpon>GroupDetailPage.xaml</DependentUpon>
|
<DependentUpon>GroupDetailPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Pages\MainPageFrames\OpenDatabasePage.xaml.cs">
|
||||||
|
<DependentUpon>OpenDatabasePage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Pages\MainPageFrames\RecentDatabasesPage.xaml.cs">
|
||||||
|
<DependentUpon>RecentDatabasesPage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Pages\MainPageFrames\SaveDatabasePage.xaml.cs">
|
||||||
|
<DependentUpon>SaveDatabasePage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="ViewModels\DatabaseVm.cs" />
|
|
||||||
<Compile Include="ViewModels\EntryVm.cs" />
|
<Compile Include="ViewModels\EntryVm.cs" />
|
||||||
<Compile Include="ViewModels\GroupVm.cs" />
|
<Compile Include="ViewModels\GroupVm.cs" />
|
||||||
|
<Compile Include="ViewModels\MainVm.cs" />
|
||||||
|
<Compile Include="ViewModels\NewVm.cs" />
|
||||||
|
<Compile Include="ViewModels\OpenVm.cs" />
|
||||||
|
<Compile Include="ViewModels\RecentVm.cs" />
|
||||||
|
<Compile Include="ViewModels\SaveVm.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AppxManifest Include="Package.appxmanifest">
|
<AppxManifest Include="Package.appxmanifest">
|
||||||
@@ -134,7 +189,9 @@
|
|||||||
</AppxManifest>
|
</AppxManifest>
|
||||||
<None Include="ModernKeePass_StoreKey.pfx" />
|
<None Include="ModernKeePass_StoreKey.pfx" />
|
||||||
<None Include="ModernKeePass_TemporaryKey.pfx" />
|
<None Include="ModernKeePass_TemporaryKey.pfx" />
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Package.StoreAssociation.xml" />
|
<None Include="Package.StoreAssociation.xml" />
|
||||||
@@ -144,10 +201,18 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</ApplicationDefinition>
|
</ApplicationDefinition>
|
||||||
<Page Include="MainPage.xaml">
|
<Page Include="Controls\OpenDatabaseUserControl.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Pages\MainPage.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="Pages\MainPageFrames\AboutPage.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
<Page Include="Pages\EntryDetailPage.xaml">
|
<Page Include="Pages\EntryDetailPage.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
@@ -156,18 +221,78 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="Pages\MainPageFrames\NewDatabasePage.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Pages\MainPageFrames\OpenDatabasePage.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Pages\MainPageFrames\RecentDatabasesPage.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Pages\MainPageFrames\SaveDatabasePage.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Pages\SettingsPage.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Pages\MainPageFrames\WelcomePage.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Styles\HamburgerButtonStyle.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Styles\ListViewLeftIndicatorStyle.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Styles\NoBorderButtonStyle.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Styles\TextBoxWithButtonStyle.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Page>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="ModernKeePassLib, Version=2.19.0.15913, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="BouncyCastle.Crypto, Version=1.8.1.0, Culture=neutral, PublicKeyToken=0e99375e54769942, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\ModernKeePassLib.2.19.2950\lib\netstandard1.2\ModernKeePassLib.dll</HintPath>
|
<HintPath>..\packages\Portable.BouncyCastle.1.8.1.3\lib\netstandard1.0\BouncyCastle.Crypto.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.Toolkit.Uwp.Notifications, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Microsoft.Toolkit.Uwp.Notifications.2.0.0\lib\dotnet\Microsoft.Toolkit.Uwp.Notifications.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Splat.2.0.0\lib\Portable-Win81+Wpa81\Splat.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\win8\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
|
<HintPath>..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\win8\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Validation, Version=2.4.0.0, Culture=neutral, PublicKeyToken=2fc06f0d701809a7, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Validation.2.4.15\lib\portable-net45+win8+wp8+wpa81\Validation.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<SDKReference Include="BehaviorsXamlSDKManaged, Version=12.0">
|
||||||
|
<Name>BehaviorsXamlSDKManaged</Name>
|
||||||
|
</SDKReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Assets\Logo.scale-100.png" />
|
<Content Include="Assets\Logo.scale-100.png" />
|
||||||
<Content Include="Assets\Logo.scale-140.png" />
|
<Content Include="Assets\Logo.scale-140.png" />
|
||||||
@@ -210,17 +335,28 @@
|
|||||||
<Content Include="Assets\Wide310x150Logo.scale-180.png" />
|
<Content Include="Assets\Wide310x150Logo.scale-180.png" />
|
||||||
<Content Include="Assets\Wide310x150Logo.scale-80.png" />
|
<Content Include="Assets\Wide310x150Logo.scale-80.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\ModernKeePassLib\ModernKeePassLib.csproj">
|
||||||
|
<Project>{2e710089-9559-4967-846c-e763dd1f3acb}</Project>
|
||||||
|
<Name>ModernKeePassLib</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Pages\SettingsPageFrames\" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '12.0' ">
|
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '12.0' ">
|
||||||
<VisualStudioVersion>12.0</VisualStudioVersion>
|
<VisualStudioVersion>12.0</VisualStudioVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
||||||
<Import Project="..\packages\NETStandard.Library.2.0.0\build\NETStandard.Library.targets" Condition="Exists('..\packages\NETStandard.Library.2.0.0\build\NETStandard.Library.targets')" />
|
|
||||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Error Condition="!Exists('..\packages\NETStandard.Library.2.0.0\build\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NETStandard.Library.2.0.0\build\NETStandard.Library.targets'))" />
|
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\NETStandard.Library.2.0.1\build\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NETStandard.Library.2.0.1\build\NETStandard.Library.targets'))" />
|
||||||
</Target>
|
</Target>
|
||||||
|
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
|
||||||
|
<Import Project="..\packages\NETStandard.Library.2.0.1\build\NETStandard.Library.targets" Condition="Exists('..\packages\NETStandard.Library.2.0.1\build\NETStandard.Library.targets')" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
<Target Name="BeforeBuild">
|
<Target Name="BeforeBuild">
|
||||||
|
3
ModernKeePass/ModernKeePass.csproj.DotSettings
Normal file
3
ModernKeePass/ModernKeePass.csproj.DotSettings
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp70</s:String>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=viewmodels_005Citems/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?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">
|
<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.1.0.2" />
|
<Identity Name="wismna.ModernKeePass" Publisher="CN=0719A91A-C322-4EE0-A257-E60733EECF06" Version="1.5.0.25" />
|
||||||
<Properties>
|
<Properties>
|
||||||
<DisplayName>ModernKeePass</DisplayName>
|
<DisplayName>ModernKeePass</DisplayName>
|
||||||
<PublisherDisplayName>wismna</PublisherDisplayName>
|
<PublisherDisplayName>wismna</PublisherDisplayName>
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
</Resources>
|
</Resources>
|
||||||
<Applications>
|
<Applications>
|
||||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="ModernKeePass.App">
|
<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. For now, it only features read-only capabilites and only opens password protected databases." ForegroundText="light" BackgroundColor="#464646" ToastCapable="true">
|
<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:DefaultTile Square310x310Logo="Assets\Square310x310Logo.png" Wide310x150Logo="Assets\Wide310x150Logo.png" Square70x70Logo="Assets\Square70x70Logo.png">
|
<m2:DefaultTile Square310x310Logo="Assets\Square310x310Logo.png" Wide310x150Logo="Assets\Wide310x150Logo.png" Square70x70Logo="Assets\Square70x70Logo.png">
|
||||||
</m2:DefaultTile>
|
</m2:DefaultTile>
|
||||||
<m2:SplashScreen Image="Assets\ModernKeePass-SplashScreen.png" />
|
<m2:SplashScreen Image="Assets\ModernKeePass-SplashScreen.png" />
|
||||||
@@ -28,6 +28,22 @@
|
|||||||
</SupportedFileTypes>
|
</SupportedFileTypes>
|
||||||
</FileOpenPicker>
|
</FileOpenPicker>
|
||||||
</Extension>
|
</Extension>
|
||||||
|
<Extension Category="windows.fileTypeAssociation">
|
||||||
|
<FileTypeAssociation Name="kdbx">
|
||||||
|
<DisplayName>KeePass 2.x database</DisplayName>
|
||||||
|
<EditFlags OpenIsSafe="true" />
|
||||||
|
<SupportedFileTypes>
|
||||||
|
<FileType ContentType="application/xml">.kdbx</FileType>
|
||||||
|
</SupportedFileTypes>
|
||||||
|
</FileTypeAssociation>
|
||||||
|
</Extension>
|
||||||
|
<Extension Category="windows.fileSavePicker">
|
||||||
|
<FileSavePicker>
|
||||||
|
<SupportedFileTypes>
|
||||||
|
<FileType>.kdbx</FileType>
|
||||||
|
</SupportedFileTypes>
|
||||||
|
</FileSavePicker>
|
||||||
|
</Extension>
|
||||||
</Extensions>
|
</Extensions>
|
||||||
</Application>
|
</Application>
|
||||||
</Applications>
|
</Applications>
|
||||||
|
209
ModernKeePass/Pages/BasePages/LayoutAwarePageBase.cs
Normal file
209
ModernKeePass/Pages/BasePages/LayoutAwarePageBase.cs
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
using ModernKeePass.Interfaces;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Pages.BasePages
|
||||||
|
{
|
||||||
|
public class LayoutAwarePageBase: Page
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// NavigationHelper is used on each page to aid in navigation and
|
||||||
|
/// process lifetime management
|
||||||
|
/// </summary>
|
||||||
|
public NavigationHelper NavigationHelper { get; }
|
||||||
|
|
||||||
|
public virtual ListView ListView { get; set; }
|
||||||
|
public virtual CollectionViewSource ListViewSource { get; set; }
|
||||||
|
public virtual IHasSelectableObject Model { get; set; }
|
||||||
|
|
||||||
|
public LayoutAwarePageBase()
|
||||||
|
{
|
||||||
|
// Setup the navigation helper
|
||||||
|
NavigationHelper = new NavigationHelper(this);
|
||||||
|
NavigationHelper.LoadState += navigationHelper_LoadState;
|
||||||
|
NavigationHelper.SaveState += navigationHelper_SaveState;
|
||||||
|
|
||||||
|
// Setup the logical page navigation components that allow
|
||||||
|
// the page to only show one pane at a time.
|
||||||
|
NavigationHelper.GoBackCommand = new RelayCommand(() => GoBack(), () => CanGoBack());
|
||||||
|
|
||||||
|
// Start listening for Window size changes
|
||||||
|
// to change from showing two panes to showing a single pane
|
||||||
|
Window.Current.SizeChanged += Window_SizeChanged;
|
||||||
|
InvalidateVisualState();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
// Invalidate the view state when logical page navigation is in effect, as a change
|
||||||
|
// in selection may cause a corresponding change in the current logical page. When
|
||||||
|
// an item is selected this has the effect of changing from displaying the item list
|
||||||
|
// to showing the selected item's details. When the selection is cleared this has the
|
||||||
|
// opposite effect.
|
||||||
|
if (!UsingLogicalPageNavigation()) return;
|
||||||
|
NavigationHelper.GoBackCommand.RaiseCanExecuteChanged();
|
||||||
|
InvalidateVisualState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Populates the page with content passed during navigation. Any saved state is also
|
||||||
|
/// provided when recreating a page from a prior session.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">
|
||||||
|
/// The source of the event; typically <see cref="Common.NavigationHelper"/>
|
||||||
|
/// </param>
|
||||||
|
/// <param name="e">Event data that provides both the navigation parameter passed to
|
||||||
|
/// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested and
|
||||||
|
/// a dictionary of state preserved by this page during an earlier
|
||||||
|
/// session. The state will be null the first time a page is visited.</param>
|
||||||
|
protected void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
|
||||||
|
{
|
||||||
|
// TODO: Assign a bindable group to Me.DefaultViewModel("Group")
|
||||||
|
// TODO: Assign a collection of bindable items to Me.DefaultViewModel("Items")
|
||||||
|
|
||||||
|
if (e.PageState == null)
|
||||||
|
{
|
||||||
|
// When this is a new page, select the first item automatically unless logical page
|
||||||
|
// navigation is being used (see the logical page navigation #region below.)
|
||||||
|
if (!UsingLogicalPageNavigation() && ListViewSource.View != null)
|
||||||
|
{
|
||||||
|
ListViewSource.View.MoveCurrentToFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Restore the previously saved state associated with this page
|
||||||
|
if (e.PageState.ContainsKey("SelectedItem") && ListViewSource.View != null)
|
||||||
|
{
|
||||||
|
ListViewSource.View.MoveCurrentTo(e.PageState["SelectedItem"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Preserves state associated with this page in case the application is suspended or the
|
||||||
|
/// page is discarded from the navigation cache. Values must conform to the serialization
|
||||||
|
/// requirements of <see cref="Common.SuspensionManager.SessionState"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The source of the event; typically <see cref="Common.NavigationHelper"/></param>
|
||||||
|
/// <param name="e">Event data that provides an empty dictionary to be populated with
|
||||||
|
/// serializable state.</param>
|
||||||
|
protected void navigationHelper_SaveState(object sender, SaveStateEventArgs e)
|
||||||
|
{
|
||||||
|
if (ListViewSource.View != null)
|
||||||
|
{
|
||||||
|
e.PageState["SelectedItem"] = Model?.SelectedItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Logical page navigation
|
||||||
|
|
||||||
|
// The split page is designed so that when the Window does have enough space to show
|
||||||
|
// both the list and the details, only one pane will be shown at at time.
|
||||||
|
//
|
||||||
|
// This is all implemented with a single physical page that can represent two logical
|
||||||
|
// pages. The code below achieves this goal without making the user aware of the
|
||||||
|
// distinction.
|
||||||
|
|
||||||
|
protected const int MinimumWidthForSupportingTwoPanes = 768;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked to determine whether the page should act as one logical page or two.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if the window should show act as one logical page, false
|
||||||
|
/// otherwise.</returns>
|
||||||
|
protected bool UsingLogicalPageNavigation()
|
||||||
|
{
|
||||||
|
return Window.Current.Bounds.Width < MinimumWidthForSupportingTwoPanes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked with the Window changes size
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The current Window</param>
|
||||||
|
/// <param name="e">Event data that describes the new size of the Window</param>
|
||||||
|
protected void Window_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
|
||||||
|
{
|
||||||
|
InvalidateVisualState();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool CanGoBack()
|
||||||
|
{
|
||||||
|
if (UsingLogicalPageNavigation() && ListView.SelectedItem != null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return NavigationHelper.CanGoBack();
|
||||||
|
}
|
||||||
|
protected void GoBack()
|
||||||
|
{
|
||||||
|
if (UsingLogicalPageNavigation() && ListView.SelectedItem != null)
|
||||||
|
{
|
||||||
|
// When logical page navigation is in effect and there's a selected item that
|
||||||
|
// item's details are currently displayed. Clearing the selection will return to
|
||||||
|
// the item list. From the user's point of view this is a logical backward
|
||||||
|
// navigation.
|
||||||
|
ListView.SelectedItem = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NavigationHelper.GoBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void InvalidateVisualState()
|
||||||
|
{
|
||||||
|
var visualState = DetermineVisualState();
|
||||||
|
VisualStateManager.GoToState(this, visualState, false);
|
||||||
|
NavigationHelper.GoBackCommand.RaiseCanExecuteChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked to determine the name of the visual state that corresponds to an application
|
||||||
|
/// view state.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The name of the desired visual state. This is the same as the name of the
|
||||||
|
/// view state except when there is a selected item in portrait and snapped views where
|
||||||
|
/// this additional logical page is represented by adding a suffix of _Detail.</returns>
|
||||||
|
protected string DetermineVisualState()
|
||||||
|
{
|
||||||
|
if (!UsingLogicalPageNavigation())
|
||||||
|
return "PrimaryView";
|
||||||
|
|
||||||
|
// Update the back button's enabled state when the view state changes
|
||||||
|
var logicalPageBack = UsingLogicalPageNavigation() && ListView?.SelectedItem != null;
|
||||||
|
|
||||||
|
return logicalPageBack ? "SinglePane_Detail" : "SinglePane";
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region NavigationHelper registration
|
||||||
|
|
||||||
|
/// The methods provided in this section are simply used to allow
|
||||||
|
/// NavigationHelper to respond to the page's navigation methods.
|
||||||
|
///
|
||||||
|
/// Page specific logic should be placed in event handlers for the
|
||||||
|
/// <see cref="Common.NavigationHelper.LoadState"/>
|
||||||
|
/// and <see cref="Common.NavigationHelper.SaveState"/>.
|
||||||
|
/// The navigation parameter is available in the LoadState method
|
||||||
|
/// in addition to page state preserved during an earlier session.
|
||||||
|
|
||||||
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
NavigationHelper.OnNavigatedTo(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
NavigationHelper.OnNavigatedFrom(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@@ -1,19 +1,402 @@
|
|||||||
<Page
|
<Page
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="using:ModernKeePass.Pages"
|
|
||||||
xmlns:common="using:ModernKeePass.Common"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:ViewModels="using:ModernKeePass.ViewModels"
|
xmlns:viewModels="using:ModernKeePass.ViewModels"
|
||||||
x:Name="pageRoot"
|
xmlns:converters="using:ModernKeePass.Converters"
|
||||||
|
xmlns:local="using:ModernKeePass.Controls"
|
||||||
|
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||||
|
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
|
||||||
|
xmlns:actions="using:ModernKeePass.Actions"
|
||||||
|
x:Name="PageRoot"
|
||||||
x:Class="ModernKeePass.Pages.EntryDetailPage"
|
x:Class="ModernKeePass.Pages.EntryDetailPage"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
<Page.Resources>
|
||||||
|
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||||
|
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
|
||||||
|
<converters:ProgressBarLegalValuesConverter x:Key="ProgressBarLegalValuesConverter"/>
|
||||||
|
<converters:DoubleToForegroungBrushComplexityConverter x:Key="DoubleToForegroungBrushComplexityConverter"/>
|
||||||
|
<Style TargetType="PasswordBox" x:Name="PasswordBoxWithButtonStyle">
|
||||||
|
<Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
|
||||||
|
<Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
|
||||||
|
<Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}" />
|
||||||
|
<Setter Property="Background" Value="{ThemeResource TextBoxBackgroundThemeBrush}" />
|
||||||
|
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextSelectionHighlightColorThemeBrush}" />
|
||||||
|
<Setter Property="BorderBrush" Value="{ThemeResource TextBoxBorderThemeBrush}" />
|
||||||
|
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
|
||||||
|
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||||
|
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
|
||||||
|
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
|
||||||
|
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
|
||||||
|
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="PasswordBox">
|
||||||
|
<Grid>
|
||||||
|
<Grid.Resources>
|
||||||
|
<Style x:Name="RevealButtonStyle" TargetType="Button">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Grid>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Pressed">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
<Border x:Name="BorderElement"
|
||||||
|
BorderBrush="{ThemeResource TextBoxButtonBorderThemeBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"/>
|
||||||
|
<Border x:Name="BackgroundElement"
|
||||||
|
Background="{ThemeResource TextBoxButtonBackgroundThemeBrush}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}">
|
||||||
|
<TextBlock x:Name="GlyphElement"
|
||||||
|
Foreground="{ThemeResource TextBoxButtonForegroundThemeBrush}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
FontStyle="Normal"
|
||||||
|
Text=""
|
||||||
|
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"/>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style x:Name="GeneratorButtonStyle" TargetType="Button">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Grid>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" >
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Pressed">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
<Border x:Name="BorderElement"
|
||||||
|
BorderBrush="{ThemeResource TextBoxButtonBorderThemeBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"/>
|
||||||
|
<Border x:Name="BackgroundElement"
|
||||||
|
Background="{ThemeResource TextBoxButtonBackgroundThemeBrush}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}">
|
||||||
|
<TextBlock x:Name="GlyphElement"
|
||||||
|
Foreground="{ThemeResource TextBoxButtonForegroundThemeBrush}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
FontStyle="Normal"
|
||||||
|
Text=""
|
||||||
|
Padding="4,0,4,0"
|
||||||
|
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"/>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</Grid.Resources>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Normal">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlBackgroundThemeOpacity}" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlBorderThemeOpacity}" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlPointerOverBackgroundThemeOpacity}" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlPointerOverBorderThemeOpacity}" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Focused" />
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="ButtonStates">
|
||||||
|
<VisualState x:Name="ButtonVisible">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RevealButton"
|
||||||
|
Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0">
|
||||||
|
<DiscreteObjectKeyFrame.Value>
|
||||||
|
<Visibility>Visible</Visibility>
|
||||||
|
</DiscreteObjectKeyFrame.Value>
|
||||||
|
</DiscreteObjectKeyFrame>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="ButtonCollapsed" />
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Border x:Name="BackgroundElement"
|
||||||
|
Grid.Row="1"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}"
|
||||||
|
Grid.ColumnSpan="3"
|
||||||
|
Grid.RowSpan="1"/>
|
||||||
|
<Border x:Name="BorderElement"
|
||||||
|
Grid.Row="1"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
Grid.ColumnSpan="3"
|
||||||
|
Grid.RowSpan="1"/>
|
||||||
|
<ContentPresenter x:Name="HeaderContentPresenter"
|
||||||
|
Grid.Row="0"
|
||||||
|
Foreground="{ThemeResource TextBoxForegroundHeaderThemeBrush}"
|
||||||
|
Margin="0,4,0,4"
|
||||||
|
Grid.ColumnSpan="3"
|
||||||
|
Content="{TemplateBinding Header}"
|
||||||
|
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||||
|
FontWeight="Semilight" />
|
||||||
|
<ScrollViewer x:Name="ContentElement"
|
||||||
|
Grid.Row="1"
|
||||||
|
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
|
||||||
|
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
|
||||||
|
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
|
||||||
|
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
|
||||||
|
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
|
||||||
|
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}"
|
||||||
|
Padding="{TemplateBinding Padding}"
|
||||||
|
IsTabStop="False"
|
||||||
|
ZoomMode="Disabled"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"/>
|
||||||
|
<ContentControl x:Name="PlaceholderTextContentPresenter"
|
||||||
|
Grid.Row="1"
|
||||||
|
Foreground="{ThemeResource TextBoxPlaceholderTextThemeBrush}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}"
|
||||||
|
Padding="{TemplateBinding Padding}"
|
||||||
|
IsTabStop="False"
|
||||||
|
Grid.ColumnSpan="3"
|
||||||
|
Content="{TemplateBinding PlaceholderText}"
|
||||||
|
IsHitTestVisible="False"/>
|
||||||
|
<Button x:Name="RevealButton"
|
||||||
|
Grid.Row="1"
|
||||||
|
Style="{StaticResource RevealButtonStyle}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
IsTabStop="False"
|
||||||
|
Grid.Column="1"
|
||||||
|
Visibility="Collapsed"
|
||||||
|
FontSize="{TemplateBinding FontSize}"
|
||||||
|
VerticalAlignment="Stretch"/>
|
||||||
|
<Button
|
||||||
|
Grid.Row="1"
|
||||||
|
Style="{StaticResource GeneratorButtonStyle}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
IsTabStop="False"
|
||||||
|
Grid.Column="2"
|
||||||
|
Visibility="Visible"
|
||||||
|
FontSize="{TemplateBinding FontSize}"
|
||||||
|
VerticalAlignment="Stretch" >
|
||||||
|
<Button.Flyout>
|
||||||
|
<Flyout>
|
||||||
|
<interactivity:Interaction.Behaviors>
|
||||||
|
<core:DataTriggerBehavior Binding="{Binding Password}" ComparisonCondition="NotEqual" Value="" >
|
||||||
|
<!--<actions:CloseFlyoutAction />-->
|
||||||
|
<core:CallMethodAction MethodName="Hide" />
|
||||||
|
</core:DataTriggerBehavior>
|
||||||
|
</interactivity:Interaction.Behaviors>
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock>
|
||||||
|
<Run Text="Password Length: "/>
|
||||||
|
<Run Text="{Binding PasswordLength}" />
|
||||||
|
</TextBlock>
|
||||||
|
<Slider Value="{Binding PasswordLength, Mode=TwoWay}" Margin="0,-10,0,-20" />
|
||||||
|
<CheckBox IsChecked="{Binding UpperCasePatternSelected, Mode=TwoWay}" Content="Upper case (A, B, C, ...)"/>
|
||||||
|
<CheckBox IsChecked="{Binding LowerCasePatternSelected, Mode=TwoWay}" Content="Lower case (a, b, c, ...)"/>
|
||||||
|
<CheckBox IsChecked="{Binding DigitsPatternSelected, Mode=TwoWay}" Content="Digits (0, 1, 2, ...)"/>
|
||||||
|
<CheckBox IsChecked="{Binding MinusPatternSelected, Mode=TwoWay}" Content="Minus (-)"/>
|
||||||
|
<CheckBox IsChecked="{Binding UnderscorePatternSelected, Mode=TwoWay}" Content="Underscore (_)"/>
|
||||||
|
<CheckBox IsChecked="{Binding SpacePatternSelected, Mode=TwoWay}" Content="Space ( )"/>
|
||||||
|
<CheckBox IsChecked="{Binding SpecialPatternSelected, Mode=TwoWay}" Content="Special (!, $, %, ...)"/>
|
||||||
|
<CheckBox IsChecked="{Binding BracketsPatternSelected, Mode=TwoWay}" Content="Brackets ([], {}, (), ...)"/>
|
||||||
|
<Button Content="Generate">
|
||||||
|
<interactivity:Interaction.Behaviors>
|
||||||
|
<core:EventTriggerBehavior EventName="Click">
|
||||||
|
<core:CallMethodAction TargetObject="{Binding}" MethodName="GeneratePassword"/>
|
||||||
|
</core:EventTriggerBehavior>
|
||||||
|
</interactivity:Interaction.Behaviors>
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</Flyout>
|
||||||
|
</Button.Flyout>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</Page.Resources>
|
||||||
<Page.DataContext>
|
<Page.DataContext>
|
||||||
<ViewModels:EntryVm/>
|
<viewModels:EntryVm/>
|
||||||
</Page.DataContext>
|
</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="Delete" Label="Delete" Click="DeleteButton_Click" />
|
||||||
|
</CommandBar>
|
||||||
|
</Page.BottomAppBar>
|
||||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
<Grid.ChildrenTransitions>
|
<Grid.ChildrenTransitions>
|
||||||
<TransitionCollection>
|
<TransitionCollection>
|
||||||
@@ -21,48 +404,80 @@
|
|||||||
</TransitionCollection>
|
</TransitionCollection>
|
||||||
</Grid.ChildrenTransitions>
|
</Grid.ChildrenTransitions>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="140"/>
|
<RowDefinition Height="40"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Grid Grid.Row="1" x:Name="contentRegion">
|
<StackPanel x:Name="stackPanel" Grid.Row="1" Margin="20,0,0,0" >
|
||||||
<Grid.RowDefinitions>
|
<StackPanel.Resources>
|
||||||
<RowDefinition Height="Auto"/>
|
<Style TargetType="TextBlock">
|
||||||
<RowDefinition Height="*"/>
|
<Setter Property="Margin" Value="0,20,0,0"/>
|
||||||
<RowDefinition Height="Auto"/>
|
</Style>
|
||||||
<RowDefinition Height="Auto"/>
|
<Style TargetType="CheckBox">
|
||||||
<RowDefinition Height="*"/>
|
<Setter Property="Margin" Value="0,20,0,0"/>
|
||||||
<RowDefinition Height="Auto"/>
|
</Style>
|
||||||
<RowDefinition Height="*"/>
|
</StackPanel.Resources>
|
||||||
<RowDefinition Height="Auto"/>
|
<TextBlock TextWrapping="Wrap" Text="User name or login" FontSize="18"/>
|
||||||
<RowDefinition Height="*"/>
|
<TextBox HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding UserName, Mode=TwoWay}" Width="350" Height="32" />
|
||||||
</Grid.RowDefinitions>
|
<TextBlock TextWrapping="Wrap" Text="Password" FontSize="18"/>
|
||||||
<TextBlock x:Name="userTextBlock" Grid.Row="0" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="User name or login" VerticalAlignment="Top" FontSize="18"/>
|
<PasswordBox HorizontalAlignment="Left" Password="{Binding Password, Mode=TwoWay}" Width="350" Height="32" IsPasswordRevealButtonEnabled="True" Visibility="{Binding IsRevealPassword, Converter={StaticResource InverseBooleanToVisibilityConverter}}" Style="{StaticResource PasswordBoxWithButtonStyle}" />
|
||||||
<TextBox x:Name="userTextBox" Grid.Row="1" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="{Binding UserName, Mode=TwoWay}" VerticalAlignment="Top" Width="250" AllowDrop="True"/>
|
<TextBox HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding Password, Mode=TwoWay}" Width="350" Height="32" Visibility="{Binding IsRevealPassword, Converter={StaticResource BooleanToVisibilityConverter}}" />
|
||||||
<TextBlock x:Name="passwordTextBlock" Grid.Row="2" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="Password" VerticalAlignment="Top" FontSize="18"/>
|
<ProgressBar Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}" Maximum="128" Width="350" HorizontalAlignment="Left" Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroungBrushComplexityConverter}}" />
|
||||||
<PasswordBox x:Name="passwordBox" Grid.Row="3" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Password="{Binding Password, Mode=TwoWay}" IsPasswordRevealButtonEnabled="True" Width="250" AllowDrop="True"/>
|
<CheckBox HorizontalAlignment="Left" Margin="-3,0,0,0" Content="Show password" IsChecked="{Binding IsRevealPassword, Mode=TwoWay}" IsEnabled="{Binding IsRevealPasswordEnabled}" />
|
||||||
<TextBox x:Name="passwordTextBox" Grid.Row="3" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="{Binding Password, Mode=TwoWay}" VerticalAlignment="Top" Width="250" FontSize="14,667" MaxLength="256" AllowDrop="True" Visibility="Collapsed"/>
|
<TextBlock TextWrapping="Wrap" Text="URL" FontSize="18"/>
|
||||||
<CheckBox x:Name="checkBox" Grid.Row="4" Content="Show password" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Checked="checkBox_Checked" Unchecked="checkBox_Unchecked"/>
|
<local:TextBoxWithButton x:Name="UrlTextBox" HorizontalAlignment="Left" Text="{Binding Url, Mode=TwoWay}" Height="32" Width="350" MaxLength="256" Style="{StaticResource TextBoxWithButtonStyle}" GotoClick="UrlButton_Click" />
|
||||||
<TextBlock x:Name="urlTextBlock" Grid.Row="5" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="URL" VerticalAlignment="Top" FontSize="18"/>
|
<TextBlock TextWrapping="Wrap" Text="Notes" FontSize="18"/>
|
||||||
<TextBox x:Name="urlTextBox" Grid.Row="6" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="{Binding URL, Mode=TwoWay}" VerticalAlignment="Top" Width="250" FontSize="14,667" MaxLength="256" AllowDrop="True"/>
|
<TextBox HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding Notes, Mode=TwoWay}" Width="350" Height="200" AcceptsReturn="True" IsSpellCheckEnabled="True" />
|
||||||
<TextBlock x:Name="notesTextBlock" Grid.Row="7" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="Notes" VerticalAlignment="Top" FontSize="18"/>
|
<CheckBox FontSize="18" IsChecked="{Binding HasExpirationDate, Mode=TwoWay}" Content="Expiration date"/>
|
||||||
<TextBox x:Name="notesTextBox" Grid.Row="8" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="{Binding Notes, Mode=TwoWay}" VerticalAlignment="Top" Width="250" Height="32" IsSpellCheckEnabled="True" AllowDrop="True"/>
|
<StackPanel Orientation="Horizontal" IsHitTestVisible="{Binding HasExpirationDate}">
|
||||||
</Grid>
|
<SymbolIcon Symbol="Important" Foreground="DarkRed" Visibility="{Binding HasExpired, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||||
|
<ToolTipService.ToolTip>
|
||||||
|
<ToolTip Content="Password has expired" />
|
||||||
|
</ToolTipService.ToolTip>
|
||||||
|
</SymbolIcon>
|
||||||
|
<DatePicker Margin="0,0,20,0" Date="{Binding ExpiryDate, Mode=TwoWay}" />
|
||||||
|
<TimePicker Time="{Binding ExpiryTime, Mode=TwoWay}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
<!-- Bouton Précédent et titre de la page -->
|
<!-- Bouton Précédent et titre de la page -->
|
||||||
<Grid>
|
<Grid Grid.Row="0" Background="{ThemeResource AppBarBackgroundThemeBrush}">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="120"/>
|
<ColumnDefinition Width="60"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="400"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Button x:Name="backButton" Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
|
<Button Grid.Column="0"
|
||||||
Style="{StaticResource NavigationBackButtonNormalStyle}"
|
x:Name="BackButton"
|
||||||
VerticalAlignment="Top"
|
Command="{Binding NavigationHelper.GoBackCommand, ElementName=PageRoot}"
|
||||||
|
Height="40"
|
||||||
|
Width="50"
|
||||||
|
VerticalAlignment="Center"
|
||||||
AutomationProperties.Name="Back"
|
AutomationProperties.Name="Back"
|
||||||
AutomationProperties.AutomationId="BackButton"
|
AutomationProperties.AutomationId="BackButton"
|
||||||
AutomationProperties.ItemType="Navigation Button"/>
|
AutomationProperties.ItemType="Navigation Button"
|
||||||
<TextBlock x:Name="pageTitle" Text="{Binding Title}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1"
|
Style="{StaticResource NoBorderButtonStyle}">
|
||||||
IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40"/>
|
<SymbolIcon Symbol="Back" />
|
||||||
|
</Button>
|
||||||
|
<TextBox
|
||||||
|
Grid.Column="1"
|
||||||
|
x:Name="TitleTextBox"
|
||||||
|
Text="{Binding Name, Mode=TwoWay}"
|
||||||
|
Foreground="{ThemeResource DefaultTextForegroundThemeBrush}"
|
||||||
|
Background="Transparent"
|
||||||
|
IsHitTestVisible="{Binding IsEditMode}"
|
||||||
|
BorderThickness="0"
|
||||||
|
FontSize="24"
|
||||||
|
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>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
@@ -1,18 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Threading.Tasks;
|
||||||
using System.IO;
|
using Windows.UI.Core;
|
||||||
using System.Linq;
|
using Windows.UI.Popups;
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using ModernKeePass.Common;
|
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
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;
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
using ModernKeePass.Common;
|
||||||
using ModernKeePass.ViewModels;
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
// Pour en savoir plus sur le modèle d'élément Page Détail de l'élément, consultez la page http://go.microsoft.com/fwlink/?LinkId=234232
|
// Pour en savoir plus sur le modèle d'élément Page Détail de l'élément, consultez la page http://go.microsoft.com/fwlink/?LinkId=234232
|
||||||
@@ -23,24 +16,23 @@ namespace ModernKeePass.Pages
|
|||||||
/// Page affichant les détails d'un élément au sein d'un groupe, offrant la possibilité de
|
/// Page affichant les détails d'un élément au sein d'un groupe, offrant la possibilité de
|
||||||
/// consulter les autres éléments qui appartiennent au même groupe.
|
/// consulter les autres éléments qui appartiennent au même groupe.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class EntryDetailPage : Page
|
public sealed partial class EntryDetailPage
|
||||||
{
|
{
|
||||||
private NavigationHelper navigationHelper;
|
private NavigationHelper navigationHelper;
|
||||||
|
|
||||||
|
public EntryVm Model => (EntryVm) DataContext;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// NavigationHelper est utilisé sur chaque page pour faciliter la navigation et
|
/// NavigationHelper est utilisé sur chaque page pour faciliter la navigation et
|
||||||
/// gestion de la durée de vie des processus
|
/// gestion de la durée de vie des processus
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public NavigationHelper NavigationHelper
|
public NavigationHelper NavigationHelper => navigationHelper;
|
||||||
{
|
|
||||||
get { return this.navigationHelper; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public EntryDetailPage()
|
public EntryDetailPage()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
this.navigationHelper = new NavigationHelper(this);
|
navigationHelper = new NavigationHelper(this);
|
||||||
this.navigationHelper.LoadState += navigationHelper_LoadState;
|
navigationHelper.LoadState += navigationHelper_LoadState;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -51,17 +43,10 @@ namespace ModernKeePass.Pages
|
|||||||
/// Source de l'événement ; en général <see cref="Common.NavigationHelper"/>
|
/// Source de l'événement ; en général <see cref="Common.NavigationHelper"/>
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="e">Données d'événement qui fournissent le paramètre de navigation transmis à
|
/// <param name="e">Données d'événement qui fournissent le paramètre de navigation transmis à
|
||||||
/// <see cref="Frame.Navigate(Type, Object)"/> lors de la requête initiale de cette page et
|
/// <see cref="Frame.Navigate(Type, object)"/> lors de la requête initiale de cette page et
|
||||||
/// un dictionnaire d'état conservé par cette page durant une session
|
/// un dictionnaire d'état conservé par cette page durant une session
|
||||||
/// antérieure. L'état n'aura pas la valeur Null lors de la première visite de la page.</param>
|
/// antérieure. L'état n'aura pas la valeur Null lors de la première visite de la page.</param>
|
||||||
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
|
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e) {}
|
||||||
{
|
|
||||||
object navigationParameter;
|
|
||||||
if (e.PageState != null && e.PageState.ContainsKey("SelectedItem"))
|
|
||||||
{
|
|
||||||
navigationParameter = e.PageState["SelectedItem"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Inscription de NavigationHelper
|
#region Inscription de NavigationHelper
|
||||||
|
|
||||||
@@ -77,10 +62,8 @@ namespace ModernKeePass.Pages
|
|||||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
{
|
{
|
||||||
navigationHelper.OnNavigatedTo(e);
|
navigationHelper.OnNavigatedTo(e);
|
||||||
if (e.Parameter is EntryVm)
|
if (!(e.Parameter is EntryVm)) return;
|
||||||
{
|
DataContext = (EntryVm)e.Parameter;
|
||||||
DataContext = e.Parameter as EntryVm;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
||||||
@@ -90,16 +73,22 @@ namespace ModernKeePass.Pages
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private void checkBox_Checked(object sender, RoutedEventArgs e)
|
private void DeleteButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
passwordBox.Visibility = Visibility.Collapsed;
|
MessageDialogHelper.ShowDeleteConfirmationDialog("Are you sure you want to delete this entry?", Model, Frame);
|
||||||
passwordTextBox.Visibility = Visibility.Visible;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkBox_Unchecked(object sender, RoutedEventArgs e)
|
private async void UrlButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
passwordBox.Visibility = Visibility.Visible;
|
try
|
||||||
passwordTextBox.Visibility = Visibility.Collapsed;
|
{
|
||||||
|
var uri = new Uri(UrlTextBox.Text);
|
||||||
|
await Windows.System.Launcher.LaunchUriAsync(uri);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// TODO: Show some error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,105 +1,297 @@
|
|||||||
<Page
|
<Page
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="using:ModernKeePass.Pages"
|
|
||||||
xmlns:common="using:ModernKeePass.Common"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:ViewModels="using:ModernKeePass.ViewModels"
|
xmlns:viewModels="using:ModernKeePass.ViewModels"
|
||||||
x:Name="pageRoot"
|
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"
|
x:Class="ModernKeePass.Pages.GroupDetailPage"
|
||||||
mc:Ignorable="d" >
|
mc:Ignorable="d" >
|
||||||
|
<Page.Resources>
|
||||||
|
<SolidColorBrush x:Key="Transparent" Color="Transparent"/>
|
||||||
|
<SolidColorBrush x:Key="SystemColor" Color="{StaticResource SystemColorButtonFaceColor}" />
|
||||||
|
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
|
||||||
|
<converters:TextToFontStyleConverter x:Key="TextToFontStyleConverter"/>
|
||||||
|
</Page.Resources>
|
||||||
<Page.DataContext>
|
<Page.DataContext>
|
||||||
<ViewModels:GroupVm />
|
<viewModels:GroupVm />
|
||||||
</Page.DataContext>
|
</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="Delete" Label="Delete" IsEnabled="{Binding IsNotRoot}" Click="DeleteButton_Click" />
|
||||||
|
</CommandBar>
|
||||||
|
</Page.BottomAppBar>
|
||||||
<Grid>
|
<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>
|
<Grid.ChildrenTransitions>
|
||||||
<TransitionCollection>
|
<TransitionCollection>
|
||||||
<EntranceThemeTransition/>
|
<EntranceThemeTransition/>
|
||||||
</TransitionCollection>
|
</TransitionCollection>
|
||||||
</Grid.ChildrenTransitions>
|
</Grid.ChildrenTransitions>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="140"/>
|
<RowDefinition Height="40"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
<Grid Grid.Row="1">
|
||||||
<Grid.Resources>
|
|
||||||
<CollectionViewSource
|
|
||||||
x:Name="groupsViewSource"
|
|
||||||
Source="{Binding Groups}"/>
|
|
||||||
<CollectionViewSource
|
|
||||||
x:Name="entriesViewSource"
|
|
||||||
Source="{Binding Entries}"/>
|
|
||||||
</Grid.Resources>
|
|
||||||
<!-- Horizontal scrolling grid -->
|
|
||||||
<GridView
|
|
||||||
x:Name="groupsGridView"
|
|
||||||
AutomationProperties.AutomationId="ItemGridView"
|
|
||||||
AutomationProperties.Name="Groups"
|
|
||||||
TabIndex="1"
|
|
||||||
Grid.RowSpan="2"
|
|
||||||
Padding="120,126,120,50"
|
|
||||||
ItemsSource="{Binding Source={StaticResource groupsViewSource}}"
|
|
||||||
IsSwipeEnabled="false"
|
|
||||||
SelectionChanged="groupsGridView_SelectionChanged"
|
|
||||||
SelectedIndex="-1" >
|
|
||||||
<GridView.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<Grid Height="110" Width="480" Margin="10">
|
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="110" Height="110">
|
<ListView
|
||||||
<Image Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
|
Grid.Column="0"
|
||||||
</Border>
|
x:Name="LeftListView"
|
||||||
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">
|
Margin="0,0,0,-10"
|
||||||
<TextBlock Text="{Binding Name}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/>
|
SelectionChanged="groups_SelectionChanged"
|
||||||
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
|
IsSwipeEnabled="false"
|
||||||
<TextBlock Text="{Binding EntryCount}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60"/>
|
IsSynchronizedWithCurrentItem="False"
|
||||||
<TextBlock Text="{Binding GroupCount}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60"/>
|
DataContext="{Binding DataContext, ElementName=PageRoot}"
|
||||||
</StackPanel>
|
RequestedTheme="Dark"
|
||||||
</Grid>
|
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>
|
||||||
</GridView.ItemTemplate>
|
<DataTemplate x:Name="Expanded">
|
||||||
<GridView.Header>
|
<StackPanel Orientation="Horizontal">
|
||||||
<StackPanel Width="480" Margin="0,4,14,0">
|
<SymbolIcon Symbol="{Binding IconSymbol}" Margin="8,0,0,0" />
|
||||||
<ListView x:Name="entriesListView" Height="100" ItemsSource="{Binding Source={StaticResource entriesViewSource}}" Margin="10,0,0,0" SelectionChanged="entriesListView_SelectionChanged">
|
<TextBlock Text="{Binding Name}" FontWeight="{Binding FontWeight}" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="30,0,20,0" FontStyle="{Binding Name, ConverterParameter=Recycle Bin, Converter={StaticResource TextToFontStyleConverter}}" />
|
||||||
<ListView.ItemTemplate>
|
<!--<TextBlock Text="{Binding EntryCount}" HorizontalAlignment="Right" VerticalAlignment="Center" />-->
|
||||||
|
</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>
|
<DataTemplate>
|
||||||
<Grid>
|
<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>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="10,0,0,0"/>
|
<SymbolIcon Grid.Column="0" Symbol="{Binding IconSymbol}" Width="100" Height="100" RenderTransformOrigin="0.5,0.5" Foreground="{ThemeResource ListViewItemSelectedBackgroundThemeBrush}" >
|
||||||
|
<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}" 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}}"/>
|
||||||
|
<!--<Line Visibility="{Binding HasExpired, Converter={StaticResource BooleanToVisibilityConverter}}" Margin="0,-10,0,0" Stretch="Fill" Stroke="{Binding ForegroundColor, ConverterParameter={StaticResource TextBoxForegroundThemeBrush}, Converter={StaticResource ColorToBrushConverter}}" StrokeThickness="1" X1="1" Width="{Binding Name, Converter={StaticResource TextToWidthConverter}, ConverterParameter=7}" HorizontalAlignment="Left" VerticalAlignment="Center" />-->
|
||||||
|
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
|
||||||
|
<!--<TextBlock Text="{Binding EntryCount, ConverterParameter=entry\,entries, Converter={StaticResource PluralizationConverter}}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
|
||||||
|
<TextBlock Text="{Binding GroupCount, ConverterParameter=group\,groups, Converter={StaticResource PluralizationConverter}}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />-->
|
||||||
|
<TextBlock Text="{Binding UserName}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
|
||||||
|
<TextBlock Text="{Binding Url}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
|
||||||
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListView.ItemTemplate>
|
</GridView.Resources>
|
||||||
</ListView>
|
<GridView.ItemsSource>
|
||||||
</StackPanel>
|
<Binding Source="{StaticResource EntriesViewSource}"/>
|
||||||
</GridView.Header>
|
</GridView.ItemsSource>
|
||||||
|
<GridView.DataContext>
|
||||||
|
<viewModels:EntryVm/>
|
||||||
|
</GridView.DataContext>
|
||||||
|
<GridView.ItemTemplateSelector>
|
||||||
|
<templateSelectors:FirstItemDataTemplateSelector
|
||||||
|
FirstItem="{StaticResource GroupFirstItem}"
|
||||||
|
OtherItem="{StaticResource GroupOtherItem}" />
|
||||||
|
</GridView.ItemTemplateSelector>
|
||||||
<GridView.ItemContainerStyle>
|
<GridView.ItemContainerStyle>
|
||||||
<Style TargetType="FrameworkElement">
|
<Style TargetType="FrameworkElement">
|
||||||
<Setter Property="Margin" Value="52,0,0,2"/>
|
<Setter Property="Margin" Value="52,0,0,2"/>
|
||||||
</Style>
|
</Style>
|
||||||
</GridView.ItemContainerStyle>
|
</GridView.ItemContainerStyle>
|
||||||
</GridView>
|
</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 -->
|
<!-- Back button and page title -->
|
||||||
<Grid>
|
<Grid Grid.Row="0" Background="{ThemeResource AppBarBackgroundThemeBrush}">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="120"/>
|
<ColumnDefinition Width="60"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="400"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Button x:Name="backButton" Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
|
<Button Grid.Column="0"
|
||||||
Style="{StaticResource NavigationBackButtonNormalStyle}"
|
x:Name="BackButton"
|
||||||
VerticalAlignment="Top"
|
Command="{Binding NavigationHelper.GoBackCommand, ElementName=PageRoot}"
|
||||||
|
Height="40"
|
||||||
|
Width="50"
|
||||||
|
VerticalAlignment="Center"
|
||||||
AutomationProperties.Name="Back"
|
AutomationProperties.Name="Back"
|
||||||
AutomationProperties.AutomationId="BackButton"
|
AutomationProperties.AutomationId="BackButton"
|
||||||
AutomationProperties.ItemType="Navigation Button"/>
|
AutomationProperties.ItemType="Navigation Button"
|
||||||
<TextBlock x:Name="pageTitle" Text="{Binding Path=Name}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1"
|
Style="{StaticResource NoBorderButtonStyle}">
|
||||||
IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40"/>
|
<SymbolIcon Symbol="Back" />
|
||||||
|
</Button>
|
||||||
|
<TextBox
|
||||||
|
Grid.Column="1"
|
||||||
|
x:Name="TitleTextBox"
|
||||||
|
Text="{Binding Name, Mode=TwoWay}"
|
||||||
|
Foreground="{ThemeResource DefaultTextForegroundThemeBrush}"
|
||||||
|
Background="Transparent"
|
||||||
|
IsHitTestVisible="{Binding IsEditMode}"
|
||||||
|
BorderThickness="0"
|
||||||
|
FontSize="24"
|
||||||
|
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>
|
||||||
|
<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>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
@@ -1,6 +1,14 @@
|
|||||||
using ModernKeePass.Common;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Windows.Storage.Streams;
|
||||||
|
using Windows.UI.Core;
|
||||||
|
using Windows.UI.Popups;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using Windows.UI.Xaml.Navigation;
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
using ModernKeePass.Events;
|
||||||
using ModernKeePass.ViewModels;
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
// The Group Detail Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234229
|
// The Group Detail Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234229
|
||||||
@@ -11,25 +19,20 @@ namespace ModernKeePass.Pages
|
|||||||
/// A page that displays an overview of a single group, including a preview of the items
|
/// A page that displays an overview of a single group, including a preview of the items
|
||||||
/// within the group.
|
/// within the group.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class GroupDetailPage : Page
|
public sealed partial class GroupDetailPage
|
||||||
{
|
{
|
||||||
private NavigationHelper navigationHelper;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// NavigationHelper is used on each page to aid in navigation and
|
/// NavigationHelper is used on each page to aid in navigation and
|
||||||
/// process lifetime management
|
/// process lifetime management
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public NavigationHelper NavigationHelper
|
public NavigationHelper NavigationHelper { get; }
|
||||||
{
|
public GroupVm Model => (GroupVm)DataContext;
|
||||||
get { return navigationHelper; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public GroupDetailPage()
|
public GroupDetailPage()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
navigationHelper = new NavigationHelper(this);
|
NavigationHelper = new NavigationHelper(this);
|
||||||
navigationHelper.LoadState += navigationHelper_LoadState;
|
NavigationHelper.LoadState += navigationHelper_LoadState;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -40,12 +43,10 @@ namespace ModernKeePass.Pages
|
|||||||
/// The source of the event; typically <see cref="Common.NavigationHelper"/>
|
/// The source of the event; typically <see cref="Common.NavigationHelper"/>
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="e">Event data that provides both the navigation parameter passed to
|
/// <param name="e">Event data that provides both the navigation parameter passed to
|
||||||
/// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested and
|
/// <see cref="Frame.Navigate(Type, object)"/> when this page was initially requested and
|
||||||
/// a dictionary of state preserved by this page during an earlier
|
/// a dictionary of state preserved by this page during an earlier
|
||||||
/// session. The state will be null the first time a page is visited.</param>
|
/// session. The state will be null the first time a page is visited.</param>
|
||||||
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
|
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#region NavigationHelper registration
|
#region NavigationHelper registration
|
||||||
|
|
||||||
@@ -60,34 +61,88 @@ namespace ModernKeePass.Pages
|
|||||||
///
|
///
|
||||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
{
|
{
|
||||||
navigationHelper.OnNavigatedTo(e);
|
NavigationHelper.OnNavigatedTo(e);
|
||||||
|
|
||||||
if (e.Parameter is GroupVm)
|
if (e.Parameter is PasswordEventArgs)
|
||||||
{
|
DataContext = ((PasswordEventArgs) e.Parameter).RootGroup;
|
||||||
DataContext = e.Parameter as GroupVm;
|
else if (e.Parameter is GroupVm)
|
||||||
groupsGridView.SelectedIndex = -1;
|
DataContext = (GroupVm) e.Parameter;
|
||||||
entriesListView.SelectedIndex = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
||||||
{
|
{
|
||||||
navigationHelper.OnNavigatedFrom(e);
|
NavigationHelper.OnNavigatedFrom(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private void groupsGridView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
||||||
|
#region Event Handlers
|
||||||
|
|
||||||
|
private void groups_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
var gridView = sender as GridView;
|
GroupVm group;
|
||||||
Frame.Navigate(typeof(GroupDetailPage), gridView.SelectedItem as GroupVm);
|
switch (LeftListView.SelectedIndex)
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
return;
|
||||||
|
case 0:
|
||||||
|
group = Model.CreateNewGroup();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
group = LeftListView.SelectedItem as GroupVm;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Frame.Navigate(typeof(GroupDetailPage), group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void entries_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
private void entriesListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
||||||
{
|
{
|
||||||
var listView = sender as ListView;
|
EntryVm entry;
|
||||||
Frame.Navigate(typeof(EntryDetailPage), listView.SelectedItem as EntryVm);
|
switch (GridView.SelectedIndex)
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
return;
|
||||||
|
case 0:
|
||||||
|
entry = Model.CreateNewEntry();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
entry = GridView.SelectedItem as EntryVm;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Frame.Navigate(typeof(EntryDetailPage), entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeleteButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
MessageDialogHelper.ShowDeleteConfirmationDialog("Are you sure you want to delete the whole group and all its entries?", Model, Frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SemanticZoom_ViewChangeStarted(object sender, SemanticZoomViewChangedEventArgs e)
|
||||||
|
{
|
||||||
|
// We need to synchronize the two lists (zoomed-in and zoomed-out) because the source is different
|
||||||
|
if (e.IsSourceZoomedInView == false)
|
||||||
|
{
|
||||||
|
e.DestinationItem.Item = e.SourceItem.Item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SearchBox_OnSuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args)
|
||||||
|
{
|
||||||
|
var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx://Assets/Logo.scale-80.png"));
|
||||||
|
var results = Model.Entries.Skip(1).Where(e => e.Name.IndexOf(args.QueryText, StringComparison.OrdinalIgnoreCase) >= 0).Take(5);
|
||||||
|
foreach (var result in results)
|
||||||
|
{
|
||||||
|
args.Request.SearchSuggestionCollection.AppendResultSuggestion(result.Name, result.ParentGroup.Name, result.Id, imageUri, string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SearchBox_OnResultSuggestionChosen(SearchBox sender, SearchBoxResultSuggestionChosenEventArgs args)
|
||||||
|
{
|
||||||
|
var entry = Model.Entries.Skip(1).FirstOrDefault(e => e.Id == args.Tag);
|
||||||
|
Frame.Navigate(typeof(EntryDetailPage), entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
159
ModernKeePass/Pages/MainPage.xaml
Normal file
159
ModernKeePass/Pages/MainPage.xaml
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
<basePages:LayoutAwarePageBase
|
||||||
|
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:controls="using:ModernKeePass.Controls"
|
||||||
|
xmlns:basePages="using:ModernKeePass.Pages.BasePages"
|
||||||
|
x:Class="ModernKeePass.Pages.MainPage"
|
||||||
|
x:Name="PageRoot"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
<Page.Resources>
|
||||||
|
<CollectionViewSource
|
||||||
|
x:Name="MenuItemsSource"
|
||||||
|
Source="{Binding MainMenuItems}"
|
||||||
|
IsSourceGrouped="True" />
|
||||||
|
</Page.Resources>
|
||||||
|
|
||||||
|
<Page.Background>
|
||||||
|
<StaticResource ResourceKey="ApplicationPageBackgroundThemeBrush"/>
|
||||||
|
</Page.Background>
|
||||||
|
<Page.DataContext>
|
||||||
|
<viewModels:MainVm />
|
||||||
|
</Page.DataContext>
|
||||||
|
|
||||||
|
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
<Grid.ChildrenTransitions>
|
||||||
|
<TransitionCollection>
|
||||||
|
<EntranceThemeTransition/>
|
||||||
|
</TransitionCollection>
|
||||||
|
</Grid.ChildrenTransitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="40"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition x:Name="PrimaryColumn" Width="250" />
|
||||||
|
<ColumnDefinition x:Name="SecondaryColumn" Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<!-- Back button and page title -->
|
||||||
|
<Grid x:Name="TitlePanel" Background="{ThemeResource AppBarBackgroundThemeBrush}">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Button x:Name="BackButton"
|
||||||
|
Command="{Binding NavigationHelper.GoBackCommand, ElementName=PageRoot}"
|
||||||
|
Visibility="Collapsed"
|
||||||
|
Height="40"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
AutomationProperties.Name="Back"
|
||||||
|
AutomationProperties.AutomationId="BackButton"
|
||||||
|
AutomationProperties.ItemType="Navigation Button"
|
||||||
|
Style="{StaticResource NoBorderButtonStyle}">
|
||||||
|
<SymbolIcon Symbol="Back" />
|
||||||
|
</Button>
|
||||||
|
<TextBlock x:Name="TitleTextBox" Text="{Binding Name}" Grid.Column="1" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||||
|
</Grid>
|
||||||
|
<controls:ListViewWithDisable
|
||||||
|
Grid.Column="0"
|
||||||
|
Grid.Row="1"
|
||||||
|
x:Name="MenuListView"
|
||||||
|
SelectionChanged="MenuListView_SelectionChanged"
|
||||||
|
Background="{ThemeResource AppBarBackgroundThemeBrush}"
|
||||||
|
ItemsSource="{Binding Source={StaticResource MenuItemsSource}}"
|
||||||
|
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
|
||||||
|
IsSynchronizedWithCurrentItem="False"
|
||||||
|
ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}">
|
||||||
|
<controls:ListViewWithDisable.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<SymbolIcon Symbol="{Binding SymbolIcon}" />
|
||||||
|
<TextBlock Text="{Binding Title}" Margin="10,5,0,0" />
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</controls:ListViewWithDisable.ItemTemplate>
|
||||||
|
<controls:ListViewWithDisable.GroupStyle>
|
||||||
|
<GroupStyle HidesIfEmpty="True">
|
||||||
|
<GroupStyle.HeaderTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid Background="DarkGray" Margin="20,0,0,0">
|
||||||
|
<Border Height="1" Width="300" HorizontalAlignment="Stretch"/>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</GroupStyle.HeaderTemplate>
|
||||||
|
</GroupStyle>
|
||||||
|
</controls:ListViewWithDisable.GroupStyle>
|
||||||
|
</controls:ListViewWithDisable>
|
||||||
|
<TextBlock x:Name="PageTitleTextBlock" Grid.Column="1" Grid.Row="0" FontSize="24" VerticalAlignment="Center" Margin="10,0,0,0" >
|
||||||
|
<Run Text="{Binding SelectedItem}" />
|
||||||
|
</TextBlock>
|
||||||
|
<Frame x:Name="MenuFrame" Grid.Column="1" Grid.Row="1" Margin="0,10,0,0" />
|
||||||
|
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<!-- Visual states reflect the application's view state -->
|
||||||
|
<VisualStateGroup x:Name="ViewStates">
|
||||||
|
<VisualState x:Name="PrimaryView" />
|
||||||
|
<VisualState x:Name="SinglePane">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PrimaryColumn" Storyboard.TargetProperty="Width">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="*"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SecondaryColumn" Storyboard.TargetProperty="Width">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MenuFrame" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PageTitleTextBlock" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MenuListView" Storyboard.TargetProperty="Padding">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="120,0,90,60"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<!--
|
||||||
|
When an item is selected and only one pane is shown the details display requires more extensive changes:
|
||||||
|
* Hide the master list and the column it was in
|
||||||
|
* Move item details down a row to make room for the title
|
||||||
|
* Move the title directly above the details
|
||||||
|
* Adjust padding for details
|
||||||
|
-->
|
||||||
|
<VisualState x:Name="SinglePane_Detail">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PrimaryColumn" Storyboard.TargetProperty="Width">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MenuListView" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MenuFrame" Storyboard.TargetProperty="(Grid.Row)">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MenuFrame" Storyboard.TargetProperty="(Grid.RowSpan)">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>-->
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TitlePanel" Storyboard.TargetProperty="(Grid.Column)">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackButton" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TitleTextBox" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PageTitleTextBlock" Storyboard.TargetProperty="Margin">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="60,0,0,0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MenuFrame" Storyboard.TargetProperty="Margin">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="10,0,0,0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>-->
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
</Grid>
|
||||||
|
</basePages:LayoutAwarePageBase>
|
37
ModernKeePass/Pages/MainPage.xaml.cs
Normal file
37
ModernKeePass/Pages/MainPage.xaml.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
|
||||||
|
|
||||||
|
namespace ModernKeePass.Pages
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class MainPage
|
||||||
|
{
|
||||||
|
public new MainVm Model => (MainVm)DataContext;
|
||||||
|
|
||||||
|
public MainPage()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
ListView = MenuListView;
|
||||||
|
ListViewSource = MenuItemsSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MenuListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
ListView_SelectionChanged(sender, e);
|
||||||
|
var selectedItem = Model.SelectedItem as MainMenuItemVm;
|
||||||
|
selectedItem?.Destination.Navigate(selectedItem.PageType, selectedItem.Parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnNavigatedTo(e);
|
||||||
|
DataContext = new MainVm(Frame, MenuFrame);
|
||||||
|
if (Model.SelectedItem == null) MenuFrame.Navigate(typeof(WelcomePage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
ModernKeePass/Pages/MainPageFrames/AboutPage.xaml
Normal file
38
ModernKeePass/Pages/MainPageFrames/AboutPage.xaml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<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"
|
||||||
|
x:Class="ModernKeePass.Pages.AboutPage"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<Page.DataContext>
|
||||||
|
<viewModels:AboutVm/>
|
||||||
|
</Page.DataContext>
|
||||||
|
|
||||||
|
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="10,0,0,0">
|
||||||
|
<Run Text="{Binding Name}"/>
|
||||||
|
<Run Text="version"/>
|
||||||
|
<Run Text="{Binding Version}" />
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="30,0,0,0">
|
||||||
|
<Run Text="A modern password manager for the Windows Store"/>
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="30,0,0,0">
|
||||||
|
<Run Text="Homepage: "/>
|
||||||
|
<Hyperlink NavigateUri="https://github.com/wismna/ModernKeePass">
|
||||||
|
<Run Text="https://github.com/wismna/ModernKeePass"/>
|
||||||
|
</Hyperlink></TextBlock>
|
||||||
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="10,0,0,0">
|
||||||
|
<Run Text="Credits:"/>
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="30,0,0,0">
|
||||||
|
<Run Text="Dominik Reichl for the KeePass application and file format"/>
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="30,0,0,0">
|
||||||
|
<Run Text="ArtjomP for his PCL adapatation of the KeePass Library"/>
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</Page>
|
15
ModernKeePass/Pages/MainPageFrames/AboutPage.xaml.cs
Normal file
15
ModernKeePass/Pages/MainPageFrames/AboutPage.xaml.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// 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 AboutPage
|
||||||
|
{
|
||||||
|
public AboutPage()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
ModernKeePass/Pages/MainPageFrames/NewDatabasePage.xaml
Normal file
39
ModernKeePass/Pages/MainPageFrames/NewDatabasePage.xaml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<Page
|
||||||
|
x:Class="ModernKeePass.Pages.NewDatabasePage"
|
||||||
|
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:local="using:ModernKeePass.Controls"
|
||||||
|
xmlns:converters="using:ModernKeePass.Converters"
|
||||||
|
xmlns:viewModels="using:ModernKeePass.ViewModels"
|
||||||
|
xmlns:interactivity="using:Microsoft.Xaml.Interactivity" xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
<Page.Resources>
|
||||||
|
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||||
|
<converters:ProgressBarLegalValuesConverter x:Key="ProgressBarLegalValuesConverter"/>
|
||||||
|
<converters:DoubleToForegroungBrushComplexityConverter x:Key="DoubleToForegroungBrushComplexityConverter"/>
|
||||||
|
</Page.Resources>
|
||||||
|
<Page.DataContext>
|
||||||
|
<viewModels:NewVm />
|
||||||
|
</Page.DataContext>
|
||||||
|
|
||||||
|
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
<HyperlinkButton Content="Create new..." Click="ButtonBase_OnClick" />
|
||||||
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">Create a new password database to the location of your chosing.</TextBlock>
|
||||||
|
<Border HorizontalAlignment="Left" BorderThickness="1" BorderBrush="AliceBlue" Width="550" Visibility="{Binding ShowPasswordBox, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||||
|
<StackPanel Margin="25,0,25,0">
|
||||||
|
<TextBlock Text="{Binding Name}" />
|
||||||
|
<local:OpenDatabaseUserControl Password="{Binding Password, Mode=TwoWay}" CreateNew="True" >
|
||||||
|
<interactivity:Interaction.Behaviors>
|
||||||
|
<Core:EventTriggerBehavior EventName="ValidationChecked">
|
||||||
|
<Core:NavigateToPageAction TargetPage="ModernKeePass.Pages.GroupDetailPage" />
|
||||||
|
</Core:EventTriggerBehavior>
|
||||||
|
</interactivity:Interaction.Behaviors>
|
||||||
|
</local:OpenDatabaseUserControl>
|
||||||
|
<TextBlock >Password complexity</TextBlock>
|
||||||
|
<ProgressBar Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}" Maximum="128" Width="500" HorizontalAlignment="Left" Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroungBrushComplexityConverter}}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
</Page>
|
48
ModernKeePass/Pages/MainPageFrames/NewDatabasePage.xaml.cs
Normal file
48
ModernKeePass/Pages/MainPageFrames/NewDatabasePage.xaml.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Windows.Storage.Pickers;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
using ModernKeePass.Events;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
// 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 NewDatabasePage
|
||||||
|
{
|
||||||
|
private Frame _mainFrame;
|
||||||
|
|
||||||
|
public NewVm Model => (NewVm)DataContext;
|
||||||
|
|
||||||
|
public NewDatabasePage()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnNavigatedTo(e);
|
||||||
|
_mainFrame = e.Parameter as Frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var savePicker = new FileSavePicker
|
||||||
|
{
|
||||||
|
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
|
||||||
|
SuggestedFileName = "New Database"
|
||||||
|
};
|
||||||
|
savePicker.FileTypeChoices.Add("KeePass 2.x database", new List<string> { ".kdbx" });
|
||||||
|
|
||||||
|
var file = await savePicker.PickSaveFileAsync();
|
||||||
|
if (file == null) return;
|
||||||
|
Model.OpenFile(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
ModernKeePass/Pages/MainPageFrames/OpenDatabasePage.xaml
Normal file
37
ModernKeePass/Pages/MainPageFrames/OpenDatabasePage.xaml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<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.OpenDatabasePage"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
<Page.Resources>
|
||||||
|
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||||
|
</Page.Resources>
|
||||||
|
<Page.DataContext>
|
||||||
|
<viewModels:OpenVm/>
|
||||||
|
</Page.DataContext>
|
||||||
|
|
||||||
|
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
<HyperlinkButton Content="Browse files..." Click="ButtonBase_OnClick" />
|
||||||
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">Open an existing password database from your PC.</TextBlock>
|
||||||
|
<HyperlinkButton Content="From Url..." IsEnabled="False" />
|
||||||
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">Open an existing password database from an Internet location (not yet implemented).</TextBlock>
|
||||||
|
<Border HorizontalAlignment="Left" BorderThickness="1" BorderBrush="AliceBlue" Width="550" Visibility="{Binding ShowPasswordBox, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||||
|
<StackPanel Margin="25,0,25,0">
|
||||||
|
<TextBlock Text="{Binding Name}" />
|
||||||
|
<local:OpenDatabaseUserControl>
|
||||||
|
<interactivity:Interaction.Behaviors>
|
||||||
|
<Core:EventTriggerBehavior EventName="ValidationChecked">
|
||||||
|
<Core:NavigateToPageAction TargetPage="ModernKeePass.Pages.GroupDetailPage" />
|
||||||
|
</Core:EventTriggerBehavior>
|
||||||
|
</interactivity:Interaction.Behaviors>
|
||||||
|
</local:OpenDatabaseUserControl>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
</Page>
|
49
ModernKeePass/Pages/MainPageFrames/OpenDatabasePage.xaml.cs
Normal file
49
ModernKeePass/Pages/MainPageFrames/OpenDatabasePage.xaml.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.Storage.Pickers;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
using ModernKeePass.Events;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
// 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 OpenDatabasePage
|
||||||
|
{
|
||||||
|
private Frame _mainFrame;
|
||||||
|
|
||||||
|
public OpenVm Model => (OpenVm)DataContext;
|
||||||
|
|
||||||
|
public OpenDatabasePage()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnNavigatedTo(e);
|
||||||
|
_mainFrame = e.Parameter as Frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var picker =
|
||||||
|
new FileOpenPicker
|
||||||
|
{
|
||||||
|
ViewMode = PickerViewMode.List,
|
||||||
|
SuggestedStartLocation = PickerLocationId.DocumentsLibrary
|
||||||
|
};
|
||||||
|
picker.FileTypeFilter.Add(".kdbx");
|
||||||
|
|
||||||
|
// Application now has read/write access to the picked file
|
||||||
|
var file = await picker.PickSingleFileAsync();
|
||||||
|
if (file == null) return;
|
||||||
|
Model.OpenFile(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
ModernKeePass/Pages/MainPageFrames/RecentDatabasesPage.xaml
Normal file
47
ModernKeePass/Pages/MainPageFrames/RecentDatabasesPage.xaml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<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:OpenDatabaseUserControl 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:OpenDatabaseUserControl>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.ItemTemplate>
|
||||||
|
</ListView>
|
||||||
|
</Page>
|
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
// Pour en savoir plus sur le modèle d'élément Page vierge, consultez la page http://go.microsoft.com/fwlink/?LinkId=234238
|
||||||
|
|
||||||
|
namespace ModernKeePass.Pages
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Une page vide peut être utilisée seule ou constituer une page de destination au sein d'un frame.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class RecentDatabasesPage
|
||||||
|
{
|
||||||
|
private Frame _mainFrame;
|
||||||
|
|
||||||
|
public RecentVm Model => (RecentVm)DataContext;
|
||||||
|
|
||||||
|
public RecentDatabasesPage()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnNavigatedTo(e);
|
||||||
|
_mainFrame = e.Parameter as Frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OpenDatabaseUserControl_OnValidationChecking(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
app.Database.DatabaseFile = Model.SelectedItem.DatabaseFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
ModernKeePass/Pages/MainPageFrames/SaveDatabasePage.xaml
Normal file
19
ModernKeePass/Pages/MainPageFrames/SaveDatabasePage.xaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<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"
|
||||||
|
x:Class="ModernKeePass.Pages.SaveDatabasePage"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
<Page.DataContext>
|
||||||
|
<viewModels:SaveVm/>
|
||||||
|
</Page.DataContext>
|
||||||
|
|
||||||
|
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
<HyperlinkButton Content="Save and close" Click="SaveButton_OnClick" />
|
||||||
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">This will save and close the currently opened database.</TextBlock>
|
||||||
|
<HyperlinkButton Content="Save as..." Click="SaveAsButton_OnClick" />
|
||||||
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">This will save the currently opened database as a new file and leave it open.</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</Page>
|
53
ModernKeePass/Pages/MainPageFrames/SaveDatabasePage.xaml.cs
Normal file
53
ModernKeePass/Pages/MainPageFrames/SaveDatabasePage.xaml.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Windows.Storage.Pickers;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
|
||||||
|
|
||||||
|
namespace ModernKeePass.Pages
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class SaveDatabasePage
|
||||||
|
{
|
||||||
|
private Frame _mainFrame;
|
||||||
|
public SaveVm Model => (SaveVm)DataContext;
|
||||||
|
public SaveDatabasePage()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnNavigatedTo(e);
|
||||||
|
_mainFrame = e.Parameter as Frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveButton_OnClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Model.Save();
|
||||||
|
_mainFrame.Navigate(typeof(MainPage));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void SaveAsButton_OnClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var savePicker = new FileSavePicker
|
||||||
|
{
|
||||||
|
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
|
||||||
|
SuggestedFileName = "New Database"
|
||||||
|
};
|
||||||
|
savePicker.FileTypeChoices.Add("KeePass 2.x database", new List<string> { ".kdbx" });
|
||||||
|
|
||||||
|
var file = await savePicker.PickSaveFileAsync();
|
||||||
|
if (file == null) return;
|
||||||
|
Model.Save(file);
|
||||||
|
|
||||||
|
_mainFrame.Navigate(typeof(MainPage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
ModernKeePass/Pages/MainPageFrames/WelcomePage.xaml
Normal file
19
ModernKeePass/Pages/MainPageFrames/WelcomePage.xaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<Page
|
||||||
|
x:Class="ModernKeePass.Pages.WelcomePage"
|
||||||
|
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"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
<StackPanel Orientation="Horizontal" Margin="0,2,0,10">
|
||||||
|
<SymbolIcon Symbol="Back" Margin="0,7,40,0" />
|
||||||
|
<TextBlock Style="{StaticResource SubheaderTextBlockStyle}">Have an existing password database? Open it here.</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal" Margin="0,6,0,10">
|
||||||
|
<SymbolIcon Symbol="Back" Margin="0,7,40,0" />
|
||||||
|
<TextBlock Style="{StaticResource SubheaderTextBlockStyle}">Want to create a new password database? Do it here.</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</Page>
|
30
ModernKeePass/Pages/MainPageFrames/WelcomePage.xaml.cs
Normal file
30
ModernKeePass/Pages/MainPageFrames/WelcomePage.xaml.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
181
ModernKeePass/Pages/SettingsPage.xaml
Normal file
181
ModernKeePass/Pages/SettingsPage.xaml
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
<Page
|
||||||
|
x:Name="pageRoot"
|
||||||
|
x:Class="ModernKeePass.Pages.SettingsPage"
|
||||||
|
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:ModernKeePass.Pages"
|
||||||
|
xmlns:common="using:ModernKeePass.Common"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<Page.Resources>
|
||||||
|
<!-- Collection of items displayed by this page -->
|
||||||
|
<CollectionViewSource
|
||||||
|
x:Name="itemsViewSource"
|
||||||
|
Source="{Binding Items}"/>
|
||||||
|
</Page.Resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This grid acts as a root panel for the page that defines two rows:
|
||||||
|
* Row 0 contains the back button and page title
|
||||||
|
* Row 1 contains the rest of the page layout
|
||||||
|
-->
|
||||||
|
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
<Grid.ChildrenTransitions>
|
||||||
|
<TransitionCollection>
|
||||||
|
<EntranceThemeTransition/>
|
||||||
|
</TransitionCollection>
|
||||||
|
</Grid.ChildrenTransitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="140"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition x:Name="primaryColumn" Width="420"/>
|
||||||
|
<ColumnDefinition x:Name="secondaryColumn" Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<!-- Back button and page title -->
|
||||||
|
<Grid x:Name="titlePanel">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="120"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Button x:Name="backButton" Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
|
||||||
|
Style="{StaticResource NavigationBackButtonNormalStyle}"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
AutomationProperties.Name="Back"
|
||||||
|
AutomationProperties.AutomationId="BackButton"
|
||||||
|
AutomationProperties.ItemType="Navigation Button"/>
|
||||||
|
<TextBlock x:Name="pageTitle" Text="{Binding Title}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1"
|
||||||
|
IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,0,40"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Vertical scrolling item list -->
|
||||||
|
<ListView
|
||||||
|
x:Name="itemListView"
|
||||||
|
AutomationProperties.AutomationId="ItemsListView"
|
||||||
|
AutomationProperties.Name="Items"
|
||||||
|
TabIndex="1"
|
||||||
|
Grid.Row="1"
|
||||||
|
Margin="-10,-10,0,0"
|
||||||
|
Padding="120,0,0,60"
|
||||||
|
ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
|
||||||
|
IsSwipeEnabled="False"
|
||||||
|
SelectionChanged="ItemListView_SelectionChanged">
|
||||||
|
<ListView.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid Margin="6">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="60" Height="60">
|
||||||
|
<Image Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
|
||||||
|
</Border>
|
||||||
|
<StackPanel Grid.Column="1" Margin="10,0,0,0">
|
||||||
|
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" MaxHeight="40"/>
|
||||||
|
<TextBlock Text="{Binding Subtitle}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.ItemTemplate>
|
||||||
|
<ListView.ItemContainerStyle>
|
||||||
|
<Style TargetType="FrameworkElement">
|
||||||
|
<Setter Property="Margin" Value="0,0,0,10"/>
|
||||||
|
</Style>
|
||||||
|
</ListView.ItemContainerStyle>
|
||||||
|
</ListView>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Details for selected item -->
|
||||||
|
<ScrollViewer
|
||||||
|
x:Name="itemDetail"
|
||||||
|
AutomationProperties.AutomationId="ItemDetailScrollViewer"
|
||||||
|
Grid.Column="1"
|
||||||
|
Grid.RowSpan="2"
|
||||||
|
Padding="60,0,66,0"
|
||||||
|
DataContext="{Binding SelectedItem, ElementName=itemListView}"
|
||||||
|
HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"
|
||||||
|
ScrollViewer.HorizontalScrollMode="Disabled" ScrollViewer.VerticalScrollMode="Enabled"
|
||||||
|
ScrollViewer.ZoomMode="Disabled">
|
||||||
|
|
||||||
|
<Grid x:Name="itemDetailGrid" Margin="0,60,0,50">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Image Grid.Row="1" Margin="0,0,20,0" Width="180" Height="180" Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
|
||||||
|
<StackPanel x:Name="itemDetailTitlePanel" Grid.Row="1" Grid.Column="1">
|
||||||
|
<TextBlock x:Name="itemTitle" Margin="0,-10,0,0" Text="{Binding Title}" Style="{StaticResource SubheaderTextBlockStyle}"/>
|
||||||
|
<TextBlock x:Name="itemSubtitle" Margin="0,0,0,20" Text="{Binding Subtitle}" Style="{StaticResource SubtitleTextBlockStyle}"/>
|
||||||
|
</StackPanel>
|
||||||
|
<TextBlock Grid.Row="2" Grid.ColumnSpan="2" Margin="0,20,0,0" Text="{Binding Content}" Style="{StaticResource BodyTextBlockStyle}"/>
|
||||||
|
</Grid>
|
||||||
|
</ScrollViewer>
|
||||||
|
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
|
||||||
|
<!-- Visual states reflect the application's view state -->
|
||||||
|
<VisualStateGroup x:Name="ViewStates">
|
||||||
|
<VisualState x:Name="PrimaryView" />
|
||||||
|
<VisualState x:Name="SinglePane">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="primaryColumn" Storyboard.TargetProperty="Width">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="*"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="secondaryColumn" Storyboard.TargetProperty="Width">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="Padding">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="120,0,90,60"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<!--
|
||||||
|
When an item is selected and only one pane is shown the details display requires more extensive changes:
|
||||||
|
* Hide the master list and the column it was in
|
||||||
|
* Move item details down a row to make room for the title
|
||||||
|
* Move the title directly above the details
|
||||||
|
* Adjust padding for details
|
||||||
|
-->
|
||||||
|
<VisualState x:Name="SinglePane_Detail">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="primaryColumn" Storyboard.TargetProperty="Width">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="(Grid.Row)">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="(Grid.RowSpan)">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="titlePanel" Storyboard.TargetProperty="(Grid.Column)">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetailGrid" Storyboard.TargetProperty="Margin">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,60"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="Padding">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="120,0,90,0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
</Grid>
|
||||||
|
</Page>
|
255
ModernKeePass/Pages/SettingsPage.xaml.cs
Normal file
255
ModernKeePass/Pages/SettingsPage.xaml.cs
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
using ModernKeePass.Common;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices.WindowsRuntime;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.Foundation.Collections;
|
||||||
|
using Windows.UI.ViewManagement;
|
||||||
|
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 Split Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234234
|
||||||
|
|
||||||
|
namespace ModernKeePass.Pages
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A page that displays a group title, a list of items within the group, and details for
|
||||||
|
/// the currently selected item.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class SettingsPage : Page
|
||||||
|
{
|
||||||
|
private NavigationHelper navigationHelper;
|
||||||
|
private ObservableDictionary defaultViewModel = new ObservableDictionary();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This can be changed to a strongly typed view model.
|
||||||
|
/// </summary>
|
||||||
|
public ObservableDictionary DefaultViewModel
|
||||||
|
{
|
||||||
|
get { return this.defaultViewModel; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// NavigationHelper is used on each page to aid in navigation and
|
||||||
|
/// process lifetime management
|
||||||
|
/// </summary>
|
||||||
|
public NavigationHelper NavigationHelper
|
||||||
|
{
|
||||||
|
get { return this.navigationHelper; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public SettingsPage()
|
||||||
|
{
|
||||||
|
this.InitializeComponent();
|
||||||
|
|
||||||
|
// Setup the navigation helper
|
||||||
|
this.navigationHelper = new NavigationHelper(this);
|
||||||
|
this.navigationHelper.LoadState += navigationHelper_LoadState;
|
||||||
|
this.navigationHelper.SaveState += navigationHelper_SaveState;
|
||||||
|
|
||||||
|
// Setup the logical page navigation components that allow
|
||||||
|
// the page to only show one pane at a time.
|
||||||
|
this.navigationHelper.GoBackCommand = new ModernKeePass.Common.RelayCommand(() => this.GoBack(), () => this.CanGoBack());
|
||||||
|
this.itemListView.SelectionChanged += itemListView_SelectionChanged;
|
||||||
|
|
||||||
|
// Start listening for Window size changes
|
||||||
|
// to change from showing two panes to showing a single pane
|
||||||
|
Window.Current.SizeChanged += Window_SizeChanged;
|
||||||
|
this.InvalidateVisualState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void itemListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (this.UsingLogicalPageNavigation())
|
||||||
|
{
|
||||||
|
this.navigationHelper.GoBackCommand.RaiseCanExecuteChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Populates the page with content passed during navigation. Any saved state is also
|
||||||
|
/// provided when recreating a page from a prior session.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">
|
||||||
|
/// The source of the event; typically <see cref="Common.NavigationHelper"/>
|
||||||
|
/// </param>
|
||||||
|
/// <param name="e">Event data that provides both the navigation parameter passed to
|
||||||
|
/// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested and
|
||||||
|
/// a dictionary of state preserved by this page during an earlier
|
||||||
|
/// session. The state will be null the first time a page is visited.</param>
|
||||||
|
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
|
||||||
|
{
|
||||||
|
// TODO: Assign a bindable group to Me.DefaultViewModel("Group")
|
||||||
|
// TODO: Assign a collection of bindable items to Me.DefaultViewModel("Items")
|
||||||
|
|
||||||
|
if (e.PageState == null)
|
||||||
|
{
|
||||||
|
// When this is a new page, select the first item automatically unless logical page
|
||||||
|
// navigation is being used (see the logical page navigation #region below.)
|
||||||
|
if (!this.UsingLogicalPageNavigation() && this.itemsViewSource.View != null)
|
||||||
|
{
|
||||||
|
this.itemsViewSource.View.MoveCurrentToFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Restore the previously saved state associated with this page
|
||||||
|
if (e.PageState.ContainsKey("SelectedItem") && this.itemsViewSource.View != null)
|
||||||
|
{
|
||||||
|
// TODO: Invoke Me.itemsViewSource.View.MoveCurrentTo() with the selected
|
||||||
|
// item as specified by the value of pageState("SelectedItem")
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Preserves state associated with this page in case the application is suspended or the
|
||||||
|
/// page is discarded from the navigation cache. Values must conform to the serialization
|
||||||
|
/// requirements of <see cref="Common.SuspensionManager.SessionState"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The source of the event; typically <see cref="Common.NavigationHelper"/></param>
|
||||||
|
/// <param name="e">Event data that provides an empty dictionary to be populated with
|
||||||
|
/// serializable state.</param>
|
||||||
|
private void navigationHelper_SaveState(object sender, SaveStateEventArgs e)
|
||||||
|
{
|
||||||
|
if (this.itemsViewSource.View != null)
|
||||||
|
{
|
||||||
|
// TODO: Derive a serializable navigation parameter and assign it to
|
||||||
|
// pageState("SelectedItem")
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Logical page navigation
|
||||||
|
|
||||||
|
// The split page is designed so that when the Window does have enough space to show
|
||||||
|
// both the list and the details, only one pane will be shown at at time.
|
||||||
|
//
|
||||||
|
// This is all implemented with a single physical page that can represent two logical
|
||||||
|
// pages. The code below achieves this goal without making the user aware of the
|
||||||
|
// distinction.
|
||||||
|
|
||||||
|
private const int MinimumWidthForSupportingTwoPanes = 768;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked to determine whether the page should act as one logical page or two.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if the window should show act as one logical page, false
|
||||||
|
/// otherwise.</returns>
|
||||||
|
private bool UsingLogicalPageNavigation()
|
||||||
|
{
|
||||||
|
return Window.Current.Bounds.Width < MinimumWidthForSupportingTwoPanes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked with the Window changes size
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The current Window</param>
|
||||||
|
/// <param name="e">Event data that describes the new size of the Window</param>
|
||||||
|
private void Window_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
|
||||||
|
{
|
||||||
|
this.InvalidateVisualState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when an item within the list is selected.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The GridView displaying the selected item.</param>
|
||||||
|
/// <param name="e">Event data that describes how the selection was changed.</param>
|
||||||
|
private void ItemListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
// Invalidate the view state when logical page navigation is in effect, as a change
|
||||||
|
// in selection may cause a corresponding change in the current logical page. When
|
||||||
|
// an item is selected this has the effect of changing from displaying the item list
|
||||||
|
// to showing the selected item's details. When the selection is cleared this has the
|
||||||
|
// opposite effect.
|
||||||
|
if (this.UsingLogicalPageNavigation()) this.InvalidateVisualState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CanGoBack()
|
||||||
|
{
|
||||||
|
if (this.UsingLogicalPageNavigation() && this.itemListView.SelectedItem != null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return this.navigationHelper.CanGoBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void GoBack()
|
||||||
|
{
|
||||||
|
if (this.UsingLogicalPageNavigation() && this.itemListView.SelectedItem != null)
|
||||||
|
{
|
||||||
|
// When logical page navigation is in effect and there's a selected item that
|
||||||
|
// item's details are currently displayed. Clearing the selection will return to
|
||||||
|
// the item list. From the user's point of view this is a logical backward
|
||||||
|
// navigation.
|
||||||
|
this.itemListView.SelectedItem = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.navigationHelper.GoBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InvalidateVisualState()
|
||||||
|
{
|
||||||
|
var visualState = DetermineVisualState();
|
||||||
|
VisualStateManager.GoToState(this, visualState, false);
|
||||||
|
this.navigationHelper.GoBackCommand.RaiseCanExecuteChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked to determine the name of the visual state that corresponds to an application
|
||||||
|
/// view state.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The name of the desired visual state. This is the same as the name of the
|
||||||
|
/// view state except when there is a selected item in portrait and snapped views where
|
||||||
|
/// this additional logical page is represented by adding a suffix of _Detail.</returns>
|
||||||
|
private string DetermineVisualState()
|
||||||
|
{
|
||||||
|
if (!UsingLogicalPageNavigation())
|
||||||
|
return "PrimaryView";
|
||||||
|
|
||||||
|
// Update the back button's enabled state when the view state changes
|
||||||
|
var logicalPageBack = this.UsingLogicalPageNavigation() && this.itemListView.SelectedItem != null;
|
||||||
|
|
||||||
|
return logicalPageBack ? "SinglePane_Detail" : "SinglePane";
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region NavigationHelper registration
|
||||||
|
|
||||||
|
/// The methods provided in this section are simply used to allow
|
||||||
|
/// NavigationHelper to respond to the page's navigation methods.
|
||||||
|
///
|
||||||
|
/// Page specific logic should be placed in event handlers for the
|
||||||
|
/// <see cref="Common.NavigationHelper.LoadState"/>
|
||||||
|
/// and <see cref="Common.NavigationHelper.SaveState"/>.
|
||||||
|
/// The navigation parameter is available in the LoadState method
|
||||||
|
/// in addition to page state preserved during an earlier session.
|
||||||
|
|
||||||
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
navigationHelper.OnNavigatedTo(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
navigationHelper.OnNavigatedFrom(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@@ -6,9 +6,9 @@ using System.Runtime.InteropServices;
|
|||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
[assembly: AssemblyTitle("ModernKeePass")]
|
[assembly: AssemblyTitle("ModernKeePass")]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription("A port of KeePass 2.x to Modern UI as a Windows Store application")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("wismna")]
|
||||||
[assembly: AssemblyProduct("ModernKeePass")]
|
[assembly: AssemblyProduct("ModernKeePass")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2017")]
|
[assembly: AssemblyCopyright("Copyright © 2017")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
@@ -24,6 +24,6 @@ using System.Runtime.InteropServices;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
[assembly: AssemblyVersion("1.5.0.0")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
[assembly: AssemblyFileVersion("1.5.0.0")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
47
ModernKeePass/Styles/HamburgerButtonStyle.xaml
Normal file
47
ModernKeePass/Styles/HamburgerButtonStyle.xaml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<ResourceDictionary
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
|
||||||
|
<Style TargetType="ToggleButton" x:Name="HamburgerToggleButton">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="ToggleButton">
|
||||||
|
<ContentControl>
|
||||||
|
<Grid Background="{StaticResource ListViewItemSelectedBackgroundThemeBrush}" Margin="0" Width="50" Height="50">
|
||||||
|
<Canvas x:Name="hampurger_menu" HorizontalAlignment="Center" Height="17" UseLayoutRounding="False" VerticalAlignment="Center" Width="28">
|
||||||
|
<Canvas x:Name="Layer_1" Height="17" Canvas.Left="0" Width="28" Margin="0" RenderTransformOrigin="0.5,0.5">
|
||||||
|
<Canvas.RenderTransform>
|
||||||
|
<CompositeTransform/>
|
||||||
|
</Canvas.RenderTransform>
|
||||||
|
<Canvas.Projection>
|
||||||
|
<PlaneProjection/>
|
||||||
|
</Canvas.Projection>
|
||||||
|
<Path x:Name="path" Data="M0,12.997 L30,12.997" Height="3" Stretch="Fill" StrokeThickness="3" Width="28" Stroke="{ThemeResource DefaultTextForegroundThemeBrush}" StrokeStartLineCap="Square" StrokeEndLineCap="Square" RenderTransformOrigin="0.5,0.5">
|
||||||
|
<Path.RenderTransform>
|
||||||
|
<CompositeTransform/>
|
||||||
|
</Path.RenderTransform>
|
||||||
|
</Path>
|
||||||
|
<Path Data="M0,12.997 L30,12.997" Height="3" Stretch="Fill" StrokeThickness="3" Width="28" Stroke="{ThemeResource DefaultTextForegroundThemeBrush}" StrokeStartLineCap="Square" StrokeEndLineCap="Square" Canvas.Top="7"/>
|
||||||
|
<Path x:Name="path1" Data="M0,12.997 L30,12.997" Height="3" Stretch="Fill" StrokeThickness="3" Width="28" Stroke="{ThemeResource DefaultTextForegroundThemeBrush}" StrokeStartLineCap="Square" StrokeEndLineCap="Square" Canvas.Top="14" RenderTransformOrigin="0.5,0.5">
|
||||||
|
<Path.RenderTransform>
|
||||||
|
<CompositeTransform/>
|
||||||
|
</Path.RenderTransform>
|
||||||
|
</Path>
|
||||||
|
</Canvas>
|
||||||
|
</Canvas>
|
||||||
|
</Grid>
|
||||||
|
</ContentControl>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
<Setter Property="VerticalAlignment" Value="Top" />
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||||
|
<Setter Property="Margin" Value="0" />
|
||||||
|
</Style>
|
||||||
|
<Style x:Key="HeaderTextBoxStyle" TargetType="TextBox">
|
||||||
|
<Setter Property="FontSize" Value="40"/>
|
||||||
|
<Setter Property="FontWeight" Value="Light"/>
|
||||||
|
<Setter Property="BorderBrush" Value="Transparent" />
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
</Style>
|
||||||
|
</ResourceDictionary>
|
401
ModernKeePass/Styles/ListViewLeftIndicatorStyle.xaml
Normal file
401
ModernKeePass/Styles/ListViewLeftIndicatorStyle.xaml
Normal file
@@ -0,0 +1,401 @@
|
|||||||
|
<ResourceDictionary
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||||
|
xmlns:core="using:Microsoft.Xaml.Interactions.Core">
|
||||||
|
|
||||||
|
<!-- Style for Windows.UI.Xaml.Controls.ListViewItem with left selection indicator -->
|
||||||
|
<Style TargetType="ListViewItem" x:Key="ListViewLeftIndicatorItemExpanded">
|
||||||
|
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||||
|
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
|
||||||
|
<Setter Property="Background" Value="Transparent"/>
|
||||||
|
<Setter Property="TabNavigation" Value="Local"/>
|
||||||
|
<Setter Property="IsHoldingEnabled" Value="True"/>
|
||||||
|
<Setter Property="Margin" Value="0"/>
|
||||||
|
<Setter Property="Padding" Value="10,0,0,0"/>
|
||||||
|
<Setter Property="HorizontalContentAlignment" Value="Left"/>
|
||||||
|
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="ListViewItem">
|
||||||
|
<Border x:Name="OuterContainer">
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal"/>
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="PointerOverBorder"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="1" />
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SelectedEarmark"
|
||||||
|
Storyboard.TargetProperty="Fill">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListViewItemSelectedPointerOverBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Pressed">
|
||||||
|
<Storyboard>
|
||||||
|
<PointerDownThemeAnimation TargetName="ContentContainer" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="PointerOverPressed">
|
||||||
|
<Storyboard>
|
||||||
|
<PointerDownThemeAnimation TargetName="ContentContainer" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="PointerOverBorder"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="1" />
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SelectedEarmark"
|
||||||
|
Storyboard.TargetProperty="Fill">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListViewItemSelectedPointerOverBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="contentPresenter"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource ListViewItemDisabledThemeOpacity}" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="FocusStates">
|
||||||
|
<VisualState x:Name="Focused">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisual" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Unfocused"/>
|
||||||
|
<VisualState x:Name="PointerFocused"/>
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="SelectionHintStates">
|
||||||
|
<VisualState x:Name="VerticalSelectionHint">
|
||||||
|
<Storyboard>
|
||||||
|
<SwipeHintThemeAnimation TargetName="ContentBorder" ToVerticalOffset="15" ToHorizontalOffset="0" />
|
||||||
|
<SwipeHintThemeAnimation TargetName="SelectedLeftIndicator" ToVerticalOffset="15" ToHorizontalOffset="0" />
|
||||||
|
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="HintGlyph"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0:0:0.500">
|
||||||
|
<DiscreteDoubleKeyFrame Value="0.5" KeyTime="0:0:0" />
|
||||||
|
<DiscreteDoubleKeyFrame Value="0" KeyTime="0:0:0.500" />
|
||||||
|
</DoubleAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="HorizontalSelectionHint">
|
||||||
|
<Storyboard>
|
||||||
|
<SwipeHintThemeAnimation TargetName="ContentBorder" ToHorizontalOffset="-23" ToVerticalOffset="0" />
|
||||||
|
<SwipeHintThemeAnimation TargetName="SelectedLeftIndicator" ToHorizontalOffset="-23" ToVerticalOffset="0" />
|
||||||
|
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="HintGlyph"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0:0:0.500">
|
||||||
|
<DiscreteDoubleKeyFrame Value="0.5" KeyTime="0:0:0" />
|
||||||
|
<DiscreteDoubleKeyFrame Value="0" KeyTime="0:0:0.500" />
|
||||||
|
</DoubleAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="NoSelectionHint" />
|
||||||
|
<VisualStateGroup.Transitions>
|
||||||
|
<VisualTransition To="NoSelectionHint" GeneratedDuration="0:0:0.65"/>
|
||||||
|
</VisualStateGroup.Transitions>
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="SelectionStates">
|
||||||
|
<VisualState x:Name="Unselecting">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="HintGlyphBorder"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="1" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Unselected">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="HintGlyphBorder"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="1" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="UnselectedPointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="HintGlyphBorder"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="1" />
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="contentPresenter"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListViewItemSelectedForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="UnselectedSwiping">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="SelectingGlyph"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="0.5" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="HintGlyphBorder"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="1" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Selecting">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="SelectedLeftIndicator"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="1" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="SelectingGlyph"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="1" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="HintGlyphBorder"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="1" />
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="contentPresenter"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListViewItemSelectedForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Selected">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="SelectedLeftIndicator"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="1" />
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="contentPresenter"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListViewItemSelectedForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="SelectedSwiping">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="SelectedLeftIndicator"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="1" />
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="contentPresenter"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListViewItemSelectedForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="SelectedUnfocused">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="SelectedLeftIndicator"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="1" />
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="contentPresenter"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListViewItemSelectedForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="DragStates">
|
||||||
|
<VisualState x:Name="NotDragging" />
|
||||||
|
<VisualState x:Name="Dragging">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="InnerDragContent"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource ListViewItemDragThemeOpacity}" />
|
||||||
|
<DragItemThemeAnimation TargetName="InnerDragContent" />
|
||||||
|
<FadeOutThemeAnimation TargetName="SelectedLeftIndicator" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="DraggingTarget">
|
||||||
|
<Storyboard>
|
||||||
|
<DropTargetItemThemeAnimation TargetName="OuterContainer" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="MultipleDraggingPrimary">
|
||||||
|
<Storyboard>
|
||||||
|
<!-- These two Opacity animations are required - the FadeInThemeAnimations
|
||||||
|
on the same elements animate an internal Opacity. -->
|
||||||
|
<DoubleAnimation Storyboard.TargetName="MultiArrangeOverlayBackground"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="1" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="MultiArrangeOverlayText"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="1" />
|
||||||
|
|
||||||
|
<DoubleAnimation Storyboard.TargetName="ContentBorder"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource ListViewItemDragThemeOpacity}" />
|
||||||
|
<FadeInThemeAnimation TargetName="MultiArrangeOverlayBackground" />
|
||||||
|
<FadeInThemeAnimation TargetName="MultiArrangeOverlayText" />
|
||||||
|
<DragItemThemeAnimation TargetName="ContentBorder" />
|
||||||
|
<FadeOutThemeAnimation TargetName="SelectedLeftIndicator" />
|
||||||
|
<FadeOutThemeAnimation TargetName="PointerOverBorder" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="MultipleDraggingSecondary">
|
||||||
|
<Storyboard>
|
||||||
|
<FadeOutThemeAnimation TargetName="ContentContainer" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualStateGroup.Transitions>
|
||||||
|
<VisualTransition To="NotDragging" GeneratedDuration="0:0:0.2"/>
|
||||||
|
</VisualStateGroup.Transitions>
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="ReorderHintStates">
|
||||||
|
<VisualState x:Name="NoReorderHint"/>
|
||||||
|
<VisualState x:Name="BottomReorderHint">
|
||||||
|
<Storyboard>
|
||||||
|
<DragOverThemeAnimation TargetName="ReorderHintContent" ToOffset="{ThemeResource ListViewItemReorderHintThemeOffset}" Direction="Bottom" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="TopReorderHint">
|
||||||
|
<Storyboard>
|
||||||
|
<DragOverThemeAnimation TargetName="ReorderHintContent" ToOffset="{ThemeResource ListViewItemReorderHintThemeOffset}" Direction="Top" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="RightReorderHint">
|
||||||
|
<Storyboard>
|
||||||
|
<DragOverThemeAnimation TargetName="ReorderHintContent" ToOffset="{ThemeResource ListViewItemReorderHintThemeOffset}" Direction="Right" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="LeftReorderHint">
|
||||||
|
<Storyboard>
|
||||||
|
<DragOverThemeAnimation TargetName="ReorderHintContent" ToOffset="{ThemeResource ListViewItemReorderHintThemeOffset}" Direction="Left" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualStateGroup.Transitions>
|
||||||
|
<VisualTransition To="NoReorderHint" GeneratedDuration="0:0:0.2"/>
|
||||||
|
</VisualStateGroup.Transitions>
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="DataVirtualizationStates">
|
||||||
|
<VisualState x:Name="DataAvailable"/>
|
||||||
|
<VisualState x:Name="DataPlaceholder">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextBlock"
|
||||||
|
Storyboard.TargetProperty="Visibility"
|
||||||
|
Duration="0">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0">
|
||||||
|
<DiscreteObjectKeyFrame.Value>
|
||||||
|
<Visibility>Visible</Visibility>
|
||||||
|
</DiscreteObjectKeyFrame.Value>
|
||||||
|
</DiscreteObjectKeyFrame>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderRect"
|
||||||
|
Storyboard.TargetProperty="Visibility"
|
||||||
|
Duration="0">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0">
|
||||||
|
<DiscreteObjectKeyFrame.Value>
|
||||||
|
<Visibility>Visible</Visibility>
|
||||||
|
</DiscreteObjectKeyFrame.Value>
|
||||||
|
</DiscreteObjectKeyFrame>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
<Grid x:Name="ReorderHintContent" Background="Transparent">
|
||||||
|
<Path x:Name="SelectingGlyph" Opacity="0" Data="F1 M133.1,17.9 L137.2,13.2 L144.6,19.6 L156.4,5.8 L161.2,9.9 L145.6,28.4 z" Fill="{ThemeResource ListViewItemCheckSelectingThemeBrush}" Height="13" Stretch="Fill" Width="15" HorizontalAlignment="Right" Margin="0,9.5,9.5,0" VerticalAlignment="Top" FlowDirection="LeftToRight"/>
|
||||||
|
<Border x:Name="HintGlyphBorder"
|
||||||
|
Height="40"
|
||||||
|
Width="40"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
Opacity="0"
|
||||||
|
Margin="4">
|
||||||
|
<Path x:Name="HintGlyph" Opacity="0" Data="F1 M133.1,17.9 L137.2,13.2 L144.6,19.6 L156.4,5.8 L161.2,9.9 L145.6,28.4 z" Fill="{ThemeResource ListViewItemCheckHintThemeBrush}" Height="13" Stretch="Fill" Width="15" HorizontalAlignment="Right" Margin="0,5.5,5.5,0" VerticalAlignment="Top" FlowDirection="LeftToRight"/>
|
||||||
|
</Border>
|
||||||
|
<Border x:Name="ContentContainer">
|
||||||
|
<Grid x:Name="InnerDragContent">
|
||||||
|
<Rectangle x:Name="PointerOverBorder"
|
||||||
|
IsHitTestVisible="False"
|
||||||
|
Opacity="0"
|
||||||
|
Fill="{ThemeResource ListViewItemPointerOverBackgroundThemeBrush}"
|
||||||
|
Margin="0" />
|
||||||
|
<Rectangle x:Name="FocusVisual"
|
||||||
|
IsHitTestVisible="False"
|
||||||
|
Opacity="0"
|
||||||
|
StrokeThickness="2"
|
||||||
|
Stroke="{ThemeResource ListViewItemFocusBorderThemeBrush}" />
|
||||||
|
<Rectangle x:Name="SelectionBackground"
|
||||||
|
Margin="0"
|
||||||
|
Fill="{ThemeResource ListViewItemSelectedBackgroundThemeBrush}"
|
||||||
|
Opacity="0" />
|
||||||
|
<Border x:Name="ContentBorder"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
Margin="0">
|
||||||
|
<Grid>
|
||||||
|
<ContentPresenter x:Name="contentPresenter"
|
||||||
|
ContentTransitions="{TemplateBinding ContentTransitions}"
|
||||||
|
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||||
|
Content="{TemplateBinding Content}"
|
||||||
|
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||||
|
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||||
|
Margin="{TemplateBinding Padding}" />
|
||||||
|
<!-- The 'Xg' text simulates the amount of space one line of text will occupy.
|
||||||
|
In the DataPlaceholder state, the Content is not loaded yet so we
|
||||||
|
approximate the size of the item using placeholder text. -->
|
||||||
|
<TextBlock x:Name="PlaceholderTextBlock"
|
||||||
|
Opacity="0"
|
||||||
|
Text="Xg"
|
||||||
|
Foreground="{x:Null}"
|
||||||
|
Margin="{TemplateBinding Padding}"
|
||||||
|
IsHitTestVisible="False"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"/>
|
||||||
|
<Rectangle x:Name="PlaceholderRect"
|
||||||
|
Visibility="Collapsed"
|
||||||
|
Fill="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}"/>
|
||||||
|
<Rectangle x:Name="MultiArrangeOverlayBackground"
|
||||||
|
IsHitTestVisible="False"
|
||||||
|
Opacity="0"
|
||||||
|
Fill="{ThemeResource ListViewItemDragBackgroundThemeBrush}" />
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
<Border x:Name="SelectedLeftIndicator"
|
||||||
|
BorderBrush="{ThemeResource ListViewItemSelectedBackgroundThemeBrush}"
|
||||||
|
BorderThickness="5,0,0,0"
|
||||||
|
Opacity="0"/>
|
||||||
|
<Rectangle x:Name="SelectedBorder"
|
||||||
|
IsHitTestVisible="False"
|
||||||
|
Opacity="0"
|
||||||
|
Stroke="{ThemeResource ListViewItemSelectedBackgroundThemeBrush}"
|
||||||
|
StrokeThickness="{ThemeResource ListViewItemSelectedBorderThemeThickness}"
|
||||||
|
Margin="0" />
|
||||||
|
<Border x:Name="SelectedCheckMarkOuter"
|
||||||
|
IsHitTestVisible="False"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
Margin="4">
|
||||||
|
<Grid x:Name="SelectedCheckMark" Opacity="0" Height="40" Width="40">
|
||||||
|
<Path x:Name="SelectedEarmark" Data="M0,0 L40,0 L40,40 z" Fill="{ThemeResource ListViewItemSelectedBackgroundThemeBrush}" Stretch="Fill"/>
|
||||||
|
<Path Data="F1 M133.1,17.9 L137.2,13.2 L144.6,19.6 L156.4,5.8 L161.2,9.9 L145.6,28.4 z" Fill="{ThemeResource ListViewItemCheckThemeBrush}" Height="13" Stretch="Fill" Width="15" HorizontalAlignment="Right" Margin="0,5.5,5.5,0" VerticalAlignment="Top" FlowDirection="LeftToRight"/>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
<TextBlock x:Name="MultiArrangeOverlayText"
|
||||||
|
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DragItemsCount}"
|
||||||
|
Foreground="{ThemeResource ListViewItemDragForegroundThemeBrush}"
|
||||||
|
FontFamily="{ThemeResource ContentControlThemeFontFamily}"
|
||||||
|
FontSize="26.667"
|
||||||
|
IsHitTestVisible="False"
|
||||||
|
Opacity="0"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
TextTrimming="WordEllipsis"
|
||||||
|
Margin="18,9,0,0"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"/>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</ResourceDictionary>
|
116
ModernKeePass/Styles/NoBorderButtonStyle.xaml
Normal file
116
ModernKeePass/Styles/NoBorderButtonStyle.xaml
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
<ResourceDictionary
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:ModernKeePass.Styles">
|
||||||
|
<!-- Default style for Windows.UI.Xaml.Controls.Button -->
|
||||||
|
<Style TargetType="Button" x:Key="NoBorderButtonStyle">
|
||||||
|
<Setter Property="Background" Value="{ThemeResource ButtonBackgroundThemeBrush}" />
|
||||||
|
<Setter Property="Foreground" Value="{ThemeResource ButtonForegroundThemeBrush}"/>
|
||||||
|
<Setter Property="BorderBrush" Value="{ThemeResource ButtonBorderThemeBrush}" />
|
||||||
|
<Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
|
||||||
|
<Setter Property="Padding" Value="12,4,12,4" />
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||||
|
<Setter Property="VerticalAlignment" Value="Center" />
|
||||||
|
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||||
|
<Setter Property="FontWeight" Value="SemiBold" />
|
||||||
|
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Grid>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPointerOverBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPointerOverForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Pressed">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPressedBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPressedForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonDisabledBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonDisabledBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonDisabledForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="FocusStates">
|
||||||
|
<VisualState x:Name="Focused">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="FocusVisualWhite"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="1"
|
||||||
|
Duration="0" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="FocusVisualBlack"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="1"
|
||||||
|
Duration="0" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Unfocused" />
|
||||||
|
<VisualState x:Name="PointerFocused" />
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
<Border x:Name="Border"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
Margin="0">
|
||||||
|
<ContentPresenter x:Name="ContentPresenter"
|
||||||
|
Content="{TemplateBinding Content}"
|
||||||
|
ContentTransitions="{TemplateBinding ContentTransitions}"
|
||||||
|
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||||
|
Margin="{TemplateBinding Padding}"
|
||||||
|
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||||
|
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"/>
|
||||||
|
</Border>
|
||||||
|
<Rectangle x:Name="FocusVisualWhite"
|
||||||
|
IsHitTestVisible="False"
|
||||||
|
Stroke="{ThemeResource FocusVisualWhiteStrokeThemeBrush}"
|
||||||
|
StrokeEndLineCap="Square"
|
||||||
|
StrokeDashArray="1,1"
|
||||||
|
Opacity="0"
|
||||||
|
StrokeDashOffset="1.5" />
|
||||||
|
<Rectangle x:Name="FocusVisualBlack"
|
||||||
|
IsHitTestVisible="False"
|
||||||
|
Stroke="{ThemeResource FocusVisualBlackStrokeThemeBrush}"
|
||||||
|
StrokeEndLineCap="Square"
|
||||||
|
StrokeDashArray="1,1"
|
||||||
|
Opacity="0"
|
||||||
|
StrokeDashOffset="0.5" />
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
</ResourceDictionary>
|
229
ModernKeePass/Styles/TextBoxWithButtonStyle.xaml
Normal file
229
ModernKeePass/Styles/TextBoxWithButtonStyle.xaml
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
<ResourceDictionary
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
|
||||||
|
<Style TargetType="TextBox" x:Name="TextBoxWithButtonStyle">
|
||||||
|
<Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
|
||||||
|
<Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
|
||||||
|
<Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}" />
|
||||||
|
<Setter Property="Background" Value="{ThemeResource TextBoxBackgroundThemeBrush}" />
|
||||||
|
<Setter Property="BorderBrush" Value="{ThemeResource TextBoxBorderThemeBrush}" />
|
||||||
|
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextSelectionHighlightColorThemeBrush}" />
|
||||||
|
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
|
||||||
|
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||||
|
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
|
||||||
|
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
|
||||||
|
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
|
||||||
|
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
|
||||||
|
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="TextBox">
|
||||||
|
<Grid>
|
||||||
|
<Grid.Resources>
|
||||||
|
<Style x:Name="GotoButtonStyle" TargetType="Button">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Grid>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Pressed">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
<Border x:Name="BorderElement"
|
||||||
|
BorderBrush="{ThemeResource TextBoxButtonBorderThemeBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"/>
|
||||||
|
<Border x:Name="BackgroundElement"
|
||||||
|
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=""
|
||||||
|
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"/>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</Grid.Resources>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Normal">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlBackgroundThemeOpacity}" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlBorderThemeOpacity}" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlPointerOverBackgroundThemeOpacity}" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlPointerOverBorderThemeOpacity}" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Focused" />
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="ButtonStates">
|
||||||
|
<VisualState x:Name="ButtonVisible">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GotoButton"
|
||||||
|
Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0">
|
||||||
|
<DiscreteObjectKeyFrame.Value>
|
||||||
|
<Visibility>Visible</Visibility>
|
||||||
|
</DiscreteObjectKeyFrame.Value>
|
||||||
|
</DiscreteObjectKeyFrame>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="ButtonCollapsed" />
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Border x:Name="BackgroundElement"
|
||||||
|
Grid.Row="1"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
Grid.RowSpan="1"/>
|
||||||
|
<Border x:Name="BorderElement"
|
||||||
|
Grid.Row="1"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
Grid.RowSpan="1"/>
|
||||||
|
<ContentPresenter x:Name="HeaderContentPresenter"
|
||||||
|
Grid.Row="0"
|
||||||
|
Foreground="{ThemeResource TextBoxForegroundHeaderThemeBrush}"
|
||||||
|
Margin="0,4,0,4"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
Content="{TemplateBinding Header}"
|
||||||
|
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||||
|
FontWeight="Semilight" />
|
||||||
|
<ScrollViewer x:Name="ContentElement"
|
||||||
|
Grid.Row="1"
|
||||||
|
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
|
||||||
|
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
|
||||||
|
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
|
||||||
|
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
|
||||||
|
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
|
||||||
|
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
|
||||||
|
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}"
|
||||||
|
Padding="{TemplateBinding Padding}"
|
||||||
|
IsTabStop="False"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"
|
||||||
|
ZoomMode="Disabled" />
|
||||||
|
<ContentControl x:Name="PlaceholderTextContentPresenter"
|
||||||
|
Grid.Row="1"
|
||||||
|
Foreground="{ThemeResource TextBoxPlaceholderTextThemeBrush}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}"
|
||||||
|
Padding="{TemplateBinding Padding}"
|
||||||
|
IsTabStop="False"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
Content="{TemplateBinding PlaceholderText}"
|
||||||
|
IsHitTestVisible="False"/>
|
||||||
|
<Button x:Name="GotoButton"
|
||||||
|
Grid.Row="1"
|
||||||
|
Style="{StaticResource GotoButtonStyle}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
IsTabStop="False"
|
||||||
|
Grid.Column="1"
|
||||||
|
Visibility="Collapsed"
|
||||||
|
FontSize="{TemplateBinding FontSize}"
|
||||||
|
VerticalAlignment="Stretch"/>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</ResourceDictionary>
|
@@ -0,0 +1,18 @@
|
|||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
|
||||||
|
namespace ModernKeePass.TemplateSelectors
|
||||||
|
{
|
||||||
|
public class FirstItemDataTemplateSelector: DataTemplateSelector
|
||||||
|
{
|
||||||
|
public DataTemplate FirstItem { get; set; }
|
||||||
|
public DataTemplate OtherItem { get; set; }
|
||||||
|
|
||||||
|
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
|
||||||
|
{
|
||||||
|
var itemsControl = ItemsControl.ItemsControlFromItemContainer(container);
|
||||||
|
var returnTemplate = itemsControl.IndexFromContainer(container) == 0 ? FirstItem : OtherItem;
|
||||||
|
return returnTemplate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
ModernKeePass/ViewModels/AboutVm.cs
Normal file
20
ModernKeePass/ViewModels/AboutVm.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using Windows.ApplicationModel;
|
||||||
|
|
||||||
|
namespace ModernKeePass.ViewModels
|
||||||
|
{
|
||||||
|
public class AboutVm
|
||||||
|
{
|
||||||
|
public string Name { get; } = Package.Current.DisplayName;
|
||||||
|
|
||||||
|
public string Version
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var package = Package.Current;
|
||||||
|
var version = package.Id.Version;
|
||||||
|
|
||||||
|
return $"{version.Major}.{version.Minor}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,69 +0,0 @@
|
|||||||
using System.ComponentModel;
|
|
||||||
using Windows.Storage;
|
|
||||||
|
|
||||||
using ModernKeePassLib;
|
|
||||||
using ModernKeePassLib.Keys;
|
|
||||||
using ModernKeePassLib.Serialization;
|
|
||||||
using ModernKeePassLib.Interfaces;
|
|
||||||
using Windows.UI.Xaml;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace ModernKeePass.ViewModels
|
|
||||||
{
|
|
||||||
public class DatabaseVm : INotifyPropertyChanged
|
|
||||||
{
|
|
||||||
private PwDatabase database = new PwDatabase();
|
|
||||||
private StorageFile databaseFile;
|
|
||||||
|
|
||||||
public string Password { get; set; }
|
|
||||||
public bool IsOpen { get; set; }
|
|
||||||
public Visibility Visibility { get; private set; }
|
|
||||||
public string ErrorMessage { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public GroupVm RootGroup { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
public DatabaseVm()
|
|
||||||
{
|
|
||||||
Visibility = Visibility.Collapsed;
|
|
||||||
}
|
|
||||||
public DatabaseVm(StorageFile databaseFile)
|
|
||||||
{
|
|
||||||
this.databaseFile = databaseFile;
|
|
||||||
Visibility = Visibility.Visible;
|
|
||||||
}
|
|
||||||
public async void Open()
|
|
||||||
{
|
|
||||||
var key = new CompositeKey();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
key.AddUserKey(new KcpPassword(Password));
|
|
||||||
await database.Open(IOConnectionInfo.FromFile(databaseFile), key, new NullStatusLogger());
|
|
||||||
IsOpen = database.IsOpen;
|
|
||||||
Name = databaseFile.DisplayName;
|
|
||||||
RootGroup = new GroupVm (database.RootGroup);
|
|
||||||
}
|
|
||||||
catch (ArgumentNullException)
|
|
||||||
{
|
|
||||||
ErrorMessage = "Password cannot be empty";
|
|
||||||
NotifyPropertyChanged("ErrorMessage");
|
|
||||||
}
|
|
||||||
catch (InvalidCompositeKeyException)
|
|
||||||
{
|
|
||||||
ErrorMessage = "Wrong password";
|
|
||||||
NotifyPropertyChanged("ErrorMessage");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
// TODO: move this when implementing write mode
|
|
||||||
database.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
|
||||||
public void NotifyPropertyChanged(string propertyName)
|
|
||||||
{
|
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,26 +1,204 @@
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using ModernKeePass.Interfaces;
|
||||||
|
using ModernKeePass.Mappings;
|
||||||
using ModernKeePassLib;
|
using ModernKeePassLib;
|
||||||
|
using ModernKeePassLib.Cryptography.PasswordGenerator;
|
||||||
|
using ModernKeePassLib.Security;
|
||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using ModernKeePassLib.Cryptography;
|
||||||
|
|
||||||
namespace ModernKeePass.ViewModels
|
namespace ModernKeePass.ViewModels
|
||||||
{
|
{
|
||||||
public class EntryVm : INotifyPropertyChanged
|
public class EntryVm : INotifyPropertyChanged, IPwEntity
|
||||||
{
|
{
|
||||||
public string Title { get; private set; }
|
public GroupVm ParentGroup { get; }
|
||||||
public string UserName { get; private set; }
|
public PwEntry Entry { get; }
|
||||||
public string Password { get; private set; }
|
|
||||||
public string URL { get; private set; }
|
|
||||||
public string Notes { get; private set; }
|
|
||||||
|
|
||||||
public EntryVm() { }
|
public System.Drawing.Color? BackgroundColor => Entry?.BackgroundColor;
|
||||||
public EntryVm(PwEntry entry)
|
public System.Drawing.Color? ForegroundColor => Entry?.ForegroundColor;
|
||||||
|
public bool IsRevealPasswordEnabled => !string.IsNullOrEmpty(Password);
|
||||||
|
public bool HasExpired => HasExpirationDate && Entry.ExpiryTime < DateTime.Now;
|
||||||
|
public double PasswordComplexityIndicator => QualityEstimation.EstimatePasswordBits(Password.ToCharArray());
|
||||||
|
|
||||||
|
public double PasswordLength { get; set; } = 25;
|
||||||
|
public bool UpperCasePatternSelected { get; set; } = true;
|
||||||
|
public bool LowerCasePatternSelected { get; set; } = true;
|
||||||
|
public bool DigitsPatternSelected { get; set; } = true;
|
||||||
|
public bool MinusPatternSelected { get; set; }
|
||||||
|
public bool UnderscorePatternSelected { get; set; }
|
||||||
|
public bool SpacePatternSelected { get; set; }
|
||||||
|
public bool SpecialPatternSelected { get; set; }
|
||||||
|
public bool BracketsPatternSelected { get; set; }
|
||||||
|
public string CustomChars { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public string Name
|
||||||
{
|
{
|
||||||
Title = entry.Strings.GetSafe(PwDefs.TitleField).ReadString();
|
get
|
||||||
UserName = entry.Strings.GetSafe(PwDefs.UserNameField).ReadString();
|
{
|
||||||
Password = entry.Strings.GetSafe(PwDefs.PasswordField).ReadString();
|
var title = GetEntryValue(PwDefs.TitleField);
|
||||||
URL = entry.Strings.GetSafe(PwDefs.UrlField).ReadString();
|
return title == null ? "New entry" : title;
|
||||||
Notes = entry.Strings.GetSafe(PwDefs.NotesField).ReadString();
|
}
|
||||||
|
set { SetEntryValue(PwDefs.TitleField, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Id => Entry.Uuid.ToHexString();
|
||||||
|
|
||||||
|
public string UserName
|
||||||
|
{
|
||||||
|
get { return GetEntryValue(PwDefs.UserNameField); }
|
||||||
|
set { SetEntryValue(PwDefs.UserNameField, value); }
|
||||||
|
}
|
||||||
|
public string Password
|
||||||
|
{
|
||||||
|
get { return GetEntryValue(PwDefs.PasswordField); }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetEntryValue(PwDefs.PasswordField, value);
|
||||||
|
NotifyPropertyChanged("Password");
|
||||||
|
NotifyPropertyChanged("PasswordComplexityIndicator");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string Url
|
||||||
|
{
|
||||||
|
get { return GetEntryValue(PwDefs.UrlField); }
|
||||||
|
set { SetEntryValue(PwDefs.UrlField, value); }
|
||||||
|
}
|
||||||
|
public string Notes
|
||||||
|
{
|
||||||
|
get { return GetEntryValue(PwDefs.NotesField); }
|
||||||
|
set { SetEntryValue(PwDefs.NotesField, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Symbol IconSymbol
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Entry == null) return Symbol.Add;
|
||||||
|
if (HasExpired) return Symbol.Priority;
|
||||||
|
var result = PwIconToSegoeMapping.GetSymbolFromIcon(Entry.IconId);
|
||||||
|
return result == Symbol.More ? Symbol.Permissions : result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTimeOffset ExpiryDate
|
||||||
|
{
|
||||||
|
get { return new DateTimeOffset(Entry.ExpiryTime.Date); }
|
||||||
|
set { if (HasExpirationDate) Entry.ExpiryTime = value.DateTime; }
|
||||||
|
}
|
||||||
|
public TimeSpan ExpiryTime
|
||||||
|
{
|
||||||
|
get { return Entry.ExpiryTime.TimeOfDay; }
|
||||||
|
set { if (HasExpirationDate) Entry.ExpiryTime = Entry.ExpiryTime.Date.Add(value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsEditMode
|
||||||
|
{
|
||||||
|
get { return _isEditMode; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isEditMode = value;
|
||||||
|
NotifyPropertyChanged("IsEditMode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsRevealPassword
|
||||||
|
{
|
||||||
|
get { return _isRevealPassword; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isRevealPassword = value;
|
||||||
|
NotifyPropertyChanged("IsRevealPassword");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public bool HasExpirationDate
|
||||||
|
{
|
||||||
|
get { return Entry.Expires; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Entry.Expires = value;
|
||||||
|
NotifyPropertyChanged("HasExpirationDate");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
private bool _isEditMode;
|
||||||
|
private bool _isRevealPassword;
|
||||||
|
|
||||||
|
private void NotifyPropertyChanged(string propertyName)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntryVm() { }
|
||||||
|
public EntryVm(PwEntry entry, GroupVm parent)
|
||||||
|
{
|
||||||
|
Entry = entry;
|
||||||
|
ParentGroup = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void GeneratePassword()
|
||||||
|
{
|
||||||
|
var pwProfile = new PwProfile()
|
||||||
|
{
|
||||||
|
GeneratorType = PasswordGeneratorType.CharSet,
|
||||||
|
Length = (uint)PasswordLength,
|
||||||
|
CharSet = new PwCharSet()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (UpperCasePatternSelected) pwProfile.CharSet.Add(PwCharSet.UpperCase);
|
||||||
|
if (LowerCasePatternSelected) pwProfile.CharSet.Add(PwCharSet.LowerCase);
|
||||||
|
if (DigitsPatternSelected) pwProfile.CharSet.Add(PwCharSet.Digits);
|
||||||
|
if (SpecialPatternSelected) pwProfile.CharSet.Add(PwCharSet.SpecialChars);
|
||||||
|
if (MinusPatternSelected) pwProfile.CharSet.Add('-');
|
||||||
|
if (UnderscorePatternSelected) pwProfile.CharSet.Add('_');
|
||||||
|
if (SpacePatternSelected) pwProfile.CharSet.Add(' ');
|
||||||
|
if (BracketsPatternSelected) pwProfile.CharSet.Add(PwCharSet.Brackets);
|
||||||
|
|
||||||
|
pwProfile.CharSet.Add(CustomChars);
|
||||||
|
|
||||||
|
ProtectedString password;
|
||||||
|
PwGenerator.Generate(out password, pwProfile, null, new CustomPwGeneratorPool());
|
||||||
|
|
||||||
|
Entry?.Strings.Set(PwDefs.PasswordField, password);
|
||||||
|
NotifyPropertyChanged("Password");
|
||||||
|
NotifyPropertyChanged("IsRevealPasswordEnabled");
|
||||||
|
NotifyPropertyChanged("PasswordComplexityIndicator");
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetEntryValue(string key)
|
||||||
|
{
|
||||||
|
return Entry?.Strings.GetSafe(key).ReadString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetEntryValue(string key, string newValue)
|
||||||
|
{
|
||||||
|
Entry?.Strings.Set(key, new ProtectedString(true, newValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MarkForDelete()
|
||||||
|
{
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
app.PendingDeleteEntities.Add(Id, this);
|
||||||
|
ParentGroup.Entries.Remove(this);
|
||||||
|
}
|
||||||
|
public void CommitDelete()
|
||||||
|
{
|
||||||
|
Entry.ParentGroup.Entries.Remove(Entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UndoDelete()
|
||||||
|
{
|
||||||
|
ParentGroup.Entries.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
app.Database.Save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,50 +1,117 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Windows.UI.Text;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
using ModernKeePass.Interfaces;
|
||||||
|
using ModernKeePass.Mappings;
|
||||||
using ModernKeePassLib;
|
using ModernKeePassLib;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace ModernKeePass.ViewModels
|
namespace ModernKeePass.ViewModels
|
||||||
{
|
{
|
||||||
public class GroupVm : INotifyPropertyChanged
|
public class GroupVm : NotifyPropertyChangedBase, IPwEntity
|
||||||
{
|
{
|
||||||
public ObservableCollection<EntryVm> Entries { get; set; }
|
public GroupVm ParentGroup { get; }
|
||||||
public ObservableCollection<GroupVm> Groups { get; set; }
|
public ObservableCollection<EntryVm> Entries { get; set; } = new ObservableCollection<EntryVm>();
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
public string EntryCount {
|
public ObservableCollection<GroupVm> Groups { get; set; } = new ObservableCollection<GroupVm>();
|
||||||
get
|
|
||||||
{
|
public int EntryCount => Entries.Count() - 1;
|
||||||
return $"{Entries?.Count} entries.";
|
public int GroupCount => Groups.Count - 1;
|
||||||
}
|
public bool IsNotRoot => ParentGroup != null;
|
||||||
}
|
public FontWeight FontWeight => _pwGroup == null ? FontWeights.Bold : FontWeights.Normal;
|
||||||
public string GroupCount
|
public string Id => _pwGroup.Uuid.ToHexString();
|
||||||
|
|
||||||
|
public IOrderedEnumerable<IGrouping<char, EntryVm>> EntriesZoomedOut
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return $"{Groups?.Count} groups.";
|
return from e in Entries
|
||||||
|
where e.Entry != null
|
||||||
|
group e by e.Name.FirstOrDefault() into grp
|
||||||
|
orderby grp.Key
|
||||||
|
select grp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GroupVm()
|
public string Name
|
||||||
{
|
{
|
||||||
Name = "GroupName";
|
get { return _pwGroup == null ? "New group" : _pwGroup.Name; }
|
||||||
Entries = new ObservableCollection<EntryVm>();
|
set { _pwGroup.Name = value; }
|
||||||
Groups = new ObservableCollection<GroupVm>();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GroupVm(PwGroup group)
|
public Symbol IconSymbol
|
||||||
{
|
{
|
||||||
Name = group.Name;
|
get
|
||||||
Entries = new ObservableCollection<EntryVm>(group.Entries.Select(e => new EntryVm(e)));
|
|
||||||
Groups = new ObservableCollection<GroupVm>(group.Groups.Select(g => new GroupVm(g)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
|
||||||
|
|
||||||
public void NotifyPropertyChanged(string propertyName)
|
|
||||||
{
|
{
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
if (_pwGroup == null) return Symbol.Add;
|
||||||
|
var result = PwIconToSegoeMapping.GetSymbolFromIcon(_pwGroup.IconId);
|
||||||
|
return result == Symbol.More ? Symbol.Folder : result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsEditMode
|
||||||
|
{
|
||||||
|
get { return _isEditMode; }
|
||||||
|
set { SetProperty(ref _isEditMode, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly PwGroup _pwGroup;
|
||||||
|
private bool _isLeftPaneOpen;
|
||||||
|
private bool _isEditMode;
|
||||||
|
|
||||||
|
public GroupVm() {}
|
||||||
|
|
||||||
|
public GroupVm(PwGroup pwGroup, GroupVm parent)
|
||||||
|
{
|
||||||
|
_pwGroup = pwGroup;
|
||||||
|
ParentGroup = parent;
|
||||||
|
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)).OrderBy(g => g.Name));
|
||||||
|
Groups.Insert(0, new GroupVm ());
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupVm CreateNewGroup()
|
||||||
|
{
|
||||||
|
var pwGroup = new PwGroup(true, true, string.Empty, PwIcon.Folder);
|
||||||
|
_pwGroup.AddGroup(pwGroup, true);
|
||||||
|
var newGroup = new GroupVm(pwGroup, this) {IsEditMode = true};
|
||||||
|
Groups.Add(newGroup);
|
||||||
|
return newGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntryVm CreateNewEntry()
|
||||||
|
{
|
||||||
|
var pwEntry = new PwEntry(true, true);
|
||||||
|
_pwGroup.AddEntry(pwEntry, true);
|
||||||
|
var newEntry = new EntryVm(pwEntry, this) {IsEditMode = true};
|
||||||
|
Entries.Add(newEntry);
|
||||||
|
return newEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MarkForDelete()
|
||||||
|
{
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
app.PendingDeleteEntities.Add(Id, this);
|
||||||
|
ParentGroup.Groups.Remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CommitDelete()
|
||||||
|
{
|
||||||
|
_pwGroup.ParentGroup.Groups.Remove(_pwGroup);
|
||||||
|
}
|
||||||
|
public void UndoDelete()
|
||||||
|
{
|
||||||
|
ParentGroup.Groups.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
app.Database.Save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
32
ModernKeePass/ViewModels/Items/MainMenuItemVm.cs
Normal file
32
ModernKeePass/ViewModels/Items/MainMenuItemVm.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
using ModernKeePass.Interfaces;
|
||||||
|
|
||||||
|
namespace ModernKeePass.ViewModels
|
||||||
|
{
|
||||||
|
public class MainMenuItemVm: NotifyPropertyChangedBase, IIsEnabled, ISelectableModel
|
||||||
|
{
|
||||||
|
private bool _isSelected;
|
||||||
|
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
public Type PageType { get; set; }
|
||||||
|
public object Parameter { get; set; }
|
||||||
|
public Frame Destination { get; set; }
|
||||||
|
public int Group { get; set; } = 0;
|
||||||
|
public Symbol SymbolIcon { get; set; }
|
||||||
|
public bool IsEnabled { get; set; } = true;
|
||||||
|
|
||||||
|
public bool IsSelected
|
||||||
|
{
|
||||||
|
get { return _isSelected; }
|
||||||
|
set { SetProperty(ref _isSelected, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
ModernKeePass/ViewModels/Items/RecentItemVm.cs
Normal file
30
ModernKeePass/ViewModels/Items/RecentItemVm.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.Storage;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
using Windows.Storage.AccessCache;
|
||||||
|
|
||||||
|
namespace ModernKeePass.ViewModels
|
||||||
|
{
|
||||||
|
public class RecentItemVm: NotifyPropertyChangedBase
|
||||||
|
{
|
||||||
|
private bool _isSelected;
|
||||||
|
|
||||||
|
public RecentItemVm(AccessListEntry entry, StorageFile file)
|
||||||
|
{
|
||||||
|
Token = entry.Token;
|
||||||
|
Name = entry.Metadata;
|
||||||
|
DatabaseFile = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StorageFile DatabaseFile { get; private set; }
|
||||||
|
public string Token { get; private set; }
|
||||||
|
public string Name { get; private set; } = "Recent file";
|
||||||
|
public string Path => DatabaseFile.Path;
|
||||||
|
|
||||||
|
public bool IsSelected
|
||||||
|
{
|
||||||
|
get { return _isSelected; }
|
||||||
|
internal set { SetProperty(ref _isSelected, value); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
96
ModernKeePass/ViewModels/MainVm.cs
Normal file
96
ModernKeePass/ViewModels/MainVm.cs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
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.Pages.BasePages;
|
||||||
|
|
||||||
|
namespace ModernKeePass.ViewModels
|
||||||
|
{
|
||||||
|
public class MainVm : NotifyPropertyChangedBase, IHasSelectableObject
|
||||||
|
{
|
||||||
|
private IOrderedEnumerable<IGrouping<int, MainMenuItemVm>> _mainMenuItems;
|
||||||
|
private MainMenuItemVm _selectedItem;
|
||||||
|
|
||||||
|
public string Name { get; } = Package.Current.DisplayName;
|
||||||
|
|
||||||
|
public IOrderedEnumerable<IGrouping<int, MainMenuItemVm>> MainMenuItems
|
||||||
|
{
|
||||||
|
get { return _mainMenuItems; }
|
||||||
|
set { SetProperty(ref _mainMenuItems, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ISelectableModel SelectedItem
|
||||||
|
{
|
||||||
|
get { return _selectedItem; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_selectedItem == value) return;
|
||||||
|
if (_selectedItem != null)
|
||||||
|
{
|
||||||
|
_selectedItem.IsSelected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetProperty(ref _selectedItem, (MainMenuItemVm)value);
|
||||||
|
|
||||||
|
if (_selectedItem != null)
|
||||||
|
{
|
||||||
|
_selectedItem.IsSelected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MainVm() {}
|
||||||
|
|
||||||
|
public MainVm(Frame referenceFrame, Frame destinationFrame)
|
||||||
|
{
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
var mru = StorageApplicationPermissions.MostRecentlyUsedList;
|
||||||
|
var isDatabaseOpen = app.Database != null && app.Database.Status == DatabaseHelper.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
|
||||||
|
},
|
||||||
|
new MainMenuItemVm
|
||||||
|
{
|
||||||
|
Title = "New" , 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
|
||||||
|
},
|
||||||
|
new MainMenuItemVm
|
||||||
|
{
|
||||||
|
Title = "About" , PageType = typeof(AboutPage), Destination = destinationFrame, SymbolIcon = Symbol.Help
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 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)
|
||||||
|
mainMenuItems.Add(new MainMenuItemVm
|
||||||
|
{
|
||||||
|
Title = app.Database.Name,
|
||||||
|
PageType = typeof(GroupDetailPage),
|
||||||
|
Destination = referenceFrame,
|
||||||
|
Parameter = app.Database.RootGroup,
|
||||||
|
Group = 1,
|
||||||
|
SymbolIcon = Symbol.ProtectedDocument
|
||||||
|
});
|
||||||
|
|
||||||
|
MainMenuItems = from item in mainMenuItems group item by item.Group into grp orderby grp.Key select grp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
ModernKeePass/ViewModels/NewVm.cs
Normal file
21
ModernKeePass/ViewModels/NewVm.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using ModernKeePassLib.Cryptography;
|
||||||
|
|
||||||
|
namespace ModernKeePass.ViewModels
|
||||||
|
{
|
||||||
|
public class NewVm : OpenVm
|
||||||
|
{
|
||||||
|
private string _password = string.Empty;
|
||||||
|
|
||||||
|
public double PasswordComplexityIndicator => QualityEstimation.EstimatePasswordBits(Password.ToCharArray());
|
||||||
|
public string Password
|
||||||
|
{
|
||||||
|
get { return _password; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_password = value;
|
||||||
|
NotifyPropertyChanged("PasswordComplexityIndicator");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
50
ModernKeePass/ViewModels/OpenVm.cs
Normal file
50
ModernKeePass/ViewModels/OpenVm.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using Windows.Storage;
|
||||||
|
using Windows.Storage.AccessCache;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
|
||||||
|
namespace ModernKeePass.ViewModels
|
||||||
|
{
|
||||||
|
public class OpenVm: INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
public bool ShowPasswordBox
|
||||||
|
{
|
||||||
|
get { return ((App)Application.Current).Database.Status == DatabaseHelper.DatabaseStatus.Opening; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return ((App)Application.Current).Database.Name; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public OpenVm()
|
||||||
|
{
|
||||||
|
var database = ((App)Application.Current).Database;
|
||||||
|
if (database == null || database.Status != DatabaseHelper.DatabaseStatus.Opening) return;
|
||||||
|
OpenFile(database.DatabaseFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
protected void NotifyPropertyChanged(string propertyName)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenFile(StorageFile file)
|
||||||
|
{
|
||||||
|
var database = ((App)Application.Current).Database;
|
||||||
|
database.DatabaseFile = file;
|
||||||
|
NotifyPropertyChanged("Name");
|
||||||
|
NotifyPropertyChanged("ShowPasswordBox");
|
||||||
|
AddToRecentList(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddToRecentList(StorageFile file)
|
||||||
|
{
|
||||||
|
var mru = StorageApplicationPermissions.MostRecentlyUsedList;
|
||||||
|
mru.Add(file, file.DisplayName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
ModernKeePass/ViewModels/RecentVm.cs
Normal file
58
ModernKeePass/ViewModels/RecentVm.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using Windows.Storage.AccessCache;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
|
||||||
|
namespace ModernKeePass.ViewModels
|
||||||
|
{
|
||||||
|
public class RecentVm : NotifyPropertyChangedBase
|
||||||
|
{
|
||||||
|
private RecentItemVm _selectedItem;
|
||||||
|
private ObservableCollection<RecentItemVm> _recentItems = new ObservableCollection<RecentItemVm>();
|
||||||
|
|
||||||
|
public ObservableCollection<RecentItemVm> RecentItems
|
||||||
|
{
|
||||||
|
get { return _recentItems; }
|
||||||
|
set { SetProperty(ref _recentItems, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecentItemVm SelectedItem
|
||||||
|
{
|
||||||
|
get { return _selectedItem; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_selectedItem == value) return;
|
||||||
|
if (_selectedItem != null)
|
||||||
|
{
|
||||||
|
_selectedItem.IsSelected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetProperty(ref _selectedItem, value);
|
||||||
|
|
||||||
|
if (_selectedItem == null) return;
|
||||||
|
_selectedItem.IsSelected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecentVm()
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (RecentItems.Count > 0)
|
||||||
|
SelectedItem = RecentItems[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
22
ModernKeePass/ViewModels/SaveVm.cs
Normal file
22
ModernKeePass/ViewModels/SaveVm.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using Windows.Storage;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
|
||||||
|
namespace ModernKeePass.ViewModels
|
||||||
|
{
|
||||||
|
public class SaveVm
|
||||||
|
{
|
||||||
|
public void Save(bool close = true)
|
||||||
|
{
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
app.Database.Save();
|
||||||
|
if (!close) return;
|
||||||
|
app.Database.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Save(StorageFile file)
|
||||||
|
{
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
app.Database.Save(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -2,10 +2,27 @@
|
|||||||
<packages>
|
<packages>
|
||||||
<package id="Microsoft.NETCore.Platforms" version="2.0.0" targetFramework="win81" />
|
<package id="Microsoft.NETCore.Platforms" version="2.0.0" targetFramework="win81" />
|
||||||
<package id="Microsoft.NETCore.Portable.Compatibility" version="1.0.2" targetFramework="win81" />
|
<package id="Microsoft.NETCore.Portable.Compatibility" version="1.0.2" targetFramework="win81" />
|
||||||
<package id="ModernKeePassLib" version="2.19.2950" targetFramework="win81" />
|
<package id="Microsoft.Toolkit.Uwp.Notifications" version="2.0.0" targetFramework="win81" />
|
||||||
<package id="NETStandard.Library" version="2.0.0" targetFramework="win81" />
|
<package id="ModernKeePassLib" version="2.37.4000" targetFramework="win81" />
|
||||||
|
<package id="NETStandard.Library" version="2.0.1" targetFramework="win81" />
|
||||||
|
<package id="Portable.BouncyCastle" version="1.8.1.3" targetFramework="win81" />
|
||||||
|
<package id="Splat" version="2.0.0" targetFramework="win81" />
|
||||||
|
<package id="System.Collections" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="System.Globalization" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="System.IO" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="System.Linq" version="4.3.0" targetFramework="win81" />
|
||||||
<package id="System.Net.Requests" version="4.3.0" targetFramework="win81" />
|
<package id="System.Net.Requests" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="System.Reflection" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="System.Reflection.Extensions" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="System.Runtime" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="win81" />
|
||||||
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="win81" />
|
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="win81" />
|
||||||
<package id="System.Runtime.WindowsRuntime" version="4.3.0" targetFramework="win81" />
|
<package id="System.Runtime.WindowsRuntime" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="System.Text.Encoding" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="System.Threading" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="System.Threading.Tasks" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="win81" />
|
||||||
<package id="System.Xml.XmlSerializer" version="4.3.0" targetFramework="win81" />
|
<package id="System.Xml.XmlSerializer" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="Validation" version="2.4.15" targetFramework="win81" />
|
||||||
</packages>
|
</packages>
|
@@ -0,0 +1,84 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Security;
|
||||||
|
using System.Text;
|
||||||
|
using ModernKeePassLib.Serialization;
|
||||||
|
using ModernKeePassLib.Utility;
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Cryptography.Cipher;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Cryptography.Cipher;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Org.BouncyCastle.Crypto.Engines;
|
||||||
|
using Org.BouncyCastle.Crypto.Parameters;
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Cryptography.Cipher
|
||||||
|
{
|
||||||
|
[TestFixture()]
|
||||||
|
public class StandardAesEngineTests
|
||||||
|
{
|
||||||
|
// Test vector (official ECB test vector #356)
|
||||||
|
private byte[] pbReferenceCT = new byte[16] {
|
||||||
|
0x75, 0xD1, 0x1B, 0x0E, 0x3A, 0x68, 0xC4, 0x22,
|
||||||
|
0x3D, 0x88, 0xDB, 0xF0, 0x17, 0x97, 0x7D, 0xD7
|
||||||
|
};
|
||||||
|
[Test]
|
||||||
|
public void TestEncryptStream()
|
||||||
|
{
|
||||||
|
byte[] pbIV = new byte[16];
|
||||||
|
byte[] pbTestKey = new byte[32];
|
||||||
|
byte[] pbTestData = new byte[16];
|
||||||
|
pbTestData[0] = 0x04;
|
||||||
|
|
||||||
|
var outStream = new MemoryStream(new byte[16]);
|
||||||
|
var aes = new StandardAesEngine();
|
||||||
|
var inStream = aes.EncryptStream(outStream, pbTestKey, pbIV);
|
||||||
|
new BinaryWriter(inStream).Write(pbTestData);
|
||||||
|
//Assert.That(outStream.Position, Is.EqualTo(16));
|
||||||
|
outStream.Position = 0;
|
||||||
|
var outBytes = new BinaryReaderEx(outStream, Encoding.UTF8, string.Empty).ReadBytes(16);
|
||||||
|
Assert.That(outBytes, Is.EqualTo(pbReferenceCT));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDecryptStream()
|
||||||
|
{
|
||||||
|
byte[] pbIV = new byte[16];
|
||||||
|
byte[] pbTestKey = new byte[32];
|
||||||
|
byte[] pbTestData = new byte[16];
|
||||||
|
pbTestData[0] = 0x04;
|
||||||
|
|
||||||
|
// Possible Mono Bug? This only works with size >= 48
|
||||||
|
var inStream = new MemoryStream(new byte[32]);
|
||||||
|
inStream.Write(pbReferenceCT, 0, pbReferenceCT.Length);
|
||||||
|
inStream.Position = 0;
|
||||||
|
var aes = new StandardAesEngine();
|
||||||
|
var outStream = aes.DecryptStream(inStream, pbTestKey, pbIV);
|
||||||
|
var outBytes = new BinaryReaderEx(outStream, Encoding.UTF8, string.Empty).ReadBytes(16);
|
||||||
|
Assert.That(outBytes, Is.EqualTo(pbTestData));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBouncyCastleAes()
|
||||||
|
{
|
||||||
|
byte[] pbIV = new byte[16];
|
||||||
|
byte[] pbTestKey = new byte[32];
|
||||||
|
byte[] pbTestData = new byte[16];
|
||||||
|
/*int i;
|
||||||
|
for (i = 0; i < 16; ++i) pbIV[i] = 0;
|
||||||
|
for (i = 0; i < 32; ++i) pbTestKey[i] = 0;
|
||||||
|
for (i = 0; i < 16; ++i) pbTestData[i] = 0;*/
|
||||||
|
pbTestData[0] = 0x04;
|
||||||
|
|
||||||
|
var aesEngine = new AesEngine();
|
||||||
|
//var parametersWithIv = new ParametersWithIV(new KeyParameter(pbTestKey), pbIV);
|
||||||
|
aesEngine.Init(true, new KeyParameter(pbTestKey));
|
||||||
|
Assert.That(aesEngine.GetBlockSize(), Is.EqualTo(pbTestData.Length));
|
||||||
|
aesEngine.ProcessBlock(pbTestData, 0, pbTestData, 0);
|
||||||
|
//Assert.That(MemUtil.ArraysEqual(pbTestData, pbReferenceCT), Is.False);
|
||||||
|
Assert.That(pbTestData, Is.EqualTo(pbReferenceCT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,60 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Cryptography;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Cryptography;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Cryptography
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class CryptoRandomStreamTests
|
||||||
|
{
|
||||||
|
void TestGetRandomBytes(CryptoRandomStream stream)
|
||||||
|
{
|
||||||
|
const uint length = 16;
|
||||||
|
var bytes1 = stream.GetRandomBytes (length);
|
||||||
|
Assert.That (bytes1.Length, Is.EqualTo (length));
|
||||||
|
var bytes2 = stream.GetRandomBytes (length);
|
||||||
|
Assert.That (bytes2, Is.Not.EqualTo (bytes1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestGetRandomBytesCrsAlgorithmSalsa20 ()
|
||||||
|
{
|
||||||
|
var stream = new CryptoRandomStream (CrsAlgorithm.Salsa20, new byte[16]);
|
||||||
|
TestGetRandomBytes (stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestGetRandomBytesCrsAlgorithmArcFourVariant ()
|
||||||
|
{
|
||||||
|
var stream = new CryptoRandomStream (CrsAlgorithm.ArcFourVariant, new byte[16]);
|
||||||
|
TestGetRandomBytes (stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestGetRandomInt64 (CryptoRandomStream stream)
|
||||||
|
{
|
||||||
|
var value1 = stream.GetRandomUInt64 ();
|
||||||
|
var value2 = stream.GetRandomUInt64 ();
|
||||||
|
Assert.That (value2, Is.Not.EqualTo (value1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestGetRandomInt64AlgorithmSalsa20 ()
|
||||||
|
{
|
||||||
|
var stream = new CryptoRandomStream (CrsAlgorithm.Salsa20, new byte[16]);
|
||||||
|
TestGetRandomInt64 (stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestGetRandomInt64AlgorithmArcFourVariant ()
|
||||||
|
{
|
||||||
|
var stream = new CryptoRandomStream (CrsAlgorithm.ArcFourVariant, new byte[16]);
|
||||||
|
TestGetRandomInt64 (stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
44
ModernKeePassLib.Test/Cryptography/CryptoRandomTests.cs
Normal file
44
ModernKeePassLib.Test/Cryptography/CryptoRandomTests.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Cryptography;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Cryptography;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Cryptography
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class CryptoRandomTests
|
||||||
|
{
|
||||||
|
[Test ()]
|
||||||
|
public void TestAddEntropy ()
|
||||||
|
{
|
||||||
|
// just making sure it does not throw an exception
|
||||||
|
CryptoRandom.Instance.AddEntropy (new byte[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestGetRandomBytes ()
|
||||||
|
{
|
||||||
|
const int length = 32;
|
||||||
|
var bytes1 = CryptoRandom.Instance.GetRandomBytes (length);
|
||||||
|
Assert.That (bytes1.Length, Is.EqualTo (length));
|
||||||
|
var bytes2 = CryptoRandom.Instance.GetRandomBytes (length);
|
||||||
|
Assert.That (bytes2, Is.Not.EqualTo (bytes1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestGeneratedBytesCount ()
|
||||||
|
{
|
||||||
|
const int length = 1;
|
||||||
|
CryptoRandom.Instance.GetRandomBytes (length);
|
||||||
|
var count1 = CryptoRandom.Instance.GeneratedBytesCount;
|
||||||
|
CryptoRandom.Instance.GetRandomBytes (length);
|
||||||
|
var count2 = CryptoRandom.Instance.GeneratedBytesCount;
|
||||||
|
Assert.That (count2, Is.GreaterThan (count1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
77
ModernKeePassLib.Test/Cryptography/HashingStreamExTests.cs
Normal file
77
ModernKeePassLib.Test/Cryptography/HashingStreamExTests.cs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Cryptography;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Cryptography;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Cryptography
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class HashingStreamExTests
|
||||||
|
{
|
||||||
|
const string data = "test";
|
||||||
|
|
||||||
|
// The expected hash includes the \n added by WriteLine
|
||||||
|
static readonly byte[] sha256HashOfData = {
|
||||||
|
0xf2, 0xca, 0x1b, 0xb6, 0xc7, 0xe9, 0x07, 0xd0,
|
||||||
|
0x6d, 0xaf, 0xe4, 0x68, 0x7e, 0x57, 0x9f, 0xce,
|
||||||
|
0x76, 0xb3, 0x7e, 0x4e, 0x93, 0xb7, 0x60, 0x50,
|
||||||
|
0x22, 0xda, 0x52, 0xe6, 0xcc, 0xc2, 0x6f, 0xd2
|
||||||
|
};
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestRead ()
|
||||||
|
{
|
||||||
|
// if we use larger size, StreamReader will read past newline and cause bad hash
|
||||||
|
var bytes = new byte[data.Length + 1];
|
||||||
|
using (var ms = new MemoryStream (bytes)) {
|
||||||
|
using (var sw = new StreamWriter (ms)) {
|
||||||
|
// set NewLine to ensure we don't run into cross-platform issues on Windows
|
||||||
|
sw.NewLine = "\n";
|
||||||
|
sw.WriteLine (data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (var ms = new MemoryStream (bytes)) {
|
||||||
|
using (var hs = new HashingStreamEx (ms, false, null)) {
|
||||||
|
using (var sr = new StreamReader (hs)) {
|
||||||
|
var read = sr.ReadLine ();
|
||||||
|
Assert.That (read, Is.EqualTo (data));
|
||||||
|
}
|
||||||
|
// When the StreamReader is disposed, it calls Dispose on the
|
||||||
|
//HasingStreamEx, which computes the hash.
|
||||||
|
Assert.That (hs.Hash, Is.EqualTo (sha256HashOfData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestWrite ()
|
||||||
|
{
|
||||||
|
var bytes = new byte[16];
|
||||||
|
using (var ms = new MemoryStream (bytes)) {
|
||||||
|
using (var hs = new HashingStreamEx (ms, true, null)) {
|
||||||
|
using (var sw = new StreamWriter (hs)) {
|
||||||
|
// set NewLine to ensure we don't run into cross-platform issues on Windows
|
||||||
|
sw.NewLine = "\n";
|
||||||
|
sw.WriteLine (data);
|
||||||
|
}
|
||||||
|
// When the StreamWriter is disposed, it calls Dispose on the
|
||||||
|
//HasingStreamEx, which computes the hash.
|
||||||
|
Assert.That (hs.Hash, Is.EqualTo (sha256HashOfData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (var ms = new MemoryStream (bytes)) {
|
||||||
|
using (var sr = new StreamReader (ms)) {
|
||||||
|
var read = sr.ReadLine ();
|
||||||
|
Assert.That (read, Is.EqualTo (data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
36
ModernKeePassLib.Test/Cryptography/HmacOtpTests.cs
Normal file
36
ModernKeePassLib.Test/Cryptography/HmacOtpTests.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Cryptography;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Cryptography;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Cryptography
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class HmacOtpTests
|
||||||
|
{
|
||||||
|
// Using the test case from Appendix D of RFC 4226
|
||||||
|
|
||||||
|
const string secret = "12345678901234567890";
|
||||||
|
static readonly string[] expectedHOTP = new string[] {
|
||||||
|
"755224", "287082", "359152", "969429", "338314",
|
||||||
|
"254676", "287922", "162583", "399871", "520489"
|
||||||
|
};
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestGenerate ()
|
||||||
|
{
|
||||||
|
var secretBytes = Encoding.UTF8.GetBytes (secret);
|
||||||
|
|
||||||
|
for (ulong i = 0; i < 10; i++) {
|
||||||
|
var hotp = HmacOtp.Generate (secretBytes, i, 6, false, -1);
|
||||||
|
Assert.That (hotp, Is.EqualTo (expectedHOTP[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
33
ModernKeePassLib.Test/Keys/CompositeKeyTests.cs
Normal file
33
ModernKeePassLib.Test/Keys/CompositeKeyTests.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using ModernKeePassLib.Cryptography.KeyDerivation;
|
||||||
|
using ModernKeePassLib.Keys;
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Keys
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class CompositeKeyTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestGenerateKey32 ()
|
||||||
|
{
|
||||||
|
var originalKey = new byte[32];
|
||||||
|
var expectedKey = new byte[32] {
|
||||||
|
0xF0, 0xED, 0x57, 0xD5, 0xF0, 0xDA, 0xF3, 0x47,
|
||||||
|
0x90, 0xD0, 0xDB, 0x43, 0x25, 0xC6, 0x81, 0x2C,
|
||||||
|
0x81, 0x6A, 0x0D, 0x94, 0x96, 0xA9, 0x03, 0xE1,
|
||||||
|
0x20, 0xD4, 0x3A, 0x3E, 0x45, 0xAD, 0x02, 0x65
|
||||||
|
};
|
||||||
|
const ulong rounds = 1;
|
||||||
|
|
||||||
|
var composite = new CompositeKey ();
|
||||||
|
AesKdf kdf = new AesKdf();
|
||||||
|
KdfParameters p = kdf.GetDefaultParameters();
|
||||||
|
p.SetUInt64(AesKdf.ParamRounds, rounds);
|
||||||
|
p.SetByteArray(AesKdf.ParamSeed, originalKey);
|
||||||
|
var key = composite.GenerateKey32(p);
|
||||||
|
Assert.That (key, Is.Not.Null);
|
||||||
|
var keyData = key.ReadData ();
|
||||||
|
Assert.That (keyData, Is.EqualTo (expectedKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
ModernKeePassLib.Test/Keys/KcpCustomKeyTests.cs
Normal file
39
ModernKeePassLib.Test/Keys/KcpCustomKeyTests.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Keys;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Keys;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Keys
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class KcpCustomKeyTests
|
||||||
|
{
|
||||||
|
static readonly byte[] testData = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestConstruct ()
|
||||||
|
{
|
||||||
|
var expectedHash = new byte[32] {
|
||||||
|
0xAF, 0x55, 0x70, 0xF5, 0xA1, 0x81, 0x0B, 0x7A,
|
||||||
|
0xF7, 0x8C, 0xAF, 0x4B, 0xC7, 0x0A, 0x66, 0x0F,
|
||||||
|
0x0D, 0xF5, 0x1E, 0x42, 0xBA, 0xF9, 0x1D, 0x4D,
|
||||||
|
0xE5, 0xB2, 0x32, 0x8D, 0xE0, 0xE8, 0x3D, 0xFC
|
||||||
|
};
|
||||||
|
|
||||||
|
var key = new KcpCustomKey ("test1", testData, false);
|
||||||
|
var keyData = key.KeyData.ReadData ();
|
||||||
|
Assert.That (keyData, Is.EqualTo (testData));
|
||||||
|
|
||||||
|
key = new KcpCustomKey ("test2", testData, true);
|
||||||
|
keyData = key.KeyData.ReadData ();
|
||||||
|
Assert.That (keyData, Is.EqualTo (expectedHash));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user