Drag drop finally works

WIP item background
New Donate page stub
Renamed some classes as services
This commit is contained in:
BONNEVILLE Geoffroy
2017-11-29 19:13:38 +01:00
parent 227bc30dde
commit f2731c49dd
28 changed files with 304 additions and 112 deletions

View File

@@ -10,6 +10,7 @@
<ResourceDictionary Source="Styles/HamburgerButtonStyle.xaml" />
<ResourceDictionary Source="Styles/ListViewLeftIndicatorStyle.xaml" />
<ResourceDictionary Source="Styles/NoBorderButtonStyle.xaml" />
<ResourceDictionary Source="Styles/TextBlockStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

View File

@@ -11,6 +11,7 @@ using Windows.UI.Xaml.Navigation;
using ModernKeePass.Common;
using ModernKeePass.Exceptions;
using ModernKeePass.Interfaces;
using ModernKeePass.Services;
// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227
@@ -21,7 +22,7 @@ namespace ModernKeePass
/// </summary>
sealed partial class App
{
public DatabaseHelper Database { get; set; } = new DatabaseHelper();
public DatabaseService Database { get; set; } = new DatabaseService();
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
@@ -48,7 +49,7 @@ namespace ModernKeePass
if (!(realException is SaveException)) return;
unhandledExceptionEventArgs.Handled = true;
MessageDialogHelper.SaveErrorDialog(realException as SaveException, Database);
MessageDialogService.SaveErrorDialog(realException as SaveException, Database);
}
/// <summary>

View File

@@ -113,14 +113,18 @@
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="Common\DatabaseHelper.cs" />
<Compile Include="Common\MessageDialogHelper.cs" />
<Compile Include="Pages\MainPageFrames\DonatePage.xaml.cs">
<DependentUpon>DonatePage.xaml</DependentUpon>
</Compile>
<Compile Include="Services\DatabaseService.cs" />
<Compile Include="Services\MessageDialogService.cs" />
<Compile Include="Common\NavigationHelper.cs" />
<Compile Include="Common\NotifyPropertyChangedBase.cs" />
<Compile Include="Common\ObservableDictionary.cs" />
<Compile Include="Common\RelayCommand.cs" />
<Compile Include="Common\SuspensionManager.cs" />
<Compile Include="Common\ToastNotificationHelper.cs" />
<Compile Include="Services\SettingsService.cs" />
<Compile Include="Services\ToastNotificationService.cs" />
<Compile Include="Converters\DiscreteIntToSolidColorBrushConverter.cs" />
<Compile Include="Converters\EmptyStringToVisibilityConverter.cs" />
<Compile Include="Converters\NullToBooleanConverter.cs" />
@@ -244,6 +248,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\MainPageFrames\DonatePage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\MainPageFrames\NewDatabasePage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -299,6 +307,11 @@
<Generator>MSBuild:Compile</Generator>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="Styles\TextBlockStyles.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="Styles\TextBoxWithButtonStyle.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@@ -4,6 +4,7 @@ using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using ModernKeePass.Common;
using ModernKeePass.Services;
using ModernKeePass.ViewModels;
// Pour en savoir plus sur le modèle d'élément Page Détail de l'élément, consultez la page http://go.microsoft.com/fwlink/?LinkId=234232
@@ -76,9 +77,9 @@ namespace ModernKeePass.Pages
? "Are you sure you want to send this entry to the recycle bin?"
: "Are you sure you want to delete this entry?";
var text = isRecycleBinEnabled ? "Item moved to the Recycle bin" : "Item permanently removed";
MessageDialogHelper.ShowActionDialog("Warning", message, "Delete", "Cancel", a =>
MessageDialogService.ShowActionDialog("Warning", message, "Delete", "Cancel", a =>
{
ToastNotificationHelper.ShowMovedToast(Model, "Deleting", text);
ToastNotificationService.ShowMovedToast(Model, "Deleting", text);
Model.MarkForDelete();
if (Frame.CanGoBack) Frame.GoBack();
});
@@ -86,7 +87,7 @@ namespace ModernKeePass.Pages
private void RestoreButton_Click(object sender, RoutedEventArgs e)
{
ToastNotificationHelper.ShowMovedToast(Model, "Restored", "Item returned to its original group");
ToastNotificationService.ShowMovedToast(Model, "Restored", "Item returned to its original group");
if (Frame.CanGoBack) Frame.GoBack();
}
@@ -99,7 +100,7 @@ namespace ModernKeePass.Pages
}
catch (Exception ex)
{
MessageDialogHelper.ShowErrorDialog(ex);
MessageDialogService.ShowErrorDialog(ex);
}
}
}

View File

@@ -106,7 +106,7 @@
DataContext="{Binding DataContext, ElementName=PageRoot}"
RequestedTheme="Dark"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
Foreground="{ThemeResource DefaultTextForegroundThemeBrush}">
Foreground="{ThemeResource DefaultTextForegroundThemeBrush}" AllowDrop="True" Drop="LeftListView_Drop">
<ListView.Resources>
<DataTemplate x:Name="Collapsed">
<SymbolIcon Symbol="{Binding IconSymbol}" Margin="8,0,0,0">
@@ -167,9 +167,12 @@
TabIndex="1"
SelectionChanged="entries_SelectionChanged"
IsSynchronizedWithCurrentItem="False"
AllowDrop="{Binding IsEditMode}"
CanReorderItems="{Binding IsEditMode}"
CanDragItems="{Binding IsEditMode}">
BorderBrush="{StaticResource ListViewItemSelectedBackgroundThemeBrush}"
AllowDrop="True"
CanReorderItems="True"
CanDragItems="True"
DragItemsStarting="GridView_DragItemsStarting"
Drop="GridView_Drop">
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="False">
<actions:SetupFocusAction TargetObject="{Binding ElementName=GridView}" />
@@ -177,22 +180,16 @@
</interactivity:Interaction.Behaviors>
<GridView.ItemTemplate>
<DataTemplate>
<Grid Height="110" Width="480" x:Name="EntryGrid" >
<Grid Height="110" Width="480" x:Name="EntryGrid" Background="{Binding BackgroundColor, ConverterParameter={StaticResource AppBarBackgroundThemeBrush}, Converter={StaticResource ColorToBrushConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border
Grid.Column="0"
BorderThickness="2"
BorderBrush="{StaticResource SystemColor}"
Background="{Binding BackgroundColor, ConverterParameter={StaticResource Transparent}, Converter={StaticResource ColorToBrushConverter}}">
<SymbolIcon Symbol="{Binding IconSymbol}" Width="100" Height="100" RenderTransformOrigin="0.5,0.5" >
<SymbolIcon.RenderTransform>
<CompositeTransform ScaleX="2" TranslateX="0" TranslateY="0" ScaleY="2"/>
</SymbolIcon.RenderTransform>
</SymbolIcon>
</Border>
<SymbolIcon Grid.Column="0" Symbol="{Binding IconSymbol}" Width="100" Height="100" RenderTransformOrigin="0.5,0.5" >
<SymbolIcon.RenderTransform>
<CompositeTransform ScaleX="2" TranslateX="0" TranslateY="0" ScaleY="2"/>
</SymbolIcon.RenderTransform>
</SymbolIcon>
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,10,0,0" >
<TextBlock x:Name="NameTextBlock" Text="{Binding Name}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" Foreground="{Binding ForegroundColor, ConverterParameter={StaticResource TextBoxForegroundThemeBrush}, Converter={StaticResource ColorToBrushConverter}}"/>
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
@@ -260,8 +257,36 @@
OtherItem="{StaticResource GroupOtherItem}" />
</GridView.ItemTemplateSelector>-->
<GridView.ItemContainerStyle>
<Style TargetType="FrameworkElement">
<!--<Style TargetType="FrameworkElement">
<Setter Property="Margin" Value="52,0,0,2"/>
</Style>-->
<Style TargetType = "GridViewItem" >
<Setter Property = "Template" >
<Setter.Value>
<ControlTemplate TargetType = "GridViewItem" >
<GridViewItemPresenter
SelectionCheckMarkVisualEnabled="True"
CheckHintBrush="{ThemeResource ListViewItemCheckHintThemeBrush}"
CheckSelectingBrush="{ThemeResource ListViewItemCheckSelectingThemeBrush}"
CheckBrush="{ThemeResource ListViewItemCheckThemeBrush}"
DragBackground="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}"
DragForeground="{ThemeResource ListViewItemDragForegroundThemeBrush}"
FocusBorderBrush="{ThemeResource ListViewItemFocusBorderThemeBrush}"
PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}"
PointerOverBackground="{ThemeResource ListViewItemPointerOverBackgroundThemeBrush}"
SelectedBorderThickness="{ThemeResource GridViewItemCompactSelectedBorderThemeThickness}"
SelectedBackground="{ThemeResource ListViewItemSelectedBackgroundThemeBrush}"
SelectedForeground="{ThemeResource ListViewItemSelectedForegroundThemeBrush}"
SelectedPointerOverBackground="{ThemeResource ListViewItemSelectedPointerOverBackgroundThemeBrush}"
SelectedPointerOverBorderBrush="{ThemeResource ListViewItemSelectedPointerOverBorderThemeBrush}"
DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}"
DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}"
ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
PointerOverBackgroundMargin="1"
ContentMargin="4" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GridView.ItemContainerStyle>
</GridView>
@@ -342,5 +367,23 @@
</StackPanel>
<SearchBox Grid.Column="2" x:Uid="GroupSearch" Width="350" Background="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" BorderThickness="0" FontSize="18" SuggestionsRequested="SearchBox_OnSuggestionsRequested" SearchHistoryEnabled="False" ResultSuggestionChosen="SearchBox_OnResultSuggestionChosen" />
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="DragDropGroup">
<VisualState x:Name="Dragging">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GridView" Storyboard.TargetProperty="BorderThickness">
<DiscreteObjectKeyFrame KeyTime="0" Value="2"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Dropped">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GridView" Storyboard.TargetProperty="BorderThickness">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>

View File

@@ -6,6 +6,7 @@ using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using ModernKeePass.Common;
using ModernKeePass.Events;
using ModernKeePass.Services;
using ModernKeePass.ViewModels;
// The Group Detail Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234229
@@ -113,9 +114,9 @@ namespace ModernKeePass.Pages
? "Are you sure you want to send the whole group and all its entries to the recycle bin?"
: "Are you sure you want to delete the whole group and all its entries?";
var text = isRecycleBinEnabled ? "Item moved to the Recycle bin" : "Item permanently removed";
MessageDialogHelper.ShowActionDialog("Warning", message, "Delete", "Cancel", a =>
MessageDialogService.ShowActionDialog("Warning", message, "Delete", "Cancel", a =>
{
ToastNotificationHelper.ShowMovedToast(Model, "Deleting", text);
ToastNotificationService.ShowMovedToast(Model, "Deleting", text);
Model.MarkForDelete();
if (Frame.CanGoBack) Frame.GoBack();
});
@@ -123,7 +124,7 @@ namespace ModernKeePass.Pages
private void RestoreButton_Click(object sender, RoutedEventArgs e)
{
ToastNotificationHelper.ShowMovedToast(Model, "Restored", "Item returned to its original group");
ToastNotificationService.ShowMovedToast(Model, "Restored", "Item returned to its original group");
if (Frame.CanGoBack) Frame.GoBack();
}
@@ -158,5 +159,19 @@ namespace ModernKeePass.Pages
{
Frame.Navigate(typeof(EntryDetailPage), Model.AddNewEntry());
}
private void GridView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
e.Cancel = !Model.IsEditMode;
}
private void GridView_Drop(object sender, DragEventArgs e)
{
}
private void LeftListView_Drop(object sender, DragEventArgs e)
{
}
}
}

View File

@@ -0,0 +1,14 @@
<Page
x:Class="ModernKeePass.Pages.MainPageFrames.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"
mc:Ignorable="d">
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Uid="DonateDesc" />
<RadioButton GroupName="DonateOptions" />
<Button x:Uid="DonateButton" />
</StackPanel>
</Page>

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace ModernKeePass.Pages.MainPageFrames
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class DonatePage : Page
{
public DonatePage()
{
this.InitializeComponent();
}
}
}

View File

@@ -19,11 +19,11 @@
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ToggleSwitch x:Uid="SettingsDatabaseRecycleBin" IsOn="{Binding HasRecycleBin, Mode=TwoWay}" />
<ComboBox ItemsSource="{Binding Source={StaticResource RecycleBinGroups}}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" IsEnabled="{Binding HasRecycleBin}" />
<TextBlock x:Uid="SettingsDatabaseEncryption" FontSize="14" Margin="5,20,0,10" />
<TextBlock x:Uid="SettingsDatabaseEncryption" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,20,0,10" />
<ComboBox ItemsSource="{Binding Source={StaticResource Ciphers}}" SelectedIndex="{Binding CipherIndex, Mode=TwoWay}" />
<TextBlock x:Uid="SettingsDatabaseCompression" FontSize="14" Margin="5,20,0,10" />
<TextBlock x:Uid="SettingsDatabaseCompression" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,20,0,10" />
<ComboBox ItemsSource="{Binding Source={StaticResource Compressions}}" SelectedItem="{Binding CompressionName, Mode=TwoWay}" />
<TextBlock x:Uid="SettingsDatabaseKdf" FontSize="14" Margin="5,20,0,10" />
<TextBlock x:Uid="SettingsDatabaseKdf" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,20,0,10" />
<ComboBox ItemsSource="{Binding Source={StaticResource KeyDerivations}}" SelectedItem="{Binding KeyDerivationName, Mode=TwoWay}" />
</StackPanel>
</Page>

View File

@@ -8,15 +8,15 @@
mc:Ignorable="d">
<Page.Resources>
<CollectionViewSource x:Name="KeyDerivations" Source="{Binding KeyDerivations}" />
<CollectionViewSource x:Name="KeyDerivations" Source="{Binding FileFormats}" />
</Page.Resources>
<Page.DataContext>
<viewModels:SettingsNewVm />
</Page.DataContext>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Uid="SettingsNewDatabaseDesc" FontSize="14" />
<TextBlock x:Uid="SettingsNewDatabaseDesc" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,0,0,10"/>
<ToggleSwitch x:Uid="SettingsNewDatabaseSample" IsOn="{Binding IsCreateSample, Mode=TwoWay}" />
<TextBlock x:Uid="SettingsNewDatabaseKdf" FontSize="14" />
<ComboBox ItemsSource="{Binding Source={StaticResource KeyDerivations}}" SelectedItem="{Binding KeyDerivationName, Mode=TwoWay}" />
<TextBlock x:Uid="SettingsNewDatabaseKdf" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,20,0,10" />
<ComboBox ItemsSource="{Binding Source={StaticResource KeyDerivations}}" SelectedItem="{Binding FileFormatVersion, Mode=TwoWay}" />
</StackPanel>
</Page>

View File

@@ -8,7 +8,7 @@
mc:Ignorable="d">
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Uid="SettingsSecurityTitle" FontSize="14" Margin="5,0,0,0" />
<TextBlock x:Uid="SettingsSecurityTitle" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,0,0,0" />
<TextBlock TextWrapping="WrapWholeWords" Margin="5,0,0,0">
<Run x:Uid="SettingsSecurityDesc1" />
<Run x:Uid="SettingsSecurityDesc2" FontWeight="SemiBold" />

View File

@@ -2,6 +2,7 @@
using ModernKeePass.Common;
using ModernKeePass.Events;
using ModernKeePass.Services;
namespace ModernKeePass.Pages
{
@@ -17,7 +18,7 @@ namespace ModernKeePass.Pages
private void CompositeKeyUserControl_OnValidationChecked(object sender, PasswordEventArgs e)
{
ToastNotificationHelper.ShowGenericToast("Composite key", "Database successfully updated.");
ToastNotificationService.ShowGenericToast("Composite key", "Database successfully updated.");
}
}
}

View File

@@ -8,7 +8,7 @@
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock FontSize="24" VerticalAlignment="Center" Margin="10,-70,0,0" x:Uid="SettingsWelcomeTitle" />
<TextBlock VerticalAlignment="Center" FontSize="14" Margin="5,0,0,0" x:Uid="SettingsWelcomeDesc" />
<TextBlock VerticalAlignment="Center" FontSize="14" Margin="5,0,0,0" x:Uid="SettingsWelcomeHowto" />
<TextBlock VerticalAlignment="Center" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,0,0,0" x:Uid="SettingsWelcomeDesc" />
<TextBlock VerticalAlignment="Center" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,0,0,0" x:Uid="SettingsWelcomeHowto" />
</StackPanel>
</Page>

View File

@@ -1,18 +1,20 @@
using System;
using System;
using Windows.Storage;
using Windows.UI.Xaml.Controls;
using ModernKeePass.Exceptions;
using ModernKeePass.Interfaces;
using ModernKeePass.ViewModels;
using ModernKeePassLib;
using ModernKeePassLib.Collections;
using ModernKeePassLib.Cryptography.KeyDerivation;
using ModernKeePassLib.Interfaces;
using ModernKeePassLib.Keys;
using ModernKeePassLib.Security;
using ModernKeePassLib.Serialization;
namespace ModernKeePass.Common
namespace ModernKeePass.Services
{
public class DatabaseHelper: IDatabase
public class DatabaseService: IDatabase
{
public enum DatabaseStatus
{
@@ -92,7 +94,20 @@ namespace ModernKeePass.Common
return;
}
var ioConnection = IOConnectionInfo.FromFile(DatabaseFile);
if (createNew) _pwDatabase.New(ioConnection, key);
if (createNew)
{
_pwDatabase.New(ioConnection, key);
//Get settings default values
if (SettingsService.GetSetting<bool>("Sample")) CreateSampleData();
var fileFormat = SettingsService.GetSetting<string>("DefaultFileFormat");
switch (fileFormat)
{
case "4":
KeyDerivation = KdfPool.Get("Argon2").GetDefaultParameters();
break;
}
}
else _pwDatabase.Open(ioConnection, key, new NullStatusLogger());
if (!_pwDatabase.IsOpen) return;
@@ -174,5 +189,37 @@ namespace ModernKeePass.Common
{
_pwDatabase.MasterKey = key;
}
private void CreateSampleData()
{
_pwDatabase.RootGroup.AddGroup(new PwGroup(true, true, "Banking", PwIcon.Count), true);
_pwDatabase.RootGroup.AddGroup(new PwGroup(true, true, "Email", PwIcon.EMail), true);
_pwDatabase.RootGroup.AddGroup(new PwGroup(true, true, "Internet", PwIcon.World), true);
var pe = new PwEntry(true, true);
pe.Strings.Set(PwDefs.TitleField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectTitle,
"Sample Entry"));
pe.Strings.Set(PwDefs.UserNameField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectUserName,
"Username"));
pe.Strings.Set(PwDefs.UrlField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectUrl,
PwDefs.HomepageUrl));
pe.Strings.Set(PwDefs.PasswordField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectPassword,
"Password"));
pe.Strings.Set(PwDefs.NotesField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectNotes,
"You may safely delete this sample"));
_pwDatabase.RootGroup.AddEntry(pe, true);
pe = new PwEntry(true, true);
pe.Strings.Set(PwDefs.TitleField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectTitle,
"Sample Entry #2"));
pe.Strings.Set(PwDefs.UserNameField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectUserName,
"Michael321"));
pe.Strings.Set(PwDefs.UrlField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectUrl,
PwDefs.HelpUrl + "kb/testform.html"));
pe.Strings.Set(PwDefs.PasswordField, new ProtectedString(_pwDatabase.MemoryProtection.ProtectPassword,
"12345"));
pe.AutoType.Add(new AutoTypeAssociation("*Test Form - KeePass*", string.Empty));
_pwDatabase.RootGroup.AddEntry(pe, true);
}
}
}

View File

@@ -5,9 +5,9 @@ using Windows.UI.Popups;
using ModernKeePass.Exceptions;
using ModernKeePass.Interfaces;
namespace ModernKeePass.Common
namespace ModernKeePass.Services
{
public static class MessageDialogHelper
public static class MessageDialogService
{
public static async void ShowActionDialog(string title, string contentText, string actionButtonText, string cancelButtonText, UICommandInvokedHandler action)
{

View File

@@ -0,0 +1,28 @@
using System;
using Windows.Storage;
namespace ModernKeePass.Services
{
public class SettingsService
{
public static T GetSetting<T>(string property)
{
try
{
return (T)Convert.ChangeType(ApplicationData.Current.LocalSettings.Values[property], typeof(T));
}
catch (InvalidCastException)
{
return default(T);
}
}
public static void PutSetting<T>(string property, T value)
{
var localSettings = ApplicationData.Current.LocalSettings;
if (localSettings.Values.ContainsKey(property))
localSettings.Values[property] = value;
else localSettings.Values.Add(property, value);
}
}
}

View File

@@ -5,9 +5,9 @@ using Windows.UI.Notifications;
using ModernKeePass.Interfaces;
using ModernKeePass.ViewModels;
namespace ModernKeePass.Common
namespace ModernKeePass.Services
{
public static class ToastNotificationHelper
public static class ToastNotificationService
{
public static void ShowMovedToast(IPwEntity entity, string action, string text)
{

View File

@@ -138,6 +138,9 @@
<data name="CompositeKeyPassword.PlaceholderText" xml:space="preserve">
<value>Password</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 this app stay ad-free :) ?</value>
</data>
<data name="EntryExpirationDate.Content" xml:space="preserve">
<value>Expiration date</value>
</data>
@@ -253,7 +256,7 @@
<value>Here, you can change some default options when creating a database.</value>
</data>
<data name="SettingsNewDatabaseKdf.Text" xml:space="preserve">
<value>Default Key Derivation algorithm</value>
<value>File format</value>
</data>
<data name="SettingsNewDatabaseSample.Header" xml:space="preserve">
<value>Create sample data</value>

View File

@@ -0,0 +1,9 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="TextBlock" x:Name="TextBlockSettingsHeaderStyle" >
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontSize" Value="14.667" />
<Setter Property="FontWeight" Value="SemiLight" />
</Style>
</ResourceDictionary>

View File

@@ -5,6 +5,7 @@ using Windows.Storage;
using Windows.UI.Xaml;
using ModernKeePass.Common;
using ModernKeePass.Interfaces;
using ModernKeePass.Services;
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Keys;
using ModernKeePassLib.Serialization;
@@ -117,19 +118,19 @@ namespace ModernKeePass.ViewModels
{
error = $"Error: {e.Message}";
}
switch ((DatabaseHelper.DatabaseStatus)Database.Status)
switch ((DatabaseService.DatabaseStatus)Database.Status)
{
case DatabaseHelper.DatabaseStatus.Opened:
case DatabaseService.DatabaseStatus.Opened:
await Task.Run( () => RootGroup = Database.RootGroup);
return true;
case DatabaseHelper.DatabaseStatus.CompositeKeyError:
case DatabaseService.DatabaseStatus.CompositeKeyError:
var errorMessage = new StringBuilder("Error: wrong ");
if (HasPassword) errorMessage.Append("password");
if (HasPassword && HasKeyFile) errorMessage.Append(" or ");
if (HasKeyFile) errorMessage.Append("key file");
UpdateStatus(errorMessage.ToString(), StatusTypes.Error);
break;
case DatabaseHelper.DatabaseStatus.Error:
case DatabaseService.DatabaseStatus.Error:
UpdateStatus(error, StatusTypes.Error);
break;
}

View File

@@ -15,17 +15,13 @@ namespace ModernKeePass.ViewModels
public class EntryVm : INotifyPropertyChanged, IPwEntity
{
public GroupVm ParentGroup { get; private set; }
public GroupVm PreviousGroup { get; private set; }
public System.Drawing.Color? BackgroundColor => _pwEntry?.BackgroundColor;
public System.Drawing.Color? ForegroundColor => _pwEntry?.ForegroundColor;
public bool IsRevealPasswordEnabled => !string.IsNullOrEmpty(Password);
public bool HasExpired => HasExpirationDate && _pwEntry.ExpiryTime < DateTime.Now;
public double PasswordComplexityIndicator => QualityEstimation.EstimatePasswordBits(Password.ToCharArray());
public bool IsFirstItem => _pwEntry == null;
public bool UpperCasePatternSelected { get; set; } = true;
public bool LowerCasePatternSelected { get; set; } = true;
public bool DigitsPatternSelected { get; set; } = true;
@@ -36,6 +32,7 @@ namespace ModernKeePass.ViewModels
public bool BracketsPatternSelected { get; set; }
public string CustomChars { get; set; } = string.Empty;
public PwUuid IdUuid => _pwEntry?.Uuid;
public string Id => _pwEntry?.Uuid.ToHexString();
public double PasswordLength
{
@@ -46,6 +43,7 @@ namespace ModernKeePass.ViewModels
NotifyPropertyChanged("PasswordLength");
}
}
public string Name
{
get
@@ -56,7 +54,6 @@ namespace ModernKeePass.ViewModels
set { SetEntryValue(PwDefs.TitleField, value); }
}
public string Id => _pwEntry?.Uuid.ToHexString();
public string UserName
{

View File

@@ -9,6 +9,7 @@ using Windows.UI.Xaml.Controls;
using ModernKeePass.Common;
using ModernKeePass.Interfaces;
using ModernKeePass.Mappings;
using ModernKeePass.Services;
using ModernKeePassLib;
namespace ModernKeePass.ViewModels
@@ -85,6 +86,7 @@ namespace ModernKeePass.ViewModels
private readonly IDatabase _database;
private bool _isEditMode;
private PwEntry _reorderedEntry;
//private int _reorderedEntryIndex;
public GroupVm() {}
@@ -115,7 +117,7 @@ namespace ModernKeePass.ViewModels
_pwGroup.Entries.RemoveAt(oldIndex);
break;
case NotifyCollectionChangedAction.Add:
if (e.OldStartingIndex == -1) _pwGroup.Entries.Add(((EntryVm)e.NewItems[0]).GetPwEntry());
if (_reorderedEntry == null) _pwGroup.AddEntry(((EntryVm) e.NewItems[0]).GetPwEntry(), true);
else _pwGroup.Entries.Insert((uint)e.NewStartingIndex, _reorderedEntry);
break;
}
@@ -184,11 +186,13 @@ namespace ModernKeePass.ViewModels
var comparer = new PwEntryComparer(PwDefs.TitleField, true, true);
try
{
// TODO: this throws an exception
_pwGroup.Entries.Sort(comparer);
Entries = new ObservableCollection<EntryVm>(Entries.OrderBy(e => e.Name));
}
catch (Exception e)
{
MessageDialogService.ShowErrorDialog(e);
}
}

View File

@@ -22,7 +22,7 @@ namespace ModernKeePass.ViewModels
set
{
_database.RecycleBinEnabled = value;
OnPropertyChanged();
OnPropertyChanged("HasRecycleBin");
}
}

View File

@@ -1,47 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Windows.Storage;
using ModernKeePassLib.Cryptography.KeyDerivation;
using System.Collections.Generic;
using ModernKeePass.Services;
namespace ModernKeePass.ViewModels
{
public class SettingsNewVm
{
private readonly ApplicationDataContainer _localSettings = ApplicationData.Current.LocalSettings;
public bool IsCreateSample
{
get { return GetSetting<bool>("Sample"); }
set { PutSetting("Sample", value); }
get { return SettingsService.GetSetting<bool>("Sample"); }
set { SettingsService.PutSetting("Sample", value); }
}
public IEnumerable<string> KeyDerivations => KdfPool.Engines.Select(e => e.Name);
public IEnumerable<string> FileFormats => new []{"2", "4"};
public string KeyDerivationName
public string FileFormatVersion
{
get { return GetSetting<string>("KeyDerivation"); }
set { PutSetting("KeyDerivation", value); }
}
// TODO: Move this to a common class
private T GetSetting<T>(string property)
{
try
{
return (T)Convert.ChangeType(_localSettings.Values[property], typeof(T));
}
catch (InvalidCastException)
{
return default(T);
}
}
private void PutSetting<T>(string property, T value)
{
if (_localSettings.Values.ContainsKey(property))
_localSettings.Values[property] = value;
else _localSettings.Values.Add(property, value);
get { return SettingsService.GetSetting<string>("DefaultFileFormat"); }
set { SettingsService.PutSetting("DefaultFileFormat", value); }
}
}
}

View File

@@ -7,6 +7,7 @@ using Windows.UI.Xaml.Controls;
using ModernKeePass.Common;
using ModernKeePass.Interfaces;
using ModernKeePass.Pages;
using ModernKeePass.Services;
namespace ModernKeePass.ViewModels
{
@@ -50,14 +51,14 @@ namespace ModernKeePass.ViewModels
public MainVm(Frame referenceFrame, Frame destinationFrame, IDatabase database)
{
var mru = StorageApplicationPermissions.MostRecentlyUsedList;
var isDatabaseOpen = database != null && database.Status == (int) DatabaseHelper.DatabaseStatus.Opened;
var isDatabaseOpen = database != null && database.Status == (int) DatabaseService.DatabaseStatus.Opened;
var mainMenuItems = new ObservableCollection<MainMenuItemVm>
{
new MainMenuItemVm
{
Title = "Open", PageType = typeof(OpenDatabasePage), Destination = destinationFrame, Parameter = referenceFrame, SymbolIcon = Symbol.Page2,
IsSelected = database != null && database.Status == (int) DatabaseHelper.DatabaseStatus.Opening
IsSelected = database != null && database.Status == (int) DatabaseService.DatabaseStatus.Opening
},
new MainMenuItemVm
{
@@ -70,7 +71,7 @@ namespace ModernKeePass.ViewModels
},
new MainMenuItemVm {
Title = "Recent" , PageType = typeof(RecentDatabasesPage), Destination = destinationFrame, Parameter = referenceFrame, SymbolIcon = Symbol.Copy,
IsSelected = (database == null || database.Status == (int) DatabaseHelper.DatabaseStatus.Closed) && mru.Entries.Count > 0, IsEnabled = mru.Entries.Count > 0
IsSelected = (database == null || database.Status == (int) DatabaseService.DatabaseStatus.Closed) && mru.Entries.Count > 0, IsEnabled = mru.Entries.Count > 0
},
new MainMenuItemVm
{
@@ -83,7 +84,7 @@ namespace ModernKeePass.ViewModels
};
// Auto-select the Recent Items menu item if the conditions are met
SelectedItem = mainMenuItems.FirstOrDefault(m => m.IsSelected);
if (database != null && database.Status == (int) DatabaseHelper.DatabaseStatus.Opened)
if (database != null && database.Status == (int) DatabaseService.DatabaseStatus.Opened)
mainMenuItems.Add(new MainMenuItemVm
{
Title = database.Name,

View File

@@ -3,12 +3,13 @@ using Windows.Storage.AccessCache;
using Windows.UI.Xaml;
using ModernKeePass.Common;
using ModernKeePass.Interfaces;
using ModernKeePass.Services;
namespace ModernKeePass.ViewModels
{
public class OpenVm: NotifyPropertyChangedBase
{
public bool ShowPasswordBox => _database?.Status == (int) DatabaseHelper.DatabaseStatus.Opening;
public bool ShowPasswordBox => _database?.Status == (int) DatabaseService.DatabaseStatus.Opening;
public string Name => _database?.Name;
@@ -19,7 +20,7 @@ namespace ModernKeePass.ViewModels
public OpenVm(IDatabase database)
{
_database = database;
if (database == null || database.Status != (int) DatabaseHelper.DatabaseStatus.Opening) return;
if (database == null || database.Status != (int) DatabaseService.DatabaseStatus.Opening) return;
OpenFile(database.DatabaseFile);
}

View File

@@ -47,7 +47,14 @@ namespace ModernKeePass.ViewModels
{
var menuItems = new ObservableCollection<ListMenuItemVm>
{
new ListMenuItemVm { Title = "New", Group = "Application", SymbolIcon = Symbol.Add, PageType = typeof(SettingsNewDatabasePage) }
new ListMenuItemVm
{
Title = "New",
Group = "Application",
SymbolIcon = Symbol.Add,
PageType = typeof(SettingsNewDatabasePage),
IsSelected = true
}
};
if (database?.Status == 2)
{
@@ -56,8 +63,7 @@ namespace ModernKeePass.ViewModels
Title = "General",
Group = "Database",
SymbolIcon = Symbol.Setting,
PageType = typeof(SettingsDatabasePage),
IsSelected = true
PageType = typeof(SettingsDatabasePage)
});
menuItems.Add(new ListMenuItemVm
{

View File

@@ -2,7 +2,7 @@
using Windows.ApplicationModel;
using Windows.Storage;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using ModernKeePass.Common;
using ModernKeePass.Services;
using ModernKeePass.ViewModels;
namespace ModernKeePassApp.Test
@@ -10,25 +10,25 @@ namespace ModernKeePassApp.Test
[TestClass]
public class DatabaseTests
{
private readonly DatabaseHelper _database = new DatabaseHelper();
private readonly DatabaseService _database = new DatabaseService();
[TestMethod]
public void TestCreate()
{
Assert.AreEqual((int) DatabaseHelper.DatabaseStatus.Closed, _database.Status);
Assert.AreEqual((int) DatabaseService.DatabaseStatus.Closed, _database.Status);
_database.DatabaseFile = ApplicationData.Current.TemporaryFolder.CreateFileAsync("NewDatabase.kdbx").GetAwaiter().GetResult();
Assert.AreEqual((int)DatabaseHelper.DatabaseStatus.Opening, _database.Status);
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Opening, _database.Status);
OpenOrCreateDatabase(true);
_database.Close();
Assert.AreEqual((int)DatabaseHelper.DatabaseStatus.Closed, _database.Status);
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Closed, _database.Status);
}
[TestMethod]
public void TestOpen()
{
Assert.AreEqual((int)DatabaseHelper.DatabaseStatus.Closed, _database.Status);
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Closed, _database.Status);
_database.DatabaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Databases\TestDatabase.kdbx").GetAwaiter().GetResult();
Assert.AreEqual((int)DatabaseHelper.DatabaseStatus.Opening, _database.Status);
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Opening, _database.Status);
OpenOrCreateDatabase(false);
}
@@ -37,23 +37,23 @@ namespace ModernKeePassApp.Test
{
TestOpen();
_database.Save(ApplicationData.Current.TemporaryFolder.CreateFileAsync("SaveDatabase.kdbx").GetAwaiter().GetResult());
Assert.AreEqual((int)DatabaseHelper.DatabaseStatus.Opened, _database.Status);
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Opened, _database.Status);
_database.Close();
Assert.AreEqual((int)DatabaseHelper.DatabaseStatus.Closed, _database.Status);
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Closed, _database.Status);
TestOpen();
}
private void OpenOrCreateDatabase(bool createNew)
{
_database.Open(null, createNew);
Assert.AreEqual((int)DatabaseHelper.DatabaseStatus.NoCompositeKey, _database.Status);
Assert.AreEqual((int)DatabaseService.DatabaseStatus.NoCompositeKey, _database.Status);
var compositeKey = new CompositeKeyVm(_database)
{
HasPassword = true,
Password = "test"
};
compositeKey.OpenDatabase(createNew);
Assert.AreEqual((int)DatabaseHelper.DatabaseStatus.Opened, _database.Status);
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Opened, _database.Status);
}
}
}