Updated deleted text information

Improved dirty status detection (restored removed variable...)
This corrected history creation on navigation when entry deleted
This commit is contained in:
Geoffroy BONNEVILLE
2020-05-14 13:32:44 +02:00
parent 72e5bf4ee1
commit d497f69a5e
9 changed files with 54 additions and 73 deletions

View File

@@ -147,35 +147,17 @@
<data name="EntityRestoredTitle" xml:space="preserve"> <data name="EntityRestoredTitle" xml:space="preserve">
<value>Restored</value> <value>Restored</value>
</data> </data>
<data name="EntryDeleted" xml:space="preserve">
<value>Entry permanently removed</value>
</data>
<data name="EntryDeletingConfirmation" xml:space="preserve"> <data name="EntryDeletingConfirmation" xml:space="preserve">
<value>Are you sure you want to delete this entry?</value> <value>Are you sure you want to delete {0} ?</value>
</data> </data>
<data name="EntryRecycled" xml:space="preserve"> <data name="EntryRecycled" xml:space="preserve">
<value>Entry moved to the Recycle bin</value> <value>{0} moved to the Recycle bin</value>
</data>
<data name="EntryRecyclingConfirmation" xml:space="preserve">
<value>Are you sure you want to send this entry to the recycle bin?</value>
</data> </data>
<data name="EntryRestored" xml:space="preserve"> <data name="EntryRestored" xml:space="preserve">
<value>Entry returned to its original group</value> <value>Entry returned to its original group</value>
</data> </data>
<data name="GroupDeleted" xml:space="preserve">
<value>Group permanently removed</value>
</data>
<data name="GroupDeletingConfirmation" xml:space="preserve">
<value>Are you sure you want to delete the whole group and all its entries?</value>
</data>
<data name="GroupRecycled" xml:space="preserve"> <data name="GroupRecycled" xml:space="preserve">
<value>Group moved to the Recycle bin</value> <value>{0} moved to the Recycle bin</value>
</data>
<data name="GroupRecyclingConfirmation" xml:space="preserve">
<value>Are you sure you want to send the whole group and all its entries to the recycle bin?</value>
</data>
<data name="GroupRestored" xml:space="preserve">
<value>Group returned to its original group</value>
</data> </data>
<data name="MainMenuItemAbout" xml:space="preserve"> <data name="MainMenuItemAbout" xml:space="preserve">
<value>About</value> <value>About</value>
@@ -288,4 +270,7 @@
<data name="SettingsMenuItemRecycleBin" xml:space="preserve"> <data name="SettingsMenuItemRecycleBin" xml:space="preserve">
<value>Recycle Bin</value> <value>Recycle Bin</value>
</data> </data>
<data name="GroupDeletingConfirmation" xml:space="preserve">
<value>Are you sure you want to delete the {0} and all its entries?</value>
</data>
</root> </root>

View File

@@ -121,7 +121,7 @@
<value>Dominik Reichl for the KeePass application and file format</value> <value>Dominik Reichl for the KeePass application and file format</value>
</data> </data>
<data name="AboutCredits2.Text" xml:space="preserve"> <data name="AboutCredits2.Text" xml:space="preserve">
<value>David Lechner for his PCL adapatation of the KeePass Library and his correlated tests</value> <value>David Lechner for his PCL adapatation of the KeePass Library and his related tests</value>
</data> </data>
<data name="AboutCreditsLabel.Text" xml:space="preserve"> <data name="AboutCreditsLabel.Text" xml:space="preserve">
<value>Credits</value> <value>Credits</value>

View File

@@ -147,35 +147,17 @@
<data name="EntityRestoredTitle" xml:space="preserve"> <data name="EntityRestoredTitle" xml:space="preserve">
<value>Restauré</value> <value>Restauré</value>
</data> </data>
<data name="EntryDeleted" xml:space="preserve">
<value>Entrée supprimée définitivement</value>
</data>
<data name="EntryDeletingConfirmation" xml:space="preserve"> <data name="EntryDeletingConfirmation" xml:space="preserve">
<value>Êtes-vous sûr de vouloir supprimer cette entrée ?</value> <value>Êtes-vous sûr de vouloir supprimer {0} ?</value>
</data> </data>
<data name="EntryRecycled" xml:space="preserve"> <data name="EntryRecycled" xml:space="preserve">
<value>Entrée placée dans la Corbeille</value> <value>{0} placé dans la Corbeille</value>
</data>
<data name="EntryRecyclingConfirmation" xml:space="preserve">
<value>Êtes-vous sûr de vouloir placer cette entrée dans la Corbeille ?</value>
</data>
<data name="EntryRestored" xml:space="preserve">
<value>Entrée replacée dans son groupe d'origine</value>
</data>
<data name="GroupDeleted" xml:space="preserve">
<value>Groupe supprimé définitivement</value>
</data> </data>
<data name="GroupDeletingConfirmation" xml:space="preserve"> <data name="GroupDeletingConfirmation" xml:space="preserve">
<value>Êtes-vous sûr de vouloir supprimer ce groupe et toutes ses entrées ?</value> <value>Êtes-vous sûr de vouloir supprimer {0} et toutes ses entrées ?</value>
</data> </data>
<data name="GroupRecycled" xml:space="preserve"> <data name="GroupRecycled" xml:space="preserve">
<value>Groupe placé dans la Corbeille</value> <value>{0} placé dans la Corbeille</value>
</data>
<data name="GroupRecyclingConfirmation" xml:space="preserve">
<value>Êtes-vous sûr de vouloir envoyer ce groupe et toutes ses entrées vers la Corbeille ?</value>
</data>
<data name="GroupRestored" xml:space="preserve">
<value>Groupe replacé à sa place originelle</value>
</data> </data>
<data name="MainMenuItemAbout" xml:space="preserve"> <data name="MainMenuItemAbout" xml:space="preserve">
<value>A propos</value> <value>A propos</value>

View File

@@ -41,9 +41,17 @@ namespace ModernKeePass.ViewModels
{ {
public class EntryDetailVm : ViewModelBase public class EntryDetailVm : ViewModelBase
{ {
public bool IsRevealPasswordEnabled => !string.IsNullOrEmpty(Password);
public bool HasExpired => HasExpirationDate && ExpiryDate < DateTime.Now; public bool HasExpired => HasExpirationDate && ExpiryDate < DateTime.Now;
public double PasswordComplexityIndicator => _mediator.Send(new EstimatePasswordComplexityQuery {Password = Password}).GetAwaiter().GetResult(); public double PasswordComplexityIndicator => _mediator.Send(new EstimatePasswordComplexityQuery {Password = Password}).GetAwaiter().GetResult();
public double PasswordLength
{
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.PasswordLength, 25); }
set
{
_settings.PutSetting(Constants.Settings.PasswordGenerationOptions.PasswordLength, value);
RaisePropertyChanged(nameof(PasswordLength));
}
}
public bool UpperCasePatternSelected public bool UpperCasePatternSelected
{ {
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.UpperCasePattern, true); } get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.UpperCasePattern, true); }
@@ -126,7 +134,7 @@ namespace ModernKeePass.ViewModels
})); }));
Attachments.CollectionChanged += (sender, args) => Attachments.CollectionChanged += (sender, args) =>
{ {
SaveCommand.RaiseCanExecuteChanged(); UpdateDirtyStatus(true);
}; };
RaisePropertyChanged(string.Empty); RaisePropertyChanged(string.Empty);
} }
@@ -154,11 +162,6 @@ namespace ModernKeePass.ViewModels
} }
} }
public double PasswordLength
{
get { return _passwordLength; }
set { Set(() => PasswordLength, ref _passwordLength, value); }
}
public string Title public string Title
{ {
@@ -279,7 +282,6 @@ namespace ModernKeePass.ViewModels
} }
} }
public bool IsEditMode public bool IsEditMode
{ {
get { return IsCurrentEntry && _isEditMode; } get { return IsCurrentEntry && _isEditMode; }
@@ -320,7 +322,7 @@ namespace ModernKeePass.ViewModels
private int _additionalFieldSelectedIndex = -1; private int _additionalFieldSelectedIndex = -1;
private bool _isEditMode; private bool _isEditMode;
private bool _isRevealPassword; private bool _isRevealPassword;
private double _passwordLength = 25; private bool _isDirty;
public EntryDetailVm(IMediator mediator, INavigationService navigation, IResourceProxy resource, IDialogService dialog, INotificationService notification, IFileProxy file, ISettingsProxy settings) public EntryDetailVm(IMediator mediator, INavigationService navigation, IResourceProxy resource, IDialogService dialog, INotificationService notification, IFileProxy file, ISettingsProxy settings)
{ {
@@ -360,7 +362,11 @@ namespace ModernKeePass.ViewModels
{ {
History.Add(entry); History.Add(entry);
} }
History.CollectionChanged += (sender, args) => SaveCommand.RaiseCanExecuteChanged(); History.CollectionChanged += (sender, args) =>
{
SelectedIndex = 0;
SaveCommand.RaiseCanExecuteChanged();
};
} }
public async Task GeneratePassword() public async Task GeneratePassword()
@@ -378,12 +384,11 @@ namespace ModernKeePass.ViewModels
UnderscorePatternSelected = UnderscorePatternSelected, UnderscorePatternSelected = UnderscorePatternSelected,
UpperCasePatternSelected = UpperCasePatternSelected UpperCasePatternSelected = UpperCasePatternSelected
}); });
RaisePropertyChanged(nameof(IsRevealPasswordEnabled));
} }
public async Task AddHistory() public async Task AddHistory()
{ {
if (Database.IsDirty) await _mediator.Send(new AddHistoryCommand { Entry = History[0] }); if (_isDirty) await _mediator.Send(new AddHistoryCommand { Entry = History[0] });
} }
public void GoToGroup(string groupId) public void GoToGroup(string groupId)
@@ -401,7 +406,7 @@ namespace ModernKeePass.ViewModels
private async Task SetFieldValue(string fieldName, object value, bool isProtected) private async Task SetFieldValue(string fieldName, object value, bool isProtected)
{ {
await _mediator.Send(new UpsertFieldCommand { EntryId = Id, FieldName = fieldName, FieldValue = value, IsProtected = isProtected}); await _mediator.Send(new UpsertFieldCommand { EntryId = Id, FieldName = fieldName, FieldValue = value, IsProtected = isProtected});
SaveCommand.RaiseCanExecuteChanged(); UpdateDirtyStatus(true);
} }
private async Task UpdateFieldName(string oldName, string newName, string value, bool isProtected) private async Task UpdateFieldName(string oldName, string newName, string value, bool isProtected)
@@ -422,7 +427,7 @@ namespace ModernKeePass.ViewModels
if (!string.IsNullOrEmpty(field.Name)) if (!string.IsNullOrEmpty(field.Name))
{ {
await _mediator.Send(new DeleteFieldCommand {EntryId = Id, FieldName = field.Name}); await _mediator.Send(new DeleteFieldCommand {EntryId = Id, FieldName = field.Name});
SaveCommand.RaiseCanExecuteChanged(); UpdateDirtyStatus(true);
} }
} }
@@ -433,12 +438,13 @@ namespace ModernKeePass.ViewModels
if (IsRecycleOnDelete) if (IsRecycleOnDelete)
{ {
await Delete(); await Delete();
_notification.Show(_resource.GetResourceValue("EntryRecyclingConfirmation"), _resource.GetResourceValue("EntryRecycled")); _notification.Show(_resource.GetResourceValue("EntityDeleting"), string.Format(_resource.GetResourceValue("EntryRecycled"), Title));
} }
else else
{ {
await _dialog.ShowMessage(_resource.GetResourceValue("EntryDeletingConfirmation"), await _dialog.ShowMessage(
_resource.GetResourceValue("EntityDeleteTitle"), string.Format(_resource.GetResourceValue("EntryDeletingConfirmation"), Title),
_resource.GetResourceValue("EntityDeleting"),
_resource.GetResourceValue("EntityDeleteActionButton"), _resource.GetResourceValue("EntityDeleteActionButton"),
_resource.GetResourceValue("EntityDeleteCancelButton"), _resource.GetResourceValue("EntityDeleteCancelButton"),
async isOk => async isOk =>
@@ -449,14 +455,14 @@ namespace ModernKeePass.ViewModels
} }
else else
{ {
await _dialog.ShowMessage(_resource.GetResourceValue("HistoryDeleteDescription"), _resource.GetResourceValue("HistoryDeleteTitle"), await _dialog.ShowMessage(_resource.GetResourceValue("HistoryDeleteDescription"),
_resource.GetResourceValue("HistoryDeleteTitle"),
_resource.GetResourceValue("EntityDeleteActionButton"), _resource.GetResourceValue("EntityDeleteActionButton"),
_resource.GetResourceValue("EntityDeleteCancelButton"), async isOk => _resource.GetResourceValue("EntityDeleteCancelButton"), async isOk =>
{ {
if (!isOk) return; if (!isOk) return;
await _mediator.Send(new DeleteHistoryCommand { Entry = History[0], HistoryIndex = History.Count - SelectedIndex - 1 }); await _mediator.Send(new DeleteHistoryCommand { Entry = History[0], HistoryIndex = History.Count - SelectedIndex - 1 });
History.RemoveAt(SelectedIndex); History.RemoveAt(SelectedIndex);
SelectedIndex = 0;
}); });
} }
} }
@@ -465,7 +471,6 @@ namespace ModernKeePass.ViewModels
{ {
await _mediator.Send(new RestoreHistoryCommand { Entry = History[0], HistoryIndex = History.Count - SelectedIndex - 1 }); await _mediator.Send(new RestoreHistoryCommand { Entry = History[0], HistoryIndex = History.Count - SelectedIndex - 1 });
History.Insert(0, SelectedItem); History.Insert(0, SelectedItem);
SelectedIndex = 0;
} }
private async Task SaveChanges() private async Task SaveChanges()
@@ -479,7 +484,7 @@ namespace ModernKeePass.ViewModels
{ {
MessengerInstance.Send(new SaveErrorMessage { Message = e.Message }); MessengerInstance.Send(new SaveErrorMessage { Message = e.Message });
} }
SaveCommand.RaiseCanExecuteChanged(); UpdateDirtyStatus(false);
} }
private async Task Delete() private async Task Delete()
@@ -490,6 +495,7 @@ namespace ModernKeePass.ViewModels
ParentGroupId = SelectedItem.ParentGroupId, ParentGroupId = SelectedItem.ParentGroupId,
RecycleBinName = _resource.GetResourceValue("RecycleBinTitle") RecycleBinName = _resource.GetResourceValue("RecycleBinTitle")
}); });
_isDirty = false;
_navigation.GoBack(); _navigation.GoBack();
} }
@@ -511,15 +517,18 @@ namespace ModernKeePass.ViewModels
var contents = await _file.ReadBinaryFile(fileInfo.Id); var contents = await _file.ReadBinaryFile(fileInfo.Id);
await _mediator.Send(new AddAttachmentCommand { Entry = SelectedItem, AttachmentName = fileInfo.Name, AttachmentContent = contents }); await _mediator.Send(new AddAttachmentCommand { Entry = SelectedItem, AttachmentName = fileInfo.Name, AttachmentContent = contents });
Attachments.Add(new Attachment { Name = fileInfo.Name, Content = contents }); Attachments.Add(new Attachment { Name = fileInfo.Name, Content = contents });
SaveCommand.RaiseCanExecuteChanged();
} }
private async Task DeleteAttachment(Attachment attachment) private async Task DeleteAttachment(Attachment attachment)
{ {
await _mediator.Send(new DeleteAttachmentCommand { Entry = SelectedItem, AttachmentName = attachment.Name }); await _mediator.Send(new DeleteAttachmentCommand { Entry = SelectedItem, AttachmentName = attachment.Name });
Attachments.Remove(attachment); Attachments.Remove(attachment);
SaveCommand.RaiseCanExecuteChanged();
} }
private void UpdateDirtyStatus(bool isDirty)
{
SaveCommand.RaiseCanExecuteChanged();
_isDirty = isDirty;
}
} }
} }

View File

@@ -261,11 +261,13 @@ namespace ModernKeePass.ViewModels
if (IsRecycleOnDelete) if (IsRecycleOnDelete)
{ {
await Delete(); await Delete();
_notification.Show(_resource.GetResourceValue("GroupRecyclingConfirmation"), _resource.GetResourceValue("GroupRecycled")); _notification.Show(_resource.GetResourceValue("EntityDeleting"), string.Format(_resource.GetResourceValue("GroupRecycled"), Title));
} }
else else
{ {
await _dialog.ShowMessage(_resource.GetResourceValue("GroupDeletingConfirmation"), _resource.GetResourceValue("EntityDeleteTitle"), await _dialog.ShowMessage(
string.Format(_resource.GetResourceValue("GroupDeletingConfirmation"), Title),
_resource.GetResourceValue("EntityDeleting"),
_resource.GetResourceValue("EntityDeleteActionButton"), _resource.GetResourceValue("EntityDeleteActionButton"),
_resource.GetResourceValue("EntityDeleteCancelButton"), _resource.GetResourceValue("EntityDeleteCancelButton"),
async isOk => async isOk =>

View File

@@ -418,7 +418,7 @@
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
</local:TextBoxWithButton> </local:TextBoxWithButton>
<ProgressBar Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}" Maximum="128" Width="350" HorizontalAlignment="Left" Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroundBrushComplexityConverter}}" /> <ProgressBar Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}" Maximum="128" Width="350" HorizontalAlignment="Left" Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroundBrushComplexityConverter}}" />
<CheckBox x:Uid="EntryShowPassword" HorizontalAlignment="Left" Margin="-3,0,0,0" IsChecked="{Binding IsRevealPassword, Mode=TwoWay}" IsEnabled="{Binding IsRevealPasswordEnabled}" /> <CheckBox x:Uid="EntryShowPassword" HorizontalAlignment="Left" Margin="-3,0,0,0" IsChecked="{Binding IsRevealPassword, Mode=TwoWay}" />
<TextBlock Text="URL" Style="{StaticResource EntryTextBlockStyle}"/> <TextBlock Text="URL" Style="{StaticResource EntryTextBlockStyle}"/>
<local:TextBoxWithButton x:Uid="UrlTextBox" Text="{Binding Url, Mode=TwoWay}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonSymbol="&#xE111;" IsEnabled="{Binding IsCurrentEntry}"> <local:TextBoxWithButton x:Uid="UrlTextBox" Text="{Binding Url, Mode=TwoWay}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonSymbol="&#xE111;" IsEnabled="{Binding IsCurrentEntry}">
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>

View File

@@ -5,3 +5,4 @@ Ability to manually reorder groups
Ability to set max history count and size Ability to set max history count and size
Design changes Design changes
Update to KeePassLib version 2.45 Update to KeePassLib version 2.45
Bug corrections

View File

@@ -5,3 +5,4 @@ Possibilite de reorganiser les groupes manuellement
Possibilite de parametrer le nombre max et la taille de l'historique Possibilite de parametrer le nombre max et la taille de l'historique
Quelques changements de design Quelques changements de design
Mise a jour de la KeePassLib version 2.45 Mise a jour de la KeePassLib version 2.45
Correction de bugs

View File

@@ -32,6 +32,7 @@
public static string SpacePattern => nameof(SpacePattern); public static string SpacePattern => nameof(SpacePattern);
public static string SpecialPattern => nameof(SpecialPattern); public static string SpecialPattern => nameof(SpecialPattern);
public static string BracketsPattern => nameof(BracketsPattern); public static string BracketsPattern => nameof(BracketsPattern);
public static string PasswordLength => nameof(PasswordLength);
} }
} }
} }