Implement add and delete entries and groups

New command bar
Some layout changes
Some refactoring
This commit is contained in:
2017-10-02 18:40:54 +02:00
committed by BONNEVILLE Geoffroy
parent 2bcc4fde60
commit 267d9f25c2
13 changed files with 228 additions and 145 deletions

View File

@@ -22,7 +22,7 @@ namespace ModernKeePass.Common
public DatabaseHelper(StorageFile databaseFile) public DatabaseHelper(StorageFile databaseFile)
{ {
this._databaseFile = databaseFile; _databaseFile = databaseFile;
} }
public string Open(string password) public string Open(string password)
{ {
@@ -31,9 +31,8 @@ namespace ModernKeePass.Common
{ {
key.AddUserKey(new KcpPassword(password)); key.AddUserKey(new KcpPassword(password));
_pwDatabase.Open(IOConnectionInfo.FromFile(_databaseFile), key, new NullStatusLogger()); _pwDatabase.Open(IOConnectionInfo.FromFile(_databaseFile), key, new NullStatusLogger());
//_pwDatabase.Open(IOConnectionInfo.FromPath(databaseFile.Path), key, new NullStatusLogger());
if (IsOpen) RootGroup = new GroupVm(_pwDatabase.RootGroup); if (IsOpen) RootGroup = new GroupVm(_pwDatabase.RootGroup, null);
} }
catch (ArgumentNullException) catch (ArgumentNullException)
{ {
@@ -47,11 +46,6 @@ namespace ModernKeePass.Common
{ {
return ex.Message; return ex.Message;
} }
/*finally
{
// TODO: move this when implementing write mode
_pwDatabase.Close();
}*/
return string.Empty; return string.Empty;
} }

View File

@@ -125,8 +125,8 @@
<DependentUpon>MainPage.xaml</DependentUpon> <DependentUpon>MainPage.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Mappings\PwIconToSegoeMapping.cs" /> <Compile Include="Mappings\PwIconToSegoeMapping.cs" />
<Compile Include="ViewModels\MainMenuItemVm.cs" /> <Compile Include="ViewModels\Items\MainMenuItemVm.cs" />
<Compile Include="ViewModels\RecentItemVm.cs" /> <Compile Include="ViewModels\Items\RecentItemVm.cs" />
<Compile Include="Pages\EntryDetailPage.xaml.cs"> <Compile Include="Pages\EntryDetailPage.xaml.cs">
<DependentUpon>EntryDetailPage.xaml</DependentUpon> <DependentUpon>EntryDetailPage.xaml</DependentUpon>
</Compile> </Compile>
@@ -216,9 +216,7 @@
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup />
<Folder Include="Models\" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Assets\Logo.scale-100.png" /> <Content Include="Assets\Logo.scale-100.png" />
<Content Include="Assets\Logo.scale-140.png" /> <Content Include="Assets\Logo.scale-140.png" />

View File

@@ -1,2 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp70</s:String></wpf:ResourceDictionary> <s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp70</s:String>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=viewmodels_005Citems/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@@ -48,15 +48,20 @@
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/> <ColumnDefinition Width="120"/>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Button x:Name="backButton" Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}" <Button Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
Style="{StaticResource NavigationBackButtonNormalStyle}" Style="{StaticResource NavigationBackButtonNormalStyle}"
VerticalAlignment="Top" VerticalAlignment="Top"
AutomationProperties.Name="Back" AutomationProperties.Name="Back"
AutomationProperties.AutomationId="BackButton" AutomationProperties.AutomationId="BackButton"
AutomationProperties.ItemType="Navigation Button"/> AutomationProperties.ItemType="Navigation Button"/>
<TextBlock x:Name="pageTitle" Text="{Binding Title}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1" <TextBlock Text="{Binding Title}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1"
IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40"/> IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40"/>
<CommandBar Grid.Column="2" Margin="0,40,0,0" Background="Transparent" IsOpen="True">
<AppBarButton Icon="Edit" Label="Edit" />
<AppBarButton Icon="Delete" Label="Delete" Click="AppBarButton_Click" />
</CommandBar>
</Grid> </Grid>
</Grid> </Grid>
</Page> </Page>

View File

@@ -83,5 +83,12 @@ namespace ModernKeePass.Pages
passwordBox.Visibility = Visibility.Visible; passwordBox.Visibility = Visibility.Visible;
passwordTextBox.Visibility = Visibility.Collapsed; passwordTextBox.Visibility = Visibility.Collapsed;
} }
private void AppBarButton_Click(object sender, RoutedEventArgs e)
{
var entry = DataContext as EntryVm;
entry?.RemoveEntry();
if (Frame.CanGoBack) Frame.GoBack();
}
} }
} }

View File

@@ -1,29 +1,27 @@
<Page <Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ModernKeePass.Pages"
xmlns:common="using:ModernKeePass.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ViewModels="using:ModernKeePass.ViewModels" xmlns:viewModels="using:ModernKeePass.ViewModels"
xmlns:Converters="using:ModernKeePass.Converters" xmlns:converters="using:ModernKeePass.Converters"
x:Name="pageRoot" x:Name="PageRoot"
x:Class="ModernKeePass.Pages.GroupDetailPage" x:Class="ModernKeePass.Pages.GroupDetailPage"
mc:Ignorable="d" > mc:Ignorable="d" >
<Page.Resources> <Page.Resources>
<Converters:PluralizationConverter x:Key="PluralizationConverter"/> <converters:PluralizationConverter x:Key="PluralizationConverter"/>
</Page.Resources> </Page.Resources>
<Page.DataContext> <Page.DataContext>
<ViewModels:GroupVm /> <viewModels:GroupVm />
</Page.DataContext> </Page.DataContext>
<Grid> <Grid>
<Grid.Resources> <Grid.Resources>
<CollectionViewSource <CollectionViewSource
x:Name="groupsViewSource" x:Name="GroupsViewSource"
Source="{Binding Groups}"/> Source="{Binding Groups}"/>
<CollectionViewSource <CollectionViewSource
x:Name="entriesViewSource" x:Name="EntriesViewSource"
Source="{Binding Entries}"/> Source="{Binding Entries}"/>
</Grid.Resources> </Grid.Resources>
<Grid.ChildrenTransitions> <Grid.ChildrenTransitions>
@@ -36,88 +34,116 @@
<RowDefinition Height="*"/> <RowDefinition Height="*"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- Horizontal scrolling grid --> <!-- Horizontal scrolling grid -->
<GridView <SemanticZoom
x:Name="groupsGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Groups"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
TabIndex="1"
Grid.RowSpan="2" Grid.RowSpan="2"
Padding="120,126,120,50" Padding="20,126,20,50">
ItemsSource="{Binding Source={StaticResource groupsViewSource}}" <SemanticZoom.ZoomedInView>
IsSwipeEnabled="false" <GridView
SelectionChanged="groupsGridView_SelectionChanged" AutomationProperties.AutomationId="ItemGridView"
IsSynchronizedWithCurrentItem="False" > AutomationProperties.Name="Groups"
<GridView.ItemTemplate> TabIndex="1"
<DataTemplate> ItemsSource="{Binding Source={StaticResource GroupsViewSource}}"
<Border BorderThickness="2" BorderBrush="DimGray" Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" Margin="0,10,0,0" > IsSwipeEnabled="false"
<Grid Height="110" Width="480" > SelectionChanged="groups_SelectionChanged"
<Grid.ColumnDefinitions> IsSynchronizedWithCurrentItem="False" >
<ColumnDefinition Width="Auto"/> <GridView.ItemTemplate>
<ColumnDefinition Width="*"/> <DataTemplate>
</Grid.ColumnDefinitions> <Border
<SymbolIcon Grid.Column="0" Symbol="{Binding IconSymbol}" Width="100" Height="100" /> BorderThickness="2"
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0"> BorderBrush="DimGray"
<TextBlock Text="{Binding Name}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/> Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}"
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/> Margin="0,10,0,0" >
<TextBlock Text="{Binding EntryCount, ConverterParameter=entry\,entries, Converter={StaticResource PluralizationConverter}}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60"/> <Grid Height="110" Width="480" >
<TextBlock Text="{Binding GroupCount, ConverterParameter=group\,groups, Converter={StaticResource PluralizationConverter}}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60"/> <Grid.ColumnDefinitions>
</StackPanel> <ColumnDefinition Width="Auto"/>
</Grid> <ColumnDefinition Width="*"/>
</Border> </Grid.ColumnDefinitions>
</DataTemplate> <SymbolIcon Grid.Column="0" Symbol="{Binding IconSymbol}" Width="100" Height="100" />
</GridView.ItemTemplate> <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0" Visibility="{Binding DetailsVisibility}" >
<GridView.Header> <TextBlock Text="{Binding Name}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/>
<ListView <TextBlock Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
x:Name="entriesListView" <TextBlock Text="{Binding EntryCount, ConverterParameter=entry\,entries, Converter={StaticResource PluralizationConverter}}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
Height="auto" <TextBlock Text="{Binding GroupCount, ConverterParameter=group\,groups, Converter={StaticResource PluralizationConverter}}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
Width="480" </StackPanel>
ItemsSource="{Binding Source={StaticResource entriesViewSource}}" <TextBlock Grid.Column="1" Text="{Binding Name}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" Visibility="{Binding NewVisibility}" VerticalAlignment="Center" Margin="13,0,0,5"/>
Margin="10,0,0,0" </Grid>
SelectionChanged="entriesListView_SelectionChanged" </Border>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.Header>
<ListView
Height="auto"
Width="480"
ItemsSource="{Binding Source={StaticResource EntriesViewSource}}"
Margin="10,0,0,0"
SelectionChanged="entriesListView_SelectionChanged"
IsSwipeEnabled="false"
IsSynchronizedWithCurrentItem="False" >
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Background="{Binding BackgroundColor}">
<SymbolIcon Symbol="{Binding IconSymbol}" />
<TextBlock Text="{Binding Title}" FontWeight="{Binding FontWeight}" TextWrapping="NoWrap" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="30,0,0,0" Foreground="{Binding ForegroundColor}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding EntryCount, ConverterParameter=entry\,entries, Converter={StaticResource PluralizationConverter}}" FontSize="20" Margin="0,20,0,20" />
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
</GridView.Header>
<GridView.ItemContainerStyle>
<Style TargetType="FrameworkElement">
<Setter Property="Margin" Value="52,0,0,2"/>
</Style>
</GridView.ItemContainerStyle>
</GridView>
</SemanticZoom.ZoomedInView>
<SemanticZoom.ZoomedOutView>
<ListView
ItemsSource="{Binding Source={StaticResource GroupsViewSource}}"
IsSwipeEnabled="false"
SelectionChanged="groups_SelectionChanged"
IsSynchronizedWithCurrentItem="False" > IsSynchronizedWithCurrentItem="False" >
<ListView.ItemTemplate> <ListView.ItemTemplate>
<DataTemplate> <DataTemplate>
<StackPanel Orientation="Horizontal" Background="{Binding BackgroundColor}"> <TextBlock Text="{Binding Name}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/>
<SymbolIcon Symbol="{Binding IconSymbol}" Margin="0,5,0,0"/>
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="30,0,0,10" Foreground="{Binding ForegroundColor}"/>
</StackPanel>
</DataTemplate> </DataTemplate>
</ListView.ItemTemplate> </ListView.ItemTemplate>
<ListView.HeaderTemplate>
<DataTemplate>
<TextBlock Text="Entries" FontSize="20" Margin="0,20,0,20" />
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
</ListView> </ListView>
</GridView.Header> </SemanticZoom.ZoomedOutView>
<GridView.ItemContainerStyle> </SemanticZoom>
<Style TargetType="FrameworkElement">
<Setter Property="Margin" Value="52,0,0,2"/>
</Style>
</GridView.ItemContainerStyle>
</GridView>
<!-- Back button and page title --> <!-- Back button and page title -->
<Grid> <Grid Grid.Row="0">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/> <ColumnDefinition Width="120"/>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Button x:Name="backButton" Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}" <Button Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=PageRoot}"
Style="{StaticResource NavigationBackButtonNormalStyle}" Style="{StaticResource NavigationBackButtonNormalStyle}"
VerticalAlignment="Top" VerticalAlignment="Top"
AutomationProperties.Name="Back" AutomationProperties.Name="Back"
AutomationProperties.AutomationId="BackButton" AutomationProperties.AutomationId="BackButton"
AutomationProperties.ItemType="Navigation Button"/> AutomationProperties.ItemType="Navigation Button"/>
<TextBlock x:Name="pageTitle" Text="{Binding Name}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1" <TextBlock Text="{Binding Name}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1"
IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40"/> IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40"/>
<CommandBar Grid.Column="2" Margin="0,40,0,0" Background="Transparent" IsOpen="True">
<AppBarButton Icon="Edit" Label="Edit" />
<AppBarButton Icon="Delete" Label="Delete" IsEnabled="{Binding IsNotRoot}" Click="AppBarButton_Click" />
</CommandBar>
</Grid> </Grid>
</Grid> </Grid>
</Page> </Page>

View File

@@ -14,20 +14,18 @@ namespace ModernKeePass.Pages
/// </summary> /// </summary>
public sealed partial class GroupDetailPage : Page public sealed partial class GroupDetailPage : Page
{ {
private NavigationHelper navigationHelper;
/// <summary> /// <summary>
/// NavigationHelper is used on each page to aid in navigation and /// NavigationHelper is used on each page to aid in navigation and
/// process lifetime management /// process lifetime management
/// </summary> /// </summary>
public NavigationHelper NavigationHelper => navigationHelper; public NavigationHelper NavigationHelper { get; }
public GroupDetailPage() public GroupDetailPage()
{ {
InitializeComponent(); InitializeComponent();
navigationHelper = new NavigationHelper(this); NavigationHelper = new NavigationHelper(this);
navigationHelper.LoadState += navigationHelper_LoadState; NavigationHelper.LoadState += navigationHelper_LoadState;
} }
/// <summary> /// <summary>
@@ -58,7 +56,7 @@ namespace ModernKeePass.Pages
/// ///
protected override void OnNavigatedTo(NavigationEventArgs e) protected override void OnNavigatedTo(NavigationEventArgs e)
{ {
navigationHelper.OnNavigatedTo(e); NavigationHelper.OnNavigatedTo(e);
if (!(e.Parameter is GroupVm)) return; if (!(e.Parameter is GroupVm)) return;
DataContext = (GroupVm) e.Parameter; DataContext = (GroupVm) e.Parameter;
@@ -66,22 +64,53 @@ namespace ModernKeePass.Pages
protected override void OnNavigatedFrom(NavigationEventArgs e) protected override void OnNavigatedFrom(NavigationEventArgs e)
{ {
navigationHelper.OnNavigatedFrom(e); NavigationHelper.OnNavigatedFrom(e);
} }
#endregion #endregion
private void groupsGridView_SelectionChanged(object sender, SelectionChangedEventArgs e) private void groups_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
var gridView = sender as GridView; GroupVm selectedItem = null;
Frame.Navigate(typeof(GroupDetailPage), gridView?.SelectedItem as GroupVm); if (sender is GridView)
{
var gridView = (GridView) sender;
if (gridView.SelectedIndex == 0)
{
var currentGroup = DataContext as GroupVm;
currentGroup?.CreateNewGroup();
gridView.SelectedIndex = -1;
// TODO: Navigate to new group?
return;
}
selectedItem = gridView.SelectedItem as GroupVm;
}
if (sender is ListView) selectedItem = ((ListView) sender).SelectedItem as GroupVm;
if (selectedItem == null) return;
Frame.Navigate(typeof(GroupDetailPage), selectedItem);
} }
private void entriesListView_SelectionChanged(object sender, SelectionChangedEventArgs e) private void entriesListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
var listView = sender as ListView; var listView = sender as ListView;
if (listView != null && listView.SelectedIndex == -1) return;
if (listView.SelectedIndex == 0)
{
var currentGroup = DataContext as GroupVm;
currentGroup?.CreateNewEntry();
listView.SelectedIndex = -1;
// TODO: Navigate to new entry?
return;
}
Frame.Navigate(typeof(EntryDetailPage), listView?.SelectedItem as EntryVm); Frame.Navigate(typeof(EntryDetailPage), listView?.SelectedItem as EntryVm);
} }
private void AppBarButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
var group = DataContext as GroupVm;
group?.RemoveGroup();
if (Frame.CanGoBack) Frame.GoBack();
}
} }
} }

View File

@@ -54,13 +54,7 @@ namespace ModernKeePass.Pages
private void AddToRecentFiles(StorageFile file) private void AddToRecentFiles(StorageFile file)
{ {
var mru = StorageApplicationPermissions.MostRecentlyUsedList; var mru = StorageApplicationPermissions.MostRecentlyUsedList;
var mruToken = mru.Add(file, file.DisplayName); mru.Add(file, file.DisplayName);
/*var localSettings = ApplicationData.Current.LocalSettings;
if (!localSettings.Containers.ContainsKey("Recent"))
localSettings.CreateContainer("Recent", ApplicationDataCreateDisposition.Always);
localSettings.Containers["Recent"].Values[file.DisplayName] = mruToken;*/
} }
private void ShowPassword(StorageFile file) private void ShowPassword(StorageFile file)

View File

@@ -24,6 +24,6 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyVersion("1.1.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]

View File

@@ -1,19 +1,25 @@
using System.ComponentModel; using Windows.UI.Xaml.Controls;
using System.Drawing;
using Windows.UI.Xaml.Controls;
using ModernKeePass.Mappings; using ModernKeePass.Mappings;
using ModernKeePassLib; using ModernKeePassLib;
using ModernKeePassLib.Security; using ModernKeePassLib.Security;
using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media;
using Windows.UI; using Windows.UI;
using Windows.UI.Text;
using Windows.UI.Xaml;
namespace ModernKeePass.ViewModels namespace ModernKeePass.ViewModels
{ {
public class EntryVm public class EntryVm
{ {
public GroupVm ParentGroup { get; }
public PwEntry Entry => _pwEntry;
public string Title public string Title
{ {
get { return GetEntryValue(PwDefs.TitleField); } get
{
var title = GetEntryValue(PwDefs.TitleField);
return title == null ? "New entry" : title;
}
set { SetEntryValue(PwDefs.TitleField, value); } set { SetEntryValue(PwDefs.TitleField, value); }
} }
public string UserName public string UserName
@@ -37,14 +43,17 @@ namespace ModernKeePass.ViewModels
set { SetEntryValue(PwDefs.NotesField, value); } set { SetEntryValue(PwDefs.NotesField, value); }
} }
public SolidColorBrush BackgroundColor => CreateFromColor(_pwEntry.BackgroundColor, Colors.Transparent); public SolidColorBrush BackgroundColor => CreateFromColor(_pwEntry?.BackgroundColor, Colors.Transparent);
public SolidColorBrush ForegroundColor => CreateFromColor(_pwEntry.ForegroundColor, Colors.White); public SolidColorBrush ForegroundColor => CreateFromColor(_pwEntry?.ForegroundColor, Colors.White);
public FontWeight FontWeight => _pwEntry == null ? FontWeights.Bold : FontWeights.Normal;
public Symbol IconSymbol public Symbol IconSymbol
{ {
get get
{ {
if (_pwEntry == null) return Symbol.Add;
var result = PwIconToSegoeMapping.GetSymbolFromIcon(_pwEntry.IconId); var result = PwIconToSegoeMapping.GetSymbolFromIcon(_pwEntry.IconId);
return result == Symbol.More ? Symbol.Permissions : result; return result == Symbol.More ? Symbol.Permissions : result;
} }
@@ -53,29 +62,35 @@ namespace ModernKeePass.ViewModels
private readonly PwEntry _pwEntry; private readonly PwEntry _pwEntry;
public EntryVm() { } public EntryVm() { }
public EntryVm(PwEntry entry) public EntryVm(PwEntry entry, GroupVm parent)
{ {
_pwEntry = entry; _pwEntry = entry;
ParentGroup = parent;
}
public void RemoveEntry()
{
ParentGroup.RemoveEntry(this);
} }
private string GetEntryValue(string key) private string GetEntryValue(string key)
{ {
return _pwEntry.Strings.GetSafe(key).ReadString(); return _pwEntry?.Strings.GetSafe(key).ReadString();
} }
private void SetEntryValue(string key, string newValue) private void SetEntryValue(string key, string newValue)
{ {
_pwEntry.Strings.Set(key, new ProtectedString(true, newValue)); _pwEntry?.Strings.Set(key, new ProtectedString(true, newValue));
} }
private SolidColorBrush CreateFromColor(System.Drawing.Color color, Windows.UI.Color defaultValue) private SolidColorBrush CreateFromColor(System.Drawing.Color? color, Windows.UI.Color defaultValue)
{ {
if (color == System.Drawing.Color.Empty) return new SolidColorBrush(defaultValue); if (!color.HasValue || color.Value == System.Drawing.Color.Empty) return new SolidColorBrush(defaultValue);
return new SolidColorBrush(Windows.UI.Color.FromArgb( return new SolidColorBrush(Windows.UI.Color.FromArgb(
color.A, color.Value.A,
color.R, color.Value.R,
color.G, color.Value.G,
color.B)); color.Value.B));
} }
} }
} }

View File

@@ -1,6 +1,7 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.Linq; using System.Linq;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using ModernKeePass.Mappings; using ModernKeePass.Mappings;
using ModernKeePassLib; using ModernKeePassLib;
@@ -9,63 +10,76 @@ namespace ModernKeePass.ViewModels
{ {
public class GroupVm : INotifyPropertyChanged public class GroupVm : INotifyPropertyChanged
{ {
private PwGroup _pwGroup; public GroupVm ParentGroup { get; }
public ObservableCollection<EntryVm> Entries { get; set; } = new ObservableCollection<EntryVm>();
public ObservableCollection<GroupVm> Groups { get; set; } = new ObservableCollection<GroupVm>();
public string Name => _pwGroup == null ? "New group" : _pwGroup.Name;
public ObservableCollection<EntryVm> Entries { get; set; } public int EntryCount => Entries.Count - 1;
public ObservableCollection<GroupVm> Groups { get; set; }
public string Name { get; set; }
public int EntryCount => Entries.Count; public int GroupCount => Groups.Count - 1;
public int GroupCount => Groups.Count; public Visibility DetailsVisibility => _pwGroup == null ? Visibility.Collapsed : Visibility.Visible;
public Visibility NewVisibility => _pwGroup == null ? Visibility.Visible : Visibility.Collapsed;
public Symbol IconSymbol public Symbol IconSymbol
{ {
get get
{ {
if (_pwGroup == null) return Symbol.Add;
var result = PwIconToSegoeMapping.GetSymbolFromIcon(_pwGroup.IconId); var result = PwIconToSegoeMapping.GetSymbolFromIcon(_pwGroup.IconId);
return result == Symbol.More ? Symbol.Folder : result; return result == Symbol.More ? Symbol.Folder : result;
} }
} }
public GroupVm() public bool IsNotRoot => ParentGroup != null;
{
Name = "GroupName";
Entries = new ObservableCollection<EntryVm>();
Groups = new ObservableCollection<GroupVm>();
}
public GroupVm(PwGroup pwGroup) private readonly PwGroup _pwGroup;
public GroupVm() {}
public GroupVm(PwGroup pwGroup, GroupVm parent)
{ {
_pwGroup = pwGroup; _pwGroup = pwGroup;
Name = pwGroup.Name; ParentGroup = parent;
Entries = new ObservableCollection<EntryVm>(pwGroup.Entries.Select(e => new EntryVm(e))); Entries = new ObservableCollection<EntryVm>(pwGroup.Entries.Select(e => new EntryVm(e, this)));
//Entries.Insert(0, new EntryVm { Title = " + New entry" }); Entries.Insert(0, new EntryVm ());
Groups = new ObservableCollection<GroupVm>(pwGroup.Groups.Select(g => new GroupVm(g))); //Entries.Add(new EntryVm { Title = " New entry" });
Groups = new ObservableCollection<GroupVm>(pwGroup.Groups.Select(g => new GroupVm(g, this)));
//Groups.Insert(0, new GroupVm { Name = " + New group" }); //Groups.Insert(0, new GroupVm { Name = " + New group" });
Groups.Insert(0, new GroupVm ());
} }
public void CreateNewGroup(string title) public void CreateNewGroup()
{ {
var pwGroup = new PwGroup(true, true, title, PwIcon.Folder); var pwGroup = new PwGroup(true, true, "New group", PwIcon.Folder);
_pwGroup.AddGroup(pwGroup, true); _pwGroup.AddGroup(pwGroup, true);
Groups.Add(new GroupVm(pwGroup)); Groups.Add(new GroupVm(pwGroup, this));
NotifyPropertyChanged("Groups");
} }
public void CreateNewEntry(string title) public void CreateNewEntry()
{ {
var pwEntry = new PwEntry(true, true); var pwEntry = new PwEntry(true, true);
_pwGroup.AddEntry(pwEntry, true); _pwGroup.AddEntry(pwEntry, true);
Entries.Add(new EntryVm(pwEntry)); Entries.Add(new EntryVm(pwEntry, this));
NotifyPropertyChanged("Entries"); }
public void RemoveGroup()
{
_pwGroup.ParentGroup.Groups.Remove(_pwGroup);
ParentGroup.Groups.Remove(this);
} }
public void RemoveEntry(EntryVm entry)
{
_pwGroup.Entries.Remove(entry.Entry);
Entries.Remove(entry);
}
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName) public void NotifyPropertyChanged(string propertyName)
{ {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
} }
} }
} }