diff --git a/ModernKeePass.Application/Application.csproj b/ModernKeePass.Application/Application.csproj index 9ea0f1f..fa6c468 100644 --- a/ModernKeePass.Application/Application.csproj +++ b/ModernKeePass.Application/Application.csproj @@ -97,6 +97,7 @@ + diff --git a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs index c73ea5e..7683686 100644 --- a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs +++ b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs @@ -41,6 +41,7 @@ namespace ModernKeePass.Application.Common.Interfaces GroupEntity GetGroup(string id); Task AddGroup(string parentGroupId, string groupId); + Task MoveGroup(string parentGroupId, string groupId, int index); void UpdateGroup(GroupEntity group); Task RemoveGroup(string parentGroupId, string groupId); void DeleteEntity(string entityId); diff --git a/ModernKeePass.Application/Group/Commands/MoveGroup/MoveGroupCommand.cs b/ModernKeePass.Application/Group/Commands/MoveGroup/MoveGroupCommand.cs new file mode 100644 index 0000000..dcaf4e1 --- /dev/null +++ b/ModernKeePass.Application/Group/Commands/MoveGroup/MoveGroupCommand.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using MediatR; +using ModernKeePass.Application.Common.Interfaces; +using ModernKeePass.Application.Group.Models; +using ModernKeePass.Domain.Exceptions; + +namespace ModernKeePass.Application.Group.Commands.MoveGroup +{ + public class MoveGroupCommand : IRequest + { + public GroupVm ParentGroup { get; set; } + public GroupVm Group { get; set; } + public int Index { get; set; } + + public class MoveGroupCommandHandler : IAsyncRequestHandler + { + private readonly IDatabaseProxy _database; + + public MoveGroupCommandHandler(IDatabaseProxy database) + { + _database = database; + } + + public async Task Handle(MoveGroupCommand message) + { + if (!_database.IsOpen) throw new DatabaseClosedException(); + + await _database.MoveGroup(message.ParentGroup.Id, message.Group.Id, message.Index); + message.ParentGroup.SubGroups.Insert(message.Index, message.Group); + } + } + } +} \ No newline at end of file diff --git a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs index b706b06..c91e497 100644 --- a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs +++ b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs @@ -189,6 +189,20 @@ namespace ModernKeePass.Infrastructure.KeePass parentPwGroup.AddGroup(pwGroup, true); }); } + + public async Task MoveGroup(string parentGroupId, string groupId, int index) + { + await Task.Run(() => + { + var parentPwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(parentGroupId), true); + var pwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(groupId), true); + var currentIndex = (uint)parentPwGroup.Groups.IndexOf(pwGroup); + + parentPwGroup.Groups.RemoveAt(currentIndex); + parentPwGroup.Groups.Insert((uint)index, pwGroup); + }); + } + public async Task RemoveEntry(string parentGroupId, string entryId) { await Task.Run(() => diff --git a/ModernKeePass/Strings/en-US/Resources.resw b/ModernKeePass/Strings/en-US/Resources.resw index 52518cd..e0ed937 100644 --- a/ModernKeePass/Strings/en-US/Resources.resw +++ b/ModernKeePass/Strings/en-US/Resources.resw @@ -376,7 +376,7 @@ New group - Groups + Navigation History @@ -540,4 +540,10 @@ Delete + + Drag and drop groups to reorder them + + + Invalid field name + \ No newline at end of file diff --git a/ModernKeePass/Strings/fr-FR/Resources.resw b/ModernKeePass/Strings/fr-FR/Resources.resw index 9bb6e82..74a1271 100644 --- a/ModernKeePass/Strings/fr-FR/Resources.resw +++ b/ModernKeePass/Strings/fr-FR/Resources.resw @@ -379,7 +379,7 @@ Nouveau groupe - Groupes + Navigation Historique @@ -537,4 +537,10 @@ Supprimer + + Drag and drop groups to reorder them + + + Nom de champ invalide + \ No newline at end of file diff --git a/ModernKeePass/ViewModels/EntryDetailVm.cs b/ModernKeePass/ViewModels/EntryDetailVm.cs index 71cf585..1470c4c 100644 --- a/ModernKeePass/ViewModels/EntryDetailVm.cs +++ b/ModernKeePass/ViewModels/EntryDetailVm.cs @@ -275,7 +275,7 @@ namespace ModernKeePass.ViewModels public RelayCommand DeleteAttachmentCommand { get; set; } private DatabaseVm Database => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult(); - + private readonly IMediator _mediator; private readonly INavigationService _navigation; private readonly IResourceProxy _resource; @@ -285,7 +285,7 @@ namespace ModernKeePass.ViewModels private GroupVm _parent; private EntryVm _selectedItem; private int _selectedIndex; - private int _additionalFieldSelectedIndex; + private int _additionalFieldSelectedIndex = -1; private bool _isEditMode; private bool _isRevealPassword; private double _passwordLength = 25; @@ -307,11 +307,11 @@ namespace ModernKeePass.ViewModels DeleteCommand = new RelayCommand(async () => await AskForDelete()); GoBackCommand = new RelayCommand(() => _navigation.GoBack()); GoToParentCommand = new RelayCommand(() => GoToGroup(_parent.Id)); - AddAdditionalField = new RelayCommand(AddField); - DeleteAdditionalField = new RelayCommand(async field => await DeleteField(field), field => field != null); + AddAdditionalField = new RelayCommand(AddField, () => IsCurrentEntry); + DeleteAdditionalField = new RelayCommand(async field => await DeleteField(field), field => field != null && IsCurrentEntry); OpenAttachmentCommand = new RelayCommand(async attachment => await OpenAttachment(attachment)); AddAttachmentCommand = new RelayCommand(async () => await AddAttachment(), () => IsCurrentEntry); - DeleteAttachmentCommand = new RelayCommand(async attachment => await DeleteAttachment(attachment)); + DeleteAttachmentCommand = new RelayCommand(async attachment => await DeleteAttachment(attachment), _ => IsCurrentEntry); MessengerInstance.Register(this, _ => SaveCommand.RaiseCanExecuteChanged()); MessengerInstance.Register(this, async message => await SetFieldValue(message.FieldName, message.FieldValue)); diff --git a/ModernKeePass/ViewModels/GroupDetailVm.cs b/ModernKeePass/ViewModels/GroupDetailVm.cs index f719813..c57d3d3 100644 --- a/ModernKeePass/ViewModels/GroupDetailVm.cs +++ b/ModernKeePass/ViewModels/GroupDetailVm.cs @@ -20,6 +20,7 @@ using ModernKeePass.Application.Group.Commands.CreateEntry; using ModernKeePass.Application.Group.Commands.CreateGroup; using ModernKeePass.Application.Group.Commands.DeleteGroup; using ModernKeePass.Application.Group.Commands.MoveEntry; +using ModernKeePass.Application.Group.Commands.MoveGroup; using ModernKeePass.Application.Group.Commands.RemoveGroup; using ModernKeePass.Application.Group.Commands.SortEntries; using ModernKeePass.Application.Group.Commands.SortGroups; @@ -106,7 +107,8 @@ namespace ModernKeePass.ViewModels private GroupVm _parent; private bool _isEditMode; private EntryVm _reorderedEntry; - + private GroupVm _reorderedGroup; + public GroupDetailVm(IMediator mediator, IResourceProxy resource, INavigationService navigation, IDialogService dialog, INotificationService notification) { _mediator = mediator; @@ -139,6 +141,7 @@ namespace ModernKeePass.ViewModels Entries = new ObservableCollection(_group.Entries); Entries.CollectionChanged += Entries_CollectionChanged; Groups = new ObservableCollection(_group.SubGroups); + Groups.CollectionChanged += Groups_CollectionChanged; } public void GoToEntry(string entryId, bool isNew = false) @@ -213,6 +216,29 @@ namespace ModernKeePass.ViewModels SaveCommand.RaiseCanExecuteChanged(); } + private async void Groups_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Remove: + var oldIndex = e.OldStartingIndex; + _reorderedGroup = _group.SubGroups[oldIndex]; + break; + case NotifyCollectionChangedAction.Add: + if (_reorderedGroup == null) + { + var group = (GroupVm)e.NewItems[0]; + await _mediator.Send(new AddGroupCommand() { GroupId = group.Id, ParentGroupId = Id }); + } + else + { + await _mediator.Send(new MoveGroupCommand { Group = _reorderedGroup, ParentGroup = _group, Index = e.NewStartingIndex }); + } + break; + } + SaveCommand.RaiseCanExecuteChanged(); + } + private async Task SortEntriesAsync() { await _mediator.Send(new SortEntriesCommand {Group = _group}); diff --git a/ModernKeePass/Views/EntryDetailPage.xaml b/ModernKeePass/Views/EntryDetailPage.xaml index bf41c8b..cd1cf3f 100644 --- a/ModernKeePass/Views/EntryDetailPage.xaml +++ b/ModernKeePass/Views/EntryDetailPage.xaml @@ -445,7 +445,6 @@ - @@ -496,10 +495,10 @@ ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}"> - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + @@ -62,7 +63,6 @@ - @@ -88,12 +88,11 @@ IsSynchronizedWithCurrentItem="False" BorderBrush="{StaticResource ListViewItemSelectedBackgroundThemeBrush}" AllowDrop="True" - CanReorderItems="True" - CanDragItems="True" - DragItemsStarting="GridView_DragItemsStarting"> + CanReorderItems="{Binding IsEditMode}" + CanDragItems="{Binding IsEditMode}"> - + @@ -183,6 +182,8 @@ + + @@ -196,24 +197,23 @@ Style="{StaticResource NoBorderButtonStyle}"> - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - diff --git a/ModernKeePass/Views/GroupDetailPage.xaml.cs b/ModernKeePass/Views/GroupDetailPage.xaml.cs index a8ed4ba..f2fb235 100644 --- a/ModernKeePass/Views/GroupDetailPage.xaml.cs +++ b/ModernKeePass/Views/GroupDetailPage.xaml.cs @@ -1,5 +1,4 @@ -using Windows.ApplicationModel.DataTransfer; -using Windows.UI.Xaml; +using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; using ModernKeePass.Application.Entry.Models; @@ -74,12 +73,6 @@ namespace ModernKeePass.Views e.DestinationItem.Item = e.SourceItem.Item; } } - - private void GridView_DragItemsStarting(object sender, DragItemsStartingEventArgs e) - { - e.Cancel = !Model.IsEditMode; - e.Data.RequestedOperation = DataPackageOperation.Move; - } private void GroupDetailPage_OnSizeChanged(object sender, SizeChangedEventArgs e) { diff --git a/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml b/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml index 0f05d91..2993bbe 100644 --- a/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml +++ b/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml @@ -12,6 +12,7 @@ mc:Ignorable="d"> + @@ -79,6 +80,9 @@ + diff --git a/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml.cs b/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml.cs index 22d87e2..8c242ff 100644 --- a/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml.cs +++ b/ModernKeePass/Views/UserControls/HamburgerMenuUserControl.xaml.cs @@ -110,6 +110,18 @@ namespace ModernKeePass.Views.UserControls typeof(bool), typeof(HamburgerMenuUserControl), new PropertyMetadata(false, (o, args) => { })); + + public bool CanDragItems + { + get { return (bool)GetValue(CanDragItemsProperty); } + set { SetValue(CanDragItemsProperty, value); } + } + public static readonly DependencyProperty CanDragItemsProperty = + DependencyProperty.Register( + nameof(CanDragItems), + typeof(bool), + typeof(HamburgerMenuUserControl), + new PropertyMetadata(false, (o, args) => { })); public ICommand ActionButtonCommand { diff --git a/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml b/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml index 21722f1..f00cae7 100644 --- a/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml +++ b/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml @@ -150,7 +150,6 @@ - diff --git a/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs b/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs index 9a37d07..06f75c6 100644 --- a/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs +++ b/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs @@ -169,8 +169,7 @@ namespace ModernKeePass.Views.UserControls private void OverflowFlyout_OnOpening(object sender, object e) { EditFlyout.IsChecked = IsEditButtonChecked; - - MoveFlyout.Visibility = MoveButtonVisibility; + RestoreFlyout.Visibility = RestoreButtonVisibility; SortEntriesFlyout.Visibility = SortButtonVisibility; SortGroupsFlyout.Visibility = SortButtonVisibility; @@ -196,7 +195,7 @@ namespace ModernKeePass.Views.UserControls private void GroupSearchBox_OnSuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args) { - var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appdata://Assets/ModernKeePass-SmallLogo.scale-80.png")); + var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appdata:/Assets/ModernKeePass-SmallLogo.scale-80.png")); var groups = Model.Groups.Where(g => g.Title.IndexOf(args.QueryText, StringComparison.OrdinalIgnoreCase) >= 0).Take(5); foreach (var group in groups) { @@ -218,7 +217,7 @@ namespace ModernKeePass.Views.UserControls private async void EntrySearchBox_OnSuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args) { - var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appdata://Assets/ModernKeePass-SmallLogo.scale-80.png")); + var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appdata:/Assets/ModernKeePass-SmallLogo.scale-80.png")); var results = (await Model.Search(args.QueryText)).Take(5); foreach (var result in results) { diff --git a/ModernKeePass/Win81App.csproj b/ModernKeePass/Win81App.csproj index 7410c03..ba6de60 100644 --- a/ModernKeePass/Win81App.csproj +++ b/ModernKeePass/Win81App.csproj @@ -372,10 +372,6 @@ ..\packages\HockeySDK.WINRT.4.1.6\lib\portable-win81\Microsoft.HockeyApp.Kit.dll True - - ..\packages\Microsoft.Toolkit.Uwp.Notifications.2.0.0\lib\dotnet\Microsoft.Toolkit.Uwp.Notifications.dll - True - ..\packages\ModernKeePassLib.2.44.3\lib\netstandard1.2\ModernKeePassLib.dll True diff --git a/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt b/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt index b58f037..37a923b 100644 --- a/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt +++ b/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt @@ -1,2 +1,4 @@ Support for additional fields -Support for attachments \ No newline at end of file +Support for attachments +Ability to manually reorder groups +Design changes \ No newline at end of file diff --git a/ModernKeePass/appMetadata/fr-fr/baselisting/releaseNotes.txt b/ModernKeePass/appMetadata/fr-fr/baselisting/releaseNotes.txt index 2e7aba2..ab65482 100644 --- a/ModernKeePass/appMetadata/fr-fr/baselisting/releaseNotes.txt +++ b/ModernKeePass/appMetadata/fr-fr/baselisting/releaseNotes.txt @@ -1,2 +1,4 @@ Ajout des champs additionnels -Ajout des pièces-jointes \ No newline at end of file +Ajout des pièces-jointes +Possibilite de reorganiser les groupes manuellement +Quelques changements de design \ No newline at end of file diff --git a/ModernKeePass/packages.config b/ModernKeePass/packages.config index 9f9ec11..82c56c4 100644 --- a/ModernKeePass/packages.config +++ b/ModernKeePass/packages.config @@ -14,7 +14,6 @@ - diff --git a/WinAppCommon/ViewModels/Items/FieldVm.cs b/WinAppCommon/ViewModels/Items/FieldVm.cs index 4fde47d..858c885 100644 --- a/WinAppCommon/ViewModels/Items/FieldVm.cs +++ b/WinAppCommon/ViewModels/Items/FieldVm.cs @@ -27,7 +27,7 @@ namespace ModernKeePass.ViewModels.ListItems Set(nameof(Value), ref _value, value); } } - + public FieldVm(string fieldName, string fieldValue) { _name = fieldName;