WIP Windows 10

Dependencies finally installed
Removal of useless code
Big cleanup in XAML styles (override colors the correct way)
This commit is contained in:
Geoffroy BONNEVILLE
2020-04-29 16:39:20 +02:00
parent d6529646a8
commit 14cd3ab57a
224 changed files with 1265 additions and 38545 deletions

22
Win10App/App.xaml Normal file
View File

@@ -0,0 +1,22 @@
<Application
x:Class="ModernKeePass.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModels="using:ModernKeePass.ViewModels"
RequestedTheme="Light">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
<ResourceDictionary Source="ResourceDictionaries/MasterDetailsView.xaml" />
<!--<ResourceDictionary Source="ResourceDictionaries/TextBoxWithButtonStyle.xaml" />-->
<ResourceDictionary Source="ResourceDictionaries/HamburgerButtonStyle.xaml" />
<ResourceDictionary Source="ResourceDictionaries/ListViewLeftIndicatorStyle.xaml" />
<ResourceDictionary Source="ResourceDictionaries/NoBorderButtonStyle.xaml" />
<ResourceDictionary Source="ResourceDictionaries/NoBorderToggleButtonStyle.xaml" />
<ResourceDictionary Source="ResourceDictionaries/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
<viewModels:ViewModelLocator x:Key="Locator" />
</ResourceDictionary>
</Application.Resources>
</Application>

281
Win10App/App.xaml.cs Normal file
View File

@@ -0,0 +1,281 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Storage;
using Windows.Storage.AccessCache;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using GalaSoft.MvvmLight.Views;
using MediatR;
using Microsoft.AppCenter;
using Microsoft.AppCenter.Analytics;
using Microsoft.AppCenter.Crashes;
using Microsoft.Extensions.DependencyInjection;
using ModernKeePass.Application;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Database.Commands.CloseDatabase;
using ModernKeePass.Application.Database.Commands.SaveDatabase;
using ModernKeePass.Application.Database.Queries.GetDatabase;
using ModernKeePass.Application.Database.Queries.ReOpenDatabase;
using ModernKeePass.Common;
using ModernKeePass.Domain.Dtos;
using ModernKeePass.Domain.Exceptions;
using ModernKeePass.Infrastructure;
// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227
namespace ModernKeePass
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App
{
private readonly IResourceProxy _resource;
private readonly IMediator _mediator;
private readonly ISettingsProxy _settings;
private readonly INavigationService _navigation;
private readonly IAppCenterService _appCenter;
private readonly IDialogService _dialog;
private readonly INotificationService _notification;
public static IServiceProvider Services { get; private set; }
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
// Setup DI
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddApplication();
serviceCollection.AddInfrastructureCommon();
serviceCollection.AddInfrastructureKeePass();
serviceCollection.AddInfrastructureUwp();
serviceCollection.AddWin10App();
Services = serviceCollection.BuildServiceProvider();
_mediator = Services.GetService<IMediator>();
_resource = Services.GetService<IResourceProxy>();
_settings = Services.GetService<ISettingsProxy>();
_navigation = Services.GetService<INavigationService>();
_dialog = Services.GetService<IDialogService>();
_notification = Services.GetService<INotificationService>();
#if DEBUG
AppCenter.Start("029ab91d-1e4b-4d4d-9661-5d438dd671a5",
typeof(Analytics), typeof(Crashes));
#else
AppCenter.Start("79d23520-a486-4f63-af81-8d90bf4e1bea", typeof(Analytics));
#endif
InitializeComponent();
Suspending += OnSuspending;
Resuming += OnResuming;
UnhandledException += OnUnhandledException;
}
#region Event Handlers
private async void OnUnhandledException(object sender, Windows.UI.Xaml.UnhandledExceptionEventArgs unhandledExceptionEventArgs)
{
// Save the argument exception because it's cleared on first access
var exception = unhandledExceptionEventArgs.Exception;
var realException =
exception is TargetInvocationException &&
exception.InnerException != null
? exception.InnerException
: exception;
if (realException is SaveException)
{
unhandledExceptionEventArgs.Handled = true;
//_hockey.TrackException(realException);
await _dialog.ShowMessage(realException.Message,
_resource.GetResourceValue("MessageDialogSaveErrorTitle"),
_resource.GetResourceValue("MessageDialogSaveErrorButtonSaveAs"),
_resource.GetResourceValue("MessageDialogSaveErrorButtonDiscard"),
async isOk =>
{
if (isOk)
{
var database = await _mediator.Send(new GetDatabaseQuery());
var savePicker = new FileSavePicker
{
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
SuggestedFileName = $"{database.Name} - copy"
};
savePicker.FileTypeChoices.Add(
_resource.GetResourceValue("MessageDialogSaveErrorFileTypeDesc"),
new List<string> { ".kdbx" });
var file = await savePicker.PickSaveFileAsync().AsTask();
if (file != null)
{
var token = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name);
await _mediator.Send(new SaveDatabaseCommand { FilePath = token });
}
}
});
}
else
{
await _dialog.ShowError(realException, realException.Message, "OK", () => { });
}
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="args">Details about the launch request and process.</param>
protected override async void OnLaunched(LaunchActivatedEventArgs args)
{
await OnLaunchOrActivated(args);
//await _hockey.SendCrashesAsync(/* sendWithoutAsking: true */);
}
protected override async void OnActivated(IActivatedEventArgs args)
{
await OnLaunchOrActivated(args);
}
private async Task OnLaunchOrActivated(IActivatedEventArgs e)
{
var rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame { Language = Windows.Globalization.ApplicationLanguages.Languages[0] };
// Set the default language
rootFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
// Load state from previously terminated application
await SuspensionManager.RestoreAsync();
#if DEBUG
await _dialog.ShowMessage("Windows or an error made the app terminate", "App terminated");
#endif
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
var launchActivatedEventArgs = e as LaunchActivatedEventArgs;
if (launchActivatedEventArgs != null && rootFrame.Content == null)
_navigation.NavigateTo(Constants.Navigation.MainPage, launchActivatedEventArgs.Arguments);
// Ensure the current window is active
Window.Current.Activate();
}
private async void OnResuming(object sender, object e)
{
try
{
await _mediator.Send(new ReOpenDatabaseQuery());
#if DEBUG
_notification.Show("App resumed", "Database reopened (changes were saved)");
#endif
}
catch (Exception)
{
_navigation.NavigateTo(Constants.Navigation.MainPage);
#if DEBUG
_notification.Show("App resumed", "Nothing to do, no previous database opened");
#endif
}
}
/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
private void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new NavigationException(e.SourcePageType);
}
/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
try
{
var database = await _mediator.Send(new GetDatabaseQuery());
if (database.IsOpen)
{
if (database.Size < Constants.File.OneMegaByte && database.IsDirty &&
_settings.GetSetting(Constants.Settings.SaveSuspend, true))
{
await _mediator.Send(new SaveDatabaseCommand()).ConfigureAwait(false);
}
await _mediator.Send(new CloseDatabaseCommand()).ConfigureAwait(false);
}
}
catch (Exception exception)
{
_notification.Show(exception.Source, exception.Message);
}
finally
{
await SuspensionManager.SaveAsync().ConfigureAwait(false);
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();
var file = args.Files[0] as StorageFile;
Window.Current.Content = rootFrame;
if (file != null)
{
// TODO: use service
var token = StorageApplicationPermissions.MostRecentlyUsedList.Add(file, file.Path);
var fileInfo = new FileInfo
{
Id = token,
Name = file.DisplayName,
Path = file.Path
};
_navigation.NavigateTo(Constants.Navigation.MainPage, fileInfo);
}
else
{
_navigation.NavigateTo(Constants.Navigation.MainPage);
}
Window.Current.Activate();
}
#endregion
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 980 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 980 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 961 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,39 @@
using System.Reflection;
using AutoMapper;
using GalaSoft.MvvmLight.Views;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AppCenter;
using Microsoft.AppCenter.Analytics;
using Microsoft.AppCenter.Crashes;
using ModernKeePass.Common;
using ModernKeePass.Views;
namespace ModernKeePass
{
public static class DependencyInjection
{
public static IServiceCollection AddWin10App(this IServiceCollection services)
{
var applicationAssembly = typeof(Application.DependencyInjection).GetTypeInfo().Assembly;
var infrastructureAssembly = typeof(Infrastructure.DependencyInjection).GetTypeInfo().Assembly;
services.AddAutoMapper(applicationAssembly, infrastructureAssembly);
services.AddSingleton<INavigationService>(provider =>
{
var nav = new NavigationService();
nav.Configure(Constants.Navigation.MainPage, typeof(MainPage10));
nav.Configure(Constants.Navigation.EntryPage, typeof(EntryPage));
nav.Configure(Constants.Navigation.GroupPage, typeof(EntriesPage));
return nav;
});
services.AddTransient(typeof(IDialogService), typeof(DialogService));
/*services.AddSingleton(provider =>
{
});*/
return services;
}
}
}

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
IgnorableNamespaces="uap mp">
<Identity
Name="967f008b-fe58-4f0c-bfc7-3ac5c451436e"
Publisher="CN=GeoffroyBONNEVILLE"
Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="967f008b-fe58-4f0c-bfc7-3ac5c451436e" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>Win10App</DisplayName>
<PublisherDisplayName>GeoffroyBONNEVILLE</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="Win10App.App">
<uap:VisualElements
DisplayName="Win10App"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png"
Description="Win10App"
BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
</Capabilities>
</Package>

View File

@@ -0,0 +1,29 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Win10App")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Win10App")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]

View File

@@ -0,0 +1,31 @@
<!--
This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most
developers. However, you can modify these parameters to modify the behavior of the .NET Native
optimizer.
Runtime Directives are documented at https://go.microsoft.com/fwlink/?LinkID=391919
To fully enable reflection for App1.MyClass and all of its public/private members
<Type Name="App1.MyClass" Dynamic="Required All"/>
To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />
Using the Namespace directive to apply reflection policy to all the types in a particular namespace
<Namespace Name="DataClasses.ViewModels" Serialize="All" />
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<!--
An Assembly element with Name="*Application*" applies to all assemblies in
the application package. The asterisks are not wildcards.
-->
<Assembly Name="*Application*" Dynamic="Required All" />
<!-- Add your application specific runtime directives here. -->
</Application>
</Directives>

View File

@@ -0,0 +1,60 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="ToggleButton" x:Key="HamburgerToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<ContentControl>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Grid"
Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="0.8" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="Grid" Background="{StaticResource MainColor}" Margin="0" Width="{StaticResource MenuSize}" Height="{StaticResource MenuSize}">
<Canvas x:Name="HamburgerMenu" HorizontalAlignment="Center" Height="17" UseLayoutRounding="False" VerticalAlignment="Center" Width="28">
<Canvas x:Name="Layer1" 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="2" Stretch="Fill" StrokeThickness="2" 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="2" Stretch="Fill" StrokeThickness="2" Width="28" Stroke="{ThemeResource DefaultTextForegroundThemeBrush}" StrokeStartLineCap="Square" StrokeEndLineCap="Square" Canvas.Top="7"/>
<Path x:Name="Path1" Data="M0,12.997 L30,12.997" Height="2" Stretch="Fill" StrokeThickness="2" 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>

View File

@@ -0,0 +1,399 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- 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="0.5" />
<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="{StaticResource MainColor}" />
</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="{StaticResource MainColor}"
BorderThickness="5,0,0,0"
Opacity="0"/>
<Rectangle x:Name="SelectedBorder"
IsHitTestVisible="False"
Opacity="0"
Stroke="{StaticResource MainColor}"
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="{StaticResource MainColor}" 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>

View File

@@ -0,0 +1,197 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls">
<Style TargetType="controls:MasterDetailsView" x:Key="ReorderMasterDetailsView">
<Setter Property="Background" Value="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource ApplicationForegroundThemeBrush}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:MasterDetailsView">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid x:Name="RootPanel">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="MasterColumn"
Width="Auto" />
<ColumnDefinition x:Name="DetailsColumn"
Width="*" />
</Grid.ColumnDefinitions>
<Grid x:Name="MasterPanel"
Width="{TemplateBinding MasterPaneWidth}"
Background="{TemplateBinding MasterPaneBackground}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="0,0,1,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid x:Name="MasterCommandBarPanel" Grid.Row="0" />
<ContentPresenter x:Name="HeaderContentPresenter"
Grid.Row="1"
Margin="12,0"
x:DeferLoadStrategy="Lazy"
Content="{TemplateBinding MasterHeader}"
ContentTemplate="{TemplateBinding MasterHeaderTemplate}"
Visibility="Collapsed" />
<ListView x:Name="MasterList"
Grid.Row="2"
CanReorderItems="True"
CanDragItems="True"
AllowDrop="True"
IsTabStop="False"
ItemContainerStyle="{TemplateBinding ItemContainerStyle}"
ItemContainerStyleSelector="{TemplateBinding ItemContainerStyleSelector}"
ItemTemplate="{TemplateBinding ItemTemplate}"
ItemTemplateSelector="{TemplateBinding ItemTemplateSelector}"
ItemsSource="{TemplateBinding ItemsSource}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" />
</Grid>
<Grid x:Name="DetailsPanel"
Grid.Column="1">
<ContentPresenter x:Name="NoSelectionPresenter"
Content="{TemplateBinding NoSelectionContent}"
ContentTemplate="{TemplateBinding NoSelectionContentTemplate}" />
<Grid x:Name="SelectionDetailsPanel">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ContentPresenter x:Name="DetailsPresenter"
Background="{TemplateBinding Background}"
ContentTemplate="{TemplateBinding DetailsTemplate}">
</ContentPresenter>
<Grid x:Name="DetailsCommandBarPanel" Grid.Row="1"></Grid>
<Grid.RenderTransform>
<TranslateTransform x:Name="DetailsPresenterTransform" />
</Grid.RenderTransform>
</Grid>
</Grid>
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualStateGroup.Transitions>
<VisualTransition From="NoSelectionWide"
To="HasSelection">
<Storyboard>
<DrillInThemeAnimation EntranceTargetName="SelectionDetailsPanel"
ExitTargetName="NoSelectionPresenter" />
</Storyboard>
</VisualTransition>
<VisualTransition From="NoSelectionNarrow"
To="HasSelection">
<Storyboard>
<DoubleAnimation BeginTime="0:0:0"
Storyboard.TargetName="DetailsPresenterTransform"
Storyboard.TargetProperty="X"
From="200"
To="0"
Duration="0:0:0.25">
<DoubleAnimation.EasingFunction>
<QuarticEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation BeginTime="0:0:0"
Storyboard.TargetName="SelectionDetailsPanel"
Storyboard.TargetProperty="Opacity"
From="0"
To="1"
Duration="0:0:0.25">
<DoubleAnimation.EasingFunction>
<QuarticEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</VisualTransition>
<VisualTransition From="HasSelection"
To="NoSelectionWide">
<Storyboard>
<DrillOutThemeAnimation EntranceTargetName="NoSelectionPresenter"
ExitTargetName="SelectionDetailsPanel" />
</Storyboard>
</VisualTransition>
<VisualTransition From="HasSelection"
To="NoSelectionNarrow">
<Storyboard>
<DoubleAnimation BeginTime="0:0:0"
Storyboard.TargetName="DetailsPresenterTransform"
Storyboard.TargetProperty="X"
From="0"
To="200"
Duration="0:0:0.25" />
<DoubleAnimation BeginTime="0:0:0.08"
Storyboard.TargetName="SelectionDetailsPanel"
Storyboard.TargetProperty="Opacity"
From="1"
To="0"
Duration="0:0:0.17">
<DoubleAnimation.EasingFunction>
<QuarticEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation BeginTime="0:0:0.0"
Storyboard.TargetName="MasterPanel"
Storyboard.TargetProperty="Opacity"
From="0"
To="1"
Duration="0:0:0.25">
<DoubleAnimation.EasingFunction>
<QuarticEase EasingMode="EaseIn" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="NoSelectionWide">
<VisualState.Setters>
<Setter Target="SelectionDetailsPanel.Visibility" Value="Collapsed" />
<Setter Target="MasterPanel.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="HasSelectionWide">
<VisualState.Setters>
<Setter Target="NoSelectionPresenter.Visibility" Value="Collapsed" />
<Setter Target="MasterPanel.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="HasSelectionNarrow">
<VisualState.Setters>
<Setter Target="MasterPanel.Visibility" Value="Collapsed" />
<Setter Target="NoSelectionPresenter.Visibility" Value="Collapsed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="NoSelectionNarrow">
<VisualState.Setters>
<Setter Target="NoSelectionPresenter.Visibility" Value="Collapsed" />
<Setter Target="SelectionDetailsPanel.Visibility" Value="Collapsed" />
<Setter Target="MasterPanel.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="WidthStates">
<VisualState x:Name="NarrowState">
<VisualState.Setters>
<Setter Target="MasterColumn.Width" Value="*" />
<Setter Target="DetailsColumn.Width" Value="0" />
<Setter Target="DetailsPanel.(Grid.Column)" Value="0" />
<Setter Target="NoSelectionPresenter.Visibility" Value="Collapsed" />
<Setter Target="MasterPanel.BorderThickness" Value="0" />
<Setter Target="MasterPanel.Width" Value="NaN" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="WideState">
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,115 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- 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 AppBarBackgroundThemeBrush}" />
</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>

View File

@@ -0,0 +1,204 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- No border style for Windows.UI.Xaml.Controls.Primitives.ToggleButton -->
<Style TargetType="ToggleButton" x:Key="NoBorderToggleButtonStyle">
<Setter Property="Background" Value="{ThemeResource ToggleButtonBackgroundThemeBrush}" />
<Setter Property="Foreground" Value="{ThemeResource ToggleButtonForegroundThemeBrush}"/>
<Setter Property="BorderBrush" Value="{ThemeResource ToggleButtonBorderThemeBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource ToggleButtonBorderThemeThickness}" />
<Setter Property="Padding" Value="12,4,12,5" />
<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="ToggleButton">
<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 ToggleButtonPointerOverBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonPressedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonPressedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonDisabledBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonDisabledForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Checked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedPointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedPointerOverBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedPointerOverBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedPressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedPressedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedPressedBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedPressedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedDisabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedDisabledBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonDisabledBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedDisabledForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Indeterminate" />
<VisualState x:Name="IndeterminatePointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonPointerOverBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="IndeterminatePressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonPressedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonPressedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="IndeterminateDisabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonDisabledBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonDisabledForegroundThemeBrush}" />
</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="0"
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>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,253 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:ModernKeePass.Controls">
<Style TargetType="controls:TextBoxWithButton" x:Key="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 MainColor}" />
<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="controls:TextBoxWithButton">
<Grid>
<Grid.Resources>
<Style x:Name="ActionButtonStyle" 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}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontStyle="Normal"
Padding="4,0,4,0"
Text="{TemplateBinding Content}"
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}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ButtonStates">
<VisualState x:Name="ButtonVisible">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="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" />
<Border x:Name="BorderElement"
Grid.Row="1"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Grid.ColumnSpan="2" Grid.Column="0" />
<ContentPresenter x:Name="HeaderContentPresenter"
Grid.Row="0"
Foreground="{ThemeResource TextBoxForegroundHeaderThemeBrush}"
Margin="0,4,0,4"
Grid.ColumnSpan="2" Grid.Column="0"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
FontWeight="Semilight" />
<ScrollViewer x:Name="ContentElement"
Grid.Row="1" Grid.Column="0"
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" Grid.Column="0"
Content="{TemplateBinding PlaceholderText}"
IsHitTestVisible="False"/>
<Button x:Name="ActionButton"
Grid.Row="1"
Style="{StaticResource ActionButtonStyle}"
BorderThickness="{TemplateBinding BorderThickness}"
IsTabStop="False"
Grid.Column="1"
Visibility="Collapsed"
FontSize="{TemplateBinding FontSize}"
Content="{TemplateBinding ButtonSymbol}"
IsEnabled="{TemplateBinding IsButtonEnabled}"
VerticalAlignment="Stretch">
<ToolTipService.ToolTip>
<ToolTip Content="{TemplateBinding ButtonTooltip}" />
</ToolTipService.ToolTip>
</Button>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,222 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="CompositeKeyDefaultKeyFile" xml:space="preserve">
<value>Select key file from disk...</value>
</data>
<data name="CompositeKeyErrorOpen" xml:space="preserve">
<value>Error: </value>
</data>
<data name="CompositeKeyErrorUserKeyFile" xml:space="preserve">
<value>- wrong key file</value>
</data>
<data name="CompositeKeyErrorUserPassword" xml:space="preserve">
<value>- password incorrect</value>
</data>
<data name="CompositeKeyOpening" xml:space="preserve">
<value>Opening...</value>
</data>
<data name="CompositeKeyUpdated" xml:space="preserve">
<value>Database composite key updated.</value>
</data>
<data name="EntityDeleteActionButton" xml:space="preserve">
<value>Delete</value>
</data>
<data name="EntityDeleteCancelButton" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="EntityDeleteTitle" xml:space="preserve">
<value>Warning</value>
</data>
<data name="EntityDeleting" xml:space="preserve">
<value>Deleting</value>
</data>
<data name="EntityRestoredTitle" xml:space="preserve">
<value>Restored</value>
</data>
<data name="EntryDeleted" xml:space="preserve">
<value>Entry permanently removed</value>
</data>
<data name="EntryDeletingConfirmation" xml:space="preserve">
<value>Are you sure you want to delete this entry?</value>
</data>
<data name="EntryRecycled" xml:space="preserve">
<value>Entry moved to the Recycle bin</value>
</data>
<data name="EntryRecyclingConfirmation" xml:space="preserve">
<value>Are you sure you want to send this entry to the recycle bin?</value>
</data>
<data name="EntryRestored" xml:space="preserve">
<value>Entry returned to its original group</value>
</data>
<data name="GroupDeleted" xml:space="preserve">
<value>Group permanently removed</value>
</data>
<data name="GroupDeletingConfirmation" xml:space="preserve">
<value>Are you sure you want to delete the whole group and all its entries?</value>
</data>
<data name="GroupRecycled" xml:space="preserve">
<value>Group moved to the Recycle bin</value>
</data>
<data name="GroupRecyclingConfirmation" xml:space="preserve">
<value>Are you sure you want to send the whole group and all its entries to the recycle bin?</value>
</data>
<data name="GroupRestored" xml:space="preserve">
<value>Group returned to its original group</value>
</data>
<data name="CompositeKeyErrorUserAccount" xml:space="preserve">
<value>- user account</value>
</data>
<data name="RecycleBinTitle" xml:space="preserve">
<value>Recycle Bin</value>
</data>
<data name="EntryCurrent" xml:space="preserve">
<value>Current</value>
</data>
<data name="MessageDialogDBOpenButtonDiscard" xml:space="preserve">
<value>Discard</value>
</data>
<data name="MessageDialogDBOpenButtonSave" xml:space="preserve">
<value>Save changes</value>
</data>
<data name="MessageDialogDBOpenDesc" xml:space="preserve">
<value>Database {0} is currently opened. What would you wish to do?</value>
</data>
<data name="MessageDialogDBOpenTitle" xml:space="preserve">
<value>Opened database</value>
</data>
<data name="MessageDialogSaveErrorButtonDiscard" xml:space="preserve">
<value>Discard</value>
</data>
<data name="MessageDialogSaveErrorButtonSaveAs" xml:space="preserve">
<value>Save as</value>
</data>
<data name="MessageDialogSaveErrorFileTypeDesc" xml:space="preserve">
<value>KeePass 2.x database</value>
</data>
<data name="MessageDialogSaveErrorTitle" xml:space="preserve">
<value>Save error</value>
</data>
<data name="ToastSavedMessage" xml:space="preserve">
<value>Database successfully saved!</value>
</data>
<data name="NewImportFormatHelpCSV" xml:space="preserve">
<value>The CSV file needs to be formatted as such: Name of the account;Login;Password;URL;Comments</value>
</data>
</root>

View File

@@ -0,0 +1,555 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AboutCredits1.Text" xml:space="preserve">
<value>Dominik Reichl for the KeePass application and file format</value>
</data>
<data name="AboutCredits2.Text" xml:space="preserve">
<value>David Lechner for his PCL adapatation of the KeePass Library and his correlated tests</value>
</data>
<data name="AboutCreditsLabel.Text" xml:space="preserve">
<value>Credits</value>
</data>
<data name="AboutDesc.Text" xml:space="preserve">
<value>A modern password manager for the Windows Store</value>
</data>
<data name="AboutHomepage.Text" xml:space="preserve">
<value>Homepage:</value>
</data>
<data name="AppBarDelete.Label" xml:space="preserve">
<value>Delete</value>
</data>
<data name="AppBarEdit.Label" xml:space="preserve">
<value>Edit</value>
</data>
<data name="AppBarHome.Label" xml:space="preserve">
<value>Home</value>
</data>
<data name="AppBarRestore.Label" xml:space="preserve">
<value>Restore</value>
</data>
<data name="AppBarSave.Label" xml:space="preserve">
<value>Save</value>
</data>
<data name="AppBarSettings.Label" xml:space="preserve">
<value>Settings</value>
</data>
<data name="AppBarSort.Label" xml:space="preserve">
<value>Sort</value>
</data>
<data name="AppBarSortEntries.Text" xml:space="preserve">
<value>Entries</value>
</data>
<data name="AppBarSortGroups.Text" xml:space="preserve">
<value>Groups</value>
</data>
<data name="DonateButton.Content" xml:space="preserve">
<value>Donate</value>
</data>
<data name="DonateDesc.Text" xml:space="preserve">
<value>Like this app? Why not make a small donation to support my work and help me keep it ad-free :) ?</value>
</data>
<data name="EntryExpirationDate.Content" xml:space="preserve">
<value>Expiration date</value>
</data>
<data name="EntryExpirationTooltip.Content" xml:space="preserve">
<value>Password has expired</value>
</data>
<data name="EntryItemCopyLogin.Text" xml:space="preserve">
<value>Copy login</value>
</data>
<data name="EntryItemCopyPassword.Text" xml:space="preserve">
<value>Copy password</value>
</data>
<data name="EntryItemCopyUrl.Text" xml:space="preserve">
<value>Navigate to URL</value>
</data>
<data name="EntryLogin.Text" xml:space="preserve">
<value>User name or login</value>
</data>
<data name="EntryNotes.Text" xml:space="preserve">
<value>Notes</value>
</data>
<data name="EntryPassword.Text" xml:space="preserve">
<value>Password</value>
</data>
<data name="EntryShowPassword.Content" xml:space="preserve">
<value>Show password</value>
</data>
<data name="GroupCreateEntry.Text" xml:space="preserve">
<value>Create new entry</value>
</data>
<data name="GroupSearch.PlaceholderText" xml:space="preserve">
<value>Search...</value>
</data>
<data name="GroupTitle.PlaceholderText" xml:space="preserve">
<value>New group name...</value>
</data>
<data name="NewCreateButton.Content" xml:space="preserve">
<value>Create new...</value>
</data>
<data name="NewCreateDesc.Text" xml:space="preserve">
<value>Create a new password database to the location of your chosing.</value>
</data>
<data name="OpenBrowseButton.Content" xml:space="preserve">
<value>Browse files...</value>
</data>
<data name="OpenBrowseDesc.Text" xml:space="preserve">
<value>Open an existing password database from your PC.</value>
</data>
<data name="OpenUrlButton.Content" xml:space="preserve">
<value>From Url...</value>
</data>
<data name="OpenUrlDesc.Text" xml:space="preserve">
<value>Open an existing password database from an Internet location (not yet implemented).</value>
</data>
<data name="PasswordGeneratorAlso.Text" xml:space="preserve">
<value>Also add these characters:</value>
</data>
<data name="PasswordGeneratorBrackets.Content" xml:space="preserve">
<value>Brackets ([], {}, (), ...)</value>
</data>
<data name="PasswordGeneratorButton.Content" xml:space="preserve">
<value>Generate</value>
</data>
<data name="PasswordGeneratorDigits.Content" xml:space="preserve">
<value>Digits (0, 1, 2, ...)</value>
</data>
<data name="PasswordGeneratorLength.Text" xml:space="preserve">
<value>Password Length:</value>
</data>
<data name="PasswordGeneratorLower.Content" xml:space="preserve">
<value>Lower case (a, b, c, ...)</value>
</data>
<data name="PasswordGeneratorMinus.Content" xml:space="preserve">
<value>Minus (-)</value>
</data>
<data name="PasswordGeneratorSpace.Content" xml:space="preserve">
<value>Space ( )</value>
</data>
<data name="PasswordGeneratorSpecial.Content" xml:space="preserve">
<value>Special (!, $, %, ...)</value>
</data>
<data name="PasswordGeneratorTooltip.Content" xml:space="preserve">
<value>Generate password</value>
</data>
<data name="PasswordGeneratorUnderscore.Content" xml:space="preserve">
<value>Underscore (_)</value>
</data>
<data name="PasswordGeneratorUpper.Content" xml:space="preserve">
<value>Upper case (A, B, C, ...)</value>
</data>
<data name="RecentClear.Text" xml:space="preserve">
<value>Clear all</value>
</data>
<data name="ReorderEntriesLabel.Text" xml:space="preserve">
<value>Drag and drop entries to reorder them</value>
</data>
<data name="SaveAsButton.Content" xml:space="preserve">
<value>Save as...</value>
</data>
<data name="SaveAsDesc.Text" xml:space="preserve">
<value>This will save the currently opened database as a new file and leave it open.</value>
</data>
<data name="SaveButton.Content" xml:space="preserve">
<value>Save and close</value>
</data>
<data name="SaveDesc.Text" xml:space="preserve">
<value>This will save and close the currently opened database.</value>
</data>
<data name="SettingsDatabaseCompression.Text" xml:space="preserve">
<value>Compression Algorithm</value>
</data>
<data name="SettingsDatabaseEncryption.Text" xml:space="preserve">
<value>Encryption Algorithm</value>
</data>
<data name="SettingsDatabaseKdf.Text" xml:space="preserve">
<value>Key Derivation Algorithm</value>
</data>
<data name="SettingsDatabaseRecycleBin.Header" xml:space="preserve">
<value>Recycle bin</value>
</data>
<data name="SettingsDatabaseRecycleBin.OffContent" xml:space="preserve">
<value>Disabled</value>
</data>
<data name="SettingsDatabaseRecycleBin.OnContent" xml:space="preserve">
<value>Enabled</value>
</data>
<data name="SettingsDatabaseRecycleBinCreate.Content" xml:space="preserve">
<value>Create a new group</value>
</data>
<data name="SettingsDatabaseRecycleBinExisting.Content" xml:space="preserve">
<value>Use an existing group</value>
</data>
<data name="SettingsNewDatabaseDesc.Text" xml:space="preserve">
<value>Here, you can change some default options when creating a database.</value>
</data>
<data name="SettingsNewDatabaseKdf.Text" xml:space="preserve">
<value>KDBX database file version</value>
</data>
<data name="SettingsNewDatabaseKdfMoreInfo.Text" xml:space="preserve">
<value>Higher is better, but there may be compatibility issues with older applications</value>
</data>
<data name="SettingsNewDatabaseSample.Header" xml:space="preserve">
<value>Create sample data</value>
</data>
<data name="SettingsNewDatabaseSample.OffContent" xml:space="preserve">
<value>No</value>
</data>
<data name="SettingsNewDatabaseSample.OnContent" xml:space="preserve">
<value>Yes</value>
</data>
<data name="SettingsSaveDatabaseSuspend.OffContent" xml:space="preserve">
<value>Don't save</value>
</data>
<data name="SettingsSaveDatabaseSuspend.OnContent" xml:space="preserve">
<value>Save</value>
</data>
<data name="SettingsSaveDatabaseSuspendDesc.Text" xml:space="preserve">
<value>This settings is generally recommended. If you enable it, database will automatically be saved on application suspension and closing. However, if your database is huge, saving may be deemed too long by Windows, which will then forcibly kill the app.</value>
</data>
<data name="SettingsSaveDatabaseSuspendTitle.Text" xml:space="preserve">
<value>Auto-save on suspend?</value>
</data>
<data name="SettingsSecurityDesc1.Text" xml:space="preserve">
<value>Here, you may change your database password, key file, or both. Just click on on</value>
</data>
<data name="SettingsSecurityDesc2.Text" xml:space="preserve">
<value>Update master key</value>
</data>
<data name="SettingsSecurityDesc3.Text" xml:space="preserve">
<value>when you're done. Please make sure to remember the password you choose here!</value>
</data>
<data name="SettingsSecurityTitle.Text" xml:space="preserve">
<value>Change database security options</value>
</data>
<data name="SettingsSecurityUpdateButton.ButtonLabel" xml:space="preserve">
<value>Update master key</value>
</data>
<data name="SettingsWelcomeDesc.Text" xml:space="preserve">
<value>Here, you may change the application or the database settings.</value>
</data>
<data name="SettingsWelcomeHowto.Text" xml:space="preserve">
<value>Select a setting pane on the left to access the options.</value>
</data>
<data name="SettingsWelcomeTitle.Text" xml:space="preserve">
<value>Settings</value>
</data>
<data name="WelcomeNew.Text" xml:space="preserve">
<value>Want to create a new password database? Do it here.</value>
</data>
<data name="WelcomeOpen.Text" xml:space="preserve">
<value>Have an existing password database? Open it here.</value>
</data>
<data name="HistoryLeftListView.HeaderLabel" xml:space="preserve">
<value>History</value>
</data>
<data name="ToastCopyLogin.Message" xml:space="preserve">
<value>Login copied to clipboard</value>
</data>
<data name="ToastCopyPassword.Message" xml:space="preserve">
<value>Password copied to clipboard</value>
</data>
<data name="ToastCopyUrl.Message" xml:space="preserve">
<value>URL copied to clipboard</value>
</data>
<data name="EntryBackgroundColor.Text" xml:space="preserve">
<value>Background color</value>
</data>
<data name="EntryForegroundColor.Text" xml:space="preserve">
<value>Foreground color</value>
</data>
<data name="EntrySymbol.Text" xml:space="preserve">
<value>Icon</value>
</data>
<data name="AddEntryTooltip.Content" xml:space="preserve">
<value>Create a new entry</value>
</data>
<data name="HamburgerMenuHomeLabel.Text" xml:space="preserve">
<value>Home</value>
</data>
<data name="HamburgerMenuHomeTooltip.Content" xml:space="preserve">
<value>Home</value>
</data>
<data name="HamburgerMenuSettingsLabel.Text" xml:space="preserve">
<value>Settings</value>
</data>
<data name="HamburgerMenuSettingsTooltip.Content" xml:space="preserve">
<value>Settings</value>
</data>
<data name="TopMenuDeleteButton.Content" xml:space="preserve">
<value>Delete</value>
</data>
<data name="TopMenuDeleteFlyout.Text" xml:space="preserve">
<value>Delete</value>
</data>
<data name="TopMenuEditButton.Content" xml:space="preserve">
<value>Edit</value>
</data>
<data name="TopMenuEditFlyout.Text" xml:space="preserve">
<value>Edit</value>
</data>
<data name="TopMenuMoreButton.Content" xml:space="preserve">
<value>More</value>
</data>
<data name="TopMenuRestoreButton.Content" xml:space="preserve">
<value>Restore</value>
</data>
<data name="TopMenuRestoreFlyout.Text" xml:space="preserve">
<value>Restore</value>
</data>
<data name="TopMenuSaveButton.Content" xml:space="preserve">
<value>Save</value>
</data>
<data name="TopMenuSaveFlyout.Text" xml:space="preserve">
<value>Save</value>
</data>
<data name="TopMenuSortButton.Content" xml:space="preserve">
<value>Sort</value>
</data>
<data name="TopMenuSortEntriesFlyout.Text" xml:space="preserve">
<value>Sort entries</value>
</data>
<data name="TopMenuSortGroupsFlyout.Text" xml:space="preserve">
<value>Sort groups</value>
</data>
<data name="ToastUpdateDatabase.Message" xml:space="preserve">
<value>Database successfully updated</value>
</data>
<data name="ToastUpdateDatabase.Title" xml:space="preserve">
<value>Composite Key</value>
</data>
<data name="EntryTitle.PlaceholderText" xml:space="preserve">
<value>New entry name...</value>
</data>
<data name="SearchButtonLabel.Text" xml:space="preserve">
<value>Search</value>
</data>
<data name="SearchButtonTooltip.Content" xml:space="preserve">
<value>Search</value>
</data>
<data name="LoginTextBox.ButtonTooltip" xml:space="preserve">
<value>Copy login</value>
</data>
<data name="PasswordTextBox.ButtonTooltip" xml:space="preserve">
<value>Copy password</value>
</data>
<data name="UrlTextBox.ButtonTooltip" xml:space="preserve">
<value>Navigate to URL</value>
</data>
<data name="RestoreEntryCommand.Message" xml:space="preserve">
<value>Entry restored to its original position</value>
</data>
<data name="RestoreGroupCommand.Message" xml:space="preserve">
<value>Group restored to its original position</value>
</data>
<data name="NewImportCheckbox.Content" xml:space="preserve">
<value>Import existing data</value>
</data>
<data name="NewImportFile.Content" xml:space="preserve">
<value>Select a file to import...</value>
</data>
<data name="NewImportFormat.Text" xml:space="preserve">
<value>Format</value>
</data>
<data name="MainMenuItemAbout.Content" xml:space="preserve">
<value>About</value>
</data>
<data name="MainMenuItemDonate.Content" xml:space="preserve">
<value>Donate</value>
</data>
<data name="MainMenuItemNew.Content" xml:space="preserve">
<value>New</value>
</data>
<data name="MainMenuItemOpen.Content" xml:space="preserve">
<value>Open</value>
</data>
<data name="MainMenuItemRecent.Content" xml:space="preserve">
<value>Recent</value>
</data>
<data name="MainMenuItemSave.Content" xml:space="preserve">
<value>Save</value>
</data>
<data name="MainMenuItemSettings.Content" xml:space="preserve">
<value>Settings</value>
</data>
<data name="MainPageOpenedDatabasesHeader.Content" xml:space="preserve">
<value>Databases</value>
</data>
<data name="SettingsMenu.Header" xml:space="preserve">
<value>Settings</value>
</data>
<data name="SettingsMenu.PaneTitle" xml:space="preserve">
<value>Settings</value>
</data>
<data name="SettingsMenuGroupApplication.Content" xml:space="preserve">
<value>Application</value>
</data>
<data name="SettingsMenuGroupDatabase.Content" xml:space="preserve">
<value>Database</value>
</data>
<data name="SettingsMenuItemGeneral.Content" xml:space="preserve">
<value>General</value>
</data>
<data name="SettingsMenuItemNew.Content" xml:space="preserve">
<value>New</value>
</data>
<data name="SettingsMenuItemSave.Content" xml:space="preserve">
<value>Saving</value>
</data>
<data name="SettingsMenuItemSecurity.Content" xml:space="preserve">
<value>Security</value>
</data>
<data name="GroupsAddNew.Text" xml:space="preserve">
<value>New group</value>
</data>
<data name="GroupsHeaderLabel.Text" xml:space="preserve">
<value>Groups</value>
</data>
<data name="AppBarAddEntry.Label" xml:space="preserve">
<value>New entry</value>
</data>
<data name="TopMenuRenameFlyout.Text" xml:space="preserve">
<value>Rename</value>
</data>
<data name="EntryIcon.Text" xml:space="preserve">
<value>Icon</value>
</data>
<data name="EntryPivotItemAdditional.Header" xml:space="preserve">
<value>Additional</value>
</data>
<data name="EntryPivotItemSettings.Header" xml:space="preserve">
<value>Settings</value>
</data>
<data name="EntryPivotItemMain.Header" xml:space="preserve">
<value>Main</value>
</data>
<data name="EntryHistoryComboBox.Text" xml:space="preserve">
<value>History</value>
</data>
<data name="EntryPivotItemHistory.Header" xml:space="preserve">
<value>History</value>
</data>
<data name="CredentialsOkButton.Content" xml:space="preserve">
<value>OK</value>
</data>
<data name="UpdateCredentialsOkButton.Content" xml:space="preserve">
<value>Set credentials</value>
</data>
</root>

View File

@@ -0,0 +1,222 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="CompositeKeyDefaultKeyFile" xml:space="preserve">
<value>Choisissez un fichier...</value>
</data>
<data name="CompositeKeyErrorOpen" xml:space="preserve">
<value>Erreur: </value>
</data>
<data name="CompositeKeyErrorUserKeyFile" xml:space="preserve">
<value>- mauvais fichier de clé</value>
</data>
<data name="CompositeKeyErrorUserPassword" xml:space="preserve">
<value>- mot de passe incorrect</value>
</data>
<data name="CompositeKeyOpening" xml:space="preserve">
<value>Ouverture...</value>
</data>
<data name="CompositeKeyUpdated" xml:space="preserve">
<value>Clé composite de la base de données mise à jour.</value>
</data>
<data name="EntityDeleteActionButton" xml:space="preserve">
<value>Supprimer</value>
</data>
<data name="EntityDeleteCancelButton" xml:space="preserve">
<value>Annuler</value>
</data>
<data name="EntityDeleteTitle" xml:space="preserve">
<value>Attention</value>
</data>
<data name="EntityDeleting" xml:space="preserve">
<value>Suppression</value>
</data>
<data name="EntityRestoredTitle" xml:space="preserve">
<value>Restauré</value>
</data>
<data name="EntryDeleted" xml:space="preserve">
<value>Entrée supprimée définitivement</value>
</data>
<data name="EntryDeletingConfirmation" xml:space="preserve">
<value>Êtes-vous sûr de vouloir supprimer cette entrée ?</value>
</data>
<data name="EntryRecycled" xml:space="preserve">
<value>Entrée placée dans la Corbeille</value>
</data>
<data name="EntryRecyclingConfirmation" xml:space="preserve">
<value>Êtes-vous sûr de vouloir placer cette entrée dans la Corbeille ?</value>
</data>
<data name="EntryRestored" xml:space="preserve">
<value>Entrée replacée dans son groupe d'origine</value>
</data>
<data name="GroupDeleted" xml:space="preserve">
<value>Groupe supprimé définitivement</value>
</data>
<data name="GroupDeletingConfirmation" xml:space="preserve">
<value>Êtes-vous sûr de vouloir supprimer ce groupe et toutes ses entrées ?</value>
</data>
<data name="GroupRecycled" xml:space="preserve">
<value>Groupe placé dans la Corbeille</value>
</data>
<data name="GroupRecyclingConfirmation" xml:space="preserve">
<value>Êtes-vous sûr de vouloir envoyer ce groupe et toutes ses entrées vers la Corbeille ?</value>
</data>
<data name="GroupRestored" xml:space="preserve">
<value>Groupe replacé à sa place originelle</value>
</data>
<data name="CompositeKeyErrorUserAccount" xml:space="preserve">
<value>- compte utilisateur</value>
</data>
<data name="RecycleBinTitle" xml:space="preserve">
<value>Corbeille</value>
</data>
<data name="EntryCurrent" xml:space="preserve">
<value>Courante</value>
</data>
<data name="MessageDialogDBOpenButtonDiscard" xml:space="preserve">
<value>Abandonner</value>
</data>
<data name="MessageDialogDBOpenButtonSave" xml:space="preserve">
<value>Sauvegarder</value>
</data>
<data name="MessageDialogDBOpenDesc" xml:space="preserve">
<value>La base de données {0} est actuellement ouverte. Que souhaitez-vous faire ?</value>
</data>
<data name="MessageDialogDBOpenTitle" xml:space="preserve">
<value>Base de données ouverte</value>
</data>
<data name="MessageDialogSaveErrorButtonDiscard" xml:space="preserve">
<value>Abandonner</value>
</data>
<data name="MessageDialogSaveErrorButtonSaveAs" xml:space="preserve">
<value>Sauvegarder sous</value>
</data>
<data name="MessageDialogSaveErrorFileTypeDesc" xml:space="preserve">
<value>Base de données KeePass 2.x</value>
</data>
<data name="MessageDialogSaveErrorTitle" xml:space="preserve">
<value>Erreur de sauvegarde</value>
</data>
<data name="ToastSavedMessage" xml:space="preserve">
<value>Base de données sauvegardée avec succès !</value>
</data>
<data name="NewImportFormatHelpCSV" xml:space="preserve">
<value>Le fichier CSV doit être formatté de la façon suivante: Nom du compte;Login;Mot de passe;URL;Commentaires</value>
</data>
</root>

View File

@@ -0,0 +1,558 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AboutCredits1.Text" xml:space="preserve">
<value>Dominik Reichl pour l'application KeePass et le format de fichier</value>
</data>
<data name="AboutCredits2.Text" xml:space="preserve">
<value>David Lechner pour son adaptation PCL de la blibliothèque KeePass et ses tests associés</value>
</data>
<data name="AboutCreditsLabel.Text" xml:space="preserve">
<value>Crédits</value>
</data>
<data name="AboutDesc.Text" xml:space="preserve">
<value>Un gestionnaire de mot de passes moderne pour le Windows Store</value>
</data>
<data name="AboutHomepage.Text" xml:space="preserve">
<value>Page d'accueil :</value>
</data>
<data name="AppBarDelete.Label" xml:space="preserve">
<value>Supprimer</value>
</data>
<data name="AppBarEdit.Label" xml:space="preserve">
<value>Editer</value>
</data>
<data name="AppBarHome.Label" xml:space="preserve">
<value>Accueil</value>
</data>
<data name="AppBarRestore.Label" xml:space="preserve">
<value>Restaurer</value>
</data>
<data name="AppBarSave.Label" xml:space="preserve">
<value>Sauvegarder</value>
</data>
<data name="AppBarSettings.Label" xml:space="preserve">
<value>Paramètres</value>
</data>
<data name="AppBarSort.Label" xml:space="preserve">
<value>Trier</value>
</data>
<data name="AppBarSortEntries.Text" xml:space="preserve">
<value>Entrées</value>
</data>
<data name="AppBarSortGroups.Text" xml:space="preserve">
<value>Groupes</value>
</data>
<data name="DonateButton.Content" xml:space="preserve">
<value>Donner</value>
</data>
<data name="DonateDesc.Text" xml:space="preserve">
<value>Vous aimez cette app? Pourquoi ne pas faire un petit don afin de m'encourager et d'éviter le recours aux publicités :) ?</value>
</data>
<data name="EntryExpirationDate.Content" xml:space="preserve">
<value>Date d'expiration</value>
</data>
<data name="EntryExpirationTooltip.Content" xml:space="preserve">
<value>Le mot de passe a expiré</value>
</data>
<data name="EntryItemCopyLogin.Text" xml:space="preserve">
<value>Copier le login</value>
</data>
<data name="EntryItemCopyPassword.Text" xml:space="preserve">
<value>Copier le mot de passe</value>
</data>
<data name="EntryItemCopyUrl.Text" xml:space="preserve">
<value>Naviguer vers l'URL</value>
</data>
<data name="EntryLogin.Text" xml:space="preserve">
<value>Nom d'utilisateur ou login</value>
</data>
<data name="EntryNotes.Text" xml:space="preserve">
<value>Notes</value>
</data>
<data name="EntryPassword.Text" xml:space="preserve">
<value>Mot de passe</value>
</data>
<data name="EntryShowPassword.Content" xml:space="preserve">
<value>Afficher le mot de passe</value>
</data>
<data name="GroupCreateEntry.Text" xml:space="preserve">
<value>Créer une nouvelle entrée</value>
</data>
<data name="GroupSearch.PlaceholderText" xml:space="preserve">
<value>Rechercher...</value>
</data>
<data name="GroupTitle.PlaceholderText" xml:space="preserve">
<value>Nom du nouveau groupe...</value>
</data>
<data name="NewCreateButton.Content" xml:space="preserve">
<value>Créer une nouvelle...</value>
</data>
<data name="NewCreateDesc.Text" xml:space="preserve">
<value>Créer une nouvelle base de données de mots de passe à l'endroit de votre choix.</value>
</data>
<data name="OpenBrowseButton.Content" xml:space="preserve">
<value>Parcourir les fichiers...</value>
</data>
<data name="OpenBrowseDesc.Text" xml:space="preserve">
<value>Ouvrir une base de données de mots de passe existante sur votre PC.</value>
</data>
<data name="OpenUrlButton.Content" xml:space="preserve">
<value>Depuis une URL...</value>
</data>
<data name="OpenUrlDesc.Text" xml:space="preserve">
<value>Ouvrir une base de données de mots de passe depuis Internet (pas encore implementé).</value>
</data>
<data name="PasswordGeneratorAlso.Text" xml:space="preserve">
<value>Ajouter aussi ces caractères :</value>
</data>
<data name="PasswordGeneratorBrackets.Content" xml:space="preserve">
<value>Parenthèses ([], {}, (), ...)</value>
</data>
<data name="PasswordGeneratorButton.Content" xml:space="preserve">
<value>Générer</value>
</data>
<data name="PasswordGeneratorDigits.Content" xml:space="preserve">
<value>Chiffres (0, 1, 2, ...)</value>
</data>
<data name="PasswordGeneratorLength.Text" xml:space="preserve">
<value>Longueur de mot de passe :</value>
</data>
<data name="PasswordGeneratorLower.Content" xml:space="preserve">
<value>Minuscules (a, b, c, ...)</value>
</data>
<data name="PasswordGeneratorMinus.Content" xml:space="preserve">
<value>Moins (-)</value>
</data>
<data name="PasswordGeneratorSpace.Content" xml:space="preserve">
<value>Espace ( )</value>
</data>
<data name="PasswordGeneratorSpecial.Content" xml:space="preserve">
<value>Spéciaux (!, $, %, ...)</value>
</data>
<data name="PasswordGeneratorTooltip.Content" xml:space="preserve">
<value>Générer le mot de passe</value>
</data>
<data name="PasswordGeneratorUnderscore.Content" xml:space="preserve">
<value>Underscore (_)</value>
</data>
<data name="PasswordGeneratorUpper.Content" xml:space="preserve">
<value>Majuscules (A, B, C, ...)</value>
</data>
<data name="RecentClear.Text" xml:space="preserve">
<value>Supprimer tout</value>
</data>
<data name="ReorderEntriesLabel.Text" xml:space="preserve">
<value>Glissez-déposez les entrées pour les réorganiser</value>
</data>
<data name="SaveAsButton.Content" xml:space="preserve">
<value>Sauvegarder sous...</value>
</data>
<data name="SaveAsDesc.Text" xml:space="preserve">
<value>Cela va sauvegarder la base de données dans un nouveau fichier et l'ouvrir.</value>
</data>
<data name="SaveButton.Content" xml:space="preserve">
<value>Sauvegarder et fermer</value>
</data>
<data name="SaveDesc.Text" xml:space="preserve">
<value>Cela va sauvegarder et fermer la base de données.</value>
</data>
<data name="SettingsDatabaseCompression.Text" xml:space="preserve">
<value>Algorithme de compression</value>
</data>
<data name="SettingsDatabaseEncryption.Text" xml:space="preserve">
<value>Algorithme de chiffrement</value>
</data>
<data name="SettingsDatabaseKdf.Text" xml:space="preserve">
<value>Algorithme de dérivation de clé</value>
</data>
<data name="SettingsDatabaseRecycleBin.Header" xml:space="preserve">
<value>Corbeille</value>
</data>
<data name="SettingsDatabaseRecycleBin.OffContent" xml:space="preserve">
<value>Désactivé</value>
</data>
<data name="SettingsDatabaseRecycleBin.OnContent" xml:space="preserve">
<value>Activé</value>
</data>
<data name="SettingsDatabaseRecycleBinCreate.Content" xml:space="preserve">
<value>Créer un nouveau groupe</value>
</data>
<data name="SettingsDatabaseRecycleBinExisting.Content" xml:space="preserve">
<value>Utiliser un groupe existant</value>
</data>
<data name="SettingsNewDatabaseDesc.Text" xml:space="preserve">
<value>Ici, vous pouvez changer certains options lors de la création d'une nouvelle base de données</value>
</data>
<data name="SettingsNewDatabaseKdf.Text" xml:space="preserve">
<value>Version de fichier KDBX</value>
</data>
<data name="SettingsNewDatabaseKdfMoreInfo.Text" xml:space="preserve">
<value>Le plus élévé est le mieux, mais vous pourriez rencontrer des problèmes de compatibilité avec des application plus anciennes</value>
</data>
<data name="SettingsNewDatabaseSample.Header" xml:space="preserve">
<value>Créer des données d'exemple</value>
</data>
<data name="SettingsNewDatabaseSample.OffContent" xml:space="preserve">
<value>Non</value>
</data>
<data name="SettingsNewDatabaseSample.OnContent" xml:space="preserve">
<value>Oui</value>
</data>
<data name="SettingsSaveDatabaseSuspend.OffContent" xml:space="preserve">
<value>Ne pas sauvegarder</value>
</data>
<data name="SettingsSaveDatabaseSuspend.OnContent" xml:space="preserve">
<value>Sauvegarder</value>
</data>
<data name="SettingsSaveDatabaseSuspendDesc.Text" xml:space="preserve">
<value>Ce paramètre est généralement recommandé. Si vous l'activez, la base de données sera sauvegardée automatiquement lors de la suspension et de la fermeture. Cependant, si votre base de données est très volumineuse, il se peut que Windows estime que cela prend trop de temps et tue l'application.</value>
</data>
<data name="SettingsSaveDatabaseSuspendTitle.Text" xml:space="preserve">
<value>Sauvegarder automatiquement lors de la suspension ?</value>
</data>
<data name="SettingsSecurityDesc1.Text" xml:space="preserve">
<value>Ici, vous pouvez changer le mot de passe maître, le fichier de clé, ou les deux. Cliquez simplement sur</value>
</data>
<data name="SettingsSecurityDesc2.Text" xml:space="preserve">
<value>Mettre à jour la clé maître</value>
</data>
<data name="SettingsSecurityDesc3.Text" xml:space="preserve">
<value>quand vous avez fini. Retenez bien le mot de passe que vous utilisez !</value>
</data>
<data name="SettingsSecurityTitle.Text" xml:space="preserve">
<value>Changer les options de sécurité de la base de données</value>
</data>
<data name="SettingsSecurityUpdateButton.ButtonLabel" xml:space="preserve">
<value>Mettre à jour la clé maître</value>
</data>
<data name="SettingsWelcomeDesc.Text" xml:space="preserve">
<value>Ici, vous pouvez changer les options de l'application ou de la base de données.</value>
</data>
<data name="SettingsWelcomeHowto.Text" xml:space="preserve">
<value>Choisissez un élément dans le menu de gauche.</value>
</data>
<data name="SettingsWelcomeTitle.Text" xml:space="preserve">
<value>Paramètres</value>
</data>
<data name="WelcomeNew.Text" xml:space="preserve">
<value>Pour créer une nouvelle base de données de mots de passe, c'est ici.</value>
</data>
<data name="WelcomeOpen.Text" xml:space="preserve">
<value>Pour ouvrir une base de données existante, c'est ici.</value>
</data>
<data name="HistoryLeftListView.HeaderLabel" xml:space="preserve">
<value>Historique</value>
</data>
<data name="ToastCopyLogin.Message" xml:space="preserve">
<value>Login copié dans le presse-papiers</value>
</data>
<data name="ToastCopyPassword.Message" xml:space="preserve">
<value>Mot de passe copié dans le presse-papiers</value>
</data>
<data name="ToastCopyUrl.Message" xml:space="preserve">
<value>URL copié dans le presse-papiers</value>
</data>
<data name="EntryBackgroundColor.Text" xml:space="preserve">
<value>Couleur d'arrière plan</value>
</data>
<data name="EntryForegroundColor.Text" xml:space="preserve">
<value>Couleur du texte</value>
</data>
<data name="EntrySymbol.Text" xml:space="preserve">
<value>Icône</value>
</data>
<data name="AddEntryTooltip.Content" xml:space="preserve">
<value>Créer une nouvelle entrée</value>
</data>
<data name="HamburgerMenuHomeLabel.Text" xml:space="preserve">
<value>Accueil</value>
</data>
<data name="HamburgerMenuHomeTooltip.Content" xml:space="preserve">
<value>Accueil</value>
</data>
<data name="HamburgerMenuSettingsLabel.Text" xml:space="preserve">
<value>Paramètres</value>
</data>
<data name="HamburgerMenuSettingsTooltip.Content" xml:space="preserve">
<value>Paramètres</value>
</data>
<data name="TopMenuDeleteButton.Content" xml:space="preserve">
<value>Supprimer</value>
</data>
<data name="TopMenuDeleteFlyout.Text" xml:space="preserve">
<value>Supprimer</value>
</data>
<data name="TopMenuEditButton.Content" xml:space="preserve">
<value>Editer</value>
</data>
<data name="TopMenuEditFlyout.Text" xml:space="preserve">
<value>Editer</value>
</data>
<data name="TopMenuMoreButton.Content" xml:space="preserve">
<value>Plus</value>
</data>
<data name="TopMenuRestoreButton.Content" xml:space="preserve">
<value>Restaurer</value>
</data>
<data name="TopMenuRestoreFlyout.Text" xml:space="preserve">
<value>Restaurer</value>
</data>
<data name="TopMenuSaveButton.Content" xml:space="preserve">
<value>Sauvegarder</value>
</data>
<data name="TopMenuSaveFlyout.Text" xml:space="preserve">
<value>Sauvegarder</value>
</data>
<data name="TopMenuSortButton.Content" xml:space="preserve">
<value>Trier</value>
</data>
<data name="TopMenuSortEntriesFlyout.Text" xml:space="preserve">
<value>Trier les entrées</value>
</data>
<data name="TopMenuSortGroupsFlyout.Text" xml:space="preserve">
<value>Trier les groupes</value>
</data>
<data name="ToastUpdateDatabase.Message" xml:space="preserve">
<value>Base de données mise à jour</value>
</data>
<data name="ToastUpdateDatabase.Title" xml:space="preserve">
<value>Clé maître</value>
</data>
<data name="EntryTitle.PlaceholderText" xml:space="preserve">
<value>Nom de la nouvelle entrée...</value>
</data>
<data name="SearchButtonLabel.Text" xml:space="preserve">
<value>Recherche</value>
</data>
<data name="SearchButtonTooltip.Content" xml:space="preserve">
<value>Rechercher</value>
</data>
<data name="LoginTextBox.ButtonTooltip" xml:space="preserve">
<value>Copier le login</value>
</data>
<data name="PasswordTextBox.ButtonTooltip" xml:space="preserve">
<value>Copier le mot de passe</value>
</data>
<data name="UrlTextBox.ButtonTooltip" xml:space="preserve">
<value>Naviguer vers l'URL</value>
</data>
<data name="RestoreEntryCommand.Message" xml:space="preserve">
<value>Entrée replacée à son emplacement d'origine</value>
</data>
<data name="RestoreGroupCommand.Message" xml:space="preserve">
<value>Groupe replacée à son emplacement d'origine</value>
</data>
<data name="NewImportCheckbox.Content" xml:space="preserve">
<value>Importer des données existantes</value>
</data>
<data name="NewImportFile.Content" xml:space="preserve">
<value>Sélectionnez un fichier à importer...</value>
</data>
<data name="NewImportFormat.Text" xml:space="preserve">
<value>Format</value>
</data>
<data name="NewImportFormatHelp.Text" xml:space="preserve">
<value>Le fichier CSV doit être formatté de la façon suivante: Nom du compte;Login;Mot de passe:URL;Commentaires</value>
</data>
<data name="MainMenuItemAbout.Content" xml:space="preserve">
<value>A propos</value>
</data>
<data name="MainMenuItemDonate.Content" xml:space="preserve">
<value>Donation</value>
</data>
<data name="MainMenuItemNew.Content" xml:space="preserve">
<value>Nouveau</value>
</data>
<data name="MainMenuItemOpen.Content" xml:space="preserve">
<value>Ouvrir</value>
</data>
<data name="MainMenuItemRecent.Content" xml:space="preserve">
<value>Récents</value>
</data>
<data name="MainMenuItemSave.Content" xml:space="preserve">
<value>Sauvegarder</value>
</data>
<data name="MainMenuItemSettings.Content" xml:space="preserve">
<value>Paramètres</value>
</data>
<data name="MainPageOpenedDatabasesHeader.Content" xml:space="preserve">
<value>Bases de données</value>
</data>
<data name="SettingsMenu.Header" xml:space="preserve">
<value>Paramètres</value>
</data>
<data name="SettingsMenu.PaneTitle" xml:space="preserve">
<value>Paramètres</value>
</data>
<data name="SettingsMenuGroupApplication.Content" xml:space="preserve">
<value>Application</value>
</data>
<data name="SettingsMenuGroupDatabase.Content" xml:space="preserve">
<value>Base de données</value>
</data>
<data name="SettingsMenuItemGeneral.Content" xml:space="preserve">
<value>Général</value>
</data>
<data name="SettingsMenuItemNew.Content" xml:space="preserve">
<value>Nouveau</value>
</data>
<data name="SettingsMenuItemSave.Content" xml:space="preserve">
<value>Sauvegardes</value>
</data>
<data name="SettingsMenuItemSecurity.Content" xml:space="preserve">
<value>Sécurité</value>
</data>
<data name="GroupsAddNew.Text" xml:space="preserve">
<value>Nouveau groupe</value>
</data>
<data name="GroupsHeaderLabel.Text" xml:space="preserve">
<value>Groupes</value>
</data>
<data name="AppBarAddEntry.Label" xml:space="preserve">
<value>Nouvelle entrée</value>
</data>
<data name="TopMenuRenameFlyout.Text" xml:space="preserve">
<value>Renommer</value>
</data>
<data name="EntryIcon.Text" xml:space="preserve">
<value>Icône</value>
</data>
<data name="EntryPivotItemAdditional.Header" xml:space="preserve">
<value>Additionel</value>
</data>
<data name="EntryPivotItemSettings.Header" xml:space="preserve">
<value>Paramètres</value>
</data>
<data name="EntryPivotItemMain.Header" xml:space="preserve">
<value>Principal</value>
</data>
<data name="EntryHistoryComboBox.Text" xml:space="preserve">
<value>Historique</value>
</data>
<data name="EntryPivotItemHistory.Header" xml:space="preserve">
<value>Historique</value>
</data>
<data name="CredentialsOkButton.Content" xml:space="preserve">
<value>OK</value>
</data>
<data name="UpdateCredentialsOkButton.Content" xml:space="preserve">
<value>Sauvegarder</value>
</data>
</root>

View File

@@ -0,0 +1,116 @@
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Threading.Tasks;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Views;
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Entry.Models;
using ModernKeePass.Application.Group.Commands.AddEntry;
using ModernKeePass.Application.Group.Commands.CreateEntry;
using ModernKeePass.Application.Group.Commands.DeleteEntry;
using ModernKeePass.Application.Group.Commands.MoveEntry;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Application.Group.Queries.GetGroup;
using ModernKeePass.ViewModels.ListItems;
namespace ModernKeePass.ViewModels
{
public class EntriesVm : ViewModelBase
{
private readonly IMediator _mediator;
private readonly INavigationService _navigation;
private readonly INotificationService _notification;
private readonly IDialogService _dialog;
private readonly IResourceProxy _resource;
private GroupVm _parentGroup;
private EntryItemVm _reorderedEntry;
private EntryItemVm _selectedEntry;
public ObservableCollection<EntryItemVm> Entries { get; set; }
public EntryItemVm SelectedEntry
{
get => _selectedEntry;
set => Set(() => SelectedEntry, ref _selectedEntry, value);
}
public EntriesVm(IMediator mediator, INavigationService navigation, INotificationService notification, IDialogService dialog, IResourceProxy resource)
{
_mediator = mediator;
_navigation = navigation;
_notification = notification;
_dialog = dialog;
_resource = resource;
}
public async Task Initialize(string groupId)
{
_parentGroup = await _mediator.Send(new GetGroupQuery {Id = groupId});
Entries = new ObservableCollection<EntryItemVm>(_parentGroup.Entries);
Entries.CollectionChanged += EntriesOnCollectionChanged;
}
private async void EntriesOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Remove:
var oldIndex = e.OldStartingIndex;
_reorderedEntry = Entries[oldIndex];
break;
case NotifyCollectionChangedAction.Add:
if (_reorderedEntry == null)
{
var entry = (EntryVm)e.NewItems[0];
await _mediator.Send(new AddEntryCommand { EntryId = entry.Id, ParentGroupId = _parentGroup.Id });
}
else
{
await _mediator.Send(new MoveEntryCommand { Entry = _reorderedEntry, ParentGroup = _parentGroup, Index = e.NewStartingIndex });
}
break;
}
}
private async Task AskForDelete(EntryItemVm entry)
{
if (IsRecycleOnDelete)
{
await Delete(entry);
_notification.Show(_resource.GetResourceValue("EntryRecyclingConfirmation"), _resource.GetResourceValue("EntryRecycled"));
}
else
{
await _dialog.ShowMessage(_resource.GetResourceValue("EntryDeletingConfirmation"),
_resource.GetResourceValue("EntityDeleteTitle"),
_resource.GetResourceValue("EntityDeleteActionButton"),
_resource.GetResourceValue("EntityDeleteCancelButton"),
async isOk =>
{
if (isOk) await Delete(entry);
});
}
}
private async Task Delete(EntryItemVm entry)
{
await _mediator.Send(new DeleteEntryCommand
{
EntryId = entry.Id,
ParentGroupId = _parentGroup.Id,
RecycleBinName = _resource.GetResourceValue("RecycleBinTitle")
});
Entries.Remove(entry);
}
public async Task AddNewEntry(string text)
{
var entry = await _mediator.Send(new CreateEntryCommand { ParentGroup = _parentGroup });
entry.Title = text;
Entries.Add(entry);
SelectedEntry = entry;
}
}
}

View File

@@ -0,0 +1,57 @@
using Autofac;
using ModernKeePass.Domain.AOP;
using ModernKeePass.Domain.Entities;
using ModernKeePass.Domain.Enums;
using ModernKeePass.Domain.Interfaces;
using ModernKeePass.ViewModels.ListItems;
namespace ModernKeePass.ViewModels
{
public class GroupsVm : NotifyPropertyChangedBase
{
private string _title;
private string _newGroupName;
public string Title
{
get => _title;
set
{
_title = value;
OnPropertyChanged(nameof(Title));
}
}
// TODO: check why binding not working
public string NewGroupName
{
get => _newGroupName;
set
{
_newGroupName = value;
OnPropertyChanged(nameof(NewGroupName));
}
}
public GroupItemVm RootItemVm { get; set; }
public GroupsVm(): this(App.Container.Resolve<IDatabaseService>().RootGroupEntity)
{ }
public GroupsVm(GroupEntity groupEntity)
{
Title = groupEntity.Name;
RootItemVm = new GroupItemVm(groupEntity, null);
}
public void AddNewGroup(string groupName = "")
{
var group = new GroupEntity
{
Name = groupName,
Icon = Icon.Folder,
};
RootItemVm.Children.Add(new GroupItemVm(group, RootItemVm));
}
}
}

View File

@@ -0,0 +1,145 @@
using System;
using System.Collections.Generic;
using Windows.UI;
using ModernKeePass.Domain.Entities;
using ModernKeePass.Domain.Enums;
using ModernKeePass.Domain.Interfaces;
namespace ModernKeePass.ViewModels.ListItems
{
public class EntryItemVm : NotifyPropertyChangedBase
{
private readonly ISecurityService _securityService;
public EntryEntity EntryEntity { get; }
public GroupItemVm Parent { get; }
public bool HasExpired => HasExpirationDate && EntryEntity.ExpirationDate < DateTime.Now;
public bool HasUrl => !string.IsNullOrEmpty(Url);
public double PasswordComplexityIndicator => _securityService.EstimatePasswordComplexity(Password);
public string Name
{
get => EntryEntity.Name;
set
{
EntryEntity.Name = value;
OnPropertyChanged(nameof(Name));
}
}
public string UserName
{
get => EntryEntity.UserName;
set => EntryEntity.UserName = value;
}
public string Password
{
get => EntryEntity.Password;
set
{
EntryEntity.Password = value;
OnPropertyChanged();
}
}
public string Url
{
get => EntryEntity.Url?.ToString();
set => EntryEntity.Url = new Uri(value);
}
public string Notes
{
get => EntryEntity.Notes;
set => EntryEntity.Notes = value;
}
public Icon Icon
{
get => HasExpired ? Icon.Important : EntryEntity.Icon;
set => EntryEntity.Icon = value;
}
public DateTimeOffset ExpiryDate
{
get => EntryEntity.ExpirationDate;
set
{
if (!HasExpirationDate) return;
EntryEntity.ExpirationDate = value;
}
}
public TimeSpan ExpiryTime
{
get => EntryEntity.ExpirationDate.TimeOfDay;
set
{
if (!HasExpirationDate) return;
EntryEntity.ExpirationDate = EntryEntity.ExpirationDate.Date.Add(value);
}
}
public bool HasExpirationDate
{
get => EntryEntity.HasExpirationDate;
set
{
EntryEntity.HasExpirationDate = value;
OnPropertyChanged();
}
}
public Color BackgroundColor
{
get => Color.FromArgb(EntryEntity.BackgroundColor.A, EntryEntity.BackgroundColor.R, EntryEntity.BackgroundColor.G, EntryEntity.BackgroundColor.B);
set
{
EntryEntity.BackgroundColor = System.Drawing.Color.FromArgb(value.A, value.R, value.G, value.B);
OnPropertyChanged();
}
}
public Color ForegroundColor
{
get => Color.FromArgb(EntryEntity.ForegroundColor.A, EntryEntity.ForegroundColor.R, EntryEntity.ForegroundColor.G, EntryEntity.ForegroundColor.B);
set
{
EntryEntity.ForegroundColor = System.Drawing.Color.FromArgb(value.A, value.R, value.G, value.B);
OnPropertyChanged();
}
}
public IEnumerable<EntryItemVm> History
{
get
{
var history = new Stack<EntryItemVm>();
foreach (var historyEntry in EntryEntity.History)
{
history.Push(new EntryItemVm(_securityService, historyEntry, Parent));
}
history.Push(this);
return history;
}
}
public Dictionary<string, string> AdditionalFields => EntryEntity.AdditionalFields;
public EntryItemVm(EntryEntity entryEntity, GroupItemVm parentGroup): this(App.Container.Resolve<ISecurityService>(), entryEntity, parentGroup)
{ }
public EntryItemVm(ISecurityService securityService, EntryEntity entryEntity, GroupItemVm parentGroup)
{
_securityService = securityService;
EntryEntity = entryEntity;
Parent = parentGroup;
}
public override string ToString() => EntryEntity.LastModificationDate.ToString("g");
}
}

View File

@@ -0,0 +1,99 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using ModernKeePass.Domain.Entities;
using ModernKeePass.Domain.Enums;
using ModernKeePass.Domain.Interfaces;
namespace ModernKeePass.ViewModels.ListItems
{
public class GroupItemVm: NotifyPropertyChangedBase
{
private readonly IDatabaseService _databaseService;
//private Group _reorderedGroup;
private bool _isEditMode;
public GroupEntity GroupEntity { get; }
public GroupItemVm ParentVm { get; }
public bool IsEditMode
{
get => _isEditMode;
set
{
_isEditMode = value;
OnPropertyChanged();
}
}
public string Text
{
get => GroupEntity.Name;
set
{
GroupEntity.Name = value;
OnPropertyChanged();
}
}
public IEnumerable<EntryItemVm> SubEntries
{
get
{
var subEntries = new List<EntryItemVm>();
subEntries.AddRange(Entries);
foreach (var group in Children)
{
subEntries.AddRange(group.SubEntries);
}
return subEntries;
}
}
public Icon Symbol => GroupEntity.Icon;
public List<EntryItemVm> Entries { get; }
public ObservableCollection<GroupItemVm> Children { get; set; } = new ObservableCollection<GroupItemVm>();
public GroupItemVm(GroupEntity groupEntity, GroupItemVm parent): this(App.Container.Resolve<IDatabaseService>(), groupEntity, parent)
{ }
public GroupItemVm(IDatabaseService databaseService, GroupEntity groupEntity, GroupItemVm parentVm)
{
_databaseService = databaseService;
GroupEntity = groupEntity;
ParentVm = parentVm;
Entries = new List<EntryItemVm>();
foreach (var entry in groupEntity.Entries)
{
Entries.Add(new EntryItemVm(entry, this));
}
foreach (var subGroup in groupEntity.SubGroups)
{
Children.Add(new GroupItemVm(subGroup, this));
}
Children.CollectionChanged += Children_CollectionChanged;
}
// TODO: not triggered when reordering
private void Children_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Remove:
/*var oldIndex = (uint)e.OldStartingIndex;
_reorderedGroup = Group.SubGroups.GetAt(oldIndex);
Group.SubGroups.RemoveAt(oldIndex);*/
_databaseService.DeleteEntity((Entity)e.OldItems[0]);
break;
case NotifyCollectionChangedAction.Add:
/*if (_reorderedGroup == null) Group.AddGroup(((GroupItem)e.NewItems[0]).Group, true);
else Group.Groups.Insert((uint)e.NewStartingIndex, _reorderedGroup);*/
_databaseService.AddEntity(ParentVm.GroupEntity, (Entity)e.NewItems[0]);
break;
}
}
}
}

View File

@@ -0,0 +1,24 @@
using Windows.Storage;
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Database.Queries.GetDatabase;
namespace ModernKeePass.ViewModels
{
public class MainVm
{
public bool IsDatabaseOpened { get; }
public bool HasRecentItems { get; }
public string OpenedDatabaseName { get; }
public IStorageFile File { get; set; }
public MainVm(IMediator mediator, IRecentProxy recent)
{
var database = mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
IsDatabaseOpened = database.IsOpen;
OpenedDatabaseName = database.Name;
HasRecentItems = recent.EntryCount > 0;
}
}
}

View File

@@ -0,0 +1,16 @@
using MediatR;
using ModernKeePass.Application.Database.Queries.GetDatabase;
namespace ModernKeePass.ViewModels
{
public class SettingsVm
{
public bool IsDatabaseOpened { get; }
public SettingsVm(IMediator mediator)
{
var database = mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
IsDatabaseOpened = database.IsOpen;
}
}
}

View File

@@ -0,0 +1,48 @@
/*
In App.xaml:
<Application.Resources>
<vm:ViewModelLocator xmlns:vm="clr-namespace:ModernKeePass"
x:Key="Locator" />
</Application.Resources>
In the View:
DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}"
You can also use Blend to do all this with the tool's support.
See http://www.galasoft.ch/mvvm
*/
using System;
using CommonServiceLocator;
using GalaSoft.MvvmLight.Ioc;
using ModernKeePass.ViewModels.ListItems;
namespace ModernKeePass.ViewModels
{
/// <summary>
/// This class contains static references to all the view models in the
/// application and provides an entry point for the bindings.
/// </summary>
public class ViewModelLocator : ViewModelLocatorCommon
{
/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
public ViewModelLocator()
{
SimpleIoc.Default.Register<SettingsVm>();
SimpleIoc.Default.Register<MainVm>();
SimpleIoc.Default.Register<GroupsVm>();
SimpleIoc.Default.Register<EntriesVm>();
SimpleIoc.Default.Register<GroupItemVm>();
SimpleIoc.Default.Register<EntryItemVm>();
}
public MainVm Main => ServiceLocator.Current.GetInstance<MainVm>(Guid.NewGuid().ToString());
public SettingsVm Settings => ServiceLocator.Current.GetInstance<SettingsVm>(Guid.NewGuid().ToString());
public GroupsVm Groups => ServiceLocator.Current.GetInstance<GroupsVm>(Guid.NewGuid().ToString());
public EntriesVm Entries => ServiceLocator.Current.GetInstance<EntriesVm>(Guid.NewGuid().ToString());
public GroupItemVm GroupItem => ServiceLocator.Current.GetInstance<GroupItemVm>(Guid.NewGuid().ToString());
public EntryItemVm EntryItem => ServiceLocator.Current.GetInstance<EntryItemVm>(Guid.NewGuid().ToString());
}
}

View File

@@ -0,0 +1,267 @@
<Page
x:Class="ModernKeePass.Views.EntriesPage"
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:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:actions="using:ModernKeePass.Actions"
xmlns:converters="using:ModernKeePass.Converters"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:userControls="using:ModernKeePass.Views.UserControls"
xmlns:listItems="using:ModernKeePass.ViewModels.ListItems"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
DataContext="{Binding Source={StaticResource Locator}, Path=Entries}">
<Page.Resources>
<converters:IconToSymbolConverter x:Key="IconToSymbolConverter"/>
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
<converters:ProgressBarLegalValuesConverter x:Key="ProgressBarLegalValuesConverter" />
<converters:DoubleToSolidColorBrushConverter x:Key="DoubleToForegroundBrushComplexityConverter" />
</Page.Resources>
<controls:MasterDetailsView
x:Name="MasterDetailList"
Style="{StaticResource ReorderMasterDetailsView}"
ItemsSource="{x:Bind Model.Entries, Mode=OneWay}"
CompactModeThresholdWidth="720"
SelectedItem="{x:Bind Model.SelectedEntry, Mode=OneWay}">
<controls:MasterDetailsView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Padding" Value="0" />
</Style>
</controls:MasterDetailsView.ItemContainerStyle>
<controls:MasterDetailsView.ItemTemplate>
<DataTemplate x:DataType="listItems:EntryItemVm">
<Grid x:Name="EntryGrid" Padding="12,0,12,0" Background="{Binding BackgroundColor, ConverterParameter={StaticResource SystemControlPageBackgroundTransparentBrush}, Converter={StaticResource ColorToBrushConverter}, Mode=OneWay}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<SymbolIcon Grid.Column="0" Symbol="{x:Bind Icon, Converter={StaticResource IconToSymbolConverter}, ConverterParameter=0}" Foreground="{Binding ForegroundColor, ConverterParameter={StaticResource SystemControlPageTextBaseMediumBrush}, Converter={StaticResource ColorToBrushConverter}, Mode=OneWay}" />
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="15">
<TextBlock Text="{x:Bind Name, Mode=OneWay}" TextWrapping="NoWrap" FontWeight="SemiBold" Foreground="{Binding ForegroundColor, ConverterParameter={StaticResource SystemControlPageTextBaseMediumBrush}, Converter={StaticResource ColorToBrushConverter}, Mode=OneWay}" />
<TextBlock Text="{x:Bind UserName, Mode=OneWay}" MaxHeight="60" Foreground="{Binding ForegroundColor, ConverterParameter={StaticResource SystemControlPageTextBaseMediumBrush}, Converter={StaticResource ColorToBrushConverter}, Mode=OneWay}" />
<TextBlock Text="{x:Bind Url, Mode=OneWay}" MaxHeight="60" Foreground="{Binding ForegroundColor, ConverterParameter={StaticResource SystemControlPageTextBaseMediumBrush}, Converter={StaticResource ColorToBrushConverter}, Mode=OneWay}"/>
</StackPanel>
<Grid.ContextFlyout>
<MenuFlyout>
<MenuFlyoutItem x:Uid="EntryItemCopyLogin" Icon="Page2">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<actions:ClipboardAction Text="{x:Bind UserName, Mode=OneWay}" />
<actions:ToastAction x:Uid="ToastCopyLogin" Title="{x:Bind Name, Mode=OneWay}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</MenuFlyoutItem>
<MenuFlyoutItem x:Uid="EntryItemCopyPassword" Icon=" ProtectedDocument">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<actions:ClipboardAction Text="{x:Bind Password, Mode=OneWay}" />
<actions:ToastAction x:Uid="ToastCopyPassword" Title="{x:Bind Name, Mode=OneWay}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</MenuFlyoutItem>
<MenuFlyoutItem x:Uid="EntryItemCopyUrl" Icon="OpenFile" IsEnabled="{x:Bind HasUrl, Mode=OneWay}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<actions:NavigateToUrlAction Url="{x:Bind Url, Mode=OneWay}" />
<actions:ToastAction x:Uid="ToastCopyUrl" Title="{x:Bind Name, Mode=OneWay}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</MenuFlyoutItem>
<MenuFlyoutSeparator />
<MenuFlyoutItem x:Uid="TopMenuDeleteFlyout" Icon="Delete" Click="DeleteFlyoutItem_OnClick" />
</MenuFlyout>
</Grid.ContextFlyout>
</Grid>
</DataTemplate>
</controls:MasterDetailsView.ItemTemplate>
<controls:MasterDetailsView.MasterCommandBar>
<CommandBar
DefaultLabelPosition="Right"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
HorizontalAlignment="Stretch"
FontFamily="Segoe UI">
<AppBarToggleButton x:Name="AddEntryButton" x:Uid="AppBarAddEntry" Icon="Add">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Checked">
<!--<core:ChangePropertyAction TargetObject="{Binding ElementName=AddEntryButton}" PropertyName="IsEnabled" Value="False" />-->
<core:ChangePropertyAction TargetObject="{Binding ElementName=NewEntryNameTextBox}" PropertyName="Visibility" Value="Visible" />
<actions:SetupFocusAction TargetObject="{Binding ElementName=NewEntryNameTextBox}" />
</core:EventTriggerBehavior>
<core:EventTriggerBehavior EventName="Unchecked">
<!--<core:ChangePropertyAction TargetObject="{Binding ElementName=AddEntryButton}" PropertyName="IsEnabled" Value="False" />-->
<core:ChangePropertyAction TargetObject="{Binding ElementName=NewEntryNameTextBox}" PropertyName="Visibility" Value="Collapsed" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</AppBarToggleButton>
</CommandBar>
</controls:MasterDetailsView.MasterCommandBar>
<controls:MasterDetailsView.MasterHeader>
<TextBox x:Name="NewEntryNameTextBox" Visibility="Collapsed" KeyUp="NewEntryNameTextBox_OnKeyDown" />
</controls:MasterDetailsView.MasterHeader>
<controls:MasterDetailsView.DetailsTemplate>
<DataTemplate x:DataType="listItems:EntryItemVm">
<!--<Frame x:Name="ContentFrame" SourcePageType="pages:EntryPage" />-->
<Pivot>
<Pivot.TitleTemplate>
<DataTemplate x:DataType="listItems:EntryItemVm">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Style="{ThemeResource TitleTextBlockStyle}" />
</StackPanel>
</DataTemplate>
</Pivot.TitleTemplate>
<PivotItem x:Uid="EntryPivotItemMain" Margin="0">
<Grid Background="White">
<ScrollViewer>
<StackPanel Margin="20">
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="0,20,0,0"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
<Style TargetType="CheckBox">
<Setter Property="Margin" Value="0,20,0,0"/>
<Setter Property="FontSize" Value="18"/>
</Style>
<Style TargetType="TextBox" x:Key="EntryTextBoxWithButtonStyle">
<Setter Property="Width" Value="350"/>
<Setter Property="Height" Value="32"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
</StackPanel.Resources>
<TextBlock x:Uid="EntryLogin" />
<TextBox Text="{x:Bind UserName, Mode=TwoWay}" Style="{StaticResource EntryTextBoxWithButtonStyle}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:ClipboardAction Text="{x:Bind UserName}" />
<actions:ToastAction x:Uid="ToastCopyLogin" Title="{x:Bind Name}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</TextBox>
<TextBlock x:Uid="EntryPassword" />
<PasswordBox x:Name="Password"
HorizontalAlignment="Left"
Password="{x:Bind Password, Mode=TwoWay}"
Width="350"
Height="32"
PasswordRevealMode="Hidden">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:ClipboardAction Text="{x:Bind Password}" />
<actions:ToastAction x:Uid="ToastCopyPassword" Title="{x:Bind Name}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</PasswordBox>
<ProgressBar
Maximum="128"
Width="350"
HorizontalAlignment="Left"
Value="{x:Bind PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}"
Foreground="{x:Bind PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroundBrushComplexityConverter}}" />
<CheckBox x:Uid="EntryShowPassword" HorizontalAlignment="Left" Margin="0">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Checked">
<core:ChangePropertyAction TargetObject="{Binding ElementName=Password}" PropertyName="PasswordRevealMode" Value="Visible" />
</core:EventTriggerBehavior>
<core:EventTriggerBehavior EventName="Unchecked">
<core:ChangePropertyAction TargetObject="{Binding ElementName=Password}" PropertyName="PasswordRevealMode" Value="Hidden" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</CheckBox>
<TextBlock TextWrapping="Wrap" Text="URL" FontSize="18"/>
<TextBox Text="{x:Bind Url, Mode=TwoWay}" MaxLength="256" Style="{StaticResource EntryTextBoxWithButtonStyle}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:NavigateToUrlAction Url="{x:Bind Url}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</TextBox>
<TextBlock x:Uid="EntryNotes" />
<TextBox
HorizontalAlignment="Left"
TextWrapping="Wrap"
Text="{x:Bind Notes, Mode=TwoWay}"
Width="350"
Height="200"
AcceptsReturn="True"
IsSpellCheckEnabled="True" />
<CheckBox
x:Uid="EntryExpirationDate"
IsChecked="{x:Bind HasExpirationDate, Mode=TwoWay}" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<SymbolIcon
Grid.Column="0"
Symbol="Important"
Foreground="DarkRed"
Visibility="{x:Bind HasExpired}">
<ToolTipService.ToolTip>
<ToolTip x:Uid="EntryExpirationTooltip" />
</ToolTipService.ToolTip>
</SymbolIcon>
<StackPanel Grid.Column="1" x:Name="ExpirationDatePanel" Visibility="{x:Bind HasExpirationDate, Mode=OneWay}">
<DatePicker Date="{x:Bind ExpiryDate, Mode=TwoWay}" Style="{StaticResource MainColorDatePicker}" />
<TimePicker Margin="0,10,0,0" Time="{x:Bind ExpiryTime, Mode=TwoWay}" Style="{StaticResource MainColorTimePicker}" />
</StackPanel>
</Grid>
</StackPanel>
</ScrollViewer>
</Grid>
</PivotItem>
<PivotItem x:Uid="EntryPivotItemAdditional">
<ItemsControl ItemsSource="{x:Bind AdditionalFields}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Key}" />
<TextBox Text="{Binding Value, Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</PivotItem>
<PivotItem x:Uid="EntryPivotItemHistory">
<ListView ItemsSource="{x:Bind History}" SelectionChanged="HistoryListView_SelectionChanged" />
</PivotItem>
<PivotItem x:Uid="EntryPivotItemSettings">
<ScrollViewer>
<StackPanel Orientation="Vertical">
<TextBlock x:Uid="EntryIcon" />
<userControls:SymbolPickerUserControl
SelectedSymbol="{Binding IconId, Converter={StaticResource IconToSymbolConverter}, ConverterParameter=0, Mode=TwoWay}" />
<TextBlock x:Uid="EntryBackgroundColor" Margin="0,0,10,0" />
<ColorPicker
HorizontalAlignment="Left"
ColorSpectrumShape="Ring"
IsColorPreviewVisible="False"
IsColorChannelTextInputVisible="False"
IsHexInputVisible="False"
LostFocus="ColorPickerBackground_LostFocus" />
<TextBlock x:Uid="EntryForegroundColor" Margin="0,0,10,0" />
<ColorPicker
HorizontalAlignment="Left"
ColorSpectrumShape="Ring"
IsColorPreviewVisible="False"
IsColorChannelTextInputVisible="False"
IsHexInputVisible="False"
LostFocus="ColorPickerForeground_LostFocus" />
</StackPanel>
</ScrollViewer>
</PivotItem>
</Pivot>
</DataTemplate>
</controls:MasterDetailsView.DetailsTemplate>
</controls:MasterDetailsView>
</Page>

View File

@@ -0,0 +1,85 @@
using System;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Navigation;
using ModernKeePass.ViewModels;
using ModernKeePass.ViewModels.ListItems;
// TODO: check https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlListView/cs/Samples/MasterDetailSelection
namespace ModernKeePass.Views
{
public partial class EntriesPage
{
public EntriesVm Model => (EntriesVm)DataContext;
public EntriesPage()
{
InitializeComponent();
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
if (e.Parameter is string groupId) await Model.Initialize(groupId);
}
private async void DeleteFlyoutItem_OnClick(object sender, RoutedEventArgs e)
{
if (sender is MenuFlyoutItem flyout)
{
var item = (EntryItemVm)flyout.DataContext;
var deleteFileDialog = new ContentDialog
{
Title = $"{_resourceService.GetResourceValue("EntityDeleteActionButton")} {item.Name} ?",
Content = _databaseService.IsRecycleBinEnabled
? _resourceService.GetResourceValue("EntryRecyclingConfirmation")
: _resourceService.GetResourceValue("EntryDeletingConfirmation"),
PrimaryButtonText = _resourceService.GetResourceValue("EntityDeleteActionButton"),
CloseButtonText = _resourceService.GetResourceValue("EntityDeleteCancelButton")
};
var result = await deleteFileDialog.ShowAsync();
// Delete the file if the user clicked the primary button.
// Otherwise, do nothing.
// TODO: move this logic to the service
if (result == ContentDialogResult.Primary)
{
Model.Entries.Remove(item);
}
}
}
private void NewEntryNameTextBox_OnKeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == VirtualKey.Enter)
{
e.Handled = true;
var text = NewEntryNameTextBox.Text;
if (string.IsNullOrEmpty(text)) return;
Model.AddNewEntry(text);
AddEntryButton.IsChecked = false;
}
else if (e.Key == VirtualKey.Escape)
{
AddEntryButton.IsChecked = false;
}
}
private void ColorPickerBackground_LostFocus(object sender, RoutedEventArgs e)
{
if (sender is ColorPicker colorPicker) ((EntryItemVm) colorPicker.DataContext).BackgroundColor = colorPicker.Color;
}
private void ColorPickerForeground_LostFocus(object sender, RoutedEventArgs e)
{
if (sender is ColorPicker colorPicker) ((EntryItemVm) colorPicker.DataContext).ForegroundColor = colorPicker.Color;
}
private void HistoryListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
}
}

View File

@@ -0,0 +1,168 @@
<Page
x:Class="ModernKeePass.Views.EntryPage"
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:userControls="using:ModernKeePass.Views.UserControls"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:actions="using:ModernKeePass.Actions"
xmlns:converters="using:ModernKeePass.Converters"
xmlns:listItems="using:ModernKeePass.ViewModels.ListItems"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<converters:ProgressBarLegalValuesConverter x:Key="ProgressBarLegalValuesConverter" />
<converters:DoubleToSolidColorBrushConverter x:Key="DoubleToForegroungBrushComplexityConverter" />
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter" />
<converters:IconToSymbolConverter x:Key="IntToSymbolConverter" />
</Page.Resources>
<Grid>
<Pivot>
<Pivot.TitleTemplate>
<DataTemplate x:DataType="listItems:EntryItemVm">
<Grid>
<TextBlock Text="{x:Bind Name}" Style="{ThemeResource HeaderTextBlockStyle}" />
</Grid>
</DataTemplate>
</Pivot.TitleTemplate>
<PivotItem Header="Main" Margin="0">
<Grid Background="White">
<RelativePanel>
<StackPanel Margin="20">
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="0,20,0,0"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
<Style TargetType="CheckBox">
<Setter Property="Margin" Value="0,20,0,0"/>
<Setter Property="FontSize" Value="18"/>
</Style>
<Style TargetType="TextBox" x:Key="EntryTextBoxWithButtonStyle">
<Setter Property="Width" Value="350"/>
<Setter Property="Height" Value="32"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
</StackPanel.Resources>
<TextBlock x:Uid="EntryLogin" />
<TextBox
Text="{x:Bind Vm.UserName, Mode=TwoWay}"
Style="{StaticResource EntryTextBoxWithButtonStyle}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:ClipboardAction Text="{x:Bind Vm.UserName}" />
<actions:ToastAction x:Uid="ToastCopyLogin" Title="{x:Bind Vm.Name}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</TextBox>
<TextBlock x:Uid="EntryPassword" />
<PasswordBox x:Name="Password"
HorizontalAlignment="Left"
Password="{x:Bind Vm.Password, Mode=TwoWay}"
Width="350"
Height="32"
PasswordRevealMode="Hidden">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:ClipboardAction Text="{x:Bind Vm.Password}" />
<actions:ToastAction x:Uid="ToastCopyPassword" Title="{x:Bind Vm.Name}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</PasswordBox>
<ProgressBar
Maximum="128"
Width="350"
HorizontalAlignment="Left"
Value="{x:Bind Vm.PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}, Mode=OneWay}"
Foreground="{x:Bind Vm.PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroungBrushComplexityConverter}, Mode=OneWay}" />
<CheckBox
x:Uid="EntryShowPassword"
HorizontalAlignment="Left"
Margin="0">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Checked">
<core:ChangePropertyAction TargetObject="{Binding ElementName=Password}" PropertyName="PasswordRevealMode" Value="Visible" />
</core:EventTriggerBehavior>
<core:EventTriggerBehavior EventName="Unchecked">
<core:ChangePropertyAction TargetObject="{Binding ElementName=Password}" PropertyName="PasswordRevealMode" Value="Hidden" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</CheckBox>
<TextBlock TextWrapping="Wrap" Text="URL" FontSize="18"/>
<TextBox
Text="{x:Bind Vm.Url, Mode=TwoWay}"
MaxLength="256"
Style="{StaticResource EntryTextBoxWithButtonStyle}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:NavigateToUrlAction Url="{x:Bind Vm.Url}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</TextBox>
<TextBlock x:Uid="EntryNotes" />
<TextBox
HorizontalAlignment="Left"
TextWrapping="Wrap"
Text="{x:Bind Vm.Notes, Mode=TwoWay}"
Width="350"
Height="200"
AcceptsReturn="True"
IsSpellCheckEnabled="True" />
<CheckBox
x:Uid="EntryExpirationDate"
IsChecked="{x:Bind Vm.HasExpirationDate, Mode=TwoWay}" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<SymbolIcon
Grid.Column="0"
Symbol="Important"
Foreground="DarkRed"
Visibility="{x:Bind Vm.HasExpired}">
<ToolTipService.ToolTip>
<ToolTip x:Uid="EntryExpirationTooltip" />
</ToolTipService.ToolTip>
</SymbolIcon>
<StackPanel
Grid.Column="1"
x:Name="ExpirationDatePanel"
Visibility="{x:Bind Vm.HasExpirationDate, Mode=OneWay}">
<DatePicker
Date="{x:Bind Vm.ExpiryDate, Mode=TwoWay}"
Style="{StaticResource MainColorDatePicker}" />
<TimePicker
Margin="0,10,0,0"
Time="{x:Bind Vm.ExpiryTime, Mode=TwoWay}"
Style="{StaticResource MainColorTimePicker}" />
</StackPanel>
</Grid>
</StackPanel>
</RelativePanel>
</Grid>
</PivotItem>
<PivotItem Header="Additional">
<StackPanel Orientation="Vertical">
<TextBlock x:Uid="EntryIcon" />
<userControls:SymbolPickerUserControl
SelectedSymbol="{x:Bind Vm.Icon, Converter={StaticResource IntToSymbolConverter}, ConverterParameter=0, Mode=TwoWay}" />
<TextBlock x:Uid="EntryBackgroundColor" />
<userControls:ColorPickerUserControl
HorizontalAlignment="Left"
SelectedColor="{x:Bind Vm.BackgroundColor, Converter={StaticResource ColorToBrushConverter}, Mode=TwoWay}" />
<TextBlock x:Uid="EntryForegroundColor" />
<userControls:ColorPickerUserControl
SelectedColor="{x:Bind Vm.ForegroundColor, Converter={StaticResource ColorToBrushConverter}, Mode=TwoWay}" />
</StackPanel>
</PivotItem>
<PivotItem Header="History" />
</Pivot>
</Grid>
</Page>

View File

@@ -0,0 +1,21 @@
using Windows.UI.Xaml.Navigation;
using ModernKeePass.ViewModels.ListItems;
namespace ModernKeePass.Views
{
public partial class EntryPage
{
public EntryItemVm Vm { get; set; }
public EntryPage()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.Parameter is EntryItemVm entry) Vm = entry;
}
}
}

View File

@@ -0,0 +1,249 @@
<Page
x:Class="ModernKeePass.Views.GroupsPage"
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:converters="using:ModernKeePass.Converters"
xmlns:actions="using:ModernKeePass.Actions"
xmlns:listItems="using:ModernKeePass.ViewModels.ListItems"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<converters:IconToSymbolConverter x:Key="IconToSymbolConverter"/>
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
</Page.Resources>
<!-- SplitView -->
<SplitView x:Name="SplitView"
CompactPaneLength="{StaticResource MenuSize}"
OpenPaneLength="320"
IsPaneOpen="True"
FontFamily="Segoe UI">
<SplitView.Pane>
<Grid x:Name="SplitViewPane">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid
x:Name="TopButtonsBorder"
Grid.Row="0"
Grid.Column="0"
BorderThickness="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button
IsEnabled="{x:Bind Frame.CanGoBack}"
Margin="0"
BorderThickness="0"
Style="{StaticResource NavigationBackButtonNormalStyle}"
Click="BackButton_OnClick" />
<TextBox x:Name="NewGroupNameTextBox"
Grid.Column="1"
Visibility="Visible"
HorizontalAlignment="Right"
Text="{x:Bind Vm.NewGroupName, Mode=TwoWay}"
Height="30"
Width="230"
KeyUp="NewGroupNameTextBox_KeyDown"
LostFocus="NewGroupNameTextBox_LostFocus" />
<Button x:Name="AddButton"
Grid.Column="2"
Margin="0"
Width="{StaticResource MenuSize}"
Height="{StaticResource MenuSize}"
Background="Transparent"
VerticalAlignment="Top"
BorderThickness="0"
FontFamily="Segoe MDL2 Assets"
Content="&#xE710;">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<core:ChangePropertyAction TargetObject="{Binding ElementName=NewGroupNameTextBox}" PropertyName="Visibility" Value="Visible"/>
<core:ChangePropertyAction TargetObject="{Binding ElementName=AddButton}" PropertyName="IsEnabled" Value="False"/>
<actions:SetupFocusAction TargetObject="{Binding ElementName=NewEntryNameTextBox}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Button>
</Grid>
<Grid
Grid.Row="1"
Grid.Column="0"
BorderThickness="0">
<AutoSuggestBox
x:Name="AutoSuggestBox"
x:Uid="GroupSearch"
Width="250"
HorizontalAlignment="Center"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
QueryIcon="Find"
TextMemberPath="Name"
TextChanged="AutoSuggestBox_TextChanged"
QuerySubmitted="AutoSuggestBox_QuerySubmitted">
<AutoSuggestBox.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Padding" Value="0" />
</Style>
</AutoSuggestBox.ItemContainerStyle>
<AutoSuggestBox.ItemTemplate>
<DataTemplate x:DataType="listItems:EntryItemVm">
<Grid x:Name="EntryGrid" Padding="12,0,12,0" Background="{Binding BackgroundColor, ConverterParameter={StaticResource SystemControlPageBackgroundTransparentBrush}, Converter={StaticResource ColorToBrushConverter}, Mode=OneWay}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<SymbolIcon Grid.Column="0" Symbol="{x:Bind Icon, Converter={StaticResource IconToSymbolConverter}, ConverterParameter=0}" Foreground="{StaticResource SystemControlPageTextBaseHighBrush}" />
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="15">
<TextBlock Text="{Binding Name}" TextWrapping="NoWrap" Foreground="{Binding ForegroundColor, ConverterParameter={StaticResource SystemControlPageTextBaseHighBrush}, Converter={StaticResource ColorToBrushConverter}}"/>
<TextBlock Text="{x:Bind Parent.Text}" Foreground="{Binding ForegroundColor, ConverterParameter={StaticResource SystemControlPageTextBaseMediumBrush}, Converter={StaticResource ColorToBrushConverter}}" MaxHeight="60" />
</StackPanel>
</Grid>
</DataTemplate>
</AutoSuggestBox.ItemTemplate>
</AutoSuggestBox>
</Grid>
<!-- Navigation Tree -->
<TreeView x:Name="NavigationTree"
Grid.Row="2"
ItemsSource="{x:Bind Vm.RootItemVm.Children}"
ItemInvoked="NavigationTree_OnItemInvoked">
<TreeView.ItemTemplate>
<DataTemplate x:DataType="listItems:GroupItemVm">
<TreeViewItem ItemsSource="{x:Bind Children}">
<Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Visibility="{x:Bind IsEditMode, Mode=OneWay, Converter={StaticResource InverseBooleanToVisibilityConverter}}">
<SymbolIcon Symbol="{x:Bind Symbol, Converter={StaticResource IconToSymbolConverter}}" />
<TextBlock x:Name="GroupName" Text="{x:Bind Text, Mode=OneWay}" Width="200" Margin="10,0,0,0" />
<StackPanel.ContextFlyout>
<MenuFlyout>
<MenuFlyoutItem x:Uid="TopMenuDeleteFlyout" Icon="Delete" Click="DeleteFlyoutItem_OnClick" />
<MenuFlyoutItem x:Uid="TopMenuRenameFlyout" Click="RenameFlyoutItem_OnClick" />
</MenuFlyout>
</StackPanel.ContextFlyout>
</StackPanel>
<TextBox
Text="{x:Bind Text, Mode=TwoWay}"
Visibility="{x:Bind IsEditMode, Mode=OneWay}"
Width="200"
KeyDown="GroupNameTextBox_KeyDown"
LostFocus="GroupNameTextBox_OnLostFocus" />
</Grid>
</TreeViewItem>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<CommandBar DefaultLabelPosition="Right"
Grid.Row="3"
Background="Transparent"
HorizontalAlignment="Center"
FontFamily="Segoe UI">
<AppBarButton x:Uid="AppBarHome" Icon="Home">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<core:NavigateToPageAction TargetPage="ModernKeePass.Views.MainPage10" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</AppBarButton>
<AppBarButton x:Uid="AppBarSettings" Icon="Setting">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<core:NavigateToPageAction TargetPage="ModernKeePass.Views.SettingsPage10" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</AppBarButton>
</CommandBar>
</Grid>
</SplitView.Pane>
<SplitView.Content>
<StackPanel Orientation="Vertical">
<Button Margin="0"
Height="{StaticResource MenuSize}"
Background="Transparent"
BorderThickness="0"
Click="HamburgerButton_OnClick">
<StackPanel Orientation="Horizontal" Margin="5,0,0,0">
<FontIcon x:Name="HamburgerButton" FontFamily="Segoe MDL2 Assets" Glyph="&#xE700;" />
<TextBlock Text="{x:Bind Vm.Title, Mode=OneWay}" FontFamily="Segoe UI" FontWeight="Bold" Margin="20,0,0,0" VerticalAlignment="Center" />
</StackPanel>
</Button>
<!-- Navigation Frame -->
<Frame x:Name="SplitViewFrame"
Padding="0"
FontFamily="Segoe UI">
<Frame.ContentTransitions>
<TransitionCollection>
<NavigationThemeTransition>
<NavigationThemeTransition.DefaultNavigationTransitionInfo>
<DrillInNavigationTransitionInfo />
</NavigationThemeTransition.DefaultNavigationTransitionInfo>
</NavigationThemeTransition>
</TransitionCollection>
</Frame.ContentTransitions>
</Frame>
</StackPanel>
</SplitView.Content>
<!-- Responsive Visual States -->
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<!-- VisualState to be triggered when window width is >=1007 effective pixels -->
<VisualState x:Name="Expanded">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="HamburgerButton.Visibility" Value="Collapsed" />
<Setter Target="SplitView.DisplayMode" Value="Inline" />
<Setter Target="SplitViewPane.Background" Value="{ThemeResource SystemControlChromeHighAcrylicWindowMediumBrush}" />
<Setter Target="TopButtonsBorder.Background" Value="{ThemeResource SystemControlChromeHighAcrylicWindowMediumBrush}" />
</VisualState.Setters>
</VisualState>
<!-- VisualState to be triggered when window width is >=640 and <=1007 effective pixels -->
<!-- Skipped -->
<!--<VisualState x:Name="Compact">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="641" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="SplitView.DisplayMode"
Value="CompactOverlay" />
<Setter Target="SplitView.IsPaneOpen"
Value="False" />
</VisualState.Setters>
</VisualState>-->
<!-- VisualState to be triggered when window width is >=0 and <641 effective pixels -->
<VisualState x:Name="Minimal">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="HamburgerButton.Visibility" Value="Visible" />
<Setter Target="SplitView.DisplayMode" Value="CompactInline" />
<Setter Target="SplitViewPane.Background" Value="{ThemeResource SystemControlChromeHighAcrylicElementMediumBrush}" />
<Setter Target="TopButtonsBorder.Background" Value="Transparent" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</SplitView>
</Page>

View File

@@ -0,0 +1,194 @@
using System;
using System.Linq;
using Windows.ApplicationModel.Core;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Navigation;
using Autofac;
using ModernKeePass.Domain.Entities;
using ModernKeePass.Domain.Interfaces;
using ModernKeePass.ViewModels.ListItems;
using ModernKeePass.ViewModels;
namespace ModernKeePass.Views
{
public partial class GroupsPage
{
private readonly IDatabaseService _databaseService;
private readonly IResourceService _resourceService;
public GroupsVm Vm { get; set; }
public GroupsPage(): this(App.Container.Resolve<IDatabaseService>(), App.Container.Resolve<IResourceService>())
{ }
public GroupsPage(IDatabaseService databaseService, IResourceService resourceService)
{
InitializeComponent();
SetTitleBar();
_databaseService = databaseService;
_resourceService = resourceService;
}
private void SetTitleBar()
{
var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
//coreTitleBar.LayoutMetricsChanged += CoreTitleBar_LayoutMetricsChanged;
//coreTitleBar.IsVisibleChanged += CoreTitleBar_IsVisibleChanged;
coreTitleBar.ExtendViewIntoTitleBar = false;
//UpdateTitleBarLayout(coreTitleBar);
// Set XAML element as a draggable region.
//Window.Current.SetTitleBar(AppTitleBar);
}
/*private void CoreTitleBar_IsVisibleChanged(CoreApplicationViewTitleBar sender, object args) =>
AppTitleBar.Visibility = sender.IsVisible ? Visibility.Visible : Visibility.Collapsed;
private void CoreTitleBar_LayoutMetricsChanged(CoreApplicationViewTitleBar coreTitleBar, object args) => UpdateTitleBarLayout(coreTitleBar);
private void UpdateTitleBarLayout(CoreApplicationViewTitleBar coreTitleBar)
{
// Get the size of the caption controls area and back button
// (returned in logical pixels), and move your content around as necessary.
LeftPaddingColumn.Width = new GridLength(coreTitleBar.SystemOverlayLeftInset);
RightPaddingColumn.Width = new GridLength(coreTitleBar.SystemOverlayRightInset);
//BackBorder.Margin = new Thickness(0, 0, coreTitleBar.SystemOverlayLeftInset, 0);
AutoSuggestBox.Margin = new Thickness(0, 5, coreTitleBar.SystemOverlayRightInset, 5);
// Update title bar control size as needed to account for system size changes.
//AppTitleBar.Height = coreTitleBar.Height;
AppTitleBar.Height = 44;
}*/
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (!(e.Parameter is GroupEntity group)) group = _databaseService.RootGroupEntity;
Vm = new GroupsVm(group);
}
private void HamburgerButton_OnClick(object sender, RoutedEventArgs e)
{
//SplitView.IsPaneOpen = !SplitView.IsPaneOpen;
switch (SplitView.DisplayMode)
{
case SplitViewDisplayMode.Inline:
SplitView.DisplayMode = SplitViewDisplayMode.CompactInline;
break;
case SplitViewDisplayMode.CompactInline:
SplitView.DisplayMode = SplitViewDisplayMode.Inline;
break;
}
}
private void BackButton_OnClick(object sender, RoutedEventArgs e)
{
if (Frame.CanGoBack)
{
Frame.GoBack();
}
}
private void NavigationTree_OnItemInvoked(TreeView sender, TreeViewItemInvokedEventArgs args)
{
if (args.InvokedItem is GroupItemVm group)
{
Vm.Title = group.Text;
SplitViewFrame.Navigate(typeof(EntriesPage), group);
}
}
private void RenameFlyoutItem_OnClick(object sender, RoutedEventArgs e)
{
if (sender is MenuFlyoutItem flyout) ((GroupItemVm)flyout.DataContext).IsEditMode = true;
}
private async void DeleteFlyoutItem_OnClick(object sender, RoutedEventArgs e)
{
if (sender is MenuFlyoutItem flyout)
{
var item = (GroupItemVm) flyout.DataContext;
var deleteFileDialog = new ContentDialog
{
Title = $"{_resourceService.GetResourceValue("EntityDeleteActionButton")} {item.Text} ?",
Content = _databaseService.IsRecycleBinEnabled
? _resourceService.GetResourceValue("GroupRecyclingConfirmation")
: _resourceService.GetResourceValue("GroupDeletingConfirmation"),
PrimaryButtonText = _resourceService.GetResourceValue("EntityDeleteActionButton"),
CloseButtonText = _resourceService.GetResourceValue("EntityDeleteCancelButton")
};
var result = await deleteFileDialog.ShowAsync();
// Delete the file if the user clicked the primary button.
// Otherwise, do nothing.
// TODO: move this logic to the service
if (result == ContentDialogResult.Primary)
{
item.ParentVm.Children.Remove(item);
// TODO: refresh treeview
}
}
}
private void GroupNameTextBox_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == VirtualKey.Enter) GroupNameTextBox_OnLostFocus(sender, null);
}
private void GroupNameTextBox_OnLostFocus(object sender, RoutedEventArgs e)
{
if (sender is TextBox textBox) ((GroupItemVm)textBox.DataContext).IsEditMode = false;
}
private void NewGroupNameTextBox_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == VirtualKey.Enter)
{
e.Handled = true;
var text = ((TextBox)sender).Text;
if (string.IsNullOrEmpty(text)) return;
Vm.AddNewGroup(text);
AddButton.IsEnabled = true;
NewGroupNameTextBox.Visibility = Visibility.Collapsed;
NewGroupNameTextBox.Text = string.Empty;
}
}
private void AutoSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
{
// Only get results when it was a user typing,
// otherwise assume the value got filled in by TextMemberPath
// or the handler for SuggestionChosen.
if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
{
//Set the ItemsSource to be your filtered dataset
//sender.ItemsSource = dataset;
sender.ItemsSource = Vm.RootItemVm.SubEntries.Where(e => e.Name.IndexOf(sender.Text, StringComparison.OrdinalIgnoreCase) >= 0);
}
}
private void AutoSuggestBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
if (args.ChosenSuggestion != null)
{
// User selected an item from the suggestion list, take an action on it here.
}
else
{
// Use args.QueryText to determine what to do.
}
}
private void NewGroupNameTextBox_LostFocus(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(NewGroupNameTextBox.Text))
{
NewGroupNameTextBox.Visibility = Visibility.Collapsed;
}
}
}
}

View File

@@ -0,0 +1,37 @@
<Page
x:Class="ModernKeePass.Views.MainPage10"
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:controls="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
DataContext="{Binding Source={StaticResource Locator}, Path=Main}">
<Grid>
<Grid x:Name="AppTitleBar" Background="Transparent" />
<controls:NavigationView
x:Name="NavigationView"
IsBackButtonVisible="Collapsed"
Header="ModernKeePass"
PaneTitle="ModernKeePass"
ItemInvoked="NavigationView_OnItemInvoked"
Loaded="NavigationView_OnLoaded">
<controls:NavigationView.MenuItems>
<controls:NavigationViewItem x:Name="Welcome" Tag="welcome" Visibility="Collapsed" />
<controls:NavigationViewItem x:Uid="MainMenuItemOpen" x:Name="Open" Icon="Page2" Tag="open" />
<controls:NavigationViewItem x:Uid="MainMenuItemNew" x:Name="New" Icon="Add" Tag="new" />
<controls:NavigationViewItem x:Uid="MainMenuItemSave" x:Name="Save" Icon="Save" IsEnabled="{x:Bind Model.IsDatabaseOpened, Mode=OneTime}" Tag="save" />
<controls:NavigationViewItem x:Uid="MainMenuItemRecent" x:Name="Recent" Icon="Copy" Tag="recent" />
<controls:NavigationViewItem x:Uid="MainMenuItemAbout" x:Name="About" Icon="Help" Tag="about" />
<controls:NavigationViewItem x:Uid="MainMenuItemDonate" x:Name="Donate" Icon="Shop" Tag="donate" />
<controls:NavigationViewItemSeparator/>
<controls:NavigationViewItemHeader x:Uid="MainPageOpenedDatabasesHeader" Visibility="{x:Bind Model.IsDatabaseOpened, Mode=OneWay}"/>
<controls:NavigationViewItem x:Name="Database" Content="{x:Bind Model.OpenedDatabaseName, Mode=OneWay}" Icon="ProtectedDocument" Visibility="{x:Bind Model.IsDatabaseOpened, Mode=OneWay}" Tag="database"/>
</controls:NavigationView.MenuItems>
<Frame x:Name="ContentFrame" Margin="24"/>
</controls:NavigationView>
</Grid>
</Page>

View File

@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Windows.ApplicationModel.Core;
using Windows.Storage;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Navigation;
using MUXC = Microsoft.UI.Xaml.Controls;
using ModernKeePass.ViewModels;
namespace ModernKeePass.Views
{
public partial class MainPage10
{
private MainVm Model => (MainVm)DataContext;
private readonly IList<(string Tag, Type Page)> _pages = new List<(string Tag, Type Page)>
{
("welcome", typeof(WelcomePage)),
("open", typeof(OpenDatabasePage)),
("new", typeof(NewDatabasePage)),
("save", typeof(SaveDatabasePage)),
("recent", typeof(RecentDatabasesPage)),
("about", typeof(AboutPage)),
("donate", typeof(DonatePage)),
("database", typeof(GroupsPage))
};
public MainPage10()
{
InitializeComponent();
SetTitleBar();
}
private void SetTitleBar()
{
var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
coreTitleBar.ExtendViewIntoTitleBar = true;
Window.Current.SetTitleBar(AppTitleBar);
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
Model.File = e.Parameter as StorageFile;
}
private void NavigationView_OnItemInvoked(MUXC.NavigationView navigationView, MUXC.NavigationViewItemInvokedEventArgs args)
{
if (args.IsSettingsInvoked)
Frame.Navigate(typeof(SettingsPage10));
else
{
// Getting the Tag from Content (args.InvokedItem is the content of NavigationViewItem)
var navItem = NavigationView.MenuItems
.OfType<MUXC.NavigationViewItem>()
.First(i => args.InvokedItem.Equals(i.Content));
NavigationView_Navigate(navItem);
}
}
private void NavigationView_Navigate(MUXC.NavigationViewItem navItem, object parameter = null)
{
var (_, page) = _pages.First(p => p.Tag.Equals(navItem.Tag));
NavigationView.Header = navItem.Content;
ContentFrame.Navigate(page, parameter);
}
private void NavigationView_OnLoaded(object sender, RoutedEventArgs e)
{
object parameter = null;
if (Model.IsDatabaseOpened)
{
NavigationView.SelectedItem = Save;
parameter = Frame;
}
else if (Model.File != null)
{
NavigationView.SelectedItem = Open;
parameter = Model.File;
}
else if (Model.HasRecentItems)
{
NavigationView.SelectedItem = Recent;
}
else
{
NavigationView.SelectedItem = Welcome;
}
NavigationView_Navigate((MUXC.NavigationViewItem)NavigationView.SelectedItem, parameter);
}
}
}

View File

@@ -0,0 +1,39 @@
<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.Views.AboutPage"
mc:Ignorable="d">
<Page.DataContext>
<viewModels:AboutViewModel/>
</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 x:Uid="AboutDesc" />
</TextBlock>
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="30,0,0,0">
<Run x:Uid="AboutHomepage" />
<Hyperlink NavigateUri="https://wismna.github.io/ModernKeePass/" Foreground="{StaticResource MainColor}">
<Run Text="https://wismna.github.io/ModernKeePass/"/>
</Hyperlink>
</TextBlock>
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="10,0,0,0">
<Run x:Uid="AboutCreditsLabel" />
</TextBlock>
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="30,0,0,0">
<Run x:Uid="AboutCredits1" />
</TextBlock>
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="30,0,0,0">
<Run x:Uid="AboutCredits2" />
</TextBlock>
</StackPanel>
</Page>

View File

@@ -0,0 +1,15 @@
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace ModernKeePass.Views
{
/// <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();
}
}
}

View File

@@ -0,0 +1,20 @@
<Page
x:Class="ModernKeePass.Views.DonatePage"
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:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
mc:Ignorable="d">
<Grid>
<ProgressRing x:Name="LoadingRing" IsActive="True" Width="50" Height="50" Foreground="{StaticResource MainColor}" />
<WebView Source="https://PayPal.Me/wismna">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="DOMContentLoaded">
<core:ChangePropertyAction TargetObject="{Binding ElementName=LoadingRing}" PropertyName="IsActive" Value="False" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</WebView>
</Grid>
</Page>

View File

@@ -0,0 +1,15 @@
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace ModernKeePass.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class DonatePage
{
public DonatePage()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,37 @@
<Page
x:Class="ModernKeePass.Views.ImportExportPage"
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">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="200" />
<ColumnDefinition Width="200" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="Import" Style="{StaticResource SubheaderTextBlockStyle}" />
<HyperlinkButton Grid.Column="0" Grid.Row="1" Content="Select file..." Style="{StaticResource MainColorHyperlinkButton}" Click="ImportFileButton_OnClick" />
<StackPanel Grid.Column="1" Grid.Row="1" >
<TextBlock Text="Format" Style="{StaticResource BodyTextBlockStyle}" Margin="0,0,0,10" />
<ComboBox Style="{StaticResource MainColorComboBox}">
<ComboBoxItem>CSV</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel Grid.Column="2" Grid.Row="1" >
<TextBlock Text="Import into..." Style="{StaticResource BodyTextBlockStyle}" Margin="0,0,0,10" />
<RadioButton GroupName="ImportDestination" Content="New database" />
<RadioButton GroupName="ImportDestination" Content="Currently opened database" />
</StackPanel>
<Button Grid.Column="3" Grid.Row="1" Content="Import" Style="{StaticResource MainColorButton}" />
</Grid>
</Page>

View File

@@ -0,0 +1,35 @@
using System;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace ModernKeePass.Views
{
/// <summary>
/// The import/export page.
/// </summary>
public sealed partial class ImportExportPage
{
public ImportExportPage()
{
InitializeComponent();
}
private async void ImportFileButton_OnClick(object sender, RoutedEventArgs e)
{
var picker =
new FileOpenPicker
{
ViewMode = PickerViewMode.List,
SuggestedStartLocation = PickerLocationId.DocumentsLibrary
};
picker.FileTypeFilter.Add(".csv");
// Application now has read/write access to the picked file
var file = await picker.PickSingleFileAsync();
if (file == null) return;
}
}
}

View File

@@ -0,0 +1,47 @@
<Page
x:Class="ModernKeePass.Views.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:userControls="using:ModernKeePass.Views.UserControls"
mc:Ignorable="d">
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<HyperlinkButton x:Uid="NewCreateButton" Click="CreateDatabaseButton_OnClick" Foreground="{StaticResource MainColor}" Style="{StaticResource MainColorHyperlinkButton}" />
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" x:Uid="NewCreateDesc" />
<Border HorizontalAlignment="Left" BorderThickness="1" BorderBrush="AliceBlue" Width="550" Visibility="{x:Bind ViewModel.IsFileSelected, Mode=OneWay}">
<StackPanel Margin="25,0,25,0">
<TextBlock Text="{x:Bind ViewModel.Name}" />
<userControls:UpdateCredentialsUserControl x:Uid="CompositeKeyNewButton" DatabaseFilePath="{x:Bind ViewModel.DatabaseFilePath, Mode=OneWay}" CredentialsUpdated="CompositeKeyUserControl_OnValidationChecked" />
</StackPanel>
</Border>
<CheckBox x:Name="CheckBox" x:Uid="NewImportCheckbox" Margin="15,10,0,0" IsChecked="{x:Bind ViewModel.IsImportChecked, Mode=TwoWay}" Visibility="{x:Bind ViewModel.IsFileSelected}" />
<Border HorizontalAlignment="Left" BorderThickness="1" BorderBrush="AliceBlue" Width="550" Visibility="{Binding IsChecked, ElementName=CheckBox}">
<StackPanel Margin="25,0,25,0">
<StackPanel Orientation="Horizontal">
<TextBlock x:Uid="NewImportFormat" Margin="0,15,0,10" Style="{StaticResource BodyTextBlockStyle}" />
<ComboBox Style="{StaticResource MainColorComboBox}" Margin="15,15,0,0" SelectionChanged="ImportFormatComboBox_OnSelectionChanged">
<ComboBoxItem>CSV</ComboBoxItem>
</ComboBox>
<Button Margin="5,10,0,0" Style="{StaticResource TextBlockButtonStyle}">
<SymbolIcon Symbol="Help" RenderTransformOrigin="0.5,0.5" >
<SymbolIcon.RenderTransform>
<CompositeTransform ScaleX="0.7" ScaleY="0.7"/>
</SymbolIcon.RenderTransform>
</SymbolIcon>
<Button.Flyout>
<Flyout>
<TextBlock Text="{x:Bind ViewModel.ImportFormatHelp}" TextWrapping="WrapWholeWords" MaxWidth="400" />
</Flyout>
</Button.Flyout>
</Button>
</StackPanel>
<HyperlinkButton x:Name="ImportFileLink" x:Uid="NewImportFile" Margin="-15,0,0,0" Style="{StaticResource MainColorHyperlinkButton}" Click="ImportFileButton_OnClick" />
</StackPanel>
</Border>
</StackPanel>
</Page>

View File

@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using Windows.Storage.AccessCache;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Autofac;
using ModernKeePass.Domain.Dtos;
using ModernKeePass.Domain.Enums;
using ModernKeePass.Domain.Interfaces;
using ModernKeePass.Events;
using ModernKeePass.ViewModels;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace ModernKeePass.Views
{
/// <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;
private readonly IResourceService _resourceService;
public NewViewModel ViewModel { get; }
public NewDatabasePage(): this(App.Container.Resolve<IResourceService>())
{ }
public NewDatabasePage(IResourceService resourceService)
{
InitializeComponent();
ViewModel = new NewViewModel();
_resourceService = resourceService;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
_mainFrame = e.Parameter as Frame;
}
private async void CreateDatabaseButton_OnClick(object sender, RoutedEventArgs e)
{
var savePicker = new FileSavePicker
{
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
SuggestedFileName = "New Database"
};
savePicker.FileTypeChoices.Add("KeePass 2.x database", new List<string> { ".kdbx" });
var file = await savePicker.PickSaveFileAsync();
if (file == null) return;
var token = StorageApplicationPermissions.FutureAccessList.Add(file);
var fileInfo = new FileInfo
{
Path = token,
Name = file.DisplayName
};
await ViewModel.OpenFile(fileInfo);
}
private void ImportFormatComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var comboBox = sender as ComboBox;
switch (comboBox?.SelectedIndex)
{
case 0:
ViewModel.ImportFormat = ImportFormat.CSV;
ViewModel.ImportFileExtensionFilter = ".csv";
ViewModel.ImportFormatHelp = _resourceService.GetResourceValue("NewImportFormatHelpCSV");
break;
}
}
private async void ImportFileButton_OnClick(object sender, RoutedEventArgs e)
{
var picker =
new FileOpenPicker
{
ViewMode = PickerViewMode.List,
SuggestedStartLocation = PickerLocationId.DocumentsLibrary
};
if (!string.IsNullOrEmpty(ViewModel.ImportFileExtensionFilter))
picker.FileTypeFilter.Add(ViewModel.ImportFileExtensionFilter);
// Application now has read/write access to the picked file
ViewModel.ImportFile = await picker.PickSingleFileAsync();
if (ViewModel.ImportFile != null) ImportFileLink.Content = ViewModel.ImportFile.Name;
}
private void CompositeKeyUserControl_OnValidationChecked(object sender, EventArgs e)
{
ViewModel.PopulateInitialData();
_mainFrame.Navigate(typeof(GroupsPage));
}
}
}

View File

@@ -0,0 +1,30 @@
<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:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:userControls="using:ModernKeePass.Views.UserControls"
x:Class="ModernKeePass.Views.OpenDatabasePage"
mc:Ignorable="d">
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<HyperlinkButton x:Uid="OpenBrowseButton" Click="ButtonBase_OnClick" Foreground="{StaticResource MainColor}" Style="{StaticResource MainColorHyperlinkButton}" />
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" x:Uid="OpenBrowseDesc" />
<!--<HyperlinkButton x:Uid="OpenUrlButton" IsEnabled="False" Foreground="{StaticResource MainColor}" Style="{StaticResource MainColorHyperlinkButton}" />
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" x:Uid="OpenUrlDesc" />-->
<Border HorizontalAlignment="Left" BorderThickness="1" BorderBrush="AliceBlue" Width="550" Visibility="{x:Bind ViewModel.IsFileSelected, Mode=OneWay}">
<StackPanel Margin="25,0,25,0">
<TextBlock Text="{x:Bind ViewModel.Name, Mode=OneWay}" />
<userControls:CredentialsUserControl x:Uid="CompositeKeyOpenButton" DatabaseFilePath="{x:Bind ViewModel.DatabaseFilePath, Mode=OneWay}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ValidationChecked">
<core:NavigateToPageAction TargetPage="ModernKeePass.Views.GroupsPage" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</userControls:CredentialsUserControl>
</StackPanel>
</Border>
</StackPanel>
</Page>

View File

@@ -0,0 +1,58 @@
using System;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Navigation;
using ModernKeePass.ViewModels;
using Windows.Storage.AccessCache;
using ModernKeePass.Domain.Dtos;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace ModernKeePass.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class OpenDatabasePage
{
public OpenViewModel ViewModel { get; }
public OpenDatabasePage()
{
InitializeComponent();
ViewModel = new OpenViewModel();
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.Parameter is FileInfo fileInfo)
{
await ViewModel.OpenFile(fileInfo);
}
}
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
var picker =
new FileOpenPicker
{
ViewMode = PickerViewMode.List,
SuggestedStartLocation = PickerLocationId.DocumentsLibrary
};
picker.FileTypeFilter.Add(".kdbx");
// Application now has read/write access to the picked file
var file = await picker.PickSingleFileAsync();
if (file == null) return;
var token = StorageApplicationPermissions.FutureAccessList.Add(file);
var fileInfo = new FileInfo
{
Path = token,
Name = file.DisplayName
};
await ViewModel.OpenFile(fileInfo);
}
}
}

View File

@@ -0,0 +1,70 @@
<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:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:userControls="using:ModernKeePass.Views.UserControls"
xmlns:listItems="using:ModernKeePass.ViewModels.ListItems"
x:Class="ModernKeePass.Views.RecentDatabasesPage"
mc:Ignorable="d">
<Page.Resources>
<CollectionViewSource x:Name="RecentItemsSource" Source="{x:Bind ViewModel.RecentItems}" />
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<HyperlinkButton Grid.Row="0"
HorizontalAlignment="Right"
Style="{StaticResource MainColorHyperlinkButton}"
Foreground="{StaticResource MainColor}"
Command="{x:Bind ViewModel.ClearAllCommand}">
<StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="Cancel" />
<TextBlock x:Uid="RecentClear" VerticalAlignment="Center" Margin="10,0,0,0" />
</StackPanel>
</HyperlinkButton>
<ListView Grid.Row="1"
ItemsSource="{Binding Source={StaticResource RecentItemsSource}}"
SelectedItem="{x:Bind ViewModel.SelectedItem, Mode=TwoWay}"
ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}">
<ListView.DataContext>
<listItems:RecentItemViewModel />
</ListView.DataContext>
<ListView.ItemTemplate>
<DataTemplate x:DataType="listItems:RecentItemViewModel">
<Grid Margin="10,0,10,0">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Text="{x:Bind Name}" Padding="5,0,0,0" />
<!--<TextBlock Grid.Row="1" Text="{Binding Path}" Padding="5,0,0,0" FontSize="10" />-->
<userControls:CredentialsUserControl Grid.Row="2"
x:Name="DatabaseUserControl"
x:Uid="CompositeKeyOpenButton"
HorizontalAlignment="Stretch"
MinWidth="400"
Margin="0,10,0,0"
Visibility="{x:Bind IsSelected}"
DatabaseFilePath="{x:Bind Token}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ValidationChecked">
<!--<core:CallMethodAction TargetObject="{Binding}" MethodName="UpdateAccessTime" />-->
<core:NavigateToPageAction TargetPage="ModernKeePass.Views.GroupsPage" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</userControls:CredentialsUserControl>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>

View File

@@ -0,0 +1,20 @@
// Pour en savoir plus sur le modèle d'élément Page vierge, consultez la page http://go.microsoft.com/fwlink/?LinkId=234238
using ModernKeePass.ViewModels;
namespace ModernKeePass.Views
{
/// <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 RecentViewModel ViewModel { get; }
public RecentDatabasesPage()
{
InitializeComponent();
ViewModel = new RecentViewModel();
}
}
}

View File

@@ -0,0 +1,15 @@
<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"
x:Class="ModernKeePass.Views.SaveDatabasePage"
mc:Ignorable="d">
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<HyperlinkButton x:Uid="SaveButton" Click="SaveButton_OnClick" Foreground="{StaticResource MainColor}" Style="{StaticResource MainColorHyperlinkButton}" />
<TextBlock x:Uid="SaveDesc" Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" />
<HyperlinkButton x:Uid="SaveAsButton" Click="SaveAsButton_OnClick" Foreground="{StaticResource MainColor}" Style="{StaticResource MainColorHyperlinkButton}" />
<TextBlock x:Uid="SaveAsDesc" Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" />
</StackPanel>
</Page>

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using Windows.Storage.AccessCache;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using ModernKeePass.ViewModels;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace ModernKeePass.Views
{
/// <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 SaveViewModel ViewModel { get; }
public SaveDatabasePage()
{
InitializeComponent();
ViewModel = new SaveViewModel();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
_mainFrame = e.Parameter as Frame;
}
private void SaveButton_OnClick(object sender, RoutedEventArgs e)
{
ViewModel.Save();
_mainFrame.Navigate(typeof(MainPage10));
}
private async void SaveAsButton_OnClick(object sender, RoutedEventArgs e)
{
var savePicker = new FileSavePicker
{
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
SuggestedFileName = "New Database"
};
savePicker.FileTypeChoices.Add("KeePass 2.x database", new List<string> { ".kdbx" });
var file = await savePicker.PickSaveFileAsync();
if (file == null) return;
var token = StorageApplicationPermissions.FutureAccessList.Add(file);
ViewModel.Save(token);
_mainFrame.Navigate(typeof(MainPage10));
}
}
}

View File

@@ -0,0 +1,19 @@
<Page
x:Class="ModernKeePass.Views.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,10,0,10">
<SymbolIcon Symbol="Back" Margin="0,7,40,0" />
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" x:Uid="WelcomeOpen" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,6,0,10">
<SymbolIcon Symbol="Back" Margin="0,7,40,0" />
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" x:Uid="WelcomeNew" />
</StackPanel>
</StackPanel>
</Page>

View File

@@ -0,0 +1,15 @@
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace ModernKeePass.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class WelcomePage
{
public WelcomePage()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,34 @@
<Page
x:Class="ModernKeePass.Views.SettingsPage10"
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"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
DataContext="{Binding Source={StaticResource Locator}, Path=Settings}">
<Grid>
<Grid x:Name="AppTitleBar" Background="Transparent" />
<NavigationView
x:Name="NavigationView"
x:Uid="SettingsMenu"
IsSettingsVisible="False"
ItemInvoked="NavigationView_OnItemInvoked"
Loaded="NavigationView_OnLoaded"
BackRequested="NavigationView_OnBackRequested">
<NavigationView.MenuItems>
<NavigationViewItem x:Name="Welcome" Tag="welcome" Visibility="Collapsed" />
<NavigationViewItemHeader x:Uid="SettingsMenuGroupApplication" />
<NavigationViewItem x:Uid="SettingsMenuItemNew" Icon="Add" Tag="new" />
<NavigationViewItem x:Uid="SettingsMenuItemSave" Icon="Save" Tag="save" />
<NavigationViewItemSeparator/>
<NavigationViewItemHeader x:Uid="SettingsMenuGroupDatabase" />
<NavigationViewItem x:Uid="SettingsMenuItemGeneral" Icon="Setting" IsEnabled="{x:Bind Model.IsDatabaseOpened, Mode=OneTime}" Tag="general" />
<NavigationViewItem x:Uid="SettingsMenuItemSecurity" Icon="Permissions" IsEnabled="{x:Bind Model.IsDatabaseOpened, Mode=OneTime}" Tag="security" />
</NavigationView.MenuItems>
<Frame x:Name="ContentFrame" Margin="24"/>
</NavigationView>
</Grid>
</Page>

View File

@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.ApplicationModel.Core;
using ModernKeePass.ViewModels;
using ModernKeePass.Views.SettingsPageFrames;
namespace ModernKeePass.Views
{
public partial class SettingsPage10
{
private SettingsVm Model => (SettingsVm) DataContext;
private readonly IList<(string Tag, Type Page)> _pages = new List<(string Tag, Type Page)>
{
("welcome", typeof(SettingsWelcomePage)),
("new", typeof(SettingsNewDatabasePage)),
("save", typeof(SettingsSavePage)),
("general", typeof(SettingsDatabasePage)),
("security", typeof(SettingsSecurityPage))
};
public SettingsPage10()
{
InitializeComponent();
SetTitleBar();
}
private void SetTitleBar()
{
var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
coreTitleBar.ExtendViewIntoTitleBar = true;
Window.Current.SetTitleBar(AppTitleBar);
}
private void NavigationView_OnItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
{
// Getting the Tag from Content (args.InvokedItem is the content of NavigationViewItem)
var navItem = NavigationView.MenuItems
.OfType<NavigationViewItem>()
.First(i => args.InvokedItem.Equals(i.Content));
NavigationView_Navigate(navItem);
}
private void NavigationView_Navigate(NavigationViewItem navItem)
{
var item = _pages.First(p => p.Tag.Equals(navItem.Tag));
NavigationView.Header = navItem.Content;
ContentFrame.Navigate(item.Page);
}
private void NavigationView_OnLoaded(object sender, RoutedEventArgs e)
{
NavigationView_Navigate(Welcome);
NavigationView.IsBackEnabled = Frame.CanGoBack;
}
private void NavigationView_OnBackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args)
{
Frame.GoBack();
}
}
}

View File

@@ -0,0 +1,23 @@
<Page
x:Class="ModernKeePass.Views.SettingsPageFrames.SettingsDatabasePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ToggleSwitch x:Uid="SettingsDatabaseRecycleBin" IsOn="{x:Bind ViewModel.HasRecycleBin, Mode=TwoWay}" Style="{StaticResource MainColorToggleSwitch}" />
<StackPanel Visibility="{x:Bind ViewModel.HasRecycleBin}">
<RadioButton x:Uid="SettingsDatabaseRecycleBinCreate" GroupName="Recycle" IsChecked="{x:Bind ViewModel.IsNewRecycleBin, Mode=TwoWay}" />
<RadioButton x:Name="RadioButton" x:Uid="SettingsDatabaseRecycleBinExisting" GroupName="Recycle" IsChecked="{x:Bind ViewModel.HasRecycleBin}" />
<ComboBox ItemsSource="{x:Bind ViewModel.Groups}" SelectedItem="{x:Bind ViewModel.SelectedRecycleBin, Mode=TwoWay}" IsEnabled="{Binding IsChecked, ElementName=RadioButton}" />
</StackPanel>
<TextBlock x:Uid="SettingsDatabaseEncryption" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,20,0,10" />
<ComboBox ItemsSource="{x:Bind ViewModel.Ciphers}" SelectedItem="{x:Bind ViewModel.SelectedCipher, Mode=TwoWay}" ItemContainerStyle="{StaticResource MainColorComboBoxItem}" Style="{StaticResource MainColorComboBox}" />
<TextBlock x:Uid="SettingsDatabaseCompression" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,20,0,10" />
<ComboBox ItemsSource="{x:Bind ViewModel.Compressions}" SelectedItem="{x:Bind ViewModel.SelectedCompression, Mode=TwoWay}" ItemContainerStyle="{StaticResource MainColorComboBoxItem}" Style="{StaticResource MainColorComboBox}" />
<TextBlock x:Uid="SettingsDatabaseKdf" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,20,0,10" />
<ComboBox ItemsSource="{x:Bind ViewModel.KeyDerivations}" SelectedItem="{x:Bind ViewModel.SelectedKeyDerivation, Mode=TwoWay}" ItemContainerStyle="{StaticResource MainColorComboBoxItem}" Style="{StaticResource MainColorComboBox}" />
</StackPanel>
</Page>

View File

@@ -0,0 +1,20 @@
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
using ModernKeePass.ViewModels.ListItems;
namespace ModernKeePass.Views.SettingsPageFrames
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class SettingsDatabasePage
{
public SettingsDatabaseViewModel ViewModel { get; }
public SettingsDatabasePage()
{
InitializeComponent();
ViewModel = new SettingsDatabaseViewModel();
}
}
}

Some files were not shown because too many files have changed in this diff Show More