Handle entities with id

No hierarchy is built anymore
WIP save issues after delete
This commit is contained in:
Geoffroy BONNEVILLE
2020-04-02 19:12:16 +02:00
parent b61a9652d1
commit 36aa8914fa
26 changed files with 213 additions and 96 deletions

View File

@@ -52,6 +52,8 @@
<Compile Include="Common\Mappings\IMapFrom.cs" /> <Compile Include="Common\Mappings\IMapFrom.cs" />
<Compile Include="Common\Mappings\MappingProfile.cs" /> <Compile Include="Common\Mappings\MappingProfile.cs" />
<Compile Include="Entry\Queries\GetEntry\GetEntryQuery.cs" /> <Compile Include="Entry\Queries\GetEntry\GetEntryQuery.cs" />
<Compile Include="Group\Commands\DeleteEntry\DeleteEntryCommand.cs" />
<Compile Include="Group\Commands\DeleteGroup\DeleteGroupCommand.cs" />
<Compile Include="Group\Queries\GetGroup\GetGroupQuery.cs" /> <Compile Include="Group\Queries\GetGroup\GetGroupQuery.cs" />
<Compile Include="Parameters\Commands\SetCipher\SetCipherCommand.cs" /> <Compile Include="Parameters\Commands\SetCipher\SetCipherCommand.cs" />
<Compile Include="Parameters\Commands\SetCompression\SetCompressionCommand.cs" /> <Compile Include="Parameters\Commands\SetCompression\SetCompressionCommand.cs" />

View File

@@ -30,8 +30,10 @@ namespace ModernKeePass.Application.Common.Interfaces
Task AddGroup(string parentGroupId, string groupId); Task AddGroup(string parentGroupId, string groupId);
void UpdateEntry(string entryId, string fieldName, object fieldValue); void UpdateEntry(string entryId, string fieldName, object fieldValue);
void UpdateGroup(string groupId); void UpdateGroup(string groupId);
Task RemoveEntry(string parentGroupId, string entryId, bool isToBeDeleted); Task RemoveEntry(string parentGroupId, string entryId);
Task RemoveGroup(string parentGroupId, string groupId, bool isToBeDeleted); Task RemoveGroup(string parentGroupId, string groupId);
Task DeleteEntry(string parentGroupId, string entryId, string recycleBinName);
Task DeleteGroup(string parentGroupId, string groupId, string recycleBinName);
EntryEntity CreateEntry(string parentGroupId); EntryEntity CreateEntry(string parentGroupId);
GroupEntity CreateGroup(string parentGroupId, string nameId, bool isRecycleBin = false); GroupEntity CreateGroup(string parentGroupId, string nameId, bool isRecycleBin = false);
void SortEntries(string groupId); void SortEntries(string groupId);

View File

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

View File

@@ -12,6 +12,7 @@ namespace ModernKeePass.Application.Entry.Models
public class EntryVm: IEntityVm, IMapFrom<EntryEntity> public class EntryVm: IEntityVm, IMapFrom<EntryEntity>
{ {
public string ParentGroupId { get; set; } public string ParentGroupId { get; set; }
public string ParentGroupName { get; set; }
public List<IEntityVm> Breadcrumb { get; } = new List<IEntityVm>(); 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; }
@@ -37,6 +38,7 @@ namespace ModernKeePass.Application.Entry.Models
{ {
profile.CreateMap<EntryEntity, EntryVm>() profile.CreateMap<EntryEntity, EntryVm>()
.ForMember(d => d.ParentGroupId, opts => opts.MapFrom(s => s.ParentId)) .ForMember(d => d.ParentGroupId, opts => opts.MapFrom(s => s.ParentId))
.ForMember(d => d.ParentGroupName, opts => opts.MapFrom(s => s.ParentName))
.ForMember(d => d.Id, opts => opts.MapFrom(s => s.Id)) .ForMember(d => d.Id, opts => opts.MapFrom(s => s.Id))
.ForMember(d => d.Title, opts => opts.MapFrom(s => s.Name)) .ForMember(d => d.Title, opts => opts.MapFrom(s => s.Name))
.ForMember(d => d.Username, opts => opts.MapFrom(s => s.UserName)) .ForMember(d => d.Username, opts => opts.MapFrom(s => s.UserName))

View File

@@ -8,7 +8,7 @@ namespace ModernKeePass.Application.Group.Commands.CreateGroup
{ {
public class CreateGroupCommand : IRequest<GroupVm> public class CreateGroupCommand : IRequest<GroupVm>
{ {
public string ParentGroupId { get; set; } public GroupVm ParentGroup { get; set; }
public string Name { get; set; } public string Name { get; set; }
public bool IsRecycleBin { get; set; } public bool IsRecycleBin { get; set; }
@@ -27,8 +27,9 @@ namespace ModernKeePass.Application.Group.Commands.CreateGroup
{ {
if (!_database.IsOpen) throw new DatabaseClosedException(); if (!_database.IsOpen) throw new DatabaseClosedException();
var group = _database.CreateGroup(message.ParentGroupId, message.Name, message.IsRecycleBin); var group = _database.CreateGroup(message.ParentGroup.Id, message.Name, message.IsRecycleBin);
var groupVm = _mapper.Map<GroupVm>(group); var groupVm = _mapper.Map<GroupVm>(group);
message.ParentGroup.SubGroups.Add(groupVm);
return groupVm; return groupVm;
} }
} }

View File

@@ -0,0 +1,31 @@
using System.Threading.Tasks;
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Group.Commands.DeleteEntry
{
public class DeleteEntryCommand : IRequest
{
public string ParentGroupId { get; set; }
public string EntryId { get; set; }
public string RecycleBinName { get; set; }
public class DeleteEntryCommandHandler : IAsyncRequestHandler<DeleteEntryCommand>
{
private readonly IDatabaseProxy _database;
public DeleteEntryCommandHandler(IDatabaseProxy database)
{
_database = database;
}
public async Task Handle(DeleteEntryCommand message)
{
if (!_database.IsOpen) throw new DatabaseClosedException();
await _database.DeleteEntry(message.ParentGroupId, message.EntryId, message.RecycleBinName);
}
}
}
}

View File

@@ -0,0 +1,31 @@
using System.Threading.Tasks;
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Group.Commands.DeleteGroup
{
public class DeleteGroupCommand : IRequest
{
public string ParentGroupId { get; set; }
public string GroupId { get; set; }
public string RecycleBinName { get; set; }
public class DeleteGroupCommandHandler : IAsyncRequestHandler<DeleteGroupCommand>
{
private readonly IDatabaseProxy _database;
public DeleteGroupCommandHandler(IDatabaseProxy database)
{
_database = database;
}
public async Task Handle(DeleteGroupCommand message)
{
if (!_database.IsOpen) throw new DatabaseClosedException();
await _database.DeleteEntry(message.ParentGroupId, message.GroupId, message.RecycleBinName);
}
}
}
}

View File

@@ -11,7 +11,6 @@ namespace ModernKeePass.Application.Group.Commands.RemoveEntry
{ {
public GroupVm ParentGroup { get; set; } public GroupVm ParentGroup { get; set; }
public EntryVm Entry { get; set; } public EntryVm Entry { get; set; }
public bool IsDelete { get; set; }
public class RemoveEntryCommandHandler : IAsyncRequestHandler<RemoveEntryCommand> public class RemoveEntryCommandHandler : IAsyncRequestHandler<RemoveEntryCommand>
{ {
@@ -26,7 +25,7 @@ namespace ModernKeePass.Application.Group.Commands.RemoveEntry
{ {
if (!_database.IsOpen) throw new DatabaseClosedException(); if (!_database.IsOpen) throw new DatabaseClosedException();
await _database.RemoveEntry(message.ParentGroup.Id, message.Entry.Id, message.IsDelete); await _database.RemoveEntry(message.ParentGroup.Id, message.Entry.Id);
message.ParentGroup.Entries.Remove(message.Entry); message.ParentGroup.Entries.Remove(message.Entry);
} }
} }

View File

@@ -10,7 +10,6 @@ namespace ModernKeePass.Application.Group.Commands.RemoveGroup
{ {
public GroupVm ParentGroup { get; set; } public GroupVm ParentGroup { get; set; }
public GroupVm Group { get; set; } public GroupVm Group { get; set; }
public bool IsDelete { get; set; }
public class RemoveGroupCommandHandler : IAsyncRequestHandler<RemoveGroupCommand> public class RemoveGroupCommandHandler : IAsyncRequestHandler<RemoveGroupCommand>
{ {
@@ -25,7 +24,7 @@ namespace ModernKeePass.Application.Group.Commands.RemoveGroup
{ {
if (!_database.IsOpen) throw new DatabaseClosedException(); if (!_database.IsOpen) throw new DatabaseClosedException();
await _database.RemoveGroup(message.ParentGroup.Id, message.Group.Id, message.IsDelete); await _database.RemoveGroup(message.ParentGroup.Id, message.Group.Id);
message.ParentGroup.SubGroups.Remove(message.Group); message.ParentGroup.SubGroups.Remove(message.Group);
} }
} }

View File

@@ -12,6 +12,7 @@ namespace ModernKeePass.Application.Group.Models
public class GroupVm: IEntityVm, ISelectableModel, IMapFrom<GroupEntity> public class GroupVm: IEntityVm, ISelectableModel, IMapFrom<GroupEntity>
{ {
public string ParentGroupId { get; set; } public string ParentGroupId { get; set; }
public string ParentGroupName { get; set; }
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; }
@@ -29,12 +30,13 @@ namespace ModernKeePass.Application.Group.Models
{ {
profile.CreateMap<GroupEntity, GroupVm>() profile.CreateMap<GroupEntity, GroupVm>()
.ForMember(d => d.ParentGroupId, opts => opts.MapFrom(s => s.ParentId)) .ForMember(d => d.ParentGroupId, opts => opts.MapFrom(s => s.ParentId))
.ForMember(d => d.ParentGroupName, opts => opts.MapFrom(s => s.ParentName))
.ForMember(d => d.Id, opts => opts.MapFrom(s => s.Id)) .ForMember(d => d.Id, opts => opts.MapFrom(s => s.Id))
.ForMember(d => d.Title, opts => opts.MapFrom(s => s.Name)) .ForMember(d => d.Title, opts => opts.MapFrom(s => s.Name))
.ForMember(d => d.Icon, opts => opts.MapFrom(s => s.Icon)) .ForMember(d => d.Icon, opts => opts.MapFrom(s => s.Icon))
.ForMember(d => d.Entries, opts => opts.MapFrom(s => s.Entries)) .ForMember(d => d.Entries, opts => opts.MapFrom(s => s.Entries))
.ForMember(d => d.SubGroups, opts => opts.MapFrom(s => s.SubGroups)) .ForMember(d => d.SubGroups, opts => opts.MapFrom(s => s.SubGroups))
.MaxDepth(1); .MaxDepth(2);
} }
} }
} }

View File

@@ -7,6 +7,7 @@ namespace ModernKeePass.Domain.Entities
public string Id { get; set; } public string Id { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string ParentId { get; set; } public string ParentId { get; set; }
public string ParentName { get; set; }
public DateTimeOffset LastModificationDate { get; set; } public DateTimeOffset LastModificationDate { get; set; }
} }
} }

View File

@@ -20,6 +20,7 @@ namespace ModernKeePass.Infrastructure.KeePass
Uri url; Uri url;
CreateMap<PwEntry, EntryEntity>() CreateMap<PwEntry, EntryEntity>()
.ForMember(dest => dest.ParentId, opt => opt.MapFrom(src => src.ParentGroup.Uuid.ToHexString())) .ForMember(dest => dest.ParentId, opt => opt.MapFrom(src => src.ParentGroup.Uuid.ToHexString()))
.ForMember(dest => dest.ParentName, opt => opt.MapFrom(src => src.ParentGroup.Name))
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Uuid.ToHexString())) .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Uuid.ToHexString()))
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => GetEntryValue(src, PwDefs.TitleField))) .ForMember(dest => dest.Name, opt => opt.MapFrom(src => GetEntryValue(src, PwDefs.TitleField)))
.ForMember(dest => dest.UserName, opt => opt.MapFrom(src => GetEntryValue(src, PwDefs.UserNameField))) .ForMember(dest => dest.UserName, opt => opt.MapFrom(src => GetEntryValue(src, PwDefs.UserNameField)))
@@ -39,9 +40,7 @@ namespace ModernKeePass.Infrastructure.KeePass
.ForMember(dest => dest.AdditionalFields, opt => opt.MapFrom(src => .ForMember(dest => dest.AdditionalFields, opt => opt.MapFrom(src =>
src.Strings.Where(s => !PwDefs.GetStandardFields().Contains(s.Key)) src.Strings.Where(s => !PwDefs.GetStandardFields().Contains(s.Key))
.ToDictionary(s => s.Key, s => GetEntryValue(src, s.Key)))) .ToDictionary(s => s.Key, s => GetEntryValue(src, s.Key))))
.ForMember(dest => dest.LastModificationDate, .ForMember(dest => dest.LastModificationDate, opt => opt.MapFrom(src => new DateTimeOffset(src.LastModificationTime)));
opt => opt.MapFrom(src => new DateTimeOffset(src.LastModificationTime)))
.MaxDepth(1);
} }
private void FromModelToDto() private void FromModelToDto()

View File

@@ -16,13 +16,14 @@ namespace ModernKeePass.Infrastructure.KeePass
{ {
CreateMap<PwGroup, GroupEntity>() CreateMap<PwGroup, GroupEntity>()
.ForMember(d => d.ParentId, opts => opts.MapFrom(s => s.ParentGroup.Uuid.ToHexString())) .ForMember(d => d.ParentId, opts => opts.MapFrom(s => s.ParentGroup.Uuid.ToHexString()))
.ForMember(d => d.ParentName, opts => opts.MapFrom(s => s.ParentGroup.Name))
.ForMember(d => d.Id, opts => opts.MapFrom(s => s.Uuid.ToHexString())) .ForMember(d => d.Id, opts => opts.MapFrom(s => s.Uuid.ToHexString()))
.ForMember(d => d.Name, opts => opts.MapFrom(s => s.Name)) .ForMember(d => d.Name, opts => opts.MapFrom(s => s.Name))
.ForMember(d => d.Icon, opts => opts.MapFrom(s => IconMapper.MapPwIconToIcon(s.IconId))) .ForMember(d => d.Icon, opts => opts.MapFrom(s => IconMapper.MapPwIconToIcon(s.IconId)))
.ForMember(d => d.LastModificationDate, opts => opts.MapFrom(s => s.LastModificationTime)) .ForMember(d => d.LastModificationDate, opts => opts.MapFrom(s => s.LastModificationTime))
.ForMember(d => d.Entries, opts => opts.MapFrom(s => s.Entries)) .ForMember(d => d.Entries, opts => opts.MapFrom(s => s.Entries))
.ForMember(d => d.SubGroups, opts => opts.MapFrom(s => s.Groups)) .ForMember(d => d.SubGroups, opts => opts.MapFrom(s => s.Groups))
.MaxDepth(1); .MaxDepth(2);
} }
private void FromModelToDto() private void FromModelToDto()

View File

@@ -194,36 +194,64 @@ namespace ModernKeePass.Infrastructure.KeePass
parentPwGroup.Groups.Add(pwGroup); parentPwGroup.Groups.Add(pwGroup);
}); });
} }
public async Task RemoveEntry(string parentGroupId, string entryId, bool isToBeDeleted) public async Task RemoveEntry(string parentGroupId, string entryId)
{ {
await Task.Run(() => await Task.Run(() =>
{ {
var parentPwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(parentGroupId), true); var parentPwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(parentGroupId), true);
var pwEntry = parentPwGroup.FindEntry(BuildIdFromString(entryId), false); var pwEntry = parentPwGroup.FindEntry(BuildIdFromString(entryId), false);
parentPwGroup.Entries.Remove(pwEntry); parentPwGroup.Entries.Remove(pwEntry);
if (isToBeDeleted && (!_pwDatabase.RecycleBinEnabled || parentPwGroup.Uuid.Equals(_pwDatabase.RecycleBinUuid)))
{
_pwDatabase.DeletedObjects.Add(new PwDeletedObject(pwEntry.Uuid, _dateTime.Now));
}
}); });
} }
public async Task RemoveGroup(string parentGroupId, string groupId, bool isToBeDeleted) public async Task RemoveGroup(string parentGroupId, string groupId)
{ {
await Task.Run(() => await Task.Run(() =>
{ {
var parentPwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(parentGroupId), true); var parentPwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(parentGroupId), true);
var pwGroup = parentPwGroup.FindGroup(BuildIdFromString(groupId), false); var pwGroup = parentPwGroup.FindGroup(BuildIdFromString(groupId), false);
parentPwGroup.Groups.Remove(pwGroup); parentPwGroup.Groups.Remove(pwGroup);
if (isToBeDeleted && (!_pwDatabase.RecycleBinEnabled || parentPwGroup.Uuid.Equals(_pwDatabase.RecycleBinUuid)))
{
_pwDatabase.DeletedObjects.Add(new PwDeletedObject(pwGroup.Uuid, _dateTime.Now));
}
}); });
} }
public async Task DeleteEntry(string parentGroupId, string entryId, string recycleBinName)
{
if (IsRecycleBinEnabled && (string.IsNullOrEmpty(RecycleBinId) || _pwDatabase.RecycleBinUuid.Equals(PwUuid.Zero)))
{
CreateGroup(RootGroupId, recycleBinName, true);
}
if (!IsRecycleBinEnabled || parentGroupId.Equals(RecycleBinId))
{
_pwDatabase.DeletedObjects.Add(new PwDeletedObject(BuildIdFromString(entryId), _dateTime.Now));
}
else
{
await AddEntry(RecycleBinId, entryId);
}
await RemoveEntry(parentGroupId, entryId);
}
public async Task DeleteGroup(string parentGroupId, string groupId, string recycleBinName)
{
if (IsRecycleBinEnabled && (string.IsNullOrEmpty(RecycleBinId) || _pwDatabase.RecycleBinUuid.Equals(PwUuid.Zero)))
{
CreateGroup(RootGroupId, recycleBinName, true);
}
if (!IsRecycleBinEnabled || parentGroupId.Equals(RecycleBinId))
{
_pwDatabase.DeletedObjects.Add(new PwDeletedObject(BuildIdFromString(groupId), _dateTime.Now));
}
else
{
await AddEntry(RecycleBinId, groupId);
}
await RemoveGroup(parentGroupId, groupId);
}
public void UpdateEntry(string entryId, string fieldName, object fieldValue) public void UpdateEntry(string entryId, string fieldName, object fieldValue)
{ {
var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true); var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);

View File

@@ -167,9 +167,9 @@ namespace ModernKeePass
try try
{ {
var database = await Mediator.Send(new ReOpenDatabaseQuery()); await Mediator.Send(new ReOpenDatabaseQuery());
#if DEBUG #if DEBUG
ToastNotificationHelper.ShowGenericToast(database.Title, "Database reopened (changes were saved)"); ToastNotificationHelper.ShowGenericToast("App resumed", "Database reopened (changes were saved)");
#endif #endif
} }
catch (Exception) catch (Exception)

View File

@@ -1,15 +1,14 @@
using System; using System;
using ModernKeePass.Application.Group.Models;
namespace ModernKeePass.Events namespace ModernKeePass.Events
{ {
public class PasswordEventArgs: EventArgs public class PasswordEventArgs: EventArgs
{ {
public GroupVm RootGroup { get; set; } public string RootGroupId { get; set; }
public PasswordEventArgs(GroupVm groupVm) public PasswordEventArgs(string groupId)
{ {
RootGroup = groupVm; RootGroupId = groupId;
} }
} }
} }

View File

@@ -5,6 +5,7 @@ using Windows.Storage;
using Windows.Storage.AccessCache; using Windows.Storage.AccessCache;
using MediatR; using MediatR;
using ModernKeePass.Application.Database.Commands.UpdateCredentials; using ModernKeePass.Application.Database.Commands.UpdateCredentials;
using ModernKeePass.Application.Database.Queries.GetDatabase;
using ModernKeePass.Application.Database.Queries.OpenDatabase; using ModernKeePass.Application.Database.Queries.OpenDatabase;
using ModernKeePass.Application.Security.Commands.GenerateKeyFile; using ModernKeePass.Application.Security.Commands.GenerateKeyFile;
using ModernKeePass.Application.Security.Queries.EstimatePasswordComplexity; using ModernKeePass.Application.Security.Queries.EstimatePasswordComplexity;
@@ -97,7 +98,7 @@ namespace ModernKeePass.ViewModels
set { SetProperty(ref _keyFileText, value); } set { SetProperty(ref _keyFileText, value); }
} }
public Application.Group.Models.GroupVm RootGroup { get; set; } public string RootGroupId { get; set; }
public double PasswordComplexityIndicator => _mediator.Send(new EstimatePasswordComplexityQuery { Password = Password }).GetAwaiter().GetResult(); public double PasswordComplexityIndicator => _mediator.Send(new EstimatePasswordComplexityQuery { Password = Password }).GetAwaiter().GetResult();
@@ -129,11 +130,12 @@ namespace ModernKeePass.ViewModels
_isOpening = true; _isOpening = true;
OnPropertyChanged(nameof(IsValid)); OnPropertyChanged(nameof(IsValid));
RootGroup = await _mediator.Send(new OpenDatabaseQuery { await _mediator.Send(new OpenDatabaseQuery {
FilePath = StorageApplicationPermissions.FutureAccessList.Add(databaseFile), FilePath = StorageApplicationPermissions.FutureAccessList.Add(databaseFile),
KeyFilePath = HasKeyFile && KeyFile != null ? StorageApplicationPermissions.FutureAccessList.Add(KeyFile) : null, KeyFilePath = HasKeyFile && KeyFile != null ? StorageApplicationPermissions.FutureAccessList.Add(KeyFile) : null,
Password = Password = HasPassword ? Password : null, Password = Password = HasPassword ? Password : null,
}); });
RootGroupId = (await _mediator.Send(new GetDatabaseQuery())).RootGroupId;
return true; return true;
} }
catch (ArgumentException) catch (ArgumentException)

View File

@@ -9,15 +9,19 @@ using ModernKeePass.Application.Database.Commands.SaveDatabase;
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.Entry.Commands.SetFieldValue; using ModernKeePass.Application.Entry.Commands.SetFieldValue;
using ModernKeePass.Application.Entry.Models;
using ModernKeePass.Application.Entry.Queries.GetEntry;
using ModernKeePass.Application.Group.Commands.AddEntry; using ModernKeePass.Application.Group.Commands.AddEntry;
using ModernKeePass.Application.Group.Commands.CreateGroup; using ModernKeePass.Application.Group.Commands.DeleteEntry;
using ModernKeePass.Application.Group.Commands.RemoveEntry; using ModernKeePass.Application.Group.Commands.RemoveEntry;
using ModernKeePass.Application.Group.Queries.GetGroup;
using ModernKeePass.Application.Security.Commands.GeneratePassword; using ModernKeePass.Application.Security.Commands.GeneratePassword;
using ModernKeePass.Application.Security.Queries.EstimatePasswordComplexity; using ModernKeePass.Application.Security.Queries.EstimatePasswordComplexity;
using ModernKeePass.Common; using ModernKeePass.Common;
using ModernKeePass.Domain.Enums; using ModernKeePass.Domain.Enums;
using ModernKeePass.Domain.Interfaces; using ModernKeePass.Domain.Interfaces;
using ModernKeePass.Interfaces; using ModernKeePass.Interfaces;
using ModernKeePass.Application.Group.Models;
namespace ModernKeePass.ViewModels namespace ModernKeePass.ViewModels
{ {
@@ -37,7 +41,7 @@ namespace ModernKeePass.ViewModels
public string CustomChars { get; set; } = string.Empty; public string CustomChars { get; set; } = string.Empty;
public string Id => _entry.Id; public string Id => _entry.Id;
public IEnumerable<Application.Group.Models.GroupVm> BreadCrumb => _entry.Breadcrumb; public IEnumerable<GroupVm> BreadCrumb => new List<GroupVm> { _parent };
/// <summary> /// <summary>
/// Determines if the Entry is current or from history /// Determines if the Entry is current or from history
@@ -174,7 +178,7 @@ namespace ModernKeePass.ViewModels
} }
} }
} }
public IEnumerable<Application.Entry.Models.EntryVm> History => _entry.History; public IEnumerable<EntryVm> History => _entry.History;
public bool IsEditMode public bool IsEditMode
{ {
@@ -206,13 +210,14 @@ namespace ModernKeePass.ViewModels
} }
} }
public bool CanRestore => _entry.ParentGroup == _database.RecycleBin; public bool CanRestore => _entry.ParentGroupId == _database.RecycleBinId;
public ICommand SaveCommand { get; } public ICommand SaveCommand { get; }
public ICommand GeneratePasswordCommand { get; } public ICommand GeneratePasswordCommand { get; }
public ICommand UndoDeleteCommand { get; } public ICommand UndoDeleteCommand { get; }
private readonly Application.Entry.Models.EntryVm _entry; 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 bool _isEditMode; private bool _isEditMode;
@@ -222,19 +227,20 @@ namespace ModernKeePass.ViewModels
public EntryDetailVm() { } public EntryDetailVm() { }
internal EntryDetailVm(Application.Entry.Models.EntryVm entry, bool isNewEntry = false) : this(entry, App.Mediator, isNewEntry) { } internal EntryDetailVm(string entryId, bool isNewEntry = false) : this(entryId, App.Mediator, isNewEntry) { }
public EntryDetailVm(Application.Entry.Models.EntryVm entry, IMediator mediator, bool isNewEntry = false) public EntryDetailVm(string entryId, IMediator mediator, bool isNewEntry = false)
{ {
_entry = entry;
_mediator = mediator; _mediator = mediator;
_database = _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult(); _database = _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
_entry = _mediator.Send(new GetEntryQuery {Id = entryId}).GetAwaiter().GetResult();
_parent = _mediator.Send(new GetGroupQuery {Id = _entry.ParentGroupId}).GetAwaiter().GetResult();
_isEditMode = isNewEntry; _isEditMode = isNewEntry;
if (isNewEntry) GeneratePassword().GetAwaiter().GetResult(); if (isNewEntry) GeneratePassword().GetAwaiter().GetResult();
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());
UndoDeleteCommand = new RelayCommand(async () => await Move(entry.ParentGroup), () => _entry.ParentGroup != null); UndoDeleteCommand = new RelayCommand(async () => await Move(_parent), () => _parent != null);
} }
public async Task GeneratePassword() public async Task GeneratePassword()
@@ -257,18 +263,16 @@ namespace ModernKeePass.ViewModels
public async Task MarkForDelete(string recycleBinTitle) public async Task MarkForDelete(string recycleBinTitle)
{ {
if (_database.IsRecycleBinEnabled && _database.RecycleBin == null) await _mediator.Send(new DeleteEntryCommand {EntryId = _entry.Id, ParentGroupId = _entry.ParentGroupId, RecycleBinName = recycleBinTitle});
_database.RecycleBin = await _mediator.Send(new CreateGroupCommand { ParentGroup = _database.RootGroup, IsRecycleBin = true, Name = recycleBinTitle});
await Move(_database.IsRecycleBinEnabled && _entry.ParentGroup != _database.RecycleBin ? _database.RecycleBin : null);
} }
public async Task Move(Application.Group.Models.GroupVm destination) public async Task Move(GroupVm destination)
{ {
await _mediator.Send(new AddEntryCommand { ParentGroup = destination, Entry = _entry }); await _mediator.Send(new AddEntryCommand { ParentGroup = destination, Entry = _entry });
await _mediator.Send(new RemoveEntryCommand { ParentGroup = _entry.ParentGroup, Entry = _entry, IsDelete = true }); await _mediator.Send(new RemoveEntryCommand { ParentGroup = _parent, Entry = _entry });
} }
public Application.Entry.Models.EntryVm GetEntry() public EntryVm GetEntry()
{ {
return _entry; return _entry;
} }

View File

@@ -9,15 +9,19 @@ using MediatR;
using ModernKeePass.Application.Database.Commands.SaveDatabase; using ModernKeePass.Application.Database.Commands.SaveDatabase;
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.Entry.Models;
using ModernKeePass.Application.Group.Commands.AddEntry; using ModernKeePass.Application.Group.Commands.AddEntry;
using ModernKeePass.Application.Group.Commands.AddGroup; using ModernKeePass.Application.Group.Commands.AddGroup;
using ModernKeePass.Application.Group.Commands.CreateEntry; using ModernKeePass.Application.Group.Commands.CreateEntry;
using ModernKeePass.Application.Group.Commands.CreateGroup; using ModernKeePass.Application.Group.Commands.CreateGroup;
using ModernKeePass.Application.Group.Commands.DeleteGroup;
using ModernKeePass.Application.Group.Commands.InsertEntry; using ModernKeePass.Application.Group.Commands.InsertEntry;
using ModernKeePass.Application.Group.Commands.RemoveEntry; using ModernKeePass.Application.Group.Commands.RemoveEntry;
using ModernKeePass.Application.Group.Commands.RemoveGroup; using ModernKeePass.Application.Group.Commands.RemoveGroup;
using ModernKeePass.Application.Group.Commands.SortEntries; using ModernKeePass.Application.Group.Commands.SortEntries;
using ModernKeePass.Application.Group.Commands.SortGroups; using ModernKeePass.Application.Group.Commands.SortGroups;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Application.Group.Queries.GetGroup;
using ModernKeePass.Common; using ModernKeePass.Common;
using ModernKeePass.Domain.Enums; using ModernKeePass.Domain.Enums;
using ModernKeePass.Domain.Interfaces; using ModernKeePass.Domain.Interfaces;
@@ -27,15 +31,15 @@ namespace ModernKeePass.ViewModels
{ {
public class GroupDetailVm : NotifyPropertyChangedBase, IVmEntity, ISelectableModel public class GroupDetailVm : NotifyPropertyChangedBase, IVmEntity, ISelectableModel
{ {
public ObservableCollection<Application.Entry.Models.EntryVm> Entries => new ObservableCollection<Application.Entry.Models.EntryVm>(_group.Entries); public ObservableCollection<EntryVm> Entries => new ObservableCollection<EntryVm>(_group.Entries);
public ObservableCollection<Application.Group.Models.GroupVm> Groups => new ObservableCollection<Application.Group.Models.GroupVm>(_group.SubGroups); public ObservableCollection<GroupVm> Groups => new ObservableCollection<GroupVm>(_group.SubGroups);
public IEnumerable<Application.Entry.Models.EntryVm> SubEntries public IEnumerable<EntryVm> SubEntries
{ {
get get
{ {
var subEntries = new List<Application.Entry.Models.EntryVm>(); var subEntries = new List<EntryVm>();
subEntries.AddRange(Entries); subEntries.AddRange(Entries);
foreach (var group in Groups) foreach (var group in Groups)
{ {
@@ -46,9 +50,9 @@ namespace ModernKeePass.ViewModels
} }
} }
public bool IsNotRoot => _database.RootGroup != _group; public bool IsNotRoot => _database.RootGroupId != _group.Id;
public bool ShowRestore => IsNotRoot && _database.RecycleBin != _group; public bool ShowRestore => IsNotRoot && _database.RecycleBinId != _group.Id;
/// <summary> /// <summary>
/// Is the Group the database Recycle Bin? /// Is the Group the database Recycle Bin?
@@ -57,15 +61,15 @@ namespace ModernKeePass.ViewModels
{ {
get get
{ {
return _database.IsRecycleBinEnabled && _database.RecycleBin == _group; return _database.IsRecycleBinEnabled && _database.RecycleBinId == _group.Id;
} }
set set
{ {
if (value && _group != null) _database.RecycleBin = _group; if (value && _group != null) _database.RecycleBinId = _group.Id;
} }
} }
public IOrderedEnumerable<IGrouping<char, Application.Entry.Models.EntryVm>> EntriesZoomedOut => from e in Entries public IOrderedEnumerable<IGrouping<char, EntryVm>> EntriesZoomedOut => from e in Entries
group e by e.Title.ToUpper().FirstOrDefault() into grp group e by e.Title.ToUpper().FirstOrDefault() into grp
orderby grp.Key orderby grp.Key
select grp; select grp;
@@ -101,30 +105,36 @@ namespace ModernKeePass.ViewModels
set { SetProperty(ref _isMenuClosed, value); } set { SetProperty(ref _isMenuClosed, value); }
} }
public IEnumerable<Application.Group.Models.GroupVm> BreadCrumb => _group.Breadcrumb; public IEnumerable<GroupVm> BreadCrumb { get; }
public ICommand SaveCommand { get; } public ICommand SaveCommand { get; }
public ICommand SortEntriesCommand { get; } public ICommand SortEntriesCommand { get; }
public ICommand SortGroupsCommand { get; } public ICommand SortGroupsCommand { get; }
public ICommand UndoDeleteCommand { get; } public ICommand UndoDeleteCommand { get; }
private readonly Application.Group.Models.GroupVm _group;
private readonly IMediator _mediator; private readonly IMediator _mediator;
private readonly DatabaseVm _database; private readonly DatabaseVm _database;
private readonly GroupVm _group;
private readonly GroupVm _parent;
private bool _isEditMode; private bool _isEditMode;
private Application.Entry.Models.EntryVm _reorderedEntry; private EntryVm _reorderedEntry;
private bool _isMenuClosed = true; private bool _isMenuClosed = true;
public GroupDetailVm() {} public GroupDetailVm() {}
internal GroupDetailVm(Application.Group.Models.GroupVm group) : this(group, App.Mediator) internal GroupDetailVm(string groupId) : this(groupId, App.Mediator)
{ } { }
public GroupDetailVm(Application.Group.Models.GroupVm group, IMediator mediator, bool isEditMode = false) public GroupDetailVm(string groupId, IMediator mediator, bool isEditMode = false)
{ {
_group = group;
_mediator = mediator; _mediator = mediator;
_database = _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult(); _database = _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
_group = _mediator.Send(new GetGroupQuery { Id = groupId }).GetAwaiter().GetResult();
if (!string.IsNullOrEmpty(_group.ParentGroupId))
{
_parent = _mediator.Send(new GetGroupQuery { Id = _group.ParentGroupId }).GetAwaiter().GetResult();
BreadCrumb = new List<GroupVm> {_parent};
}
_isEditMode = isEditMode; _isEditMode = isEditMode;
SaveCommand = new RelayCommand(async () => await _mediator.Send(new SaveDatabaseCommand())); SaveCommand = new RelayCommand(async () => await _mediator.Send(new SaveDatabaseCommand()));
@@ -132,7 +142,7 @@ namespace ModernKeePass.ViewModels
await SortEntriesAsync().ConfigureAwait(false), () => IsEditMode); await SortEntriesAsync().ConfigureAwait(false), () => IsEditMode);
SortGroupsCommand = new RelayCommand(async () => SortGroupsCommand = new RelayCommand(async () =>
await SortGroupsAsync().ConfigureAwait(false), () => IsEditMode); await SortGroupsAsync().ConfigureAwait(false), () => IsEditMode);
UndoDeleteCommand = new RelayCommand(async () => await Move(group.ParentGroup), () => _group.ParentGroup != null); UndoDeleteCommand = new RelayCommand(async () => await Move(_parent), () => _parent != null);
Entries.CollectionChanged += Entries_CollectionChanged; Entries.CollectionChanged += Entries_CollectionChanged;
} }
@@ -160,28 +170,27 @@ namespace ModernKeePass.ViewModels
} }
} }
public async Task<Application.Group.Models.GroupVm> AddNewGroup(string name = "") public async Task<string> AddNewGroup(string name = "")
{ {
return await _mediator.Send(new CreateGroupCommand {Name = name, ParentGroup = _group}); return (await _mediator.Send(new CreateGroupCommand {Name = name, ParentGroup = _group})).Id;
} }
public async Task<Application.Entry.Models.EntryVm> AddNewEntry() public async Task<string> AddNewEntry()
{ {
return await _mediator.Send(new CreateEntryCommand { ParentGroup = _group }); return (await _mediator.Send(new CreateEntryCommand { ParentGroup = _group })).Id;
} }
public async Task MarkForDelete(string recycleBinTitle) public async Task MarkForDelete(string recycleBinTitle)
{ {
if (_database.IsRecycleBinEnabled && _database.RecycleBin == null) await _mediator.Send(new DeleteGroupCommand { GroupId = _group.Id, ParentGroupId = _group.ParentGroupId, RecycleBinName = recycleBinTitle });
_database.RecycleBin = await _mediator.Send(new CreateGroupCommand {ParentGroup = _database.RootGroup, IsRecycleBin = true, Name = recycleBinTitle});
await Move(_database.IsRecycleBinEnabled && !IsSelected ? _database.RecycleBin : null);
((RelayCommand)UndoDeleteCommand).RaiseCanExecuteChanged(); ((RelayCommand)UndoDeleteCommand).RaiseCanExecuteChanged();
} }
public async Task Move(Application.Group.Models.GroupVm destination) public async Task Move(GroupVm destination)
{ {
await _mediator.Send(new AddGroupCommand {ParentGroup = destination, Group = _group}); await _mediator.Send(new AddGroupCommand {ParentGroup = destination, Group = _group });
await _mediator.Send(new RemoveGroupCommand {ParentGroup = _group.ParentGroup, Group = _group, IsDelete = true }); await _mediator.Send(new RemoveGroupCommand {ParentGroup = _parent, Group = _group });
} }
private async Task SortEntriesAsync() private async Task SortEntriesAsync()

View File

@@ -4,6 +4,8 @@ using System.Linq;
using MediatR; using MediatR;
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.Parameters.Commands.SetCipher; using ModernKeePass.Application.Parameters.Commands.SetCipher;
using ModernKeePass.Application.Parameters.Commands.SetCompression; using ModernKeePass.Application.Parameters.Commands.SetCompression;
using ModernKeePass.Application.Parameters.Commands.SetHasRecycleBin; using ModernKeePass.Application.Parameters.Commands.SetHasRecycleBin;
@@ -37,14 +39,14 @@ namespace ModernKeePass.ViewModels
public bool IsNewRecycleBin public bool IsNewRecycleBin
{ {
get { return _database.RecycleBin == null; } get { return string.IsNullOrEmpty(_database.RecycleBinId); }
set set
{ {
if (value) _mediator.Send(new SetRecycleBinCommand { RecycleBin = null }).Wait(); if (value) _mediator.Send(new SetRecycleBinCommand { RecycleBin = null }).Wait();
} }
} }
public ObservableCollection<Application.Group.Models.GroupVm> Groups { get; set; } public ObservableCollection<GroupVm> 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();
@@ -119,7 +121,8 @@ namespace ModernKeePass.ViewModels
{ {
_mediator = mediator; _mediator = mediator;
_database = _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult(); _database = _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
Groups = new ObservableCollection<Application.Group.Models.GroupVm>(_database.RootGroup.SubGroups); var rootGroup = _mediator.Send(new GetGroupQuery { Id = _database.RootGroupId }).GetAwaiter().GetResult();
Groups = new ObservableCollection<GroupVm>(rootGroup.SubGroups);
} }
} }
} }

View File

@@ -127,7 +127,7 @@ namespace ModernKeePass.ViewModels
Title = database.Name, Title = database.Name,
PageType = typeof(GroupDetailPage), PageType = typeof(GroupDetailPage),
Destination = referenceFrame, Destination = referenceFrame,
Parameter = database.RootGroup, Parameter = database.RootGroupId,
Group = "Databases", Group = "Databases",
SymbolIcon = Symbol.ProtectedDocument SymbolIcon = Symbol.ProtectedDocument
}); });

View File

@@ -5,6 +5,8 @@ using ModernKeePass.Application.Database.Queries.GetDatabase;
using ModernKeePass.Application.Entry.Commands.SetFieldValue; using ModernKeePass.Application.Entry.Commands.SetFieldValue;
using ModernKeePass.Application.Group.Commands.CreateEntry; using ModernKeePass.Application.Group.Commands.CreateEntry;
using ModernKeePass.Application.Group.Commands.CreateGroup; using ModernKeePass.Application.Group.Commands.CreateGroup;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Application.Group.Queries.GetGroup;
using ModernKeePass.Domain.Enums; using ModernKeePass.Domain.Enums;
using ModernKeePass.Interfaces; using ModernKeePass.Interfaces;
using ModernKeePass.Services; using ModernKeePass.Services;
@@ -44,14 +46,15 @@ namespace ModernKeePass.ViewModels
_settings = settings; _settings = settings;
} }
public async Task<Application.Group.Models.GroupVm> PopulateInitialData() public async Task<GroupVm> PopulateInitialData()
{ {
var database = await _mediator.Send(new GetDatabaseQuery()); var database = await _mediator.Send(new GetDatabaseQuery());
if (_settings.GetSetting<bool>("Sample") && !IsImportChecked) await CreateSampleData(database.RootGroup); var rootGroup = await _mediator.Send(new GetGroupQuery {Id = database.RootGroupId});
return database.RootGroup; if (_settings.GetSetting<bool>("Sample") && !IsImportChecked) await CreateSampleData(rootGroup);
return rootGroup;
} }
private async Task CreateSampleData(Application.Group.Models.GroupVm group) private async Task CreateSampleData(GroupVm group)
{ {
/*var converter = new IntToSymbolConverter(); /*var converter = new IntToSymbolConverter();

View File

@@ -42,9 +42,7 @@ namespace ModernKeePass.Views
protected override void OnNavigatedTo(NavigationEventArgs e) protected override void OnNavigatedTo(NavigationEventArgs e)
{ {
NavigationHelper.OnNavigatedTo(e); NavigationHelper.OnNavigatedTo(e);
/*if (!(e.Parameter is EntryVm)) return; var args = e.Parameter as string;
DataContext = (EntryVm)e.Parameter;*/
var args = e.Parameter as Application.Entry.Models.EntryVm;
if (args != null) DataContext = new EntryDetailVm(args); if (args != null) DataContext = new EntryDetailVm(args);
} }

View File

@@ -50,12 +50,12 @@ namespace ModernKeePass.Views
var args = e.Parameter as PasswordEventArgs; var args = e.Parameter as PasswordEventArgs;
if (args != null) if (args != null)
DataContext = new GroupDetailVm(args.RootGroup); DataContext = new GroupDetailVm(args.RootGroupId);
else else
{ {
var vm = e.Parameter as Application.Group.Models.GroupVm; var id = e.Parameter as string;
if (vm != null) if (id != null)
DataContext = new GroupDetailVm(vm); DataContext = new GroupDetailVm(id);
} }
} }
@@ -77,7 +77,7 @@ namespace ModernKeePass.Views
return; return;
default: default:
var group = listView?.SelectedItem as Application.Group.Models.GroupVm; var group = listView?.SelectedItem as Application.Group.Models.GroupVm;
Frame.Navigate(typeof(GroupDetailPage), group); Frame.Navigate(typeof(GroupDetailPage), group?.Id);
break; break;
} }
} }
@@ -90,7 +90,7 @@ namespace ModernKeePass.Views
return; return;
default: default:
var entry = GridView.SelectedItem as EntryVm; var entry = GridView.SelectedItem as EntryVm;
Frame.Navigate(typeof(EntryDetailPage), entry); Frame.Navigate(typeof(EntryDetailPage), entry?.Id);
break; break;
} }
} }
@@ -124,7 +124,7 @@ namespace ModernKeePass.Views
var results = Model.SubEntries.Where(e => e.Title.IndexOf(args.QueryText, StringComparison.OrdinalIgnoreCase) >= 0).Take(5); var results = Model.SubEntries.Where(e => e.Title.IndexOf(args.QueryText, StringComparison.OrdinalIgnoreCase) >= 0).Take(5);
foreach (var result in results) foreach (var result in results)
{ {
args.Request.SearchSuggestionCollection.AppendResultSuggestion(result.Title, result.ParentGroup.Title, result.Id, imageUri, string.Empty); args.Request.SearchSuggestionCollection.AppendResultSuggestion(result.Title, result.ParentGroupName, result.Id, imageUri, string.Empty);
} }
} }

View File

@@ -19,7 +19,7 @@
<HyperlinkButton Foreground="{StaticResource MainColor}" Content="{Binding Title}" Style="{StaticResource MainColorHyperlinkButton}" FontWeight="Light" FontSize="12" Padding="0"> <HyperlinkButton Foreground="{StaticResource MainColor}" Content="{Binding Title}" Style="{StaticResource MainColorHyperlinkButton}" FontWeight="Light" FontSize="12" Padding="0">
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click"> <core:EventTriggerBehavior EventName="Click">
<core:NavigateToPageAction Parameter="{Binding}" TargetPage="ModernKeePass.Views.GroupDetailPage" /> <core:NavigateToPageAction Parameter="{Binding Id}" TargetPage="ModernKeePass.Views.GroupDetailPage" />
</core:EventTriggerBehavior> </core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
</HyperlinkButton> </HyperlinkButton>
@@ -32,7 +32,7 @@
<HyperlinkButton Foreground="{StaticResource MainColor}" Content="{Binding Title}" Style="{StaticResource MainColorHyperlinkButton}" FontWeight="Light" FontSize="12" Padding="0"> <HyperlinkButton Foreground="{StaticResource MainColor}" Content="{Binding Title}" Style="{StaticResource MainColorHyperlinkButton}" FontWeight="Light" FontSize="12" Padding="0">
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click"> <core:EventTriggerBehavior EventName="Click">
<core:NavigateToPageAction Parameter="{Binding}" TargetPage="ModernKeePass.Views.GroupDetailPage" /> <core:NavigateToPageAction Parameter="{Binding Id}" TargetPage="ModernKeePass.Views.GroupDetailPage" />
</core:EventTriggerBehavior> </core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
</HyperlinkButton> </HyperlinkButton>

View File

@@ -95,7 +95,7 @@ namespace ModernKeePass.Views.UserControls
if (UpdateKey) if (UpdateKey)
{ {
await Model.UpdateKey(); await Model.UpdateKey();
ValidationChecked?.Invoke(this, new PasswordEventArgs(Model.RootGroup)); ValidationChecked?.Invoke(this, new PasswordEventArgs(Model.RootGroupId));
} }
else else
{ {
@@ -175,7 +175,7 @@ namespace ModernKeePass.Views.UserControls
ButtonLabel = resource.GetResourceValue("CompositeKeyOpening"); ButtonLabel = resource.GetResourceValue("CompositeKeyOpening");
if (await Dispatcher.RunTaskAsync(async () => await Model.OpenDatabase(DatabaseFile, CreateNew))) if (await Dispatcher.RunTaskAsync(async () => await Model.OpenDatabase(DatabaseFile, CreateNew)))
{ {
ValidationChecked?.Invoke(this, new PasswordEventArgs(Model.RootGroup)); ValidationChecked?.Invoke(this, new PasswordEventArgs(Model.RootGroupId));
} }
ButtonLabel = oldLabel; ButtonLabel = oldLabel;