Added dirty behavior

Removed restore action (-> Move action wip)
Added additional check on DB size before auto saving
Code cleanup
This commit is contained in:
Geoffroy BONNEVILLE
2020-04-14 13:44:07 +02:00
parent d972b6cb5a
commit a2eba91a3b
34 changed files with 236 additions and 190 deletions

View File

@@ -211,16 +211,17 @@ namespace ModernKeePass
var deferral = e.SuspendingOperation.GetDeferral();
try
{
if (_settings.GetSetting("SaveSuspend", true))
var database = await _mediator.Send(new GetDatabaseQuery());
if (database.IsOpen)
{
await _mediator.Send(new SaveDatabaseCommand()).ConfigureAwait(false);
}
if (database.Size < Constants.File.OneMegaByte && database.IsDirty &&
_settings.GetSetting(Constants.Settings.SaveSuspend, true))
{
await _mediator.Send(new SaveDatabaseCommand()).ConfigureAwait(false);
}
await _mediator.Send(new CloseDatabaseCommand()).ConfigureAwait(false);
}
catch (DatabaseClosedException)
{
// Do nothing on purpose
await _mediator.Send(new CloseDatabaseCommand()).ConfigureAwait(false);
}
}
catch (Exception exception)
{

View File

@@ -0,0 +1,15 @@
namespace ModernKeePass.Common
{
public class Constants
{
public class File
{
public static int OneMegaByte => 1048576;
}
public class Settings
{
public static string SaveSuspend => nameof(SaveSuspend);
}
}
}

View File

@@ -19,10 +19,6 @@ namespace ModernKeePass.Interfaces
/// </summary>
ICommand SaveCommand { get; }
/// <summary>
/// Restore ViewModel
/// </summary>
ICommand UndoDeleteCommand { get; }
/// <summary>
/// Move a entity to the destination group
/// </summary>
/// <param name="destination">The destination to move the entity to</param>

View File

@@ -4,7 +4,9 @@
<!-- Common theme values -->
<x:Double x:Key="MenuSize">60</x:Double>
<x:Double x:Key="ExpandedMenuSize">300</x:Double>
<GridLength x:Key="MenuGridLength">60</GridLength>
<GridLength x:Key="ExpandedMenuGridLength">300</GridLength>
<!-- Only available for Windows 10 -->
<!--<SolidColorBrush x:Key="MainColor" Color="{ThemeResource SystemAccentColor}" />
<SolidColorBrush x:Key="TextColor" Color="{ThemeResource SystemColorHighlightTextColor}" />-->

View File

@@ -432,11 +432,11 @@
<data name="TopMenuMoreButton.Content" xml:space="preserve">
<value>More</value>
</data>
<data name="TopMenuRestoreButton.Content" xml:space="preserve">
<value>Restore</value>
<data name="TopMenuMoveButton.Content" xml:space="preserve">
<value>Move</value>
</data>
<data name="TopMenuRestoreFlyout.Text" xml:space="preserve">
<value>Restore</value>
<data name="TopMenuMoveFlyout.Text" xml:space="preserve">
<value>Move</value>
</data>
<data name="TopMenuSaveButton.Content" xml:space="preserve">
<value>Save</value>

View File

@@ -432,11 +432,11 @@
<data name="TopMenuMoreButton.Content" xml:space="preserve">
<value>Plus</value>
</data>
<data name="TopMenuRestoreButton.Content" xml:space="preserve">
<value>Restaurer</value>
<data name="TopMenuMoveButton.Content" xml:space="preserve">
<value>Déplacer</value>
</data>
<data name="TopMenuRestoreFlyout.Text" xml:space="preserve">
<value>Restaurer</value>
<data name="TopMenuMoveFlyout.Text" xml:space="preserve">
<value>Déplacer</value>
</data>
<data name="TopMenuSaveButton.Content" xml:space="preserve">
<value>Sauvegarder</value>

View File

@@ -20,14 +20,13 @@ using ModernKeePass.Application.Security.Commands.GeneratePassword;
using ModernKeePass.Application.Security.Queries.EstimatePasswordComplexity;
using ModernKeePass.Common;
using ModernKeePass.Domain.Enums;
using ModernKeePass.Domain.Interfaces;
using ModernKeePass.Interfaces;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Domain.AOP;
namespace ModernKeePass.ViewModels
{
public class EntryDetailVm : NotifyPropertyChangedBase, IVmEntity, ISelectableModel
public class EntryDetailVm : NotifyPropertyChangedBase, IVmEntity
{
public bool IsRevealPasswordEnabled => !string.IsNullOrEmpty(Password);
public bool HasExpired => HasExpirationDate && ExpiryDate < DateTime.Now;
@@ -65,7 +64,7 @@ namespace ModernKeePass.ViewModels
get { return _entry.Title; }
set
{
_mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(Title), FieldValue = value}).Wait();
SetFieldValue(nameof(Title), value).Wait();
_entry.Title = value;
}
}
@@ -81,7 +80,7 @@ namespace ModernKeePass.ViewModels
get { return _entry.Password; }
set
{
_mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(Password), FieldValue = value }).Wait();
SetFieldValue(nameof(Password), value).Wait();
_entry.Password = value;
OnPropertyChanged();
OnPropertyChanged(nameof(PasswordComplexityIndicator));
@@ -93,7 +92,7 @@ namespace ModernKeePass.ViewModels
get { return _entry.Url?.ToString(); }
set
{
_mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(Url), FieldValue = value }).Wait();
SetFieldValue(nameof(Url), value).Wait();
_entry.Url = new Uri(value);
}
}
@@ -103,7 +102,7 @@ namespace ModernKeePass.ViewModels
get { return _entry.Notes; }
set
{
_mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(Notes), FieldValue = value }).Wait();
SetFieldValue(nameof(Notes), value).Wait();
_entry.Notes = value;
}
}
@@ -117,7 +116,7 @@ namespace ModernKeePass.ViewModels
}
set
{
_mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(Icon), FieldValue = value }).Wait();
SetFieldValue(nameof(Icon), value).Wait();
_entry.Icon = (Icon)value;
}
}
@@ -128,7 +127,8 @@ namespace ModernKeePass.ViewModels
set
{
if (!HasExpirationDate) return;
_mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = "ExpirationDate", FieldValue = value.Date }).Wait();
SetFieldValue("ExpirationDate", value).Wait();
_entry.ExpirationDate = value.Date;
}
}
@@ -139,7 +139,8 @@ namespace ModernKeePass.ViewModels
set
{
if (!HasExpirationDate) return;
_mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = "ExpirationDate", FieldValue = ExpiryDate.Date.Add(value) }).Wait();
SetFieldValue("ExpirationDate", value).Wait();
_entry.ExpirationDate = _entry.ExpirationDate.Date.Add(value);
}
}
@@ -149,7 +150,7 @@ namespace ModernKeePass.ViewModels
get { return _entry.HasExpirationDate; }
set
{
_mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(HasExpirationDate), FieldValue = value }).Wait();
SetFieldValue(nameof(HasExpirationDate), value).Wait();
_entry.HasExpirationDate = value;
OnPropertyChanged();
}
@@ -162,7 +163,7 @@ namespace ModernKeePass.ViewModels
{
if (value != null)
{
_mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(BackgroundColor), FieldValue = value }).Wait();
SetFieldValue(nameof(BackgroundColor), value).Wait();
_entry.BackgroundColor = (Color)value;
}
}
@@ -175,12 +176,12 @@ namespace ModernKeePass.ViewModels
{
if (value != null)
{
_mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(ForegroundColor), FieldValue = value }).Wait();
SetFieldValue(nameof(ForegroundColor), value).Wait();
_entry.ForegroundColor = (Color)value;
}
}
}
public IEnumerable<EntryVm> History => _history;
public IEnumerable<EntryVm> History { get; }
public bool IsEditMode
{
@@ -200,16 +201,14 @@ namespace ModernKeePass.ViewModels
set { SetProperty(ref _isRevealPassword, value); }
}
public bool CanRestore => _entry.ParentGroupId == _database.RecycleBinId;
public ICommand SaveCommand { get; }
public ICommand GeneratePasswordCommand { get; }
public ICommand UndoDeleteCommand { get; }
public ICommand MoveCommand { get; }
private DatabaseVm Database => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
private readonly IMediator _mediator;
private readonly DatabaseVm _database;
private readonly GroupVm _parent;
private readonly IEnumerable<EntryVm> _history;
private EntryVm _entry;
private bool _isEditMode;
private bool _isRevealPassword;
@@ -224,17 +223,16 @@ namespace ModernKeePass.ViewModels
public EntryDetailVm(string entryId, IMediator mediator, bool isNewEntry = false)
{
_mediator = mediator;
_database = _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
_entry = _mediator.Send(new GetEntryQuery {Id = entryId}).GetAwaiter().GetResult();
_parent = _mediator.Send(new GetGroupQuery {Id = _entry.ParentGroupId}).GetAwaiter().GetResult();
_history = _entry.History;
History = _entry.History;
_isEditMode = isNewEntry;
if (isNewEntry) GeneratePassword().GetAwaiter().GetResult();
IsSelected = true;
SaveCommand = new RelayCommand(async () => await _mediator.Send(new SaveDatabaseCommand()));
SaveCommand = new RelayCommand(async () => await SaveChanges(), () => Database.IsDirty);
GeneratePasswordCommand = new RelayCommand(async () => await GeneratePassword());
UndoDeleteCommand = new RelayCommand(async () => await Move(_parent), () => _parent != null);
MoveCommand = new RelayCommand(async () => await Move(_parent), () => _parent != null);
}
public async Task GeneratePassword()
@@ -269,6 +267,7 @@ namespace ModernKeePass.ViewModels
public async Task SetFieldValue(string fieldName, object value)
{
await _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = fieldName, FieldValue = value });
((RelayCommand)SaveCommand).RaiseCanExecuteChanged();
}
internal void SetEntry(EntryVm entry, int index)
@@ -276,5 +275,11 @@ namespace ModernKeePass.ViewModels
_entry = entry;
IsSelected = index == 0;
}
private async Task SaveChanges()
{
await _mediator.Send(new SaveDatabaseCommand());
((RelayCommand)SaveCommand).RaiseCanExecuteChanged();
}
}
}

View File

@@ -25,12 +25,11 @@ using ModernKeePass.Application.Group.Queries.GetGroup;
using ModernKeePass.Common;
using ModernKeePass.Domain.AOP;
using ModernKeePass.Domain.Enums;
using ModernKeePass.Domain.Interfaces;
using ModernKeePass.Interfaces;
namespace ModernKeePass.ViewModels
{
public class GroupDetailVm : NotifyPropertyChangedBase, IVmEntity, ISelectableModel
public class GroupDetailVm : NotifyPropertyChangedBase, IVmEntity
{
public ObservableCollection<EntryVm> Entries { get; }
@@ -51,25 +50,8 @@ namespace ModernKeePass.ViewModels
}
}
public bool IsNotRoot => _database.RootGroupId != _group.Id;
public bool IsNotRoot => Database.RootGroupId != _group.Id;
public bool ShowRestore => IsNotRoot && _database.RecycleBinId != _group.Id;
/// <summary>
/// Is the Group the database Recycle Bin?
/// </summary>
public bool IsSelected
{
get
{
return _database.IsRecycleBinEnabled && _database.RecycleBinId == _group.Id;
}
set
{
if (value && _group != null) _database.RecycleBinId = _group.Id;
}
}
public IOrderedEnumerable<IGrouping<char, EntryVm>> EntriesZoomedOut => from e in Entries
group e by e.Title.ToUpper().FirstOrDefault() into grp
orderby grp.Key
@@ -111,10 +93,11 @@ namespace ModernKeePass.ViewModels
public ICommand SaveCommand { get; }
public ICommand SortEntriesCommand { get; }
public ICommand SortGroupsCommand { get; }
public ICommand UndoDeleteCommand { get; }
public ICommand MoveCommand { get; }
private DatabaseVm Database => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
private readonly IMediator _mediator;
private readonly DatabaseVm _database;
private readonly GroupVm _group;
private readonly GroupVm _parent;
private bool _isEditMode;
@@ -129,7 +112,6 @@ namespace ModernKeePass.ViewModels
public GroupDetailVm(string groupId, IMediator mediator, bool isEditMode = false)
{
_mediator = mediator;
_database = _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
_group = _mediator.Send(new GetGroupQuery { Id = groupId }).GetAwaiter().GetResult();
if (!string.IsNullOrEmpty(_group.ParentGroupId))
{
@@ -138,18 +120,43 @@ namespace ModernKeePass.ViewModels
}
_isEditMode = isEditMode;
SaveCommand = new RelayCommand(async () => await _mediator.Send(new SaveDatabaseCommand()));
SortEntriesCommand = new RelayCommand(async () =>
await SortEntriesAsync(), () => IsEditMode);
SortGroupsCommand = new RelayCommand(async () =>
await SortGroupsAsync(), () => IsEditMode);
UndoDeleteCommand = new RelayCommand(async () => await Move(_parent), () => _parent != null);
SaveCommand = new RelayCommand(async () => await SaveChanges(), () => Database.IsDirty);
SortEntriesCommand = new RelayCommand(async () => await SortEntriesAsync(), () => IsEditMode);
SortGroupsCommand = new RelayCommand(async () => await SortGroupsAsync(), () => IsEditMode);
MoveCommand = new RelayCommand(async () => await Move(_parent), () => IsNotRoot);
Entries = new ObservableCollection<EntryVm>(_group.Entries);
Entries.CollectionChanged += Entries_CollectionChanged;
Groups = new ObservableCollection<GroupVm>(_group.SubGroups);
}
public async Task<string> AddNewGroup(string name = "")
{
return (await _mediator.Send(new CreateGroupCommand {Name = name, ParentGroup = _group})).Id;
}
public async Task<string> AddNewEntry()
{
return (await _mediator.Send(new CreateEntryCommand { ParentGroup = _group })).Id;
}
public async Task MarkForDelete(string recycleBinTitle)
{
await _mediator.Send(new DeleteGroupCommand { GroupId = _group.Id, ParentGroupId = _group.ParentGroupId, RecycleBinName = recycleBinTitle });
}
public async Task Move(GroupVm destination)
{
await _mediator.Send(new AddGroupCommand {ParentGroup = destination, Group = _group });
await _mediator.Send(new RemoveGroupCommand {ParentGroup = _parent, Group = _group });
}
private async Task SaveChanges()
{
await _mediator.Send(new SaveDatabaseCommand());
((RelayCommand)SaveCommand).RaiseCanExecuteChanged();
}
private async void Entries_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
@@ -170,41 +177,21 @@ namespace ModernKeePass.ViewModels
}
break;
}
}
public async Task<string> AddNewGroup(string name = "")
{
return (await _mediator.Send(new CreateGroupCommand {Name = name, ParentGroup = _group})).Id;
}
public async Task<string> AddNewEntry()
{
return (await _mediator.Send(new CreateEntryCommand { ParentGroup = _group })).Id;
}
public async Task MarkForDelete(string recycleBinTitle)
{
await _mediator.Send(new DeleteGroupCommand { GroupId = _group.Id, ParentGroupId = _group.ParentGroupId, RecycleBinName = recycleBinTitle });
((RelayCommand)UndoDeleteCommand).RaiseCanExecuteChanged();
}
public async Task Move(GroupVm destination)
{
await _mediator.Send(new AddGroupCommand {ParentGroup = destination, Group = _group });
await _mediator.Send(new RemoveGroupCommand {ParentGroup = _parent, Group = _group });
((RelayCommand)SaveCommand).RaiseCanExecuteChanged();
}
private async Task SortEntriesAsync()
{
await _mediator.Send(new SortEntriesCommand {Group = _group});
OnPropertyChanged(nameof(Entries));
((RelayCommand)SaveCommand).RaiseCanExecuteChanged();
}
private async Task SortGroupsAsync()
{
await _mediator.Send(new SortGroupsCommand {Group = _group});
OnPropertyChanged(nameof(Groups));
((RelayCommand)SaveCommand).RaiseCanExecuteChanged();
}
}
}

View File

@@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Common;
namespace ModernKeePass.ViewModels
{
@@ -17,8 +18,8 @@ namespace ModernKeePass.ViewModels
public bool IsSaveSuspend
{
get { return _settings.GetSetting("SaveSuspend", true); }
set { _settings.PutSetting("SaveSuspend", value); }
get { return _settings.GetSetting(Constants.Settings.SaveSuspend, true); }
set { _settings.PutSetting(Constants.Settings.SaveSuspend, value); }
}
}
}

View File

@@ -390,7 +390,7 @@
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<userControls:HamburgerMenuUserControl x:Uid="HistoryLeftListView" ItemsSource="{Binding History}" ResizeTarget="{Binding ElementName=LeftListViewColumn}" SelectionChanged="HamburgerMenuUserControl_OnSelectionChanged" />
<Grid x:Name="StackPanel" Grid.Column="1">
<Grid Grid.Column="1">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Margin="20,0,0,20">
<StackPanel.Resources>
@@ -487,7 +487,7 @@
Style="{StaticResource NoBorderButtonStyle}">
<SymbolIcon Symbol="Back" />
</Button>
<Grid Grid.Column="1" x:Name="TopGrid">
<Grid Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60" />
<ColumnDefinition Width="*" />
@@ -523,12 +523,10 @@
<userControls:BreadCrumbUserControl Grid.Column="1" Grid.Row="1" ItemsSource="{Binding BreadCrumb}" Margin="5,-5,0,0" />
</Grid>
<userControls:TopMenuUserControl
x:Name="TopMenu" Grid.Column="2"
RestoreButtonVisibility="{Binding CanRestore, Converter={StaticResource BooleanToVisibilityConverter}}"
DeleteButtonVisibility="{Binding IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}"
x:Name="TopMenu" Grid.Column="2"
IsEditButtonChecked="{Binding IsEditMode, Mode=TwoWay}"
SaveCommand="{Binding SaveCommand}"
RestoreCommand="{Binding UndoDeleteCommand}">
MoveCommand="{Binding MoveCommand}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="EditButtonClick">
<actions:SetupFocusAction TargetObject="{Binding ElementName=TitleTextBox}" />
@@ -536,9 +534,9 @@
<core:EventTriggerBehavior EventName="DeleteButtonClick">
<actions:DeleteEntityAction Entity="{Binding}" Command="{Binding NavigationHelper.GoBackCommand, ElementName=PageRoot}" />
</core:EventTriggerBehavior>
<core:EventTriggerBehavior EventName="RestoreButtonClick">
<core:EventTriggerBehavior EventName="MoveButtonClick">
<core:InvokeCommandAction Command="{Binding NavigationHelper.GoBackCommand, ElementName=PageRoot}" />
<actions:ToastAction x:Uid="RestoreEntryCommand" Title="{Binding Title}" />
<!--<actions:ToastAction x:Uid="RestoreEntryCommand" Title="{Binding Title}" />-->
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</userControls:TopMenuUserControl>

View File

@@ -45,10 +45,10 @@
</Grid.RowDefinitions>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{StaticResource MenuGridLength}" x:Name="LeftListViewColumn" />
<ColumnDefinition Width="{StaticResource ExpandedMenuGridLength}" x:Name="LeftListViewColumn" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<userControls:HamburgerMenuUserControl x:Uid="GroupsLeftListView" ItemsSource="{Binding Groups}" SelectionChanged="groups_SelectionChanged" ButtonClicked="CreateGroup_ButtonClick" ResizeTarget="{Binding ElementName=LeftListViewColumn}" IsButtonVisible="{Binding IsSelected, Converter={StaticResource InverseBooleanToVisibilityConverter}}" IsOpen="true" />
<userControls:HamburgerMenuUserControl x:Uid="GroupsLeftListView" ItemsSource="{Binding Groups}" SelectionChanged="groups_SelectionChanged" ButtonClicked="CreateGroup_ButtonClick" ResizeTarget="{Binding ElementName=LeftListViewColumn}" IsOpen="True" />
<Grid Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
@@ -61,7 +61,7 @@
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" x:Uid="ReorderEntriesLabel" Margin="10,10,0,0" Visibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}" Style="{StaticResource BodyTextBlockStyle}" />
<!--<TextBlock Grid.Column="1" Grid.Row="0" x:Uid="EntrySymbol" Margin="40,20,0,0" Visibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}" Style="{StaticResource BodyTextBlockStyle}" />-->
<HyperlinkButton Grid.Column="2" Grid.Row="0" VerticalAlignment="Top" Click="CreateEntry_ButtonClick" Visibility="{Binding IsSelected, Converter={StaticResource InverseBooleanToVisibilityConverter}}" HorizontalAlignment="Right" Foreground="{StaticResource MainColor}" Style="{StaticResource MainColorHyperlinkButton}">
<HyperlinkButton Grid.Column="2" Grid.Row="0" VerticalAlignment="Top" Click="CreateEntry_ButtonClick" HorizontalAlignment="Right" Foreground="{StaticResource MainColor}" Style="{StaticResource MainColorHyperlinkButton}">
<StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="Add">
<ToolTipService.ToolTip>
@@ -233,13 +233,12 @@
<userControls:BreadCrumbUserControl Grid.Column="1" Grid.Row="1" ItemsSource="{Binding BreadCrumb}" Margin="5,-5,0,0" />
</Grid>
<userControls:TopMenuUserControl x:Name="TopMenu" Grid.Column="2"
RestoreButtonVisibility="{Binding ShowRestore, Converter={StaticResource BooleanToVisibilityConverter}}"
DeleteButtonVisibility="{Binding IsSelected, Converter={StaticResource InverseBooleanToVisibilityConverter}}"
SortButtonVisibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}"
IsEditButtonChecked="{Binding IsEditMode, Mode=TwoWay}"
IsMoveButtonEnabled="{Binding IsNotRoot}"
IsDeleteButtonEnabled="{Binding IsNotRoot}"
SaveCommand="{Binding SaveCommand}"
RestoreCommand="{Binding UndoDeleteCommand}"
MoveCommand="{Binding MoveCommand}"
SortEntriesCommand="{Binding SortEntriesCommand}"
SortGroupsCommand="{Binding SortGroupsCommand}">
<interactivity:Interaction.Behaviors>
@@ -249,9 +248,9 @@
<core:EventTriggerBehavior EventName="DeleteButtonClick">
<actions:DeleteEntityAction Entity="{Binding}" Command="{Binding NavigationHelper.GoBackCommand, ElementName=PageRoot}" />
</core:EventTriggerBehavior>
<core:EventTriggerBehavior EventName="RestoreButtonClick">
<core:EventTriggerBehavior EventName="MoveButtonClick">
<core:InvokeCommandAction Command="{Binding NavigationHelper.GoBackCommand, ElementName=PageRoot}" />
<actions:ToastAction x:Uid="RestoreGroupCommand" Title="{Binding Title}" />
<!--<actions:ToastAction x:Uid="RestoreGroupCommand" Title="{Binding Title}" />-->
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</userControls:TopMenuUserControl>

View File

@@ -21,7 +21,7 @@ namespace ModernKeePass.Views.UserControls
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register(
"ItemsSource",
nameof(ItemsSource),
typeof(IEnumerable<IEntityVm>),
typeof(BreadCrumbUserControl),
new PropertyMetadata(new Stack<IEntityVm>(), (o, args) => { }));

View File

@@ -26,7 +26,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty SelectedColorProperty =
DependencyProperty.Register(
"SelectedColor",
nameof(SelectedColor),
typeof(SolidColorBrush),
typeof(ColorPickerUserControl),
new PropertyMetadata(new SolidColorBrush(), (o, args) => { }));

View File

@@ -34,7 +34,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty CreateNewProperty =
DependencyProperty.Register(
"CreateNew",
nameof(CreateNew),
typeof(bool),
typeof(CompositeKeyUserControl),
new PropertyMetadata(false, (o, args) => { }));
@@ -46,7 +46,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty UpdateKeyProperty =
DependencyProperty.Register(
"UpdateKey",
nameof(UpdateKey),
typeof(bool),
typeof(CompositeKeyUserControl),
new PropertyMetadata(false, (o, args) => { }));
@@ -58,7 +58,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty ButtonLabelProperty =
DependencyProperty.Register(
"ButtonLabel",
nameof(ButtonLabel),
typeof(string),
typeof(CompositeKeyUserControl),
new PropertyMetadata("OK", (o, args) => { }));
@@ -70,7 +70,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty DatabaseFilePathProperty =
DependencyProperty.Register(
"DatabaseFilePath",
nameof(DatabaseFilePath),
typeof(string),
typeof(CompositeKeyUserControl),
new PropertyMetadata(null, (o, args) => { }));

View File

@@ -23,7 +23,6 @@
Foreground="{ThemeResource DefaultTextForegroundThemeBrush}"
ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}">
<ListView.Resources>
<x:Double x:Key="HamburgerMenuSize">300</x:Double>
<DataTemplate x:Name="IsSpecial">
<StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="{Binding Icon, Converter={StaticResource IconToSymbolConverter}, ConverterParameter=48}" Margin="7,15,0,15">
@@ -51,13 +50,13 @@
<ListView.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ToggleButton Style="{StaticResource HamburgerToggleButton}" IsChecked="{Binding Path={Binding IsOpen, ElementName=UserControl}}">
<ToggleButton Style="{StaticResource HamburgerToggleButton}" IsChecked="{Binding IsOpen, ElementName=UserControl}">
<ToolTipService.ToolTip>
<ToolTip Content="{Binding HeaderLabel, ElementName=UserControl}" />
</ToolTipService.ToolTip>
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Checked">
<core:ChangePropertyAction PropertyName="Width" Value="{StaticResource HamburgerMenuSize}" TargetObject="{Binding ResizeTarget, ElementName=UserControl}"/>
<core:ChangePropertyAction PropertyName="Width" Value="{StaticResource ExpandedMenuSize}" TargetObject="{Binding ResizeTarget, ElementName=UserControl}"/>
</core:EventTriggerBehavior>
<core:EventTriggerBehavior EventName="Unchecked">
<core:ChangePropertyAction PropertyName="Width" Value="{StaticResource MenuSize}" TargetObject="{Binding ResizeTarget, ElementName=UserControl}"/>
@@ -72,7 +71,7 @@
<DataTemplate>
<StackPanel Orientation="Vertical">
<Border BorderBrush="White" BorderThickness="0,0,0,1" />
<Button Padding="0" Height="{StaticResource MenuSize}" Margin="0" Visibility="{Binding IsButtonVisible, ElementName=UserControl}" Style="{StaticResource NoBorderButtonStyle}" Background="Transparent" BorderThickness="0" Width="{StaticResource HamburgerMenuSize}" HorizontalContentAlignment="Left" Click="ButtonBase_OnClick">
<Button Padding="0" Height="{StaticResource MenuSize}" Margin="0" Visibility="{Binding IsButtonVisible, ElementName=UserControl}" Style="{StaticResource NoBorderButtonStyle}" Background="Transparent" BorderThickness="0" Width="{StaticResource ExpandedMenuSize}" HorizontalContentAlignment="Left" Click="ButtonBase_OnClick">
<StackPanel Orientation="Horizontal" Margin="17,0,5,0">
<SymbolIcon Symbol="Add">
<ToolTipService.ToolTip>
@@ -82,7 +81,7 @@
<TextBlock Text="{Binding ButtonLabel, ElementName=UserControl}" FontWeight="SemiBold" TextWrapping="NoWrap" FontSize="16" VerticalAlignment="Center" Margin="30,0,20,0" />
</StackPanel>
</Button>
<Button Padding="0" Height="{StaticResource MenuSize}" Margin="0" Style="{StaticResource NoBorderButtonStyle}" Background="Transparent" BorderThickness="0" Width="{StaticResource HamburgerMenuSize}" HorizontalContentAlignment="Left">
<Button Padding="0" Height="{StaticResource MenuSize}" Margin="0" Style="{StaticResource NoBorderButtonStyle}" Background="Transparent" BorderThickness="0" Width="{StaticResource ExpandedMenuSize}" HorizontalContentAlignment="Left">
<StackPanel Orientation="Horizontal" Margin="17,0,5,0">
<SymbolIcon Symbol="Home">
<ToolTipService.ToolTip>
@@ -97,7 +96,7 @@
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Button>
<Button Padding="0" Height="{StaticResource MenuSize}" Margin="0" Style="{StaticResource NoBorderButtonStyle}" Background="Transparent" BorderThickness="0" Width="{StaticResource HamburgerMenuSize}" HorizontalContentAlignment="Left">
<Button Padding="0" Height="{StaticResource MenuSize}" Margin="0" Style="{StaticResource NoBorderButtonStyle}" Background="Transparent" BorderThickness="0" Width="{StaticResource ExpandedMenuSize}" HorizontalContentAlignment="Left">
<StackPanel Orientation="Horizontal" Margin="17,0,5,0">
<SymbolIcon Symbol="Setting">
<ToolTipService.ToolTip>

View File

@@ -22,7 +22,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty HeaderLabelProperty =
DependencyProperty.Register(
"HeaderLabel",
nameof(HeaderLabel),
typeof(string),
typeof(HamburgerMenuUserControl),
new PropertyMetadata("Header", (o, args) => { }));
@@ -34,7 +34,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty ButtonLabelProperty =
DependencyProperty.Register(
"ButtonLabel",
nameof(ButtonLabel),
typeof(string),
typeof(HamburgerMenuUserControl),
new PropertyMetadata("Button", (o, args) => { }));
@@ -46,7 +46,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty DisplayMemberPathProperty =
DependencyProperty.Register(
"DisplayMemberPath",
nameof(DisplayMemberPath),
typeof(string),
typeof(HamburgerMenuUserControl),
new PropertyMetadata("Title", (o, args) => { }));
@@ -58,7 +58,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty ResizeTargetProperty =
DependencyProperty.Register(
"ResizeTarget",
nameof(ResizeTarget),
typeof(object),
typeof(HamburgerMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
@@ -70,7 +70,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty IsButtonVisibleProperty =
DependencyProperty.Register(
"IsButtonVisible",
nameof(IsButtonVisible),
typeof(Visibility),
typeof(HamburgerMenuUserControl),
new PropertyMetadata(Visibility.Collapsed, (o, args) => { }));
@@ -83,7 +83,7 @@ namespace ModernKeePass.Views.UserControls
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register(
"ItemsSource",
nameof(ItemsSource),
typeof(IEnumerable<IEntityVm>),
typeof(HamburgerMenuUserControl),
new PropertyMetadata(new List<IEntityVm>(), (o, args) => { }));
@@ -95,7 +95,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.Register(
"SelectedItem",
nameof(SelectedItem),
typeof(object),
typeof(HamburgerMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
@@ -107,10 +107,10 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty IsOpenProperty =
DependencyProperty.Register(
"IsOpen",
nameof(IsOpen),
typeof(bool),
typeof(HamburgerMenuUserControl),
new PropertyMetadata(false, (o, args) => { }));
new PropertyMetadata(true, (o, args) => { }));
public event EventHandler<SelectionChangedEventArgs> SelectionChanged;
private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e)

View File

@@ -19,7 +19,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty SelectedSymbolProperty =
DependencyProperty.Register(
"SelectedSymbol",
nameof(SelectedSymbol),
typeof(Symbol),
typeof(SymbolPickerUserControl),
new PropertyMetadata(Symbol.Stop, (o, args) => { }));

View File

@@ -42,10 +42,10 @@
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel x:Name="OverflowButtons" Orientation="Horizontal">
<Button Command="{Binding RestoreCommand, ElementName=UserControl}" Visibility="{Binding RestoreButtonVisibility, ElementName=UserControl}" Click="RestoreButton_Click" Style="{StaticResource MenuButtonStyle}">
<Button Command="{Binding MoveCommand, ElementName=UserControl}" IsEnabled="{Binding IsMoveButtonEnabled, ElementName=UserControl}" Click="MoveButton_Click" Style="{StaticResource MenuButtonStyle}">
<SymbolIcon Symbol="Undo">
<ToolTipService.ToolTip>
<ToolTip x:Uid="TopMenuRestoreButton" />
<ToolTip x:Uid="TopMenuMoveButton" />
</ToolTipService.ToolTip>
</SymbolIcon>
</Button>
@@ -76,7 +76,7 @@
</ToolTipService.ToolTip>
</SymbolIcon>
</ToggleButton>
<Button Command="{Binding DeleteCommand, ElementName=UserControl}" IsEnabled="{Binding IsDeleteButtonEnabled, ElementName=UserControl}" Visibility="{Binding DeleteButtonVisibility, ElementName=UserControl}" Click="DeleteButton_Click" Style="{StaticResource MenuButtonStyle}">
<Button Command="{Binding DeleteCommand, ElementName=UserControl}" IsEnabled="{Binding IsDeleteButtonEnabled, ElementName=UserControl}" Click="DeleteButton_Click" Style="{StaticResource MenuButtonStyle}">
<SymbolIcon Symbol="Delete">
<ToolTipService.ToolTip>
<ToolTip x:Uid="TopMenuDeleteButton" />
@@ -88,10 +88,10 @@
<SymbolIcon Symbol="More" />
<Button.Flyout>
<MenuFlyout Opening="OverflowFlyout_OnOpening">
<MenuFlyoutItem x:Uid="TopMenuRestoreFlyout" x:Name="RestoreFlyout" Command="{Binding RestoreCommand, ElementName=UserControl}" Click="RestoreButton_Click" Visibility="{Binding RestoreButtonVisibility, ElementName=UserControl}" />
<MenuFlyoutItem x:Uid="TopMenuMoveFlyout" x:Name="MoveFlyout" Command="{Binding MoveCommand, ElementName=UserControl}" Click="MoveButton_Click" IsEnabled="{Binding IsMoveButtonEnabled, ElementName=UserControl}" />
<MenuFlyoutItem x:Uid="TopMenuSaveFlyout" Command="{Binding SaveCommand, ElementName=UserControl}" />
<ToggleMenuFlyoutItem x:Uid="TopMenuEditFlyout" x:Name="EditFlyout" Command="{Binding EditCommand, ElementName=UserControl}" IsChecked="{Binding IsEditButtonChecked, ElementName=UserControl, Mode=TwoWay}" Click="EditButton_Click" />
<MenuFlyoutItem x:Uid="TopMenuDeleteFlyout" x:Name="DeleteFlyout" Command="{Binding DeleteCommand, ElementName=UserControl}" Click="DeleteButton_Click" Visibility="{Binding DeleteButtonVisibility, ElementName=UserControl}" IsEnabled="{Binding IsDeleteButtonEnabled, ElementName=UserControl}" />
<MenuFlyoutItem x:Uid="TopMenuDeleteFlyout" x:Name="DeleteFlyout" Command="{Binding DeleteCommand, ElementName=UserControl}" Click="DeleteButton_Click" IsEnabled="{Binding IsDeleteButtonEnabled, ElementName=UserControl}" />
<MenuFlyoutItem x:Uid="TopMenuSortEntriesFlyout" x:Name="SortEntriesFlyout" Command="{Binding SortEntriesCommand, ElementName=UserControl}" Visibility="{Binding SortButtonVisibility, ElementName=UserControl}" />
<MenuFlyoutItem x:Uid="TopMenuSortGroupsFlyout" x:Name="SortGroupsFlyout" Command="{Binding SortGroupsCommand, ElementName=UserControl}" Visibility="{Binding SortButtonVisibility, ElementName=UserControl}" />
</MenuFlyout>

View File

@@ -15,7 +15,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty SaveCommandProperty =
DependencyProperty.Register(
"SaveCommand",
nameof(SaveCommand),
typeof(ICommand),
typeof(TopMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
@@ -27,7 +27,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty EditCommandProperty =
DependencyProperty.Register(
"EditCommand",
nameof(EditCommand),
typeof(ICommand),
typeof(TopMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
@@ -39,19 +39,19 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty DeleteCommandProperty =
DependencyProperty.Register(
"DeleteCommand",
nameof(DeleteCommand),
typeof(ICommand),
typeof(TopMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
public ICommand RestoreCommand
public ICommand MoveCommand
{
get { return (ICommand)GetValue(RestoreCommandProperty); }
set { SetValue(RestoreCommandProperty, value); }
get { return (ICommand)GetValue(MoveCommandProperty); }
set { SetValue(MoveCommandProperty, value); }
}
public static readonly DependencyProperty RestoreCommandProperty =
public static readonly DependencyProperty MoveCommandProperty =
DependencyProperty.Register(
"RestoreCommand",
nameof(MoveCommand),
typeof(ICommand),
typeof(TopMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
@@ -63,7 +63,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty SortEntriesCommandProperty =
DependencyProperty.Register(
"SortEntriesCommand",
nameof(SortEntriesCommand),
typeof(ICommand),
typeof(TopMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
@@ -75,34 +75,22 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty SortGroupsCommandProperty =
DependencyProperty.Register(
"SortGroupsCommand",
nameof(SortGroupsCommand),
typeof(ICommand),
typeof(TopMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
public Visibility RestoreButtonVisibility
public bool IsMoveButtonEnabled
{
get { return (Visibility)GetValue(RestoreButtonVisibilityProperty); }
set { SetValue(RestoreButtonVisibilityProperty, value); }
get { return (bool)GetValue(IsMoveButtonEnabledProperty); }
set { SetValue(IsMoveButtonEnabledProperty, value); }
}
public static readonly DependencyProperty RestoreButtonVisibilityProperty =
public static readonly DependencyProperty IsMoveButtonEnabledProperty =
DependencyProperty.Register(
"RestoreButtonVisibility",
typeof(Visibility),
nameof(IsMoveButtonEnabled),
typeof(bool),
typeof(TopMenuUserControl),
new PropertyMetadata(Visibility.Collapsed, (o, args) => { }));
public Visibility DeleteButtonVisibility
{
get { return (Visibility)GetValue(DeleteButtonVisibilityProperty); }
set { SetValue(DeleteButtonVisibilityProperty, value); }
}
public static readonly DependencyProperty DeleteButtonVisibilityProperty =
DependencyProperty.Register(
"DeleteButtonVisibility",
typeof(Visibility),
typeof(TopMenuUserControl),
new PropertyMetadata(Visibility.Collapsed, (o, args) => { }));
new PropertyMetadata(true, (o, args) => { }));
public Visibility SortButtonVisibility
{
@@ -111,7 +99,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty SortButtonVisibilityProperty =
DependencyProperty.Register(
"SortButtonVisibility",
nameof(SortButtonVisibility),
typeof(Visibility),
typeof(TopMenuUserControl),
new PropertyMetadata(Visibility.Collapsed, (o, args) => { }));
@@ -123,7 +111,7 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty IsDeleteButtonEnabledProperty =
DependencyProperty.Register(
"IsDeleteButtonEnabled",
nameof(IsDeleteButtonEnabled),
typeof(bool),
typeof(TopMenuUserControl),
new PropertyMetadata(true, (o, args) => { }));
@@ -135,14 +123,14 @@ namespace ModernKeePass.Views.UserControls
}
public static readonly DependencyProperty IsEditButtonCheckedProperty =
DependencyProperty.Register(
"IsEditButtonChecked",
nameof(IsEditButtonChecked),
typeof(bool),
typeof(TopMenuUserControl),
new PropertyMetadata(false, (o, args) => { }));
public event EventHandler<RoutedEventArgs> EditButtonClick;
public event EventHandler<RoutedEventArgs> DeleteButtonClick;
public event EventHandler<RoutedEventArgs> RestoreButtonClick;
public event EventHandler<RoutedEventArgs> MoveButtonClick;
public TopMenuUserControl()
{
@@ -166,19 +154,19 @@ namespace ModernKeePass.Views.UserControls
DeleteButtonClick?.Invoke(sender, e);
}
private void RestoreButton_Click(object sender, RoutedEventArgs e)
private void MoveButton_Click(object sender, RoutedEventArgs e)
{
RestoreButtonClick?.Invoke(sender, e);
MoveButtonClick?.Invoke(sender, e);
}
private void OverflowFlyout_OnOpening(object sender, object e)
{
DeleteFlyout.IsEnabled = IsDeleteButtonEnabled;
DeleteFlyout.Visibility = DeleteButtonVisibility;
DeleteFlyout.IsEnabled = IsDeleteButtonEnabled;
EditFlyout.IsChecked = IsEditButtonChecked;
RestoreFlyout.Visibility = RestoreButtonVisibility;
MoveFlyout.IsEnabled = IsMoveButtonEnabled;
SortEntriesFlyout.Visibility = SortButtonVisibility;
SortGroupsFlyout.Visibility = SortButtonVisibility;

View File

@@ -97,6 +97,7 @@
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="Common\Constants.cs" />
<Compile Include="Common\ResourceHelper.cs" />
<Compile Include="Converters\IconToSymbolConverter.cs" />
<Compile Include="DependencyInjection.cs" />

View File

@@ -1,5 +1,4 @@
Improved search box
Changing entry icon creates a new history entry
Corrected startup crash on some versions of Windows
Entry delete button now shows up correctly
List of icons now only displays valid values
Database corruption issues should now be a thing of the past !
Added the ability to move entries and groups
Edits are now in a popup instead of inline
Updated KeePass lib to version 2.44