diff --git a/ModernKeePass.Application/Application.csproj b/ModernKeePass.Application/Application.csproj index 0ce2905..1659906 100644 --- a/ModernKeePass.Application/Application.csproj +++ b/ModernKeePass.Application/Application.csproj @@ -93,6 +93,7 @@ + diff --git a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs index a805cbb..6906743 100644 --- a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs +++ b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Threading.Tasks; using ModernKeePass.Domain.Dtos; using ModernKeePass.Domain.Entities; using ModernKeePass.Domain.Enums; @@ -28,6 +29,8 @@ namespace ModernKeePass.Application.Common.Interfaces void UpdateCredentials(Credentials credentials); void CloseDatabase(); + EntryEntity GetEntry(string id); + GroupEntity GetGroup(string id); Task AddEntry(string parentGroupId, string entryId); Task MoveEntry(string parentGroupId, string entryId, int index); Task AddGroup(string parentGroupId, string groupId); @@ -40,7 +43,7 @@ namespace ModernKeePass.Application.Common.Interfaces GroupEntity CreateGroup(string parentGroupId, string name, bool isRecycleBin = false); void SortEntries(string groupId); void SortSubGroups(string groupId); - EntryEntity GetEntry(string id); - GroupEntity GetGroup(string id); + + IEnumerable Search(string groupId, string text); } } \ No newline at end of file diff --git a/ModernKeePass.Application/Group/Queries/SearchEntries/SearchEntriesQuery.cs b/ModernKeePass.Application/Group/Queries/SearchEntries/SearchEntriesQuery.cs new file mode 100644 index 0000000..105a180 --- /dev/null +++ b/ModernKeePass.Application/Group/Queries/SearchEntries/SearchEntriesQuery.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.Linq; +using AutoMapper; +using MediatR; +using ModernKeePass.Application.Common.Interfaces; +using ModernKeePass.Application.Entry.Models; +using ModernKeePass.Domain.Exceptions; + +namespace ModernKeePass.Application.Group.Queries.SearchEntries +{ + public class SearchEntriesQuery : IRequest> + { + public string GroupId { get; set; } + public string SearchText { get; set; } + + public class SearchEntriesQueryHandler : IRequestHandler> + { + private readonly IDatabaseProxy _database; + private readonly IMapper _mapper; + + public SearchEntriesQueryHandler(IDatabaseProxy database, IMapper mapper) + { + _database = database; + _mapper = mapper; + } + + public IEnumerable Handle(SearchEntriesQuery message) + { + if (!_database.IsOpen) throw new DatabaseClosedException(); + return _database.Search(message.GroupId, message.SearchText).Select(e => _mapper.Map(e)); + } + } + } +} \ No newline at end of file diff --git a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs index 705a09d..5b878f7 100644 --- a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs +++ b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Threading.Tasks; @@ -9,6 +10,7 @@ using ModernKeePass.Domain.Entities; using ModernKeePass.Domain.Enums; using ModernKeePass.Domain.Interfaces; using ModernKeePassLib; +using ModernKeePassLib.Collections; using ModernKeePassLib.Cryptography.KeyDerivation; using ModernKeePassLib.Interfaces; using ModernKeePassLib.Keys; @@ -311,6 +313,21 @@ namespace ModernKeePass.Infrastructure.KeePass _pwDatabase.MasterKey = CreateCompositeKey(credentials); } + public IEnumerable Search(string groupId, string text) + { + var pwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(groupId), true); + var searchResults = new PwObjectList(); + pwGroup.SearchEntries(new SearchParameters + { + ComparisonMode = StringComparison.OrdinalIgnoreCase, + SearchInTitles = true, + //SearchInUserNames = true, + SearchString = text + + }, searchResults); + return searchResults.Select(e => _mapper.Map(e)); + } + private CompositeKey CreateCompositeKey(Credentials credentials) { var compositeKey = new CompositeKey(); diff --git a/ModernKeePass/Actions/DeleteEntityAction.cs b/ModernKeePass/Actions/DeleteEntityAction.cs index 2da4459..70b2ef2 100644 --- a/ModernKeePass/Actions/DeleteEntityAction.cs +++ b/ModernKeePass/Actions/DeleteEntityAction.cs @@ -58,7 +58,7 @@ namespace ModernKeePass.Actions ToastNotificationHelper.ShowMovedToast(Entity, resource.GetResourceValue("EntityDeleting"), text); Entity.MarkForDelete(resource.GetResourceValue("RecycleBinTitle")); Command.Execute(null); - }, null).GetAwaiter().GetResult(); + }, null).Wait(); return null; } diff --git a/ModernKeePass/Common/MessageDialogHelper.cs b/ModernKeePass/Common/MessageDialogHelper.cs index 7fd6010..45ba232 100644 --- a/ModernKeePass/Common/MessageDialogHelper.cs +++ b/ModernKeePass/Common/MessageDialogHelper.cs @@ -15,7 +15,7 @@ namespace ModernKeePass.Common messageDialog.Commands.Add(new UICommand(actionButtonText, actionCommand)); // Show the message dialog - await messageDialog.ShowAsync().AsTask(); + await messageDialog.ShowAsync().AsTask().ConfigureAwait(false); } public static async Task ShowErrorDialog(Exception exception) @@ -25,7 +25,7 @@ namespace ModernKeePass.Common var messageDialog = CreateBasicDialog(exception.Message, exception.StackTrace, "OK"); // Show the message dialog - await messageDialog.ShowAsync().AsTask();; + await messageDialog.ShowAsync().AsTask().ConfigureAwait(false); } public static async Task ShowNotificationDialog(string title, string message) @@ -33,7 +33,7 @@ namespace ModernKeePass.Common var dialog = CreateBasicDialog(title, message, "OK"); // Show the message dialog - await dialog.ShowAsync().AsTask();; + await dialog.ShowAsync().AsTask().ConfigureAwait(false); } private static MessageDialog CreateBasicDialog(string title, string message, string dismissActionText, UICommandInvokedHandler cancelCommand = null) diff --git a/ModernKeePass/Models/NavigationItem.cs b/ModernKeePass/Models/NavigationItem.cs new file mode 100644 index 0000000..2ba4be8 --- /dev/null +++ b/ModernKeePass/Models/NavigationItem.cs @@ -0,0 +1,8 @@ +namespace ModernKeePass.Models +{ + public class NavigationItem + { + public string Id { get; set; } + public bool IsNew { get; set; } + } +} \ No newline at end of file diff --git a/ModernKeePass/ViewModels/EntryDetailVm.cs b/ModernKeePass/ViewModels/EntryDetailVm.cs index 21f54b6..7c43227 100644 --- a/ModernKeePass/ViewModels/EntryDetailVm.cs +++ b/ModernKeePass/ViewModels/EntryDetailVm.cs @@ -181,12 +181,6 @@ namespace ModernKeePass.ViewModels set { SetProperty(ref _isEditMode, value); } } - public bool IsVisible - { - get { return _isVisible; } - set { SetProperty(ref _isVisible, value); } - } - public bool IsRevealPassword { get { return _isRevealPassword; } @@ -205,21 +199,18 @@ namespace ModernKeePass.ViewModels private bool _isEditMode; private bool _isRevealPassword; private double _passwordLength = 25; - private bool _isVisible = true; private bool _isSelected; public EntryDetailVm() { } - internal EntryDetailVm(string entryId, bool isNewEntry = false) : this(entryId, App.Services.GetRequiredService(), isNewEntry) { } + internal EntryDetailVm(string entryId) : this(entryId, App.Services.GetRequiredService()) { } - public EntryDetailVm(string entryId, IMediator mediator, bool isNewEntry = false) + public EntryDetailVm(string entryId, IMediator mediator) { _mediator = mediator; _entry = _mediator.Send(new GetEntryQuery {Id = entryId}).GetAwaiter().GetResult(); _parent = _mediator.Send(new GetGroupQuery {Id = _entry.ParentGroupId}).GetAwaiter().GetResult(); History = _entry.History; - _isEditMode = isNewEntry; - if (isNewEntry) GeneratePassword().GetAwaiter().GetResult(); IsSelected = true; SaveCommand = new RelayCommand(async () => await SaveChanges(), () => Database.IsDirty); diff --git a/ModernKeePass/ViewModels/GroupDetailVm.cs b/ModernKeePass/ViewModels/GroupDetailVm.cs index f59c780..017168b 100644 --- a/ModernKeePass/ViewModels/GroupDetailVm.cs +++ b/ModernKeePass/ViewModels/GroupDetailVm.cs @@ -23,6 +23,7 @@ using ModernKeePass.Application.Group.Commands.SortEntries; using ModernKeePass.Application.Group.Commands.SortGroups; using ModernKeePass.Application.Group.Models; using ModernKeePass.Application.Group.Queries.GetGroup; +using ModernKeePass.Application.Group.Queries.SearchEntries; using ModernKeePass.Common; using ModernKeePass.Domain.AOP; using ModernKeePass.Domain.Enums; @@ -35,22 +36,7 @@ namespace ModernKeePass.ViewModels public ObservableCollection Entries { get; } public ObservableCollection Groups { get; } - - public IEnumerable SubEntries - { - get - { - var subEntries = new List(); - subEntries.AddRange(Entries); - foreach (var group in Groups) - { - subEntries.AddRange(group.Entries); - } - - return subEntries; - } - } - + public bool IsNotRoot => Database.RootGroupId != _group.Id; public IOrderedEnumerable> EntriesZoomedOut => from e in Entries @@ -83,12 +69,6 @@ namespace ModernKeePass.ViewModels } } - public bool IsMenuClosed - { - get { return _isMenuClosed; } - set { SetProperty(ref _isMenuClosed, value); } - } - public IEnumerable BreadCrumb { get; } public ICommand SaveCommand { get; } @@ -103,14 +83,13 @@ namespace ModernKeePass.ViewModels private readonly GroupVm _parent; private bool _isEditMode; private EntryVm _reorderedEntry; - private bool _isMenuClosed = true; public GroupDetailVm() {} internal GroupDetailVm(string groupId) : this(groupId, App.Services.GetRequiredService()) { } - public GroupDetailVm(string groupId, IMediator mediator, bool isEditMode = false) + public GroupDetailVm(string groupId, IMediator mediator) { _mediator = mediator; _group = _mediator.Send(new GetGroupQuery { Id = groupId }).GetAwaiter().GetResult(); @@ -119,7 +98,6 @@ namespace ModernKeePass.ViewModels _parent = _mediator.Send(new GetGroupQuery { Id = _group.ParentGroupId }).GetAwaiter().GetResult(); BreadCrumb = new List {_parent}; } - _isEditMode = isEditMode; SaveCommand = new RelayCommand(async () => await SaveChanges(), () => Database.IsDirty); SortEntriesCommand = new RelayCommand(async () => await SortEntriesAsync(), () => IsEditMode); @@ -152,6 +130,11 @@ namespace ModernKeePass.ViewModels await _mediator.Send(new RemoveGroupCommand {ParentGroup = _parent, Group = _group }); } + public async Task> Search(string queryText) + { + return await _mediator.Send(new SearchEntriesQuery {GroupId = Id, SearchText = queryText}); + } + private async Task SaveChanges() { await _mediator.Send(new SaveDatabaseCommand()); diff --git a/ModernKeePass/ViewModels/MainVm.cs b/ModernKeePass/ViewModels/MainVm.cs index faadf5d..8457527 100644 --- a/ModernKeePass/ViewModels/MainVm.cs +++ b/ModernKeePass/ViewModels/MainVm.cs @@ -10,6 +10,7 @@ using ModernKeePass.Common; using ModernKeePass.Domain.AOP; using ModernKeePass.Domain.Dtos; using ModernKeePass.Domain.Interfaces; +using ModernKeePass.Models; using ModernKeePass.Views; namespace ModernKeePass.ViewModels @@ -128,7 +129,7 @@ namespace ModernKeePass.ViewModels Title = database.Name, PageType = typeof(GroupDetailPage), Destination = referenceFrame, - Parameter = database.RootGroupId, + Parameter = new NavigationItem { Id = database.RootGroupId }, Group = "Databases", SymbolIcon = Symbol.ProtectedDocument }); diff --git a/ModernKeePass/Views/EntryDetailPage.xaml.cs b/ModernKeePass/Views/EntryDetailPage.xaml.cs index 054b6fb..3874888 100644 --- a/ModernKeePass/Views/EntryDetailPage.xaml.cs +++ b/ModernKeePass/Views/EntryDetailPage.xaml.cs @@ -2,6 +2,7 @@ using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; using ModernKeePass.Common; +using ModernKeePass.Models; using ModernKeePass.ViewModels; // Pour en savoir plus sur le modèle d'élément Page Détail de l'élément, consultez la page http://go.microsoft.com/fwlink/?LinkId=234232 @@ -39,11 +40,15 @@ namespace ModernKeePass.Views /// Le paramètre de navigation est disponible dans la méthode LoadState /// en plus de l'état de page conservé durant une session antérieure. - protected override void OnNavigatedTo(NavigationEventArgs e) + protected override async void OnNavigatedTo(NavigationEventArgs e) { NavigationHelper.OnNavigatedTo(e); - var args = e.Parameter as string; - if (args != null) DataContext = new EntryDetailVm(args); + var args = e.Parameter as NavigationItem; + if (args != null) + { + DataContext = new EntryDetailVm(args.Id) { IsEditMode = args.IsNew }; + await Model.GeneratePassword(); + } } protected override async void OnNavigatedFrom(NavigationEventArgs e) diff --git a/ModernKeePass/Views/GroupDetailPage.xaml b/ModernKeePass/Views/GroupDetailPage.xaml index 8ff6b57..3c946fe 100644 --- a/ModernKeePass/Views/GroupDetailPage.xaml +++ b/ModernKeePass/Views/GroupDetailPage.xaml @@ -48,7 +48,7 @@ - + diff --git a/ModernKeePass/Views/GroupDetailPage.xaml.cs b/ModernKeePass/Views/GroupDetailPage.xaml.cs index 936fec6..4ce1bf5 100644 --- a/ModernKeePass/Views/GroupDetailPage.xaml.cs +++ b/ModernKeePass/Views/GroupDetailPage.xaml.cs @@ -7,6 +7,7 @@ using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; using ModernKeePass.Common; using ModernKeePass.Events; +using ModernKeePass.Models; using ModernKeePass.ViewModels; using EntryVm = ModernKeePass.Application.Entry.Models.EntryVm; @@ -53,9 +54,9 @@ namespace ModernKeePass.Views DataContext = new GroupDetailVm(args.RootGroupId); else { - var id = e.Parameter as string; - if (id != null) - DataContext = new GroupDetailVm(id); + var navigationItem = e.Parameter as NavigationItem; + if (navigationItem != null) + DataContext = new GroupDetailVm(navigationItem.Id) { IsEditMode = navigationItem.IsNew }; } } @@ -77,7 +78,7 @@ namespace ModernKeePass.Views return; default: var group = listView?.SelectedItem as Application.Group.Models.GroupVm; - Frame.Navigate(typeof(GroupDetailPage), group?.Id); + Frame.Navigate(typeof(GroupDetailPage), new NavigationItem { Id = group?.Id }); break; } } @@ -90,7 +91,7 @@ namespace ModernKeePass.Views return; default: var entry = GridView.SelectedItem as EntryVm; - Frame.Navigate(typeof(EntryDetailPage), entry?.Id); + Frame.Navigate(typeof(EntryDetailPage), new NavigationItem { Id = entry?.Id }); break; } } @@ -105,11 +106,19 @@ namespace ModernKeePass.Views } private async void CreateEntry_ButtonClick(object sender, RoutedEventArgs e) { - Frame.Navigate(typeof(EntryDetailPage), await Model.AddNewEntry()); + Frame.Navigate(typeof(EntryDetailPage), new NavigationItem + { + Id = await Model.AddNewEntry(), + IsNew = true + }); } private async void CreateGroup_ButtonClick(object sender, RoutedEventArgs e) { - Frame.Navigate(typeof(GroupDetailPage), await Model.AddNewGroup()); + Frame.Navigate(typeof(GroupDetailPage), new NavigationItem + { + Id = await Model.AddNewGroup(), + IsNew = true + }); } private void GridView_DragItemsStarting(object sender, DragItemsStartingEventArgs e) @@ -118,10 +127,10 @@ namespace ModernKeePass.Views e.Data.RequestedOperation = DataPackageOperation.Move; } - private void SearchBox_OnSuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args) + private async void SearchBox_OnSuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args) { var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appdata://Assets/ModernKeePass-SmallLogo.scale-80.png")); - var results = Model.SubEntries.Where(e => e.Title.IndexOf(args.QueryText, StringComparison.OrdinalIgnoreCase) >= 0).Take(5); + var results = (await Model.Search(args.QueryText)).Take(5); foreach (var result in results) { args.Request.SearchSuggestionCollection.AppendResultSuggestion(result.Title, result.ParentGroupName, result.Id, imageUri, string.Empty); @@ -130,7 +139,7 @@ namespace ModernKeePass.Views private void SearchBox_OnResultSuggestionChosen(SearchBox sender, SearchBoxResultSuggestionChosenEventArgs args) { - Frame.Navigate(typeof(EntryDetailPage), args.Tag); + Frame.Navigate(typeof(EntryDetailPage), new NavigationItem { Id = args.Tag }); } private void GroupDetailPage_OnSizeChanged(object sender, SizeChangedEventArgs e) diff --git a/ModernKeePass/Win81App.csproj b/ModernKeePass/Win81App.csproj index e1a8070..0751cf2 100644 --- a/ModernKeePass/Win81App.csproj +++ b/ModernKeePass/Win81App.csproj @@ -102,6 +102,7 @@ + @@ -556,6 +557,7 @@ Infrastructure + 12.0