diff --git a/ModernKeePass.Application/Application.csproj b/ModernKeePass.Application/Application.csproj
index 5cee244..5e83155 100644
--- a/ModernKeePass.Application/Application.csproj
+++ b/ModernKeePass.Application/Application.csproj
@@ -75,6 +75,7 @@
+
diff --git a/ModernKeePass.Application/Common/Behaviors/SetDirtyBehavior.cs b/ModernKeePass.Application/Common/Behaviors/SetDirtyBehavior.cs
new file mode 100644
index 0000000..d2034ed
--- /dev/null
+++ b/ModernKeePass.Application/Common/Behaviors/SetDirtyBehavior.cs
@@ -0,0 +1,35 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using MediatR;
+using ModernKeePass.Application.Common.Interfaces;
+using ModernKeePass.Application.Database.Commands.CloseDatabase;
+using ModernKeePass.Application.Database.Commands.SaveDatabase;
+
+namespace ModernKeePass.Application.Common.Behaviors
+{
+ public class SetDirtyBehavior : IPipelineBehavior
+ {
+ private readonly List _excludedCommands = new List
+ {nameof(SaveDatabaseCommand), nameof(CloseDatabaseCommand)};
+
+ private readonly IDatabaseProxy _database;
+
+ public SetDirtyBehavior(IDatabaseProxy database)
+ {
+ _database = database;
+ }
+
+ public async Task Handle(TRequest request, RequestHandlerDelegate next)
+ {
+ var response = await next();
+ var queryName = typeof(TRequest).Name;
+ if (queryName.Contains("Command") && !_excludedCommands.Contains(queryName))
+ {
+ _database.IsDirty = true;
+ }
+
+ return response;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs
index 1657f15..c7c9458 100644
--- a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs
+++ b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs
@@ -7,7 +7,6 @@ namespace ModernKeePass.Application.Common.Interfaces
{
public interface IDatabaseProxy
{
- string ZeroId { get; }
bool IsOpen { get; }
string Name { get; }
string RootGroupId { get; }
@@ -17,6 +16,8 @@ namespace ModernKeePass.Application.Common.Interfaces
string Compression { get; set; }
bool IsRecycleBinEnabled { get; set; }
string FileAccessToken { get; set; }
+ int Size { get; set; }
+ bool IsDirty { get; set; }
Task Open(byte[] file, Credentials credentials);
Task ReOpen(byte[] file);
diff --git a/ModernKeePass.Application/Database/Commands/SaveDatabase/SaveDatabaseCommand.cs b/ModernKeePass.Application/Database/Commands/SaveDatabase/SaveDatabaseCommand.cs
index e3fa59f..36eafb3 100644
--- a/ModernKeePass.Application/Database/Commands/SaveDatabase/SaveDatabaseCommand.cs
+++ b/ModernKeePass.Application/Database/Commands/SaveDatabase/SaveDatabaseCommand.cs
@@ -48,8 +48,10 @@ namespace ModernKeePass.Application.Database.Commands.SaveDatabase
_file.ReleaseFile(_database.FileAccessToken);
_database.FileAccessToken = message.FilePath;
}
+
+ _database.IsDirty = false;
}
- catch (Exception exception)
+ catch (ArgumentException exception)
{
throw new SaveException(exception);
}
diff --git a/ModernKeePass.Application/Database/Models/DatabaseVm.cs b/ModernKeePass.Application/Database/Models/DatabaseVm.cs
index 8ad5e47..4f21cfd 100644
--- a/ModernKeePass.Application/Database/Models/DatabaseVm.cs
+++ b/ModernKeePass.Application/Database/Models/DatabaseVm.cs
@@ -10,5 +10,7 @@
public string Compression { get; set; }
public string CipherId { get; set; }
public string KeyDerivationId { get; set; }
+ public int Size { get; internal set; }
+ public bool IsDirty { get; internal set; }
}
}
\ No newline at end of file
diff --git a/ModernKeePass.Application/Database/Queries/GetDatabase/GetDatabaseQuery.cs b/ModernKeePass.Application/Database/Queries/GetDatabase/GetDatabaseQuery.cs
index 4d207a8..35659f7 100644
--- a/ModernKeePass.Application/Database/Queries/GetDatabase/GetDatabaseQuery.cs
+++ b/ModernKeePass.Application/Database/Queries/GetDatabase/GetDatabaseQuery.cs
@@ -31,6 +31,8 @@ namespace ModernKeePass.Application.Database.Queries.GetDatabase
database.Compression = _databaseProxy.Compression;
database.CipherId = _databaseProxy.CipherId;
database.KeyDerivationId = _databaseProxy.KeyDerivationId;
+ database.Size = _databaseProxy.Size;
+ database.IsDirty = _databaseProxy.IsDirty;
}
return database;
}
diff --git a/ModernKeePass.Application/Database/Queries/OpenDatabase/OpenDatabaseQuery.cs b/ModernKeePass.Application/Database/Queries/OpenDatabase/OpenDatabaseQuery.cs
index ace9e79..baafb10 100644
--- a/ModernKeePass.Application/Database/Queries/OpenDatabase/OpenDatabaseQuery.cs
+++ b/ModernKeePass.Application/Database/Queries/OpenDatabase/OpenDatabaseQuery.cs
@@ -33,6 +33,7 @@ namespace ModernKeePass.Application.Database.Queries.OpenDatabase
KeyFileContents = !string.IsNullOrEmpty(message.KeyFilePath) ? await _file.OpenBinaryFile(message.KeyFilePath): null,
Password = message.Password
});
+ _database.Size = file.Length;
_database.FileAccessToken = message.FilePath;
}
diff --git a/ModernKeePass.Application/DependencyInjection.cs b/ModernKeePass.Application/DependencyInjection.cs
index c29f8ed..8b02a02 100644
--- a/ModernKeePass.Application/DependencyInjection.cs
+++ b/ModernKeePass.Application/DependencyInjection.cs
@@ -2,6 +2,7 @@
using FluentValidation;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
+using ModernKeePass.Application.Common.Behaviors;
namespace ModernKeePass.Application
{
@@ -11,6 +12,7 @@ namespace ModernKeePass.Application
{
var assembly = typeof(DependencyInjection).GetTypeInfo().Assembly;
services.AddMediatR(assembly);
+ services.AddTransient(typeof(IPipelineBehavior<,>), typeof(SetDirtyBehavior<,>));
//services.AddValidatorsFromAssembly(assembly);
return services;
diff --git a/ModernKeePass.Application/Group/Commands/DeleteEntry/DeleteEntryCommand.cs b/ModernKeePass.Application/Group/Commands/DeleteEntry/DeleteEntryCommand.cs
index 73f47fd..d9a43bb 100644
--- a/ModernKeePass.Application/Group/Commands/DeleteEntry/DeleteEntryCommand.cs
+++ b/ModernKeePass.Application/Group/Commands/DeleteEntry/DeleteEntryCommand.cs
@@ -1,6 +1,7 @@
using System.Threading.Tasks;
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
+using ModernKeePass.Domain.Common;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Group.Commands.DeleteEntry
@@ -24,7 +25,7 @@ namespace ModernKeePass.Application.Group.Commands.DeleteEntry
{
if (!_database.IsOpen) throw new DatabaseClosedException();
- if (_database.IsRecycleBinEnabled && (string.IsNullOrEmpty(_database.RecycleBinId) || _database.RecycleBinId.Equals(_database.ZeroId)))
+ if (_database.IsRecycleBinEnabled && (string.IsNullOrEmpty(_database.RecycleBinId) || _database.RecycleBinId.Equals(Constants.EmptyId)))
{
_database.CreateGroup(_database.RootGroupId, message.RecycleBinName, true);
}
diff --git a/ModernKeePass.Application/Group/Commands/DeleteGroup/DeleteGroupCommand.cs b/ModernKeePass.Application/Group/Commands/DeleteGroup/DeleteGroupCommand.cs
index 0b09268..d157536 100644
--- a/ModernKeePass.Application/Group/Commands/DeleteGroup/DeleteGroupCommand.cs
+++ b/ModernKeePass.Application/Group/Commands/DeleteGroup/DeleteGroupCommand.cs
@@ -1,6 +1,7 @@
using System.Threading.Tasks;
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
+using ModernKeePass.Domain.Common;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Group.Commands.DeleteGroup
@@ -24,7 +25,7 @@ namespace ModernKeePass.Application.Group.Commands.DeleteGroup
{
if (!_database.IsOpen) throw new DatabaseClosedException();
- if (_database.IsRecycleBinEnabled && (string.IsNullOrEmpty(_database.RecycleBinId) || _database.RecycleBinId.Equals(_database.ZeroId)))
+ if (_database.IsRecycleBinEnabled && (string.IsNullOrEmpty(_database.RecycleBinId) || _database.RecycleBinId.Equals(Constants.EmptyId)))
{
_database.CreateGroup(_database.RootGroupId, message.RecycleBinName, true);
}
diff --git a/ModernKeePass.Domain/Domain.csproj b/ModernKeePass.Domain/Domain.csproj
index e75a3d8..2b52280 100644
--- a/ModernKeePass.Domain/Domain.csproj
+++ b/ModernKeePass.Domain/Domain.csproj
@@ -90,6 +90,7 @@
+
diff --git a/ModernKeePass.Domain/Exceptions/DatabaseTooBigException.cs b/ModernKeePass.Domain/Exceptions/DatabaseTooBigException.cs
new file mode 100644
index 0000000..6dfb764
--- /dev/null
+++ b/ModernKeePass.Domain/Exceptions/DatabaseTooBigException.cs
@@ -0,0 +1,6 @@
+using System;
+
+namespace ModernKeePass.Domain.Exceptions
+{
+ public class DatabaseTooBigException: Exception { }
+}
\ No newline at end of file
diff --git a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs
index f889343..c8932dc 100644
--- a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs
+++ b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs
@@ -25,9 +25,7 @@ namespace ModernKeePass.Infrastructure.KeePass
private Credentials _credentials;
// Flag: Has Dispose already been called?
private bool _disposed;
-
- public string ZeroId => PwUuid.Zero.ToHexString();
-
+
// Main information
public bool IsOpen => (_pwDatabase?.IsOpen).GetValueOrDefault();
public string Name => _pwDatabase?.Name;
@@ -35,6 +33,8 @@ namespace ModernKeePass.Infrastructure.KeePass
// TODO: find a correct place for this
public string FileAccessToken { get; set; }
+ public int Size { get; set; }
+ public bool IsDirty { get; set; }
// Settings
public bool IsRecycleBinEnabled
diff --git a/ModernKeePass/App.xaml.cs b/ModernKeePass/App.xaml.cs
index fa58839..5365dc0 100644
--- a/ModernKeePass/App.xaml.cs
+++ b/ModernKeePass/App.xaml.cs
@@ -211,16 +211,17 @@ namespace ModernKeePass
var deferral = e.SuspendingOperation.GetDeferral();
try
{
- if (_settings.GetSetting("SaveSuspend", true))
+ var database = await _mediator.Send(new GetDatabaseQuery());
+ if (database.IsOpen)
{
- await _mediator.Send(new SaveDatabaseCommand()).ConfigureAwait(false);
- }
+ if (database.Size < Constants.File.OneMegaByte && database.IsDirty &&
+ _settings.GetSetting(Constants.Settings.SaveSuspend, true))
+ {
+ await _mediator.Send(new SaveDatabaseCommand()).ConfigureAwait(false);
+ }
- await _mediator.Send(new CloseDatabaseCommand()).ConfigureAwait(false);
- }
- catch (DatabaseClosedException)
- {
- // Do nothing on purpose
+ await _mediator.Send(new CloseDatabaseCommand()).ConfigureAwait(false);
+ }
}
catch (Exception exception)
{
diff --git a/ModernKeePass/Common/Constants.cs b/ModernKeePass/Common/Constants.cs
new file mode 100644
index 0000000..f2850b2
--- /dev/null
+++ b/ModernKeePass/Common/Constants.cs
@@ -0,0 +1,15 @@
+namespace ModernKeePass.Common
+{
+ public class Constants
+ {
+ public class File
+ {
+ public static int OneMegaByte => 1048576;
+ }
+
+ public class Settings
+ {
+ public static string SaveSuspend => nameof(SaveSuspend);
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePass/Interfaces/IVmEntity.cs b/ModernKeePass/Interfaces/IVmEntity.cs
index 4b9a174..714ce18 100644
--- a/ModernKeePass/Interfaces/IVmEntity.cs
+++ b/ModernKeePass/Interfaces/IVmEntity.cs
@@ -19,10 +19,6 @@ namespace ModernKeePass.Interfaces
///
ICommand SaveCommand { get; }
///
- /// Restore ViewModel
- ///
- ICommand UndoDeleteCommand { get; }
- ///
/// Move a entity to the destination group
///
/// The destination to move the entity to
diff --git a/ModernKeePass/ResourceDictionaries/Styles.xaml b/ModernKeePass/ResourceDictionaries/Styles.xaml
index ad8132f..923a753 100644
--- a/ModernKeePass/ResourceDictionaries/Styles.xaml
+++ b/ModernKeePass/ResourceDictionaries/Styles.xaml
@@ -4,7 +4,9 @@
60
+ 300
60
+ 300
diff --git a/ModernKeePass/Strings/en-US/Resources.resw b/ModernKeePass/Strings/en-US/Resources.resw
index 0b0bba4..ad79d51 100644
--- a/ModernKeePass/Strings/en-US/Resources.resw
+++ b/ModernKeePass/Strings/en-US/Resources.resw
@@ -432,11 +432,11 @@
More
-
- Restore
+
+ Move
-
- Restore
+
+ Move
Save
diff --git a/ModernKeePass/Strings/fr-FR/Resources.resw b/ModernKeePass/Strings/fr-FR/Resources.resw
index ab51db7..6cd16ab 100644
--- a/ModernKeePass/Strings/fr-FR/Resources.resw
+++ b/ModernKeePass/Strings/fr-FR/Resources.resw
@@ -432,11 +432,11 @@
Plus
-
- Restaurer
+
+ Déplacer
-
- Restaurer
+
+ Déplacer
Sauvegarder
diff --git a/ModernKeePass/ViewModels/EntryDetailVm.cs b/ModernKeePass/ViewModels/EntryDetailVm.cs
index 1ce5ca4..41c1ef8 100644
--- a/ModernKeePass/ViewModels/EntryDetailVm.cs
+++ b/ModernKeePass/ViewModels/EntryDetailVm.cs
@@ -20,14 +20,13 @@ using ModernKeePass.Application.Security.Commands.GeneratePassword;
using ModernKeePass.Application.Security.Queries.EstimatePasswordComplexity;
using ModernKeePass.Common;
using ModernKeePass.Domain.Enums;
-using ModernKeePass.Domain.Interfaces;
using ModernKeePass.Interfaces;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Domain.AOP;
namespace ModernKeePass.ViewModels
{
- public class EntryDetailVm : NotifyPropertyChangedBase, IVmEntity, ISelectableModel
+ public class EntryDetailVm : NotifyPropertyChangedBase, IVmEntity
{
public bool IsRevealPasswordEnabled => !string.IsNullOrEmpty(Password);
public bool HasExpired => HasExpirationDate && ExpiryDate < DateTime.Now;
@@ -65,7 +64,7 @@ namespace ModernKeePass.ViewModels
get { return _entry.Title; }
set
{
- _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(Title), FieldValue = value}).Wait();
+ SetFieldValue(nameof(Title), value).Wait();
_entry.Title = value;
}
}
@@ -81,7 +80,7 @@ namespace ModernKeePass.ViewModels
get { return _entry.Password; }
set
{
- _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(Password), FieldValue = value }).Wait();
+ SetFieldValue(nameof(Password), value).Wait();
_entry.Password = value;
OnPropertyChanged();
OnPropertyChanged(nameof(PasswordComplexityIndicator));
@@ -93,7 +92,7 @@ namespace ModernKeePass.ViewModels
get { return _entry.Url?.ToString(); }
set
{
- _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(Url), FieldValue = value }).Wait();
+ SetFieldValue(nameof(Url), value).Wait();
_entry.Url = new Uri(value);
}
}
@@ -103,7 +102,7 @@ namespace ModernKeePass.ViewModels
get { return _entry.Notes; }
set
{
- _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(Notes), FieldValue = value }).Wait();
+ SetFieldValue(nameof(Notes), value).Wait();
_entry.Notes = value;
}
}
@@ -117,7 +116,7 @@ namespace ModernKeePass.ViewModels
}
set
{
- _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(Icon), FieldValue = value }).Wait();
+ SetFieldValue(nameof(Icon), value).Wait();
_entry.Icon = (Icon)value;
}
}
@@ -128,7 +127,8 @@ namespace ModernKeePass.ViewModels
set
{
if (!HasExpirationDate) return;
- _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = "ExpirationDate", FieldValue = value.Date }).Wait();
+
+ SetFieldValue("ExpirationDate", value).Wait();
_entry.ExpirationDate = value.Date;
}
}
@@ -139,7 +139,8 @@ namespace ModernKeePass.ViewModels
set
{
if (!HasExpirationDate) return;
- _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = "ExpirationDate", FieldValue = ExpiryDate.Date.Add(value) }).Wait();
+
+ SetFieldValue("ExpirationDate", value).Wait();
_entry.ExpirationDate = _entry.ExpirationDate.Date.Add(value);
}
}
@@ -149,7 +150,7 @@ namespace ModernKeePass.ViewModels
get { return _entry.HasExpirationDate; }
set
{
- _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(HasExpirationDate), FieldValue = value }).Wait();
+ SetFieldValue(nameof(HasExpirationDate), value).Wait();
_entry.HasExpirationDate = value;
OnPropertyChanged();
}
@@ -162,7 +163,7 @@ namespace ModernKeePass.ViewModels
{
if (value != null)
{
- _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(BackgroundColor), FieldValue = value }).Wait();
+ SetFieldValue(nameof(BackgroundColor), value).Wait();
_entry.BackgroundColor = (Color)value;
}
}
@@ -175,12 +176,12 @@ namespace ModernKeePass.ViewModels
{
if (value != null)
{
- _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(ForegroundColor), FieldValue = value }).Wait();
+ SetFieldValue(nameof(ForegroundColor), value).Wait();
_entry.ForegroundColor = (Color)value;
}
}
}
- public IEnumerable History => _history;
+ public IEnumerable History { get; }
public bool IsEditMode
{
@@ -200,16 +201,14 @@ namespace ModernKeePass.ViewModels
set { SetProperty(ref _isRevealPassword, value); }
}
- public bool CanRestore => _entry.ParentGroupId == _database.RecycleBinId;
-
public ICommand SaveCommand { get; }
public ICommand GeneratePasswordCommand { get; }
- public ICommand UndoDeleteCommand { get; }
-
+ public ICommand MoveCommand { get; }
+
+ private DatabaseVm Database => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
+
private readonly IMediator _mediator;
- private readonly DatabaseVm _database;
private readonly GroupVm _parent;
- private readonly IEnumerable _history;
private EntryVm _entry;
private bool _isEditMode;
private bool _isRevealPassword;
@@ -224,17 +223,16 @@ namespace ModernKeePass.ViewModels
public EntryDetailVm(string entryId, IMediator mediator, bool isNewEntry = false)
{
_mediator = mediator;
- _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();
- _history = _entry.History;
+ History = _entry.History;
_isEditMode = isNewEntry;
if (isNewEntry) GeneratePassword().GetAwaiter().GetResult();
IsSelected = true;
- SaveCommand = new RelayCommand(async () => await _mediator.Send(new SaveDatabaseCommand()));
+ SaveCommand = new RelayCommand(async () => await SaveChanges(), () => Database.IsDirty);
GeneratePasswordCommand = new RelayCommand(async () => await GeneratePassword());
- UndoDeleteCommand = new RelayCommand(async () => await Move(_parent), () => _parent != null);
+ MoveCommand = new RelayCommand(async () => await Move(_parent), () => _parent != null);
}
public async Task GeneratePassword()
@@ -269,6 +267,7 @@ namespace ModernKeePass.ViewModels
public async Task SetFieldValue(string fieldName, object value)
{
await _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = fieldName, FieldValue = value });
+ ((RelayCommand)SaveCommand).RaiseCanExecuteChanged();
}
internal void SetEntry(EntryVm entry, int index)
@@ -276,5 +275,11 @@ namespace ModernKeePass.ViewModels
_entry = entry;
IsSelected = index == 0;
}
+
+ private async Task SaveChanges()
+ {
+ await _mediator.Send(new SaveDatabaseCommand());
+ ((RelayCommand)SaveCommand).RaiseCanExecuteChanged();
+ }
}
}
diff --git a/ModernKeePass/ViewModels/GroupDetailVm.cs b/ModernKeePass/ViewModels/GroupDetailVm.cs
index 4875d92..d665928 100644
--- a/ModernKeePass/ViewModels/GroupDetailVm.cs
+++ b/ModernKeePass/ViewModels/GroupDetailVm.cs
@@ -25,12 +25,11 @@ using ModernKeePass.Application.Group.Queries.GetGroup;
using ModernKeePass.Common;
using ModernKeePass.Domain.AOP;
using ModernKeePass.Domain.Enums;
-using ModernKeePass.Domain.Interfaces;
using ModernKeePass.Interfaces;
namespace ModernKeePass.ViewModels
{
- public class GroupDetailVm : NotifyPropertyChangedBase, IVmEntity, ISelectableModel
+ public class GroupDetailVm : NotifyPropertyChangedBase, IVmEntity
{
public ObservableCollection Entries { get; }
@@ -51,25 +50,8 @@ namespace ModernKeePass.ViewModels
}
}
- public bool IsNotRoot => _database.RootGroupId != _group.Id;
+ public bool IsNotRoot => Database.RootGroupId != _group.Id;
- public bool ShowRestore => IsNotRoot && _database.RecycleBinId != _group.Id;
-
- ///
- /// Is the Group the database Recycle Bin?
- ///
- public bool IsSelected
- {
- get
- {
- return _database.IsRecycleBinEnabled && _database.RecycleBinId == _group.Id;
- }
- set
- {
- if (value && _group != null) _database.RecycleBinId = _group.Id;
- }
- }
-
public IOrderedEnumerable> EntriesZoomedOut => from e in Entries
group e by e.Title.ToUpper().FirstOrDefault() into grp
orderby grp.Key
@@ -111,10 +93,11 @@ namespace ModernKeePass.ViewModels
public ICommand SaveCommand { get; }
public ICommand SortEntriesCommand { get; }
public ICommand SortGroupsCommand { get; }
- public ICommand UndoDeleteCommand { get; }
+ public ICommand MoveCommand { get; }
+
+ private DatabaseVm Database => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
private readonly IMediator _mediator;
- private readonly DatabaseVm _database;
private readonly GroupVm _group;
private readonly GroupVm _parent;
private bool _isEditMode;
@@ -129,7 +112,6 @@ namespace ModernKeePass.ViewModels
public GroupDetailVm(string groupId, IMediator mediator, bool isEditMode = false)
{
_mediator = mediator;
- _database = _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
_group = _mediator.Send(new GetGroupQuery { Id = groupId }).GetAwaiter().GetResult();
if (!string.IsNullOrEmpty(_group.ParentGroupId))
{
@@ -138,18 +120,43 @@ namespace ModernKeePass.ViewModels
}
_isEditMode = isEditMode;
- SaveCommand = new RelayCommand(async () => await _mediator.Send(new SaveDatabaseCommand()));
- SortEntriesCommand = new RelayCommand(async () =>
- await SortEntriesAsync(), () => IsEditMode);
- SortGroupsCommand = new RelayCommand(async () =>
- await SortGroupsAsync(), () => IsEditMode);
- UndoDeleteCommand = new RelayCommand(async () => await Move(_parent), () => _parent != null);
+ SaveCommand = new RelayCommand(async () => await SaveChanges(), () => Database.IsDirty);
+ SortEntriesCommand = new RelayCommand(async () => await SortEntriesAsync(), () => IsEditMode);
+ SortGroupsCommand = new RelayCommand(async () => await SortGroupsAsync(), () => IsEditMode);
+ MoveCommand = new RelayCommand(async () => await Move(_parent), () => IsNotRoot);
Entries = new ObservableCollection(_group.Entries);
Entries.CollectionChanged += Entries_CollectionChanged;
Groups = new ObservableCollection(_group.SubGroups);
}
+ public async Task AddNewGroup(string name = "")
+ {
+ return (await _mediator.Send(new CreateGroupCommand {Name = name, ParentGroup = _group})).Id;
+ }
+
+ public async Task AddNewEntry()
+ {
+ return (await _mediator.Send(new CreateEntryCommand { ParentGroup = _group })).Id;
+ }
+
+ public async Task MarkForDelete(string recycleBinTitle)
+ {
+ await _mediator.Send(new DeleteGroupCommand { GroupId = _group.Id, ParentGroupId = _group.ParentGroupId, RecycleBinName = recycleBinTitle });
+ }
+
+ public async Task Move(GroupVm destination)
+ {
+ await _mediator.Send(new AddGroupCommand {ParentGroup = destination, Group = _group });
+ await _mediator.Send(new RemoveGroupCommand {ParentGroup = _parent, Group = _group });
+ }
+
+ private async Task SaveChanges()
+ {
+ await _mediator.Send(new SaveDatabaseCommand());
+ ((RelayCommand)SaveCommand).RaiseCanExecuteChanged();
+ }
+
private async void Entries_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
@@ -170,41 +177,21 @@ namespace ModernKeePass.ViewModels
}
break;
}
- }
-
- public async Task AddNewGroup(string name = "")
- {
- return (await _mediator.Send(new CreateGroupCommand {Name = name, ParentGroup = _group})).Id;
- }
-
- public async Task AddNewEntry()
- {
- return (await _mediator.Send(new CreateEntryCommand { ParentGroup = _group })).Id;
- }
-
- public async Task MarkForDelete(string recycleBinTitle)
- {
- await _mediator.Send(new DeleteGroupCommand { GroupId = _group.Id, ParentGroupId = _group.ParentGroupId, RecycleBinName = recycleBinTitle });
-
- ((RelayCommand)UndoDeleteCommand).RaiseCanExecuteChanged();
- }
-
- public async Task Move(GroupVm destination)
- {
- await _mediator.Send(new AddGroupCommand {ParentGroup = destination, Group = _group });
- await _mediator.Send(new RemoveGroupCommand {ParentGroup = _parent, Group = _group });
+ ((RelayCommand)SaveCommand).RaiseCanExecuteChanged();
}
private async Task SortEntriesAsync()
{
await _mediator.Send(new SortEntriesCommand {Group = _group});
OnPropertyChanged(nameof(Entries));
+ ((RelayCommand)SaveCommand).RaiseCanExecuteChanged();
}
private async Task SortGroupsAsync()
{
await _mediator.Send(new SortGroupsCommand {Group = _group});
OnPropertyChanged(nameof(Groups));
+ ((RelayCommand)SaveCommand).RaiseCanExecuteChanged();
}
}
}
diff --git a/ModernKeePass/ViewModels/Items/SettingsSaveVm.cs b/ModernKeePass/ViewModels/Items/SettingsSaveVm.cs
index 4289d7f..66f8034 100644
--- a/ModernKeePass/ViewModels/Items/SettingsSaveVm.cs
+++ b/ModernKeePass/ViewModels/Items/SettingsSaveVm.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using ModernKeePass.Application.Common.Interfaces;
+using ModernKeePass.Common;
namespace ModernKeePass.ViewModels
{
@@ -17,8 +18,8 @@ namespace ModernKeePass.ViewModels
public bool IsSaveSuspend
{
- get { return _settings.GetSetting("SaveSuspend", true); }
- set { _settings.PutSetting("SaveSuspend", value); }
+ get { return _settings.GetSetting(Constants.Settings.SaveSuspend, true); }
+ set { _settings.PutSetting(Constants.Settings.SaveSuspend, value); }
}
}
}
\ No newline at end of file
diff --git a/ModernKeePass/Views/EntryDetailPage.xaml b/ModernKeePass/Views/EntryDetailPage.xaml
index f75adde..39cf40b 100644
--- a/ModernKeePass/Views/EntryDetailPage.xaml
+++ b/ModernKeePass/Views/EntryDetailPage.xaml
@@ -390,7 +390,7 @@
-
+
@@ -487,7 +487,7 @@
Style="{StaticResource NoBorderButtonStyle}">
-
+
@@ -523,12 +523,10 @@
+ MoveCommand="{Binding MoveCommand}">
@@ -536,9 +534,9 @@
-
+
-
+
diff --git a/ModernKeePass/Views/GroupDetailPage.xaml b/ModernKeePass/Views/GroupDetailPage.xaml
index 90ab9b6..72e6b2e 100644
--- a/ModernKeePass/Views/GroupDetailPage.xaml
+++ b/ModernKeePass/Views/GroupDetailPage.xaml
@@ -45,10 +45,10 @@
-
+
-
+
@@ -61,7 +61,7 @@
-
+
@@ -233,13 +233,12 @@
@@ -249,9 +248,9 @@
-
+
-
+
diff --git a/ModernKeePass/Views/UserControls/BreadCrumbUserControl.xaml.cs b/ModernKeePass/Views/UserControls/BreadCrumbUserControl.xaml.cs
index 9b50c61..62fa708 100644
--- a/ModernKeePass/Views/UserControls/BreadCrumbUserControl.xaml.cs
+++ b/ModernKeePass/Views/UserControls/BreadCrumbUserControl.xaml.cs
@@ -21,7 +21,7 @@ namespace ModernKeePass.Views.UserControls
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register(
- "ItemsSource",
+ nameof(ItemsSource),
typeof(IEnumerable),
typeof(BreadCrumbUserControl),
new PropertyMetadata(new Stack(), (o, args) => { }));
diff --git a/ModernKeePass/Views/UserControls/ColorPickerUserControl.xaml.cs b/ModernKeePass/Views/UserControls/ColorPickerUserControl.xaml.cs
index 692648e..417202e 100644
--- a/ModernKeePass/Views/UserControls/ColorPickerUserControl.xaml.cs
+++ b/ModernKeePass/Views/UserControls/ColorPickerUserControl.xaml.cs
@@ -26,7 +26,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty SelectedColorProperty =
DependencyProperty.Register(
- "SelectedColor",
+ nameof(SelectedColor),
typeof(SolidColorBrush),
typeof(ColorPickerUserControl),
new PropertyMetadata(new SolidColorBrush(), (o, args) => { }));
diff --git a/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs b/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs
index a66bb7d..8cd8cc0 100644
--- a/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs
+++ b/ModernKeePass/Views/UserControls/CompositeKeyUserControl.xaml.cs
@@ -34,7 +34,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty CreateNewProperty =
DependencyProperty.Register(
- "CreateNew",
+ nameof(CreateNew),
typeof(bool),
typeof(CompositeKeyUserControl),
new PropertyMetadata(false, (o, args) => { }));
@@ -46,7 +46,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty UpdateKeyProperty =
DependencyProperty.Register(
- "UpdateKey",
+ nameof(UpdateKey),
typeof(bool),
typeof(CompositeKeyUserControl),
new PropertyMetadata(false, (o, args) => { }));
@@ -58,7 +58,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty ButtonLabelProperty =
DependencyProperty.Register(
- "ButtonLabel",
+ nameof(ButtonLabel),
typeof(string),
typeof(CompositeKeyUserControl),
new PropertyMetadata("OK", (o, args) => { }));
@@ -70,7 +70,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty DatabaseFilePathProperty =
DependencyProperty.Register(
- "DatabaseFilePath",
+ nameof(DatabaseFilePath),
typeof(string),
typeof(CompositeKeyUserControl),
new PropertyMetadata(null, (o, args) => { }));
diff --git a/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml b/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml
index 4912863..a8cd6c0 100644
--- a/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml
+++ b/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml
@@ -23,7 +23,6 @@
Foreground="{ThemeResource DefaultTextForegroundThemeBrush}"
ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}">
- 300
@@ -51,13 +50,13 @@
-
+
-
+
@@ -72,7 +71,7 @@
-
-
+
diff --git a/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml.cs b/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml.cs
index 93df2a7..f94a2a8 100644
--- a/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml.cs
+++ b/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml.cs
@@ -22,7 +22,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty HeaderLabelProperty =
DependencyProperty.Register(
- "HeaderLabel",
+ nameof(HeaderLabel),
typeof(string),
typeof(HamburgerMenuUserControl),
new PropertyMetadata("Header", (o, args) => { }));
@@ -34,7 +34,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty ButtonLabelProperty =
DependencyProperty.Register(
- "ButtonLabel",
+ nameof(ButtonLabel),
typeof(string),
typeof(HamburgerMenuUserControl),
new PropertyMetadata("Button", (o, args) => { }));
@@ -46,7 +46,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty DisplayMemberPathProperty =
DependencyProperty.Register(
- "DisplayMemberPath",
+ nameof(DisplayMemberPath),
typeof(string),
typeof(HamburgerMenuUserControl),
new PropertyMetadata("Title", (o, args) => { }));
@@ -58,7 +58,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty ResizeTargetProperty =
DependencyProperty.Register(
- "ResizeTarget",
+ nameof(ResizeTarget),
typeof(object),
typeof(HamburgerMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
@@ -70,7 +70,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty IsButtonVisibleProperty =
DependencyProperty.Register(
- "IsButtonVisible",
+ nameof(IsButtonVisible),
typeof(Visibility),
typeof(HamburgerMenuUserControl),
new PropertyMetadata(Visibility.Collapsed, (o, args) => { }));
@@ -83,7 +83,7 @@ namespace ModernKeePass.Views.UserControls
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register(
- "ItemsSource",
+ nameof(ItemsSource),
typeof(IEnumerable),
typeof(HamburgerMenuUserControl),
new PropertyMetadata(new List(), (o, args) => { }));
@@ -95,7 +95,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.Register(
- "SelectedItem",
+ nameof(SelectedItem),
typeof(object),
typeof(HamburgerMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
@@ -107,10 +107,10 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty IsOpenProperty =
DependencyProperty.Register(
- "IsOpen",
+ nameof(IsOpen),
typeof(bool),
typeof(HamburgerMenuUserControl),
- new PropertyMetadata(false, (o, args) => { }));
+ new PropertyMetadata(true, (o, args) => { }));
public event EventHandler SelectionChanged;
private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
diff --git a/ModernKeePass/Views/UserControls/SymbolPickerUserControl.xaml.cs b/ModernKeePass/Views/UserControls/SymbolPickerUserControl.xaml.cs
index 545e5a0..e9e6844 100644
--- a/ModernKeePass/Views/UserControls/SymbolPickerUserControl.xaml.cs
+++ b/ModernKeePass/Views/UserControls/SymbolPickerUserControl.xaml.cs
@@ -19,7 +19,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty SelectedSymbolProperty =
DependencyProperty.Register(
- "SelectedSymbol",
+ nameof(SelectedSymbol),
typeof(Symbol),
typeof(SymbolPickerUserControl),
new PropertyMetadata(Symbol.Stop, (o, args) => { }));
diff --git a/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml b/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml
index 8976a85..018e0cf 100644
--- a/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml
+++ b/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml
@@ -42,10 +42,10 @@
-
+
-
+
@@ -76,7 +76,7 @@
-
+
@@ -88,10 +88,10 @@
-
+
-
+
diff --git a/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs b/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs
index 46a8a61..481771d 100644
--- a/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs
+++ b/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs
@@ -15,7 +15,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty SaveCommandProperty =
DependencyProperty.Register(
- "SaveCommand",
+ nameof(SaveCommand),
typeof(ICommand),
typeof(TopMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
@@ -27,7 +27,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty EditCommandProperty =
DependencyProperty.Register(
- "EditCommand",
+ nameof(EditCommand),
typeof(ICommand),
typeof(TopMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
@@ -39,19 +39,19 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty DeleteCommandProperty =
DependencyProperty.Register(
- "DeleteCommand",
+ nameof(DeleteCommand),
typeof(ICommand),
typeof(TopMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
- public ICommand RestoreCommand
+ public ICommand MoveCommand
{
- get { return (ICommand)GetValue(RestoreCommandProperty); }
- set { SetValue(RestoreCommandProperty, value); }
+ get { return (ICommand)GetValue(MoveCommandProperty); }
+ set { SetValue(MoveCommandProperty, value); }
}
- public static readonly DependencyProperty RestoreCommandProperty =
+ public static readonly DependencyProperty MoveCommandProperty =
DependencyProperty.Register(
- "RestoreCommand",
+ nameof(MoveCommand),
typeof(ICommand),
typeof(TopMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
@@ -63,7 +63,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty SortEntriesCommandProperty =
DependencyProperty.Register(
- "SortEntriesCommand",
+ nameof(SortEntriesCommand),
typeof(ICommand),
typeof(TopMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
@@ -75,34 +75,22 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty SortGroupsCommandProperty =
DependencyProperty.Register(
- "SortGroupsCommand",
+ nameof(SortGroupsCommand),
typeof(ICommand),
typeof(TopMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
- public Visibility RestoreButtonVisibility
+ public bool IsMoveButtonEnabled
{
- get { return (Visibility)GetValue(RestoreButtonVisibilityProperty); }
- set { SetValue(RestoreButtonVisibilityProperty, value); }
+ get { return (bool)GetValue(IsMoveButtonEnabledProperty); }
+ set { SetValue(IsMoveButtonEnabledProperty, value); }
}
- public static readonly DependencyProperty RestoreButtonVisibilityProperty =
+ public static readonly DependencyProperty IsMoveButtonEnabledProperty =
DependencyProperty.Register(
- "RestoreButtonVisibility",
- typeof(Visibility),
+ nameof(IsMoveButtonEnabled),
+ typeof(bool),
typeof(TopMenuUserControl),
- new PropertyMetadata(Visibility.Collapsed, (o, args) => { }));
-
- public Visibility DeleteButtonVisibility
- {
- get { return (Visibility)GetValue(DeleteButtonVisibilityProperty); }
- set { SetValue(DeleteButtonVisibilityProperty, value); }
- }
- public static readonly DependencyProperty DeleteButtonVisibilityProperty =
- DependencyProperty.Register(
- "DeleteButtonVisibility",
- typeof(Visibility),
- typeof(TopMenuUserControl),
- new PropertyMetadata(Visibility.Collapsed, (o, args) => { }));
+ new PropertyMetadata(true, (o, args) => { }));
public Visibility SortButtonVisibility
{
@@ -111,7 +99,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty SortButtonVisibilityProperty =
DependencyProperty.Register(
- "SortButtonVisibility",
+ nameof(SortButtonVisibility),
typeof(Visibility),
typeof(TopMenuUserControl),
new PropertyMetadata(Visibility.Collapsed, (o, args) => { }));
@@ -123,7 +111,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty IsDeleteButtonEnabledProperty =
DependencyProperty.Register(
- "IsDeleteButtonEnabled",
+ nameof(IsDeleteButtonEnabled),
typeof(bool),
typeof(TopMenuUserControl),
new PropertyMetadata(true, (o, args) => { }));
@@ -135,14 +123,14 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty IsEditButtonCheckedProperty =
DependencyProperty.Register(
- "IsEditButtonChecked",
+ nameof(IsEditButtonChecked),
typeof(bool),
typeof(TopMenuUserControl),
new PropertyMetadata(false, (o, args) => { }));
public event EventHandler EditButtonClick;
public event EventHandler DeleteButtonClick;
- public event EventHandler RestoreButtonClick;
+ public event EventHandler MoveButtonClick;
public TopMenuUserControl()
{
@@ -166,19 +154,19 @@ namespace ModernKeePass.Views.UserControls
DeleteButtonClick?.Invoke(sender, e);
}
- private void RestoreButton_Click(object sender, RoutedEventArgs e)
+ private void MoveButton_Click(object sender, RoutedEventArgs e)
{
- RestoreButtonClick?.Invoke(sender, e);
+ MoveButtonClick?.Invoke(sender, e);
}
private void OverflowFlyout_OnOpening(object sender, object e)
{
DeleteFlyout.IsEnabled = IsDeleteButtonEnabled;
- DeleteFlyout.Visibility = DeleteButtonVisibility;
+ DeleteFlyout.IsEnabled = IsDeleteButtonEnabled;
EditFlyout.IsChecked = IsEditButtonChecked;
-
- RestoreFlyout.Visibility = RestoreButtonVisibility;
+
+ MoveFlyout.IsEnabled = IsMoveButtonEnabled;
SortEntriesFlyout.Visibility = SortButtonVisibility;
SortGroupsFlyout.Visibility = SortButtonVisibility;
diff --git a/ModernKeePass/Win81App.csproj b/ModernKeePass/Win81App.csproj
index f4ad11e..d22a1c0 100644
--- a/ModernKeePass/Win81App.csproj
+++ b/ModernKeePass/Win81App.csproj
@@ -97,6 +97,7 @@
App.xaml
+
diff --git a/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt b/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt
index ebf3006..5c60c70 100644
--- a/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt
+++ b/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt
@@ -1,5 +1,4 @@
-Improved search box
-Changing entry icon creates a new history entry
-Corrected startup crash on some versions of Windows
-Entry delete button now shows up correctly
-List of icons now only displays valid values
\ No newline at end of file
+Database corruption issues should now be a thing of the past !
+Added the ability to move entries and groups
+Edits are now in a popup instead of inline
+Updated KeePass lib to version 2.44
\ No newline at end of file