Recycle bin restore function (actually implemented a move functionality, for later)

This commit is contained in:
2017-10-31 18:49:18 +01:00
committed by BONNEVILLE Geoffroy
parent d32f312d60
commit 7e642e3b73
16 changed files with 163 additions and 141 deletions

View File

@@ -20,7 +20,6 @@ namespace ModernKeePass
sealed partial class App sealed partial class App
{ {
public DatabaseHelper Database { get; set; } = new DatabaseHelper(); public DatabaseHelper Database { get; set; } = new DatabaseHelper();
public Dictionary<string, IPwEntity> PendingDeleteEntities = new Dictionary<string, IPwEntity>();
/// <summary> /// <summary>
/// Initializes the singleton application object. This is the first line of authored code /// Initializes the singleton application object. This is the first line of authored code
@@ -89,11 +88,11 @@ namespace ModernKeePass
// parameter // parameter
rootFrame.Navigate(typeof(Pages.MainPage), lauchActivatedEventArgs.Arguments); rootFrame.Navigate(typeof(Pages.MainPage), lauchActivatedEventArgs.Arguments);
} }
else /*else
{ {
// App is "launched" via the Toast Activation event // App is "launched" via the Toast Activation event
UndoEntityDelete(lauchActivatedEventArgs.Arguments); UndoEntityDelete(lauchActivatedEventArgs.Arguments);
} }*/
} }
// This is only available on Windows 10... // This is only available on Windows 10...
/*else if (e is ToastNotificationActivatedEventArgs) /*else if (e is ToastNotificationActivatedEventArgs)
@@ -145,14 +144,5 @@ namespace ModernKeePass
Window.Current.Activate(); Window.Current.Activate();
} }
#endregion #endregion
private void UndoEntityDelete(string arguments)
{
if (arguments == null) return;
var args = JsonObject.Parse(arguments);
var entity = PendingDeleteEntities[args["entityId"].GetString()];
PendingDeleteEntities.Remove(args["entityId"].GetString());
entity.UndoDelete();
}
} }
} }

View File

@@ -1,5 +1,6 @@
using System; using System;
using Windows.Storage; using Windows.Storage;
using Windows.UI.Xaml;
using ModernKeePass.ViewModels; using ModernKeePass.ViewModels;
using ModernKeePassLib; using ModernKeePassLib;
using ModernKeePassLib.Interfaces; using ModernKeePassLib.Interfaces;
@@ -104,8 +105,15 @@ namespace ModernKeePass.Common
/// </summary> /// </summary>
public void Save() public void Save()
{ {
if (_pwDatabase != null && _pwDatabase.IsOpen) if (_pwDatabase == null || !_pwDatabase.IsOpen) return;
_pwDatabase.Save(new NullStatusLogger()); // Commit real changes to DB
/*var app = (App) Application.Current;
foreach (var entity in app.PendingDeleteEntities)
{
entity.Value.CommitDelete();
}
app.PendingDeleteEntities.Clear();*/
_pwDatabase.Save(new NullStatusLogger());
} }
/// <summary> /// <summary>

View File

@@ -1,25 +1,17 @@
using System; using System;
using Windows.UI.Popups; using Windows.UI.Popups;
using Windows.UI.Xaml.Controls;
using ModernKeePass.Interfaces;
using ModernKeePass.ViewModels;
namespace ModernKeePass.Common namespace ModernKeePass.Common
{ {
public static class MessageDialogHelper public static class MessageDialogHelper
{ {
public static async void ShowDeleteConfirmationDialog(string text, IPwEntity model, Frame backFrame) public static async void ShowDeleteConfirmationDialog(string actionText, string contentText, UICommandInvokedHandler action)
{ {
// Create the message dialog and set its content // Create the message dialog and set its content
var messageDialog = new MessageDialog(text); var messageDialog = new MessageDialog(contentText);
// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers // Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
messageDialog.Commands.Add(new UICommand("Delete", delete => messageDialog.Commands.Add(new UICommand(actionText, action));
{
ToastNotificationHelper.ShowUndoToast(model);
model.MarkForDelete();
if (backFrame.CanGoBack) backFrame.GoBack();
}));
messageDialog.Commands.Add(new UICommand("Cancel")); messageDialog.Commands.Add(new UICommand("Cancel"));
// Set the command that will be invoked by default // Set the command that will be invoked by default

View File

@@ -10,67 +10,14 @@ namespace ModernKeePass.Common
{ {
public static class ToastNotificationHelper public static class ToastNotificationHelper
{ {
public static /*async*/ void ShowUndoToast(IPwEntity entity) public static void ShowMovedToast(IPwEntity entity, string action, string text)
{ {
// This is for Windows 10 var app = (App)Application.Current;
// Construct the visuals of the toast
/*var visual = new ToastVisual
{
BindingGeneric = new ToastBindingGeneric
{
Children =
{
new AdaptiveText
{
Text = $"{entityType} {entity.Name} deleted."
}
}
}
};
// Construct the actions for the toast (inputs and buttons)
var actions = new ToastActionsCustom
{
Buttons =
{
new ToastButton("Undo", new QueryString
{
{ "action", "undo" },
{ "entityType", entityType },
{ "entityId", entity.Id }
}.ToString())
}
};
// Now we can construct the final toast content
var toastContent = new ToastContent
{
Visual = visual,
Actions = actions,
// Arguments when the user taps body of toast
Launch = new QueryString()
{
{ "action", "undo" },
{ "entityType", "group" },
{ "entityId", entity.Id }
}.ToString()
};
// And create the toast notification
var toastXml = new XmlDocument();
toastXml.LoadXml(toastContent.GetContent());
var toast = new ToastNotification(toastXml) {ExpirationTime = DateTime.Now.AddSeconds(5)};
toast.Dismissed += Toast_Dismissed;
*/
var entityType = entity is GroupVm ? "Group" : "Entry"; var entityType = entity is GroupVm ? "Group" : "Entry";
var notificationXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02); var notificationXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
var toastElements = notificationXml.GetElementsByTagName("text"); var toastElements = notificationXml.GetElementsByTagName("text");
toastElements[0].AppendChild(notificationXml.CreateTextNode($"{entityType} {entity.Name} deleted")); toastElements[0].AppendChild(notificationXml.CreateTextNode($"{action} {entityType} {entity.Name}"));
toastElements[1].AppendChild(notificationXml.CreateTextNode("Click me to undo")); toastElements[1].AppendChild(notificationXml.CreateTextNode(text));
var toastNode = notificationXml.SelectSingleNode("/toast"); var toastNode = notificationXml.SelectSingleNode("/toast");
var launch = new JsonObject var launch = new JsonObject
@@ -84,19 +31,8 @@ namespace ModernKeePass.Common
{ {
ExpirationTime = DateTime.Now.AddSeconds(5) ExpirationTime = DateTime.Now.AddSeconds(5)
}; };
toast.Dismissed += Toast_Dismissed;
ToastNotificationManager.CreateToastNotifier().Show(toast); ToastNotificationManager.CreateToastNotifier().Show(toast);
} }
private static void Toast_Dismissed(ToastNotification sender, ToastDismissedEventArgs args)
{
var toastNode = sender.Content.SelectSingleNode("/toast");
if (toastNode == null) return;
var launchArguments = JsonObject.Parse(((XmlElement)toastNode).GetAttribute("launch"));
var app = (App)Application.Current;
var entity = app.PendingDeleteEntities[launchArguments["entityId"].GetString()];
app.PendingDeleteEntities.Remove(launchArguments["entityId"].GetString());
entity.CommitDelete();
}
} }
} }

View File

@@ -0,0 +1,18 @@
using System;
using Windows.UI.Xaml.Data;
namespace ModernKeePass.Converters
{
public class NullToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return value != null;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
}

View File

@@ -6,12 +6,18 @@ namespace ModernKeePass.Interfaces
public interface IPwEntity public interface IPwEntity
{ {
GroupVm ParentGroup { get; } GroupVm ParentGroup { get; }
GroupVm PreviousGroup { get; }
Symbol IconSymbol { get; } Symbol IconSymbol { get; }
string Id { get; } string Id { get; }
string Name { get; set; } string Name { get; set; }
string Path { get; } string Path { get; }
bool IsEditMode { get; } bool IsEditMode { get; }
/// <summary>
/// Move a entity to the destination group
/// </summary>
/// <param name="destination">The destination to move the entity to</param>
void Move(GroupVm destination);
/// <summary> /// <summary>
/// Delete from Model /// Delete from Model
/// </summary> /// </summary>

View File

@@ -120,6 +120,7 @@
<Compile Include="Common\RelayCommand.cs" /> <Compile Include="Common\RelayCommand.cs" />
<Compile Include="Common\SuspensionManager.cs" /> <Compile Include="Common\SuspensionManager.cs" />
<Compile Include="Common\ToastNotificationHelper.cs" /> <Compile Include="Common\ToastNotificationHelper.cs" />
<Compile Include="Converters\NullToBooleanConverter.cs" />
<Compile Include="Interfaces\IHasSelectableObject.cs" /> <Compile Include="Interfaces\IHasSelectableObject.cs" />
<Compile Include="Interfaces\ISelectableModel.cs" /> <Compile Include="Interfaces\ISelectableModel.cs" />
<Compile Include="Pages\BasePages\LayoutAwarePageBase.cs" /> <Compile Include="Pages\BasePages\LayoutAwarePageBase.cs" />

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest"> <Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest">
<Identity Name="wismna.ModernKeePass" Publisher="CN=0719A91A-C322-4EE0-A257-E60733EECF06" Version="1.5.0.25" /> <Identity Name="wismna.ModernKeePass" Publisher="CN=0719A91A-C322-4EE0-A257-E60733EECF06" Version="1.6.0.25" />
<Properties> <Properties>
<DisplayName>ModernKeePass</DisplayName> <DisplayName>ModernKeePass</DisplayName>
<PublisherDisplayName>wismna</PublisherDisplayName> <PublisherDisplayName>wismna</PublisherDisplayName>

View File

@@ -17,6 +17,7 @@
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/> <converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
<converters:ProgressBarLegalValuesConverter x:Key="ProgressBarLegalValuesConverter"/> <converters:ProgressBarLegalValuesConverter x:Key="ProgressBarLegalValuesConverter"/>
<converters:DoubleToForegroungBrushComplexityConverter x:Key="DoubleToForegroungBrushComplexityConverter"/> <converters:DoubleToForegroungBrushComplexityConverter x:Key="DoubleToForegroungBrushComplexityConverter"/>
<converters:NullToBooleanConverter x:Key="NullToBooleanConverter"/>
<Style TargetType="PasswordBox" x:Name="PasswordBoxWithButtonStyle"> <Style TargetType="PasswordBox" x:Name="PasswordBoxWithButtonStyle">
<Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" /> <Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
<Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" /> <Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
@@ -396,6 +397,13 @@
</core:EventTriggerBehavior> </core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
</AppBarToggleButton> </AppBarToggleButton>
<AppBarButton Icon="Undo" Label="Restore" Visibility="{Binding ParentGroup.IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}" IsEnabled="{Binding PreviousGroup, Converter={StaticResource NullToBooleanConverter}}" Click="RestoreButton_Click">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<core:CallMethodAction MethodName="UndoDelete" TargetObject="{Binding}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</AppBarButton>
<AppBarButton Icon="Delete" Label="Delete" Click="DeleteButton_Click" /> <AppBarButton Icon="Delete" Label="Delete" Click="DeleteButton_Click" />
</CommandBar> </CommandBar>
</Page.BottomAppBar> </Page.BottomAppBar>

View File

@@ -1,7 +1,4 @@
using System; using System;
using System.Threading.Tasks;
using Windows.UI.Core;
using Windows.UI.Popups;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation; using Windows.UI.Xaml.Navigation;
@@ -18,21 +15,19 @@ namespace ModernKeePass.Pages
/// </summary> /// </summary>
public sealed partial class EntryDetailPage public sealed partial class EntryDetailPage
{ {
private NavigationHelper navigationHelper;
public EntryVm Model => (EntryVm) DataContext; public EntryVm Model => (EntryVm) DataContext;
/// <summary> /// <summary>
/// NavigationHelper est utilisé sur chaque page pour faciliter la navigation et /// NavigationHelper est utilisé sur chaque page pour faciliter la navigation et
/// gestion de la durée de vie des processus /// gestion de la durée de vie des processus
/// </summary> /// </summary>
public NavigationHelper NavigationHelper => navigationHelper; public NavigationHelper NavigationHelper { get; }
public EntryDetailPage() public EntryDetailPage()
{ {
InitializeComponent(); InitializeComponent();
navigationHelper = new NavigationHelper(this); NavigationHelper = new NavigationHelper(this);
navigationHelper.LoadState += navigationHelper_LoadState; NavigationHelper.LoadState += navigationHelper_LoadState;
} }
/// <summary> /// <summary>
@@ -61,25 +56,37 @@ namespace ModernKeePass.Pages
protected override void OnNavigatedTo(NavigationEventArgs e) protected override void OnNavigatedTo(NavigationEventArgs e)
{ {
navigationHelper.OnNavigatedTo(e); NavigationHelper.OnNavigatedTo(e);
if (!(e.Parameter is EntryVm)) return; if (!(e.Parameter is EntryVm)) return;
DataContext = (EntryVm)e.Parameter; DataContext = (EntryVm)e.Parameter;
} }
protected override void OnNavigatedFrom(NavigationEventArgs e) protected override void OnNavigatedFrom(NavigationEventArgs e)
{ {
navigationHelper.OnNavigatedFrom(e); NavigationHelper.OnNavigatedFrom(e);
} }
#endregion #endregion
private void DeleteButton_Click(object sender, RoutedEventArgs e) private void DeleteButton_Click(object sender, RoutedEventArgs e)
{ {
var app = (App)Application.Current; var isRecycleBinEnabled = ((App)Application.Current).Database.RecycleBinEnabled && !Model.ParentGroup.IsSelected;
var message = app.Database.RecycleBinEnabled var message = isRecycleBinEnabled
? "Are you sure you want to send this entry to the recycle bin?" ? "Are you sure you want to send this entry to the recycle bin?"
: "Are you sure you want to delete this entry?"; : "Are you sure you want to delete this entry?";
MessageDialogHelper.ShowDeleteConfirmationDialog(message, Model, Frame); var text = isRecycleBinEnabled ? "Item moved to the Recycle bin" : "Item permanently removed";
MessageDialogHelper.ShowDeleteConfirmationDialog("Delete", message, a =>
{
ToastNotificationHelper.ShowMovedToast(Model, "Deleting", text);
Model.MarkForDelete();
if (Frame.CanGoBack) Frame.GoBack();
});
}
private void RestoreButton_Click(object sender, RoutedEventArgs e)
{
ToastNotificationHelper.ShowMovedToast(Model, "Restored", "Item returned to its original group");
if (Frame.CanGoBack) Frame.GoBack();
} }
private async void UrlButton_Click(object sender, RoutedEventArgs e) private async void UrlButton_Click(object sender, RoutedEventArgs e)
@@ -94,5 +101,6 @@ namespace ModernKeePass.Pages
// TODO: Show some error // TODO: Show some error
} }
} }
} }
} }

View File

@@ -17,6 +17,8 @@
<SolidColorBrush x:Key="SystemColor" Color="{StaticResource SystemColorButtonFaceColor}" /> <SolidColorBrush x:Key="SystemColor" Color="{StaticResource SystemColorButtonFaceColor}" />
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/> <converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
<converters:BooleanToFontStyleConverter x:Key="BooleanToFontStyleConverter"/> <converters:BooleanToFontStyleConverter x:Key="BooleanToFontStyleConverter"/>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<converters:NullToBooleanConverter x:Key="NullToBooleanConverter"/>
</Page.Resources> </Page.Resources>
<Page.DataContext> <Page.DataContext>
<viewModels:GroupVm /> <viewModels:GroupVm />
@@ -47,6 +49,13 @@
</core:EventTriggerBehavior> </core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
</AppBarToggleButton> </AppBarToggleButton>
<AppBarButton Icon="Undo" Label="Restore" Visibility="{Binding ShowRestore, Converter={StaticResource BooleanToVisibilityConverter}}" IsEnabled="{Binding PreviousGroup, Converter={StaticResource NullToBooleanConverter}}" Click="RestoreButton_Click">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<core:CallMethodAction MethodName="UndoDelete" TargetObject="{Binding}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</AppBarButton>
<AppBarButton Icon="Delete" Label="Delete" IsEnabled="{Binding IsNotRoot}" Click="DeleteButton_Click" /> <AppBarButton Icon="Delete" Label="Delete" IsEnabled="{Binding IsNotRoot}" Click="DeleteButton_Click" />
</CommandBar> </CommandBar>
</Page.BottomAppBar> </Page.BottomAppBar>

View File

@@ -72,8 +72,7 @@ namespace ModernKeePass.Pages
} }
#endregion #endregion
#region Event Handlers #region Event Handlers
private void groups_SelectionChanged(object sender, SelectionChangedEventArgs e) private void groups_SelectionChanged(object sender, SelectionChangedEventArgs e)
@@ -112,13 +111,25 @@ namespace ModernKeePass.Pages
private void DeleteButton_Click(object sender, RoutedEventArgs e) private void DeleteButton_Click(object sender, RoutedEventArgs e)
{ {
var app = (App) Application.Current; var isRecycleBinEnabled = ((App)Application.Current).Database.RecycleBinEnabled && !Model.IsSelected && !Model.ParentGroup.IsSelected;
var message = app.Database.RecycleBinEnabled var message = isRecycleBinEnabled
? "Are you sure you want to send the whole group and all its entries to the recycle bin?" ? "Are you sure you want to send the whole group and all its entries to the recycle bin?"
: "Are you sure you want to delete the whole group and all its entries?"; : "Are you sure you want to delete the whole group and all its entries?";
MessageDialogHelper.ShowDeleteConfirmationDialog(message, Model, Frame); var text = isRecycleBinEnabled ? "Item moved to the Recycle bin" : "Item permanently removed";
MessageDialogHelper.ShowDeleteConfirmationDialog("Delete", message, a =>
{
ToastNotificationHelper.ShowMovedToast(Model, "Deleting", text);
Model.MarkForDelete();
if (Frame.CanGoBack) Frame.GoBack();
});
} }
private void RestoreButton_Click(object sender, RoutedEventArgs e)
{
ToastNotificationHelper.ShowMovedToast(Model, "Restored", "Item returned to its original group");
if (Frame.CanGoBack) Frame.GoBack();
}
private void SemanticZoom_ViewChangeStarted(object sender, SemanticZoomViewChangedEventArgs e) private void SemanticZoom_ViewChangeStarted(object sender, SemanticZoomViewChangedEventArgs e)
{ {
// We need to synchronize the two lists (zoomed-in and zoomed-out) because the source is different // We need to synchronize the two lists (zoomed-in and zoomed-out) because the source is different

View File

@@ -24,6 +24,6 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.5.0.0")] [assembly: AssemblyVersion("1.6.0.0")]
[assembly: AssemblyFileVersion("1.5.0.0")] [assembly: AssemblyFileVersion("1.6.0.0")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]

View File

@@ -14,7 +14,9 @@ namespace ModernKeePass.ViewModels
{ {
public class EntryVm : INotifyPropertyChanged, IPwEntity public class EntryVm : INotifyPropertyChanged, IPwEntity
{ {
public GroupVm ParentGroup { get; } public GroupVm ParentGroup { get; private set; }
public GroupVm PreviousGroup { get; private set; }
public System.Drawing.Color? BackgroundColor => _pwEntry?.BackgroundColor; public System.Drawing.Color? BackgroundColor => _pwEntry?.BackgroundColor;
public System.Drawing.Color? ForegroundColor => _pwEntry?.ForegroundColor; public System.Drawing.Color? ForegroundColor => _pwEntry?.ForegroundColor;
@@ -194,22 +196,34 @@ namespace ModernKeePass.ViewModels
public void MarkForDelete() public void MarkForDelete()
{ {
_app.PendingDeleteEntities.Add(Id, this); Move(_app.Database.RecycleBinEnabled && !ParentGroup.IsSelected ? _app.Database.RecycleBin : null);
ParentGroup.Entries.Remove(this);
if (_app.Database.RecycleBinEnabled && !ParentGroup.IsSelected) _app.Database.RecycleBin.Entries.Add(this);
}
public void CommitDelete()
{
_pwEntry.ParentGroup.Entries.Remove(_pwEntry);
if (_app.Database.RecycleBinEnabled && !ParentGroup.IsSelected) _app.Database.RecycleBin.AddPwEntry(_pwEntry);
else _app.Database.AddDeletedItem(IdUuid);
} }
public void UndoDelete() public void UndoDelete()
{ {
Move(PreviousGroup);
}
public void Move(GroupVm destination)
{
PreviousGroup = ParentGroup;
PreviousGroup.Entries.Remove(this);
PreviousGroup.RemovePwEntry(_pwEntry);
if (destination == null)
{
_app.Database.AddDeletedItem(IdUuid);
return;
}
ParentGroup = destination;
ParentGroup.Entries.Add(this); ParentGroup.Entries.Add(this);
if (_app.Database.RecycleBinEnabled && !ParentGroup.IsSelected) _app.Database.RecycleBin.Entries.Remove(this); ParentGroup.AddPwEntry(_pwEntry);
}
public void CommitDelete()
{
_pwEntry.ParentGroup.Entries.Remove(_pwEntry);
if (_app.Database.RecycleBinEnabled && !PreviousGroup.IsSelected) _app.Database.RecycleBin.AddPwEntry(_pwEntry);
else _app.Database.AddDeletedItem(IdUuid);
} }
public void Save() public void Save()

View File

@@ -13,7 +13,8 @@ namespace ModernKeePass.ViewModels
{ {
public class GroupVm : NotifyPropertyChangedBase, IPwEntity, ISelectableModel public class GroupVm : NotifyPropertyChangedBase, IPwEntity, ISelectableModel
{ {
public GroupVm ParentGroup { get; } public GroupVm ParentGroup { get; private set; }
public GroupVm PreviousGroup { get; private set; }
public ObservableCollection<EntryVm> Entries { get; set; } = new ObservableCollection<EntryVm>(); public ObservableCollection<EntryVm> Entries { get; set; } = new ObservableCollection<EntryVm>();
public ObservableCollection<GroupVm> Groups { get; set; } = new ObservableCollection<GroupVm>(); public ObservableCollection<GroupVm> Groups { get; set; } = new ObservableCollection<GroupVm>();
@@ -24,6 +25,8 @@ namespace ModernKeePass.ViewModels
public PwUuid IdUuid => _pwGroup?.Uuid; public PwUuid IdUuid => _pwGroup?.Uuid;
public string Id => IdUuid?.ToHexString(); public string Id => IdUuid?.ToHexString();
public bool IsNotRoot => ParentGroup != null; public bool IsNotRoot => ParentGroup != null;
public bool ShowRestore => IsNotRoot && ParentGroup.IsSelected;
/// <summary> /// <summary>
/// Is the Group the database Recycle Bin? /// Is the Group the database Recycle Bin?
/// </summary> /// </summary>
@@ -122,27 +125,45 @@ namespace ModernKeePass.ViewModels
{ {
_pwGroup.AddEntry(entry, true); _pwGroup.AddEntry(entry, true);
} }
public void RemovePwEntry(PwEntry entry)
{
_pwGroup.Entries.Remove(entry);
}
public void MarkForDelete() public void MarkForDelete()
{ {
_app.PendingDeleteEntities.Add(Id, this); Move(_app.Database.RecycleBinEnabled && !IsSelected ? _app.Database.RecycleBin : null);
ParentGroup.Groups.Remove(this); }
if (_app.Database.RecycleBinEnabled && !IsSelected) _app.Database.RecycleBin.Groups.Add(this);
public void UndoDelete()
{
Move(PreviousGroup);
}
public void Move(GroupVm destination)
{
PreviousGroup = ParentGroup;
PreviousGroup.Groups.Remove(this);
PreviousGroup._pwGroup.Groups.Remove(_pwGroup);
if (destination == null)
{
_app.Database.AddDeletedItem(IdUuid);
return;
}
ParentGroup = destination;
ParentGroup.Groups.Add(this);
ParentGroup._pwGroup.AddGroup(_pwGroup, true);
} }
public void CommitDelete() public void CommitDelete()
{ {
_pwGroup.ParentGroup.Groups.Remove(_pwGroup); _pwGroup.ParentGroup.Groups.Remove(_pwGroup);
if (_app.Database.RecycleBinEnabled && !IsSelected) _app.Database.RecycleBin._pwGroup.AddGroup(_pwGroup, true); if (_app.Database.RecycleBinEnabled && !PreviousGroup.IsSelected) _app.Database.RecycleBin._pwGroup.AddGroup(_pwGroup, true);
else _app.Database.AddDeletedItem(IdUuid); else _app.Database.AddDeletedItem(IdUuid);
} }
public void UndoDelete()
{
ParentGroup.Groups.Add(this);
if (_app.Database.RecycleBinEnabled && !IsSelected) _app.Database.RecycleBin.Groups.Remove(this);
}
public void Save() public void Save()
{ {
_app.Database.Save(); _app.Database.Save();

View File

@@ -4,7 +4,7 @@
{ {
public static bool IsRequired(int i) public static bool IsRequired(int i)
{ {
throw new System.NotImplementedException(); return false;
} }
} }
} }