add "Add to group" context menu action

This commit is contained in:
2026-05-07 21:11:19 +03:00
parent cc64f55d93
commit 1bde43cc24
3 changed files with 81 additions and 1 deletions

View File

@@ -126,6 +126,23 @@ public class UnlockedRepositoryViewModel : ViewModelBase
OnPropertyChanged(nameof(Passwords));
}
public bool AddEntryToGroup(PassStoreEntry entry, PassStoreEntryGroup targetGroup)
{
PassStoreEntryPassword? pwd = FollowLinkIfNeeded(entry);
if (pwd == null) return false;
foreach (var bl in pwd.Backlinks)
{
if (bl is PassStoreEntryLink lnk && lnk.Parent == targetGroup)
return false;
}
passStore.AddEntry(targetGroup, new PassStoreEntryLink(Guid.NewGuid(), DateTime.Now, DateTime.Now, pwd.Id, pwd));
HasUnsavedChanges = true;
OnPropertyChanged(nameof(Passwords));
return true;
}
public void UpdateEntry(PassStoreEntryPassword updatedEntry)
{
passStore.UpdateEntry(null, updatedEntry.Id, updatedEntry);

View File

@@ -154,10 +154,11 @@
</TextBlock>
</StackPanel>
<Border.ContextMenu>
<ContextMenu>
<ContextMenu Opened="EntryContextMenu_Opening">
<MenuItem Name="entryCtxMenuCopyUsername" Header="Copy username" Click="EntryContextMenuItem_Click"/>
<MenuItem Name="entryCtxMenuCopyPassword" Header="Copy password" Click="EntryContextMenuItem_Click"/>
<MenuItem Name="entryCtxMenuEdit" Header="Edit" Click="EntryContextMenuItem_Click"/>
<MenuItem Name="entryCtxMenuAddToGroup" Header="Add to group" />
<MenuItem Name="entryCtxMenuDelete" Header="Delete" Click="EntryContextMenuItem_Click"/>
</ContextMenu>
</Border.ContextMenu>

View File

@@ -1,4 +1,5 @@
using System;
using System.Linq;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
@@ -14,6 +15,7 @@ public partial class RepositoryWindow : Window
{
private bool allowClose;
private bool closeConfirmationShown;
private PassStoreEntry? _contextMenuEntry;
public RepositoryWindow(RepositoryWindowViewModel model)
{
@@ -223,6 +225,66 @@ public partial class RepositoryWindow : Window
}
}
private void EntryContextMenu_Opening(object? sender, RoutedEventArgs args)
{
if (sender is not ContextMenu contextMenu || DataContext is not RepositoryWindowViewModel vm ||
vm.CurrentPage is not UnlockedRepositoryViewModel pageVm)
return;
_contextMenuEntry = null;
if (contextMenu.Parent?.Parent is Border border && border.DataContext is PassStoreEntry entry)
{
_contextMenuEntry = entry;
}
var addToGroupItem = contextMenu.Items
.OfType<MenuItem>()
.FirstOrDefault(m => m.Name == "entryCtxMenuAddToGroup");
if (addToGroupItem == null)
return;
addToGroupItem.Items.Clear();
var nonDefaultGroups = pageVm.PasswordGroups
.Where(g => g.GroupType != FileFormatConstants.GROUP_TYPE_DEFAULT)
.ToList();
EventHandler<RoutedEventArgs> onSubmenuClick = (sender, args) => AddToGroup_Click(sender, args, _contextMenuEntry!);
foreach (var group in nonDefaultGroups)
{
var menuItem = new MenuItem
{
Header = group.DisplayName,
Tag = group
};
menuItem.Click += onSubmenuClick;
addToGroupItem.Items.Add(menuItem);
}
}
private void AddToGroup_Click(object? sender, RoutedEventArgs args, PassStoreEntry entry)
{
if (sender is not MenuItem item || item.Tag is not PassStoreEntryGroup targetGroup)
return;
if (entry == null)
return;
if (DataContext is not RepositoryWindowViewModel vm ||
vm.CurrentPage is not UnlockedRepositoryViewModel pageVm)
return;
var notificationHost = this.FindControlRecursive<ToastNotificationHost>("NotificationHost");
if (pageVm.AddEntryToGroup(entry, targetGroup))
notificationHost?.Show($"Added to {targetGroup.DisplayName}");
else
notificationHost?.Show($"This entry is already in {targetGroup.DisplayName}!");
_contextMenuEntry = null;
}
private async void EntryContextMenuItem_Click(object sender, RoutedEventArgs args)
{
if (args.Source is StyledElement s && s.DataContext is PassStoreEntry ent)