diff --git a/ModernKeePass.Application/Application.csproj b/ModernKeePass.Application/Application.csproj
index 5e83155..0ce2905 100644
--- a/ModernKeePass.Application/Application.csproj
+++ b/ModernKeePass.Application/Application.csproj
@@ -88,6 +88,7 @@
+
diff --git a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs
index c7c9458..a805cbb 100644
--- a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs
+++ b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs
@@ -21,6 +21,7 @@ namespace ModernKeePass.Application.Common.Interfaces
Task Open(byte[] file, Credentials credentials);
Task ReOpen(byte[] file);
+ void AddHistory(string entryId);
Task Create(Credentials credentials, string name, DatabaseVersion version = DatabaseVersion.V2);
Task SaveDatabase();
Task SaveDatabase(byte[] newFileContents);
diff --git a/ModernKeePass.Application/Entry/Commands/AddHistory/AddHistoryCommand.cs b/ModernKeePass.Application/Entry/Commands/AddHistory/AddHistoryCommand.cs
new file mode 100644
index 0000000..44f67a6
--- /dev/null
+++ b/ModernKeePass.Application/Entry/Commands/AddHistory/AddHistoryCommand.cs
@@ -0,0 +1,28 @@
+using MediatR;
+using ModernKeePass.Application.Common.Interfaces;
+using ModernKeePass.Domain.Exceptions;
+
+namespace ModernKeePass.Application.Entry.Commands.AddHistory
+{
+ public class AddHistoryCommand : IRequest
+ {
+ public string EntryId { get; set; }
+
+ public class AddHistoryCommandHandler : IRequestHandler
+ {
+ private readonly IDatabaseProxy _database;
+
+ public AddHistoryCommandHandler(IDatabaseProxy database)
+ {
+ _database = database;
+ }
+
+ public void Handle(AddHistoryCommand message)
+ {
+ if (!_database.IsOpen) throw new DatabaseClosedException();
+
+ _database.AddHistory(message.EntryId);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePass.Application/Entry/Models/EntryVm.cs b/ModernKeePass.Application/Entry/Models/EntryVm.cs
index 85aafae..7b31543 100644
--- a/ModernKeePass.Application/Entry/Models/EntryVm.cs
+++ b/ModernKeePass.Application/Entry/Models/EntryVm.cs
@@ -28,6 +28,7 @@ namespace ModernKeePass.Application.Entry.Models
public bool HasExpirationDate { get; set; }
public DateTimeOffset ExpirationDate { get; set; }
public DateTimeOffset ModificationDate { get; set; }
+ public bool IsDirty { get; set; }
public override string ToString()
{
diff --git a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs
index 8af147c..705a09d 100644
--- a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs
+++ b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs
@@ -222,8 +222,6 @@ namespace ModernKeePass.Infrastructure.KeePass
public void UpdateEntry(string entryId, string fieldName, object fieldValue)
{
var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
- pwEntry.Touch(true);
- pwEntry.CreateBackup(null);
switch (fieldName)
{
@@ -252,6 +250,13 @@ namespace ModernKeePass.Infrastructure.KeePass
}
}
+ public void AddHistory(string entryId)
+ {
+ var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
+ pwEntry.Touch(true);
+ pwEntry.CreateBackup(null);
+ }
+
public void UpdateGroup(string groupId)
{
throw new NotImplementedException();
diff --git a/ModernKeePass/Converters/IconToSymbolConverter.cs b/ModernKeePass/Converters/IconToSymbolConverter.cs
index 16b50bd..503a788 100644
--- a/ModernKeePass/Converters/IconToSymbolConverter.cs
+++ b/ModernKeePass/Converters/IconToSymbolConverter.cs
@@ -10,119 +10,10 @@ namespace ModernKeePass.Converters
public object Convert(object value, Type targetType, object parameter, string language)
{
return Enum.Parse(typeof(Symbol), value.ToString());
- /*var icon = (Icon)value;
- switch (icon)
- {
- case Icon.Delete: return Symbol.Delete;
- case Icon.Edit: return Symbol.Edit;
- case Icon.Save: return Symbol.Save;
- case Icon.Cancel: return Symbol.Cancel;
- case Icon.Accept: return Symbol.Accept;
- case Icon.Home: return Symbol.Home;
- case Icon.Camera: return Symbol.Camera;
- case Icon.Setting: return Symbol.Setting;
- case Icon.Mail: return Symbol.Mail;
- case Icon.Find: return Symbol.Find;
- case Icon.Help: return Symbol.Help;
- case Icon.Clock: return Symbol.Clock;
- case Icon.Crop: return Symbol.Crop;
- case Icon.World: return Symbol.World;
- case Icon.Flag: return Symbol.Flag;
- case Icon.PreviewLink: return Symbol.PreviewLink;
- case Icon.Document: return Symbol.Document;
- case Icon.ProtectedDocument: return Symbol.ProtectedDocument;
- case Icon.ContactInfo: return Symbol.ContactInfo;
- case Icon.ViewAll: return Symbol.ViewAll;
- case Icon.Rotate: return Symbol.Rotate;
- case Icon.List: return Symbol.List;
- case Icon.Shop: return Symbol.Shop;
- case Icon.BrowsePhotos: return Symbol.BrowsePhotos;
- case Icon.Caption: return Symbol.Caption;
- case Icon.Repair: return Symbol.Repair;
- case Icon.Page: return Symbol.Page;
- case Icon.Paste: return Symbol.Paste;
- case Icon.Important: return Symbol.Important;
- case Icon.SlideShow: return Symbol.SlideShow;
- case Icon.MapDrive: return Symbol.MapDrive;
- case Icon.ContactPresence: return Symbol.ContactPresence;
- case Icon.Contact: return Symbol.Contact;
- case Icon.Folder: return Symbol.Folder;
- case Icon.View: return Symbol.View;
- case Icon.Permissions: return Symbol.Permissions;
- case Icon.Map: return Symbol.Map;
- case Icon.CellPhone: return Symbol.CellPhone;
- case Icon.OutlineStar: return Symbol.OutlineStar;
- case Icon.Calculator: return Symbol.Calculator;
- case Icon.Library: return Symbol.Library;
- case Icon.SyncFolder: return Symbol.SyncFolder;
- case Icon.GoToStart: return Symbol.GoToStart;
- case Icon.ZeroBars: return Symbol.ZeroBars;
- case Icon.FourBars: return Symbol.FourBars;
- case Icon.Scan: return Symbol.Scan;
- case Icon.ReportHacked: return Symbol.ReportHacked;
- case Icon.Stop: return Symbol.Stop;
- default:
- throw new ArgumentOutOfRangeException();
- }*/
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
- /*var symbol = (Symbol)value;
- var defaultIcon = parameter != null ? int.Parse(parameter as string) : -1;
- switch (symbol)
- {
- case Symbol.Delete: return Icon.Delete;
- case Symbol.Edit: return Icon.Edit;
- case Symbol.Save: return Icon.Save;
- case Symbol.Cancel: return Icon.Cancel;
- case Symbol.Accept: return Icon.Accept;
- case Symbol.Home: return Icon.Home;
- case Symbol.Camera: return Icon.Camera;
- case Symbol.Setting: return Icon.Setting;
- case Symbol.Mail: return Icon.Mail;
- case Symbol.Find: return Icon.Find;
- case Symbol.Help: return Icon.Help;
- case Symbol.Clock: return Icon.Clock;
- case Symbol.Crop: return Icon.Crop;
- case Symbol.World: return Icon.World;
- case Symbol.Flag: return Icon.Flag;
- case Symbol.PreviewLink: return Icon.PreviewLink;
- case Symbol.Document: return Icon.Document;
- case Symbol.ProtectedDocument: return Icon.ProtectedDocument;
- case Symbol.ContactInfo: return Icon.ContactInfo;
- case Symbol.ViewAll: return Icon.ViewAll;
- case Symbol.Rotate: return Icon.Rotate;
- case Symbol.List: return Icon.List;
- case Symbol.Shop: return Icon.Shop;
- case Symbol.BrowsePhotos: return Icon.BrowsePhotos;
- case Symbol.Caption: return Icon.Caption;
- case Symbol.Repair: return Icon.Repair;
- case Symbol.Page: return Icon.Page;
- case Symbol.Paste: return Icon.Paste;
- case Symbol.Important: return Icon.Important;
- case Symbol.SlideShow: return Icon.SlideShow;
- case Symbol.MapDrive: return Icon.MapDrive;
- case Symbol.ContactPresence: return Icon.ContactPresence;
- case Symbol.Contact: return Icon.Contact;
- case Symbol.Folder: return Icon.Folder;
- case Symbol.View: return Icon.View;
- case Symbol.Permissions: return Icon.Permissions;
- case Symbol.Map: return Icon.Map;
- case Symbol.CellPhone: return Icon.CellPhone;
- case Symbol.OutlineStar: return Icon.OutlineStar;
- case Symbol.Calculator: return Icon.Calculator;
- case Symbol.Library: return Icon.Library;
- case Symbol.SyncFolder: return Icon.SyncFolder;
- case Symbol.GoToStart: return Icon.GoToStart;
- case Symbol.ZeroBars: return Icon.ZeroBars;
- case Symbol.FourBars: return Icon.FourBars;
- case Symbol.Scan: return Icon.Scan;
- case Symbol.ReportHacked: return Icon.ReportHacked;
- case Symbol.Stop: return Icon.Stop;
- default: return defaultIcon;
- }*/
-
return Enum.Parse(typeof(Icon), value.ToString());
}
}
diff --git a/ModernKeePass/ViewModels/EntryDetailVm.cs b/ModernKeePass/ViewModels/EntryDetailVm.cs
index 2f3ee01..21f54b6 100644
--- a/ModernKeePass/ViewModels/EntryDetailVm.cs
+++ b/ModernKeePass/ViewModels/EntryDetailVm.cs
@@ -9,6 +9,7 @@ using Microsoft.Extensions.DependencyInjection;
using ModernKeePass.Application.Database.Commands.SaveDatabase;
using ModernKeePass.Application.Database.Models;
using ModernKeePass.Application.Database.Queries.GetDatabase;
+using ModernKeePass.Application.Entry.Commands.AddHistory;
using ModernKeePass.Application.Entry.Commands.SetFieldValue;
using ModernKeePass.Application.Entry.Models;
using ModernKeePass.Application.Entry.Queries.GetEntry;
@@ -83,7 +84,7 @@ namespace ModernKeePass.ViewModels
{
_entry.Password = value;
SetFieldValue(nameof(Password), value).Wait();
- OnPropertyChanged();
+ OnPropertyChanged(nameof(Password));
OnPropertyChanged(nameof(PasswordComplexityIndicator));
}
}
@@ -246,7 +247,7 @@ namespace ModernKeePass.ViewModels
public async Task MarkForDelete(string recycleBinTitle)
{
- await _mediator.Send(new DeleteEntryCommand {EntryId = _entry.Id, ParentGroupId = _entry.ParentGroupId, RecycleBinName = recycleBinTitle});
+ await _mediator.Send(new DeleteEntryCommand {EntryId = Id, ParentGroupId = _entry.ParentGroupId, RecycleBinName = recycleBinTitle});
}
public async Task Move(GroupVm destination)
@@ -259,18 +260,28 @@ namespace ModernKeePass.ViewModels
{
await _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = fieldName, FieldValue = value });
((RelayCommand)SaveCommand).RaiseCanExecuteChanged();
+ _entry.IsDirty = true;
+ }
+
+ public async Task AddHistory()
+ {
+ if (_entry.IsDirty) await _mediator.Send(new AddHistoryCommand {EntryId = Id});
}
internal void SetEntry(EntryVm entry, int index)
{
_entry = entry;
IsSelected = index == 0;
+ OnPropertyChanged();
}
private async Task SaveChanges()
{
+ await AddHistory();
await _mediator.Send(new SaveDatabaseCommand());
((RelayCommand)SaveCommand).RaiseCanExecuteChanged();
+ _entry.IsDirty = false;
}
+
}
}
diff --git a/ModernKeePass/Views/EntryDetailPage.xaml.cs b/ModernKeePass/Views/EntryDetailPage.xaml.cs
index 4d0a9e3..054b6fb 100644
--- a/ModernKeePass/Views/EntryDetailPage.xaml.cs
+++ b/ModernKeePass/Views/EntryDetailPage.xaml.cs
@@ -46,8 +46,9 @@ namespace ModernKeePass.Views
if (args != null) DataContext = new EntryDetailVm(args);
}
- protected override void OnNavigatedFrom(NavigationEventArgs e)
+ protected override async void OnNavigatedFrom(NavigationEventArgs e)
{
+ await Model.AddHistory();
NavigationHelper.OnNavigatedFrom(e);
}
@@ -69,7 +70,7 @@ namespace ModernKeePass.Views
case -1:
return;
default:
- var entry = listView?.SelectedItem as Application.Entry.Models.EntryVm;
+ var entry = listView.SelectedItem as Application.Entry.Models.EntryVm;
Model.SetEntry(entry, index);
break;
}