Adding entries and groups works again

Entry history almost fully functional
Some refactoring
This commit is contained in:
Geoffroy BONNEVILLE
2020-04-03 17:33:53 +02:00
parent 36aa8914fa
commit b875f3c89d
12 changed files with 75 additions and 40 deletions

View File

@@ -8,7 +8,6 @@ namespace ModernKeePass.Application.Common.Interfaces
string Id { get; set; } string Id { get; set; }
string Title { get; set; } string Title { get; set; }
Icon Icon { get; set; } Icon Icon { get; set; }
List<IEntityVm> Breadcrumb { get; }
string ParentGroupId { get; set; } string ParentGroupId { get; set; }
string ParentGroupName { get; set; } string ParentGroupName { get; set; }
} }

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq;
using AutoMapper; using AutoMapper;
using ModernKeePass.Application.Common.Interfaces; using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Common.Mappings; using ModernKeePass.Application.Common.Mappings;
@@ -13,7 +14,6 @@ namespace ModernKeePass.Application.Entry.Models
{ {
public string ParentGroupId { get; set; } public string ParentGroupId { get; set; }
public string ParentGroupName { get; set; } public string ParentGroupName { get; set; }
public List<IEntityVm> Breadcrumb { get; } = new List<IEntityVm>();
public string Id { get; set; } public string Id { get; set; }
public string Title { get; set; } public string Title { get; set; }
public string Username { get; set; } public string Username { get; set; }
@@ -46,7 +46,7 @@ namespace ModernKeePass.Application.Entry.Models
.ForMember(d => d.Url, opts => opts.MapFrom(s => s.Url)) .ForMember(d => d.Url, opts => opts.MapFrom(s => s.Url))
.ForMember(d => d.Notes, opts => opts.MapFrom(s => s.Notes)) .ForMember(d => d.Notes, opts => opts.MapFrom(s => s.Notes))
.ForMember(d => d.AdditionalFields, opts => opts.MapFrom(s => s.AdditionalFields)) .ForMember(d => d.AdditionalFields, opts => opts.MapFrom(s => s.AdditionalFields))
.ForMember(d => d.History, opts => opts.MapFrom(s => s.History)) .ForMember(d => d.History, opts => opts.MapFrom(s => s.History.OrderByDescending(h => h.LastModificationDate)))
.ForMember(d => d.HasExpirationDate, opts => opts.MapFrom(s => s.HasExpirationDate)) .ForMember(d => d.HasExpirationDate, opts => opts.MapFrom(s => s.HasExpirationDate))
.ForMember(d => d.ExpirationDate, opts => opts.MapFrom(s => s.ExpirationDate)) .ForMember(d => d.ExpirationDate, opts => opts.MapFrom(s => s.ExpirationDate))
.ForMember(d => d.ModificationDate, opts => opts.MapFrom(s => s.LastModificationDate)) .ForMember(d => d.ModificationDate, opts => opts.MapFrom(s => s.LastModificationDate))

View File

@@ -16,7 +16,6 @@ namespace ModernKeePass.Application.Group.Models
public string Id { get; set; } public string Id { get; set; }
public string Title { get; set; } public string Title { get; set; }
public Icon Icon { get; set; } public Icon Icon { get; set; }
public List<IEntityVm> Breadcrumb { get; } = new List<IEntityVm>();
public List<GroupVm> SubGroups { get; set; } public List<GroupVm> SubGroups { get; set; }
public List<EntryVm> Entries { get; set; } public List<EntryVm> Entries { get; set; }
public bool IsSelected { get; set; } public bool IsSelected { get; set; }

View File

@@ -1,13 +1,12 @@
using MediatR; using MediatR;
using ModernKeePass.Application.Common.Interfaces; using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Domain.Exceptions; using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Parameters.Commands.SetRecycleBin namespace ModernKeePass.Application.Parameters.Commands.SetRecycleBin
{ {
public class SetRecycleBinCommand : IRequest public class SetRecycleBinCommand : IRequest
{ {
public GroupVm RecycleBin { get; set; } public string RecycleBinId { get; set; }
public class SetRecycleBinCommandHandler : IRequestHandler<SetRecycleBinCommand> public class SetRecycleBinCommandHandler : IRequestHandler<SetRecycleBinCommand>
{ {
@@ -20,7 +19,7 @@ namespace ModernKeePass.Application.Parameters.Commands.SetRecycleBin
public void Handle(SetRecycleBinCommand message) public void Handle(SetRecycleBinCommand message)
{ {
if (_database.IsOpen) _database.SetRecycleBin(message.RecycleBin.Id); if (_database.IsOpen) _database.SetRecycleBin(message.RecycleBinId);
else throw new DatabaseClosedException(); else throw new DatabaseClosedException();
} }
} }

View File

@@ -191,7 +191,7 @@ namespace ModernKeePass.Infrastructure.KeePass
{ {
var parentPwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(parentGroupId), true); var parentPwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(parentGroupId), true);
var pwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(groupId), true); var pwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(groupId), true);
parentPwGroup.Groups.Add(pwGroup); parentPwGroup.AddGroup(pwGroup, true);
}); });
} }
public async Task RemoveEntry(string parentGroupId, string entryId) public async Task RemoveEntry(string parentGroupId, string entryId)
@@ -288,7 +288,7 @@ namespace ModernKeePass.Infrastructure.KeePass
{ {
var pwEntry = new PwEntry(true, true); var pwEntry = new PwEntry(true, true);
var parentPwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(parentGroupId), true); var parentPwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(parentGroupId), true);
parentPwGroup.Entries.Add(pwEntry); parentPwGroup.AddEntry(pwEntry, true);
return _mapper.Map<EntryEntity>(pwEntry); return _mapper.Map<EntryEntity>(pwEntry);
} }
@@ -297,7 +297,7 @@ namespace ModernKeePass.Infrastructure.KeePass
{ {
var pwGroup = new PwGroup(true, true, name, isRecycleBin? PwIcon.TrashBin : PwIcon.Folder); var pwGroup = new PwGroup(true, true, name, isRecycleBin? PwIcon.TrashBin : PwIcon.Folder);
var parentPwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(parentGroupId), true); var parentPwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(parentGroupId), true);
parentPwGroup.Groups.Add(pwGroup); parentPwGroup.AddGroup(pwGroup, true);
if (isRecycleBin) _pwDatabase.RecycleBinUuid = pwGroup.Uuid; if (isRecycleBin) _pwDatabase.RecycleBinUuid = pwGroup.Uuid;
return _mapper.Map<GroupEntity>(pwGroup); return _mapper.Map<GroupEntity>(pwGroup);

View File

@@ -46,7 +46,15 @@ namespace ModernKeePass.ViewModels
/// <summary> /// <summary>
/// Determines if the Entry is current or from history /// Determines if the Entry is current or from history
/// </summary> /// </summary>
public bool IsSelected { get; set; } = true; public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
OnPropertyChanged();
}
}
public double PasswordLength public double PasswordLength
{ {
@@ -178,7 +186,7 @@ namespace ModernKeePass.ViewModels
} }
} }
} }
public IEnumerable<EntryVm> History => _entry.History; public IEnumerable<EntryVm> History => _history;
public bool IsEditMode public bool IsEditMode
{ {
@@ -216,14 +224,16 @@ namespace ModernKeePass.ViewModels
public ICommand GeneratePasswordCommand { get; } public ICommand GeneratePasswordCommand { get; }
public ICommand UndoDeleteCommand { get; } public ICommand UndoDeleteCommand { get; }
private readonly EntryVm _entry;
private readonly GroupVm _parent;
private readonly IMediator _mediator; private readonly IMediator _mediator;
private readonly DatabaseVm _database; private readonly DatabaseVm _database;
private readonly GroupVm _parent;
private readonly IEnumerable<EntryVm> _history;
private EntryVm _entry;
private bool _isEditMode; private bool _isEditMode;
private bool _isRevealPassword; private bool _isRevealPassword;
private double _passwordLength = 25; private double _passwordLength = 25;
private bool _isVisible = true; private bool _isVisible = true;
private bool _isSelected;
public EntryDetailVm() { } public EntryDetailVm() { }
@@ -235,8 +245,10 @@ namespace ModernKeePass.ViewModels
_database = _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult(); _database = _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
_entry = _mediator.Send(new GetEntryQuery {Id = entryId}).GetAwaiter().GetResult(); _entry = _mediator.Send(new GetEntryQuery {Id = entryId}).GetAwaiter().GetResult();
_parent = _mediator.Send(new GetGroupQuery {Id = _entry.ParentGroupId}).GetAwaiter().GetResult(); _parent = _mediator.Send(new GetGroupQuery {Id = _entry.ParentGroupId}).GetAwaiter().GetResult();
_history = _entry.History;
_isEditMode = isNewEntry; _isEditMode = isNewEntry;
if (isNewEntry) GeneratePassword().GetAwaiter().GetResult(); if (isNewEntry) GeneratePassword().GetAwaiter().GetResult();
IsSelected = true;
SaveCommand = new RelayCommand(() => _mediator.Send(new SaveDatabaseCommand())); SaveCommand = new RelayCommand(() => _mediator.Send(new SaveDatabaseCommand()));
GeneratePasswordCommand = new RelayCommand(async () => await GeneratePassword()); GeneratePasswordCommand = new RelayCommand(async () => await GeneratePassword());
@@ -272,14 +284,26 @@ namespace ModernKeePass.ViewModels
await _mediator.Send(new RemoveEntryCommand { ParentGroup = _parent, Entry = _entry }); await _mediator.Send(new RemoveEntryCommand { ParentGroup = _parent, Entry = _entry });
} }
public EntryVm GetEntry()
{
return _entry;
}
public async Task SetFieldValue(string fieldName, object value) public async Task SetFieldValue(string fieldName, object value)
{ {
await _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = fieldName, FieldValue = value }); await _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = fieldName, FieldValue = value });
} }
internal void SetEntry(EntryVm entry, int index)
{
_entry = entry;
IsSelected = index == 0;
/*OnPropertyChanged(nameof(Title));
OnPropertyChanged(nameof(UserName));
OnPropertyChanged(nameof(Password));
OnPropertyChanged(nameof(Url));
OnPropertyChanged(nameof(Notes));
OnPropertyChanged(nameof(Icon));
OnPropertyChanged(nameof(ForegroundColor));
OnPropertyChanged(nameof(BackgroundColor));
OnPropertyChanged(nameof(HasExpirationDate));
OnPropertyChanged(nameof(ExpiryDate));
OnPropertyChanged(nameof(ExpiryTime));*/
}
} }
} }

View File

@@ -159,7 +159,7 @@ namespace ModernKeePass.ViewModels
case NotifyCollectionChangedAction.Add: case NotifyCollectionChangedAction.Add:
if (_reorderedEntry == null) if (_reorderedEntry == null)
{ {
var entry = ((EntryDetailVm) e.NewItems[0]).GetEntry(); var entry = (EntryVm) e.NewItems[0];
await _mediator.Send(new AddEntryCommand {Entry = entry, ParentGroup = _group}); await _mediator.Send(new AddEntryCommand {Entry = entry, ParentGroup = _group});
} }
else else

View File

@@ -2,9 +2,9 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using MediatR; using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Database.Models; using ModernKeePass.Application.Database.Models;
using ModernKeePass.Application.Database.Queries.GetDatabase; using ModernKeePass.Application.Database.Queries.GetDatabase;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Application.Group.Queries.GetGroup; using ModernKeePass.Application.Group.Queries.GetGroup;
using ModernKeePass.Application.Parameters.Commands.SetCipher; using ModernKeePass.Application.Parameters.Commands.SetCipher;
using ModernKeePass.Application.Parameters.Commands.SetCompression; using ModernKeePass.Application.Parameters.Commands.SetCompression;
@@ -16,16 +16,14 @@ using ModernKeePass.Application.Parameters.Queries.GetCiphers;
using ModernKeePass.Application.Parameters.Queries.GetCompressions; using ModernKeePass.Application.Parameters.Queries.GetCompressions;
using ModernKeePass.Application.Parameters.Queries.GetKeyDerivations; using ModernKeePass.Application.Parameters.Queries.GetKeyDerivations;
using ModernKeePass.Common; using ModernKeePass.Common;
using ModernKeePass.Domain.Interfaces;
namespace ModernKeePass.ViewModels namespace ModernKeePass.ViewModels
{ {
// TODO: implement Kdf settings // TODO: implement Kdf settings
public class SettingsDatabaseVm: NotifyPropertyChangedBase, IHasSelectableObject public class SettingsDatabaseVm: NotifyPropertyChangedBase
{ {
private readonly IMediator _mediator; private readonly IMediator _mediator;
private readonly DatabaseVm _database; private readonly DatabaseVm _database;
private GroupDetailVm _selectedItem;
public bool HasRecycleBin public bool HasRecycleBin
{ {
@@ -42,11 +40,11 @@ namespace ModernKeePass.ViewModels
get { return string.IsNullOrEmpty(_database.RecycleBinId); } get { return string.IsNullOrEmpty(_database.RecycleBinId); }
set set
{ {
if (value) _mediator.Send(new SetRecycleBinCommand { RecycleBin = null }).Wait(); if (value) _mediator.Send(new SetRecycleBinCommand { RecycleBinId = null }).Wait();
} }
} }
public ObservableCollection<GroupVm> Groups { get; set; } public ObservableCollection<IEntityVm> Groups { get; set; }
public IEnumerable<CipherVm> Ciphers => _mediator.Send(new GetCiphersQuery()).GetAwaiter().GetResult(); public IEnumerable<CipherVm> Ciphers => _mediator.Send(new GetCiphersQuery()).GetAwaiter().GetResult();
public IEnumerable<string> Compressions => _mediator.Send(new GetCompressionsQuery()).GetAwaiter().GetResult(); public IEnumerable<string> Compressions => _mediator.Send(new GetCompressionsQuery()).GetAwaiter().GetResult();
@@ -70,6 +68,14 @@ namespace ModernKeePass.ViewModels
set { _mediator.Send(new SetKeyDerivationCommand {KeyDerivationId = value.Id}).Wait(); } set { _mediator.Send(new SetKeyDerivationCommand {KeyDerivationId = value.Id}).Wait(); }
} }
public IEntityVm SelectedRecycleBin
{
get { return Groups.FirstOrDefault(g => g.Id == _database.RecycleBinId); }
set { _mediator.Send(new SetRecycleBinCommand { RecycleBinId = value.Id}).Wait(); }
}
/*public int CipherIndex /*public int CipherIndex
{ {
get get
@@ -93,7 +99,7 @@ namespace ModernKeePass.ViewModels
{ {
get { return KdfPool.Get(_database.KeyDerivation.KdfUuid).Name; } get { return KdfPool.Get(_database.KeyDerivation.KdfUuid).Name; }
set { _database.KeyDerivation = KdfPool.Engines.FirstOrDefault(e => e.Name == value)?.GetDefaultParameters(); } set { _database.KeyDerivation = KdfPool.Engines.FirstOrDefault(e => e.Name == value)?.GetDefaultParameters(); }
}*/ }
public ISelectableModel SelectedItem public ISelectableModel SelectedItem
{ {
@@ -106,14 +112,14 @@ namespace ModernKeePass.ViewModels
_selectedItem.IsSelected = false; _selectedItem.IsSelected = false;
} }
SetProperty(ref _selectedItem, (GroupDetailVm)value); SetProperty(ref _selectedItem, (IEntityVm)value);
if (_selectedItem != null) if (_selectedItem != null)
{ {
_selectedItem.IsSelected = true; _selectedItem.IsSelected = true;
} }
} }
} }*/
public SettingsDatabaseVm() : this(App.Mediator) { } public SettingsDatabaseVm() : this(App.Mediator) { }
@@ -122,7 +128,7 @@ namespace ModernKeePass.ViewModels
_mediator = mediator; _mediator = mediator;
_database = _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult(); _database = _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
var rootGroup = _mediator.Send(new GetGroupQuery { Id = _database.RootGroupId }).GetAwaiter().GetResult(); var rootGroup = _mediator.Send(new GetGroupQuery { Id = _database.RootGroupId }).GetAwaiter().GetResult();
Groups = new ObservableCollection<GroupVm>(rootGroup.SubGroups); Groups = new ObservableCollection<IEntityVm>(rootGroup.SubGroups);
} }
} }
} }

View File

@@ -62,14 +62,17 @@ namespace ModernKeePass.Views
private void HamburgerMenuUserControl_OnSelectionChanged(object sender, SelectionChangedEventArgs e) private void HamburgerMenuUserControl_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
var listView = sender as ListView; var listView = sender as ListView;
switch (listView?.SelectedIndex) if (listView == null) return;
var index = listView.SelectedIndex;
switch (index)
{ {
case -1: case -1:
return; return;
default: default:
var entry = listView?.SelectedItem as Application.Entry.Models.EntryVm; var entry = listView?.SelectedItem as Application.Entry.Models.EntryVm;
StackPanel.DataContext = entry; Model.SetEntry(entry, index);
TopGrid.DataContext = entry; /*StackPanel.DataContext = entry;
TopGrid.DataContext = entry;*/
break; break;
} }
} }

View File

@@ -130,8 +130,7 @@ namespace ModernKeePass.Views
private void SearchBox_OnResultSuggestionChosen(SearchBox sender, SearchBoxResultSuggestionChosenEventArgs args) private void SearchBox_OnResultSuggestionChosen(SearchBox sender, SearchBoxResultSuggestionChosenEventArgs args)
{ {
var entry = Model.SubEntries.FirstOrDefault(e => e.Id == args.Tag); Frame.Navigate(typeof(EntryDetailPage), args.Tag);
Frame.Navigate(typeof(EntryDetailPage), entry);
} }
private void GroupDetailPage_OnSizeChanged(object sender, SizeChangedEventArgs e) private void GroupDetailPage_OnSizeChanged(object sender, SizeChangedEventArgs e)

View File

@@ -23,8 +23,8 @@
<ToggleSwitch x:Uid="SettingsDatabaseRecycleBin" IsOn="{Binding HasRecycleBin, Mode=TwoWay}" Style="{StaticResource MainColorToggleSwitch}" /> <ToggleSwitch x:Uid="SettingsDatabaseRecycleBin" IsOn="{Binding HasRecycleBin, Mode=TwoWay}" Style="{StaticResource MainColorToggleSwitch}" />
<StackPanel Visibility="{Binding HasRecycleBin, Converter={StaticResource BooleanToVisibilityConverter}}"> <StackPanel Visibility="{Binding HasRecycleBin, Converter={StaticResource BooleanToVisibilityConverter}}">
<RadioButton x:Uid="SettingsDatabaseRecycleBinCreate" GroupName="Recycle" IsChecked="{Binding IsNewRecycleBin, Mode=TwoWay}" /> <RadioButton x:Uid="SettingsDatabaseRecycleBinCreate" GroupName="Recycle" IsChecked="{Binding IsNewRecycleBin, Mode=TwoWay}" />
<RadioButton x:Name="RadioButton" x:Uid="SettingsDatabaseRecycleBinExisting" GroupName="Recycle" IsChecked="{Binding SelectedItem, Converter={StaticResource NullToBooleanConverter}}" /> <RadioButton x:Name="RadioButton" x:Uid="SettingsDatabaseRecycleBinExisting" GroupName="Recycle" IsChecked="{Binding SelectedRecycleBin, Converter={StaticResource NullToBooleanConverter}}" />
<ComboBox ItemsSource="{Binding Source={StaticResource RecycleBinGroups}}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" IsEnabled="{Binding IsChecked, ElementName=RadioButton}" /> <ComboBox ItemsSource="{Binding Source={StaticResource RecycleBinGroups}}" SelectedItem="{Binding SelectedRecycleBin, Mode=TwoWay}" IsEnabled="{Binding IsChecked, ElementName=RadioButton}" />
</StackPanel> </StackPanel>
<TextBlock x:Uid="SettingsDatabaseEncryption" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,20,0,10" /> <TextBlock x:Uid="SettingsDatabaseEncryption" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,20,0,10" />
<ComboBox ItemsSource="{Binding Source={StaticResource Ciphers}}" DisplayMemberPath="Name" SelectedItem="{Binding SelectedCipher, Mode=TwoWay}" ItemContainerStyle="{StaticResource MainColorComboBoxItem}" Style="{StaticResource MainColorComboBox}" /> <ComboBox ItemsSource="{Binding Source={StaticResource Ciphers}}" DisplayMemberPath="Name" SelectedItem="{Binding SelectedCipher, Mode=TwoWay}" ItemContainerStyle="{StaticResource MainColorComboBoxItem}" Style="{StaticResource MainColorComboBox}" />

View File

@@ -5,7 +5,13 @@
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"> mc:Ignorable="d">
<ComboBox x:Name="ComboBox" ItemsSource="{Binding Colors, ElementName=UserControl}" SelectionChanged="Selector_OnSelectionChanged" Loaded="ComboBox_Loaded" ItemContainerStyle="{StaticResource MainColorComboBoxItem}" Style="{StaticResource MainColorComboBox}"> <ComboBox x:Name="ComboBox"
ItemsSource="{Binding Colors, ElementName=UserControl}"
SelectionChanged="Selector_OnSelectionChanged"
Loaded="ComboBox_Loaded"
ItemContainerStyle="{StaticResource MainColorComboBoxItem}"
Style="{StaticResource MainColorComboBox}"
IsEnabled="{Binding IsEnabled, ElementName=UserControl}">
<ComboBox.ItemTemplate> <ComboBox.ItemTemplate>
<DataTemplate> <DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,10,0"> <StackPanel Orientation="Horizontal" Margin="0,0,10,0">