Main page now allows password input

Group nesting works
This commit is contained in:
2017-09-15 15:58:51 +02:00
parent e97344011d
commit b54fff2502
7 changed files with 103 additions and 29 deletions

Binary file not shown.

View File

@@ -1,14 +1,41 @@
<Page <Page
x:Class="ModernKeePass.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ModernKeePass" xmlns:local="using:ModernKeePass"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> xmlns:ViewModels="using:ModernKeePass.ViewModels"
x:Class="ModernKeePass.MainPage"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
<Page.DataContext>
<ViewModels:DatabaseVm/>
</Page.DataContext>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Button Content="Open password database" HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click" /> <Grid.ColumnDefinitions>
<TextBlock Name="textBlock" HorizontalAlignment="Center" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Center" Margin="0,100,0,0" /> <ColumnDefinition Width="250" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="50" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Grid.Column="0" Grid.Row="0" x:Name="selectButton" Content="Select password database" Click="Button_Click" HorizontalAlignment="Center" />
<Grid Grid.Column="0" Grid.Row="2" HorizontalAlignment="Center" Height="auto" VerticalAlignment="Top" Width="auto" Visibility="{Binding Visibility}" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" x:Name="passwordTextBlock" HorizontalAlignment="Left" TextWrapping="Wrap" Text="Password" VerticalAlignment="Center" Height="auto" Width="auto" FontSize="16" Margin="10,7,0,6" />
<PasswordBox Grid.Column="1" Grid.Row="0" x:Name="passwordBox" VerticalAlignment="Top" HorizontalAlignment="Right" Width="130" Password="{Binding Password, Mode=TwoWay}" IsPasswordRevealButtonEnabled="True" Margin="0,0,10,0"/>
<Button Grid.Column="1" Grid.Row="1" x:Name="openBbutton" Content="Open" HorizontalAlignment="Right" VerticalAlignment="Top" Click="openBbutton_Click" Margin="0,0,7,0" Width="auto"/>
<TextBlock Grid.Column="1" Grid.Row="2" x:Name="errorTextBlock" TextWrapping="Wrap" Text="{Binding ErrorMessage}" HorizontalAlignment="Right" Height="auto" Width="auto" Foreground="#FF9E0909" Margin="0,0,10,0"/>
</Grid>
</Grid> </Grid>
</Page> </Page>

View File

@@ -31,15 +31,19 @@ namespace ModernKeePass
if (file != null) if (file != null)
{ {
// Application now has read/write access to the picked file // Application now has read/write access to the picked file
textBlock.Text = "Opened database: " + file.Name; DataContext = new DatabaseVm(file);
var database = new DatabaseVm();
database.Open(file, "test");
Frame.Navigate(typeof(GroupDetailPage), database.RootGroup);
} }
else else
{ {
textBlock.Text = "Operation cancelled."; }
} }
private void openBbutton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
var database = DataContext as DatabaseVm;
database.Open();
if (database.IsOpen)
Frame.Navigate(typeof(GroupDetailPage), database.RootGroup);
} }
} }
} }

View File

@@ -26,20 +26,21 @@
<Grid.Resources> <Grid.Resources>
<CollectionViewSource <CollectionViewSource
x:Name="itemsViewSource" x:Name="groupsViewSource"
Source="{Binding Groups}"/> Source="{Binding Groups}"/>
</Grid.Resources> </Grid.Resources>
<!-- Horizontal scrolling grid --> <!-- Horizontal scrolling grid -->
<GridView <GridView
x:Name="itemGridView" x:Name="groupGridView"
AutomationProperties.AutomationId="ItemGridView" AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Groups" AutomationProperties.Name="Groups"
TabIndex="1" TabIndex="1"
Grid.RowSpan="2" Grid.RowSpan="2"
Padding="120,126,120,50" Padding="120,126,120,50"
ItemsSource="{Binding Source={StaticResource itemsViewSource}}" ItemsSource="{Binding Source={StaticResource groupsViewSource}}"
SelectionMode="None" IsSwipeEnabled="false"
IsSwipeEnabled="false"> SelectionChanged="itemGridView_SelectionChanged"
SelectedIndex="-1" >
<GridView.ItemTemplate> <GridView.ItemTemplate>
<DataTemplate> <DataTemplate>
<Grid Height="110" Width="480" Margin="10"> <Grid Height="110" Width="480" Margin="10">
@@ -54,15 +55,14 @@
<TextBlock Text="{Binding Name}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/> <TextBlock Text="{Binding Name}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/>
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/> <TextBlock Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
<TextBlock Text="{Binding EntryCount}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60"/> <TextBlock Text="{Binding EntryCount}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60"/>
<TextBlock Text="{Binding GroupCount}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60"/>
</StackPanel> </StackPanel>
</Grid> </Grid>
</DataTemplate> </DataTemplate>
</GridView.ItemTemplate> </GridView.ItemTemplate>
<GridView.Header> <GridView.Header>
<StackPanel Width="480" Margin="0,4,14,0"> <StackPanel Width="480" Margin="0,4,14,0">
<TextBlock Margin="0,0,0,20" Style="{StaticResource SubheaderTextBlockStyle}" MaxHeight="60" Text="{Binding Entries.Count}"/> <ListView x:Name="listView" Height="100"/>
<Image Height="400" Margin="0,0,0,20" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
<TextBlock Margin="0,0,0,0" Style="{StaticResource BodyTextBlockStyle}"/>
</StackPanel> </StackPanel>
</GridView.Header> </GridView.Header>
<GridView.ItemContainerStyle> <GridView.ItemContainerStyle>

View File

@@ -47,8 +47,6 @@ namespace ModernKeePass.Pages
/// session. The state will be null the first time a page is visited.</param> /// session. The state will be null the first time a page is visited.</param>
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e) private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
{ {
// TODO: Assign a bindable group to this.DefaultViewModel["Group"]
// TODO: Assign a collection of bindable items to this.DefaultViewModel["Items"]
} }
#region NavigationHelper registration #region NavigationHelper registration
@@ -69,6 +67,7 @@ namespace ModernKeePass.Pages
if (e.Parameter is GroupVm) if (e.Parameter is GroupVm)
{ {
DataContext = e.Parameter as GroupVm; DataContext = e.Parameter as GroupVm;
groupGridView.SelectedIndex = -1;
} }
} }
@@ -78,5 +77,11 @@ namespace ModernKeePass.Pages
} }
#endregion #endregion
private void itemGridView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var gridView = sender as GridView;
Frame.Navigate(typeof(GroupDetailPage), gridView.SelectedItem as GroupVm);
}
} }
} }

View File

@@ -5,33 +5,65 @@ using ModernKeePassLib;
using ModernKeePassLib.Keys; using ModernKeePassLib.Keys;
using ModernKeePassLib.Serialization; using ModernKeePassLib.Serialization;
using ModernKeePassLib.Interfaces; using ModernKeePassLib.Interfaces;
using Windows.UI.Xaml;
using System;
namespace ModernKeePass.ViewModels namespace ModernKeePass.ViewModels
{ {
public class DatabaseVm : INotifyPropertyChanged public class DatabaseVm : INotifyPropertyChanged
{ {
private PwDatabase _database = new PwDatabase(); private PwDatabase database = new PwDatabase();
private StorageFile databaseFile;
public string Password { get; set; }
public bool IsOpen { get; set; }
public Visibility Visibility { get; private set; }
public string ErrorMessage { get; set; }
public string Name { get; set; } public string Name { get; set; }
public GroupVm RootGroup { get; set; } public GroupVm RootGroup { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public async void Open(StorageFile databaseFile, string password) public DatabaseVm()
{
Visibility = Visibility.Collapsed;
}
public DatabaseVm(StorageFile databaseFile)
{
this.databaseFile = databaseFile;
Visibility = Visibility.Visible;
}
public async void Open()
{ {
var key = new CompositeKey(); var key = new CompositeKey();
key.AddUserKey(new KcpPassword(password));
try try
{ {
await _database.Open(IOConnectionInfo.FromFile(databaseFile), key, new NullStatusLogger()); key.AddUserKey(new KcpPassword(Password));
if (!_database.IsOpen) return; await database.Open(IOConnectionInfo.FromFile(databaseFile), key, new NullStatusLogger());
IsOpen = database.IsOpen;
Name = databaseFile.DisplayName; Name = databaseFile.DisplayName;
RootGroup = new GroupVm (_database.RootGroup); RootGroup = new GroupVm (database.RootGroup);
}
catch (ArgumentNullException)
{
ErrorMessage = "Password cannot be empty";
NotifyPropertyChanged("ErrorMessage");
}
catch (InvalidCompositeKeyException)
{
ErrorMessage = "Wrong password";
NotifyPropertyChanged("ErrorMessage");
} }
finally finally
{ {
_database.Close(); // TODO: move this when implementing write mode
} database.Close();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
} }
} }
} }

View File

@@ -17,6 +17,13 @@ namespace ModernKeePass.ViewModels
return $"{Entries?.Count} entries."; return $"{Entries?.Count} entries.";
} }
} }
public string GroupCount
{
get
{
return $"{Groups?.Count} groups.";
}
}
public GroupVm() public GroupVm()
{ {
@@ -39,6 +46,5 @@ namespace ModernKeePass.ViewModels
{ {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
} }
} }
} }