diff --git a/ModernKeePass.Application/Application.csproj b/ModernKeePass.Application/Application.csproj
index e23b926..baba6de 100644
--- a/ModernKeePass.Application/Application.csproj
+++ b/ModernKeePass.Application/Application.csproj
@@ -88,7 +88,9 @@
+
+
diff --git a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs
index c7a7ce2..a91a751 100644
--- a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs
+++ b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs
@@ -44,6 +44,8 @@ namespace ModernKeePass.Application.Common.Interfaces
GroupEntity CreateGroup(string parentGroupId, string name, bool isRecycleBin = false);
void SortEntries(string groupId);
void SortSubGroups(string groupId);
+ void AddAttachment(string entryId, string attachmentName, byte[] attachmentContent);
+ void DeleteAttachment(string entryId, string attachmentName);
EntryEntity AddHistory(string entryId);
EntryEntity RestoreFromHistory(string entryId, int historyIndex);
diff --git a/ModernKeePass.Application/Entry/Commands/AddAttachment/AddAttachmentCommand.cs b/ModernKeePass.Application/Entry/Commands/AddAttachment/AddAttachmentCommand.cs
new file mode 100644
index 0000000..7097aac
--- /dev/null
+++ b/ModernKeePass.Application/Entry/Commands/AddAttachment/AddAttachmentCommand.cs
@@ -0,0 +1,34 @@
+using System;
+using MediatR;
+using ModernKeePass.Application.Common.Interfaces;
+using ModernKeePass.Application.Entry.Models;
+using ModernKeePass.Domain.Exceptions;
+
+namespace ModernKeePass.Application.Entry.Commands.AddAttachment
+{
+ public class AddAttachmentCommand : IRequest
+ {
+ public EntryVm Entry { get; set; }
+ public string AttachmentName { get; set; }
+ public byte[] AttachmentContent { get; set; }
+
+ public class AddAttachmentCommandHandler : IRequestHandler
+ {
+ private readonly IDatabaseProxy _database;
+
+ public AddAttachmentCommandHandler(IDatabaseProxy database)
+ {
+ _database = database;
+ }
+
+ public void Handle(AddAttachmentCommand message)
+ {
+ if (!_database.IsOpen) throw new DatabaseClosedException();
+
+ if (message.Entry.Attachments.ContainsKey(message.AttachmentName)) throw new ArgumentException("AttachmentAlreadyExists", nameof(message.AttachmentName));
+ _database.AddAttachment(message.Entry.Id, message.AttachmentName, message.AttachmentContent);
+ message.Entry.Attachments.Add(message.AttachmentName, message.AttachmentContent);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePass.Application/Entry/Commands/DeleteAttachment/DeleteAttachmentCommand.cs b/ModernKeePass.Application/Entry/Commands/DeleteAttachment/DeleteAttachmentCommand.cs
new file mode 100644
index 0000000..4453fe1
--- /dev/null
+++ b/ModernKeePass.Application/Entry/Commands/DeleteAttachment/DeleteAttachmentCommand.cs
@@ -0,0 +1,33 @@
+using System.Collections.Generic;
+using MediatR;
+using ModernKeePass.Application.Common.Interfaces;
+using ModernKeePass.Application.Entry.Models;
+using ModernKeePass.Domain.Exceptions;
+
+namespace ModernKeePass.Application.Entry.Commands.DeleteAttachment
+{
+ public class DeleteAttachmentCommand : IRequest
+ {
+ public EntryVm Entry { get; set; }
+ public string AttachmentName { get; set; }
+
+ public class DeleteAttachmentCommandHandler : IRequestHandler
+ {
+ private readonly IDatabaseProxy _database;
+
+ public DeleteAttachmentCommandHandler(IDatabaseProxy database)
+ {
+ _database = database;
+ }
+
+ public void Handle(DeleteAttachmentCommand message)
+ {
+ if (!_database.IsOpen) throw new DatabaseClosedException();
+
+ if (!message.Entry.Attachments.ContainsKey(message.AttachmentName)) throw new KeyNotFoundException("AttachmentDoesntExist");
+ _database.DeleteAttachment(message.Entry.Id, message.AttachmentName);
+ message.Entry.Attachments.Remove(message.AttachmentName);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs
index 7eac76b..513d2d9 100644
--- a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs
+++ b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs
@@ -244,7 +244,7 @@ namespace ModernKeePass.Infrastructure.KeePass
break;
}
}
-
+
public EntryEntity AddHistory(string entryId)
{
var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
@@ -307,6 +307,18 @@ namespace ModernKeePass.Infrastructure.KeePass
pwGroup.SortSubGroups(false);
}
+ public void AddAttachment(string entryId, string attachmentName, byte[] attachmentContent)
+ {
+ var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
+ pwEntry.Binaries.Set(attachmentName, new ProtectedBinary(true, attachmentContent));
+ }
+
+ public void DeleteAttachment(string entryId, string attachmentName)
+ {
+ var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
+ pwEntry.Binaries.Remove(attachmentName);
+ }
+
public EntryEntity GetEntry(string id)
{
var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(id), true);
diff --git a/ModernKeePass/Strings/en-US/Resources.resw b/ModernKeePass/Strings/en-US/Resources.resw
index 4de65c4..6d369ab 100644
--- a/ModernKeePass/Strings/en-US/Resources.resw
+++ b/ModernKeePass/Strings/en-US/Resources.resw
@@ -531,4 +531,7 @@
Icon
+
+ Add attachment
+
\ No newline at end of file
diff --git a/ModernKeePass/Strings/fr-FR/Resources.resw b/ModernKeePass/Strings/fr-FR/Resources.resw
index e3125ac..09d162c 100644
--- a/ModernKeePass/Strings/fr-FR/Resources.resw
+++ b/ModernKeePass/Strings/fr-FR/Resources.resw
@@ -531,4 +531,7 @@
Icone
+
+ Ajouter une pièce jointe
+
\ No newline at end of file
diff --git a/ModernKeePass/ViewModels/EntryDetailVm.cs b/ModernKeePass/ViewModels/EntryDetailVm.cs
index e5dad60..714f03a 100644
--- a/ModernKeePass/ViewModels/EntryDetailVm.cs
+++ b/ModernKeePass/ViewModels/EntryDetailVm.cs
@@ -13,7 +13,9 @@ using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Database.Commands.SaveDatabase;
using ModernKeePass.Application.Database.Models;
using ModernKeePass.Application.Database.Queries.GetDatabase;
+using ModernKeePass.Application.Entry.Commands.AddAttachment;
using ModernKeePass.Application.Entry.Commands.AddHistory;
+using ModernKeePass.Application.Entry.Commands.DeleteAttachment;
using ModernKeePass.Application.Entry.Commands.DeleteHistory;
using ModernKeePass.Application.Entry.Commands.RestoreHistory;
using ModernKeePass.Application.Entry.Commands.SetFieldValue;
@@ -90,6 +92,11 @@ namespace ModernKeePass.ViewModels
Name = f.Key,
Content = f.Value
}));
+ Attachments.CollectionChanged += (sender, args) =>
+ {
+ SaveCommand.RaiseCanExecuteChanged();
+ _isDirty = true;
+ };
RaisePropertyChanged(string.Empty);
}
}
@@ -102,6 +109,7 @@ namespace ModernKeePass.ViewModels
{
Set(() => SelectedIndex, ref _selectedIndex, value);
RaisePropertyChanged(nameof(IsCurrentEntry));
+ AddAttachmentCommand.RaiseCanExecuteChanged();
}
}
@@ -251,6 +259,8 @@ namespace ModernKeePass.ViewModels
public RelayCommand GoBackCommand { get; }
public RelayCommand GoToParentCommand { get; set; }
public RelayCommand OpenAttachmentCommand { get; set; }
+ public RelayCommand AddAttachmentCommand { get; set; }
+ public RelayCommand DeleteAttachmentCommand { get; set; }
private DatabaseVm Database => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
@@ -285,13 +295,15 @@ namespace ModernKeePass.ViewModels
GoBackCommand = new RelayCommand(() => _navigation.GoBack());
GoToParentCommand = new RelayCommand(() => GoToGroup(_parent.Id));
OpenAttachmentCommand = new RelayCommand(async attachment => await OpenAttachment(attachment));
+ AddAttachmentCommand = new RelayCommand(async () => await AddAttachment(), () => IsCurrentEntry);
+ DeleteAttachmentCommand = new RelayCommand(async attachment => await DeleteAttachment(attachment));
MessengerInstance.Register(this, _ => SaveCommand.RaiseCanExecuteChanged());
}
-
-
+
public async Task Initialize(string entryId)
{
+ SelectedIndex = 0;
SelectedItem = await _mediator.Send(new GetEntryQuery { Id = entryId });
_parent = await _mediator.Send(new GetGroupQuery { Id = SelectedItem.ParentGroupId });
History = new ObservableCollection { SelectedItem };
@@ -299,7 +311,7 @@ namespace ModernKeePass.ViewModels
{
History.Add(entry);
}
- SelectedIndex = 0;
+ History.CollectionChanged += (sender, args) => SaveCommand.RaiseCanExecuteChanged();
}
private async Task AskForDelete()
@@ -333,7 +345,6 @@ namespace ModernKeePass.ViewModels
await _mediator.Send(new DeleteHistoryCommand { Entry = History[0], HistoryIndex = History.Count - SelectedIndex - 1 });
History.RemoveAt(SelectedIndex);
SelectedIndex = 0;
- SaveCommand.RaiseCanExecuteChanged();
});
}
}
@@ -385,7 +396,6 @@ namespace ModernKeePass.ViewModels
await _mediator.Send(new RestoreHistoryCommand { Entry = History[0], HistoryIndex = History.Count - SelectedIndex - 1 });
History.Insert(0, SelectedItem);
SelectedIndex = 0;
- SaveCommand.RaiseCanExecuteChanged();
}
private async Task SaveChanges()
@@ -424,5 +434,21 @@ namespace ModernKeePass.ViewModels
if (fileInfo == null) return;
await _file.WriteBinaryContentsToFile(fileInfo.Id, attachment.Content);
}
+
+ private async Task AddAttachment()
+ {
+ var fileInfo = await _file.OpenFile(string.Empty, Domain.Common.Constants.Extensions.Any, false);
+ if (fileInfo == null) return;
+ var contents = await _file.ReadBinaryFile(fileInfo.Id);
+ await _mediator.Send(new AddAttachmentCommand { Entry = SelectedItem, AttachmentName = fileInfo.Name, AttachmentContent = contents });
+ Attachments.Add(new Attachment { Name = fileInfo.Name, Content = contents });
+ }
+
+ private async Task DeleteAttachment(Attachment attachment)
+ {
+ await _mediator.Send(new DeleteAttachmentCommand { Entry = SelectedItem, AttachmentName = attachment.Name });
+ Attachments.Remove(attachment);
+ }
+
}
}
diff --git a/ModernKeePass/ViewModels/ViewModelLocator.cs b/ModernKeePass/ViewModels/ViewModelLocator.cs
index 135b62c..f5959ca 100644
--- a/ModernKeePass/ViewModels/ViewModelLocator.cs
+++ b/ModernKeePass/ViewModels/ViewModelLocator.cs
@@ -37,7 +37,7 @@ namespace ModernKeePass.ViewModels
public MainVm Main => ServiceLocator.Current.GetInstance(Guid.NewGuid().ToString());
public SettingsVm Settings => ServiceLocator.Current.GetInstance(Guid.NewGuid().ToString());
- public GroupDetailVm Group => ServiceLocator.Current.GetInstance();
- public EntryDetailVm Entry => ServiceLocator.Current.GetInstance();
+ public GroupDetailVm Group => ServiceLocator.Current.GetInstance(Guid.NewGuid().ToString());
+ public EntryDetailVm Entry => ServiceLocator.Current.GetInstance(Guid.NewGuid().ToString());
}
}
\ No newline at end of file
diff --git a/ModernKeePass/Views/EntryDetailPage.xaml b/ModernKeePass/Views/EntryDetailPage.xaml
index ebfe659..8c78946 100644
--- a/ModernKeePass/Views/EntryDetailPage.xaml
+++ b/ModernKeePass/Views/EntryDetailPage.xaml
@@ -1,4 +1,4 @@
-
-
+
@@ -499,15 +499,31 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+