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}">
-
+
-
@@ -508,7 +507,7 @@
-
+
@@ -556,6 +555,8 @@
+
+
@@ -569,44 +570,41 @@
Style="{StaticResource NoBorderButtonStyle}">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -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;