Save error is now handled via Messenger instead of unhandled exception handler (which didn't work)

Save as actually works now
WIP Styles
Code cleanup
This commit is contained in:
Geoffroy BONNEVILLE
2020-05-04 12:48:27 +02:00
parent 97b10baedc
commit 1e7662def7
33 changed files with 268 additions and 268 deletions

View File

@@ -1,17 +1,16 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Storage;
using Windows.Storage.AccessCache;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Views;
using MediatR;
using Messages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.HockeyApp;
using ModernKeePass.Application;
@@ -41,6 +40,7 @@ namespace ModernKeePass
private readonly IHockeyClient _hockey;
private readonly IDialogService _dialog;
private readonly INotificationService _notification;
private readonly IFileProxy _file;
public static IServiceProvider Services { get; private set; }
@@ -66,57 +66,33 @@ namespace ModernKeePass
_dialog = Services.GetService<IDialogService>();
_notification = Services.GetService<INotificationService>();
_hockey = Services.GetService<IHockeyClient>();
_file = Services.GetService<IFileProxy>();
var messenger = Services.GetService<IMessenger>();
InitializeComponent();
Suspending += OnSuspending;
Resuming += OnResuming;
UnhandledException += OnUnhandledException;
messenger.Register<SaveErrorMessage>(this, async message => await HandelSaveError(message.Message));
}
private async Task HandelSaveError(string message)
{
_notification.Show(_resource.GetResourceValue("MessageDialogSaveErrorTitle"), message);
var database = await _mediator.Send(new GetDatabaseQuery());
var file = await _file.CreateFile($"{database.Name} - copy",
Domain.Common.Constants.Extensions.Kdbx,
_resource.GetResourceValue("MessageDialogSaveErrorFileTypeDesc"), true);
if (file != null) await _mediator.Send(new SaveDatabaseCommand { FilePath = file.Id });
}
#region Event Handlers
private async void OnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs)
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// Save the argument exception because it's cleared on first access
var exception = unhandledExceptionEventArgs.Exception;
var realException =
exception is TargetInvocationException &&
exception.InnerException != null
? exception.InnerException
: exception;
_hockey.TrackException(realException);
if (realException is SaveException)
{
// TODO: this is not working
unhandledExceptionEventArgs.Handled = true;
await _dialog.ShowMessage(realException.Message,
_resource.GetResourceValue("MessageDialogSaveErrorTitle"),
_resource.GetResourceValue("MessageDialogSaveErrorButtonSaveAs"),
_resource.GetResourceValue("MessageDialogSaveErrorButtonDiscard"),
async isOk =>
{
if (isOk)
{
var database = await _mediator.Send(new GetDatabaseQuery());
var savePicker = new FileSavePicker
{
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
SuggestedFileName = $"{database.Name} - copy"
};
savePicker.FileTypeChoices.Add(
_resource.GetResourceValue("MessageDialogSaveErrorFileTypeDesc"),
new List<string> {".kdbx"});
var file = await savePicker.PickSaveFileAsync();
if (file != null)
{
var token = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name);
await _mediator.Send(new SaveDatabaseCommand {FilePath = token});
}
}
});
}
_hockey.TrackException(e.Exception);
_hockey.Flush();
}
/// <summary>

View File

@@ -1,5 +1,6 @@
using System.Reflection;
using AutoMapper;
using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Views;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.HockeyApp;
@@ -24,6 +25,7 @@ namespace ModernKeePass
nav.Configure(Constants.Navigation.GroupPage, typeof(GroupDetailPage));
return nav;
});
services.AddSingleton(provider => Messenger.Default);
services.AddTransient(typeof(IDialogService), typeof(DialogService));
services.AddSingleton(provider =>

View File

@@ -83,4 +83,7 @@
<SolidColorBrush x:Key="SliderTrackDecreaseBackgroundThemeBrush" Color="{ThemeResource MainColor}" />
<SolidColorBrush x:Key="SliderTrackDecreasePressedBackgroundThemeBrush" Color="{ThemeResource MainColorDark}" />
<SolidColorBrush x:Key="SliderTrackDecreasePointerOverBackgroundThemeBrush" Color="{ThemeResource MainColorLight}" />
<Thickness x:Key="FlyoutBorderThemeThickness">0</Thickness>
<Thickness x:Key="MenuFlyoutPresenterThemePadding">0</Thickness>
</ResourceDictionary>

View File

@@ -9,6 +9,7 @@ using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Views;
using MediatR;
using Messages;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Database.Commands.SaveDatabase;
using ModernKeePass.Application.Database.Models;
@@ -28,12 +29,13 @@ using ModernKeePass.Application.Security.Queries.EstimatePasswordComplexity;
using ModernKeePass.Domain.Enums;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Common;
using ModernKeePass.Domain.Exceptions;
using ModernKeePass.Extensions;
using ModernKeePass.Models;
namespace ModernKeePass.ViewModels
{
public class EntryDetailVm : ObservableObject
public class EntryDetailVm : ViewModelBase
{
public bool IsRevealPasswordEnabled => !string.IsNullOrEmpty(Password);
public bool HasExpired => HasExpirationDate && ExpiryDate < DateTime.Now;
@@ -362,7 +364,14 @@ namespace ModernKeePass.ViewModels
private async Task SaveChanges()
{
await AddHistory();
await _mediator.Send(new SaveDatabaseCommand());
try
{
await _mediator.Send(new SaveDatabaseCommand());
}
catch (SaveException e)
{
MessengerInstance.Send(new SaveErrorMessage { Message = e.Message });
}
SaveCommand.RaiseCanExecuteChanged();
_isDirty = false;
}

View File

@@ -9,6 +9,7 @@ using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Views;
using MediatR;
using Messages;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Database.Commands.SaveDatabase;
using ModernKeePass.Application.Database.Models;
@@ -29,11 +30,12 @@ using ModernKeePass.Application.Group.Queries.GetGroup;
using ModernKeePass.Application.Group.Queries.SearchEntries;
using ModernKeePass.Common;
using ModernKeePass.Domain.Enums;
using ModernKeePass.Domain.Exceptions;
using ModernKeePass.Models;
namespace ModernKeePass.ViewModels
{
public class GroupDetailVm : ObservableObject
public class GroupDetailVm : ViewModelBase
{
public ObservableCollection<EntryVm> Entries { get; private set; }
@@ -182,7 +184,14 @@ namespace ModernKeePass.ViewModels
private async Task SaveChanges()
{
await _mediator.Send(new SaveDatabaseCommand());
try
{
await _mediator.Send(new SaveDatabaseCommand());
}
catch (SaveException e)
{
MessengerInstance.Send(new SaveErrorMessage { Message = e.Message });
}
SaveCommand.RaiseCanExecuteChanged();
}

View File

@@ -183,6 +183,7 @@ namespace ModernKeePass.ViewModels
}
catch (SaveException exception)
{
// TODO: Implement save as
_notification.Show(exception.Source, exception.Message);
return;
}

View File

@@ -13,7 +13,7 @@
</Page.Resources>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<HyperlinkButton x:Uid="NewCreateButton" Click="CreateDatabaseButton_OnClick" />
<HyperlinkButton x:Uid="NewCreateButton" Command="{Binding CreateDatabaseFileCommand}" />
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" x:Uid="NewCreateDesc" />
<Border HorizontalAlignment="Left" BorderThickness="1" BorderBrush="AliceBlue" Width="550" Visibility="{Binding IsFileSelected, Converter={StaticResource BooleanToVisibilityConverter}}">
<StackPanel Margin="25,0,25,0">

View File

@@ -1,11 +1,4 @@
using System;
using System.Collections.Generic;
using Windows.Storage.AccessCache;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using ModernKeePass.ViewModels;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace ModernKeePass.Views
{
@@ -14,28 +7,9 @@ namespace ModernKeePass.Views
/// </summary>
public sealed partial class NewDatabasePage
{
private NewVm Model => (NewVm)DataContext;
public NewDatabasePage()
{
InitializeComponent();
}
private async void CreateDatabaseButton_OnClick(object sender, RoutedEventArgs e)
{
var savePicker = new FileSavePicker
{
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
SuggestedFileName = "New Database"
};
savePicker.FileTypeChoices.Add("KeePass 2.x database", new List<string> {".kdbx"});
var file = await savePicker.PickSaveFileAsync().AsTask();
if (file == null) return;
Model.Token = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name);
Model.Name = file.Name;
Model.Path = file.Path;
}
}
}

View File

@@ -13,7 +13,7 @@
</Page.Resources>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<HyperlinkButton x:Uid="OpenBrowseButton" Click="ButtonBase_OnClick" />
<HyperlinkButton x:Uid="OpenBrowseButton" Command="{Binding OpenDatabaseFileCommand}" />
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" x:Uid="OpenBrowseDesc" />
<!--<HyperlinkButton x:Uid="OpenUrlButton" IsEnabled="False" Foreground="{StaticResource MainColor}" Style="{StaticResource MainColorHyperlinkButton}" />
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" x:Uid="OpenUrlDesc" />-->

View File

@@ -1,8 +1,4 @@
using System;
using Windows.Storage.AccessCache;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Navigation;
using ModernKeePass.Domain.Dtos;
using ModernKeePass.ViewModels;
@@ -26,31 +22,7 @@ namespace ModernKeePass.Views
{
base.OnNavigatedTo(e);
var file = e.Parameter as FileInfo;
if (file != null)
{
Model.Path = file.Path;
Model.Name = file.Name;
Model.Token = file.Id;
}
}
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
var picker = new FileOpenPicker
{
ViewMode = PickerViewMode.List,
SuggestedStartLocation = PickerLocationId.DocumentsLibrary
};
picker.FileTypeFilter.Add(".kdbx");
// Application now has read/write access to the picked file
var file = await picker.PickSingleFileAsync().AsTask();
if (file == null) return;
// TODO: use service
Model.Token = StorageApplicationPermissions.MostRecentlyUsedList.Add(file, file.Path);
Model.Path = file.Path;
Model.Name = file.Name;
Model.SetFileInformation(file);
}
}
}

View File

@@ -1,7 +1,5 @@
// Pour en savoir plus sur le modèle d'élément Page vierge, consultez la page http://go.microsoft.com/fwlink/?LinkId=234238
using ModernKeePass.ViewModels;
namespace ModernKeePass.Views
{
/// <summary>

View File

@@ -10,7 +10,7 @@
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<HyperlinkButton x:Uid="SaveButton" Command="{Binding SaveCommand}" />
<TextBlock x:Uid="SaveDesc" Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" />
<HyperlinkButton x:Uid="SaveAsButton" Click="SaveAsButton_OnClick" />
<HyperlinkButton x:Uid="SaveAsButton" Command="{Binding SaveAsCommand}" />
<TextBlock x:Uid="SaveAsDesc" Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" />
<HyperlinkButton x:Uid="CloseButton" Command="{Binding CloseCommand}" />
<TextBlock x:Uid="CloseDesc" Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" />

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using ModernKeePass.ViewModels;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace ModernKeePass.Views
{
@@ -13,24 +7,9 @@ namespace ModernKeePass.Views
/// </summary>
public sealed partial class SaveDatabasePage
{
public SaveVm Model => (SaveVm)DataContext;
public SaveDatabasePage()
{
InitializeComponent();
}
private async void SaveAsButton_OnClick(object sender, RoutedEventArgs e)
{
var savePicker = new FileSavePicker
{
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
SuggestedFileName = "New Database"
};
savePicker.FileTypeChoices.Add("KeePass 2.x database", new List<string> { ".kdbx" });
var file = await savePicker.PickSaveFileAsync().AsTask();
if (file == null) return;
await Model.Save(file);
}
}
}

View File

@@ -40,7 +40,7 @@
<HyperlinkButton Grid.Row="1" Grid.Column="1" Margin="-15,0,0,0"
x:Name="HyperlinkButton"
Content="{Binding KeyFileText}"
Click="KeyFileButton_Click" />
Command="{Binding OpenKeyFileCommand}" />
<Button Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2"
x:Uid="OpenDatabaseControlButton"

View File

@@ -1,7 +1,4 @@
using System;
using Windows.Storage.AccessCache;
using Windows.Storage.Pickers;
using Windows.System;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Input;
using ModernKeePass.ViewModels;
@@ -38,24 +35,5 @@ namespace ModernKeePass.Views.UserControls
// Stop the event from triggering twice
e.Handled = true;
}
private async void KeyFileButton_Click(object sender, RoutedEventArgs e)
{
var picker = new FileOpenPicker
{
ViewMode = PickerViewMode.List,
SuggestedStartLocation = PickerLocationId.DocumentsLibrary
};
picker.FileTypeFilter.Add("*");
// Application now has read/write access to the picked file
var file = await picker.PickSingleFileAsync();
if (file == null) return;
var token = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name);
Model.KeyFilePath = token;
Model.KeyFileText = file.Name;
Model.HasKeyFile = true;
}
}
}

View File

@@ -13,7 +13,7 @@
<converters:DoubleToSolidColorBrushConverter x:Key="DoubleToSolidColorBrushConverter"/>
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
</UserControl.Resources>
<Grid x:Name="Grid" DataContext="{Binding Source={StaticResource Locator}, Path=SetCredentials}">
<Grid DataContext="{Binding Source={StaticResource Locator}, Path=SetCredentials}">
<Grid.Resources>
<SolidColorBrush x:Key="ErrorBrush" Color="Red" />
<SolidColorBrush x:Key="ValidBrush" Color="Green" />
@@ -57,11 +57,9 @@
<HyperlinkButton Grid.Row="3" Grid.Column="1" Margin="-15,0,0,0"
x:Name="HyperlinkButton"
Content="{Binding KeyFileText}"
IsEnabled="{Binding HasKeyFile}"
Click="KeyFileButton_Click" />
Command="{Binding OpenKeyFileCommand}" />
<HyperlinkButton Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right"
IsEnabled="{Binding HasKeyFile}"
Click="CreateKeyFileButton_Click">
Command="{Binding CreateKeyFileCommand}">
<SymbolIcon Symbol="Add">
<ToolTipService.ToolTip>
<ToolTip x:Uid="CompositeKeyNewKeyFileTooltip" />

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using Windows.Storage.AccessCache;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using ModernKeePass.ViewModels;
using Windows.UI.Xaml;
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
@@ -11,8 +6,6 @@ namespace ModernKeePass.Views.UserControls
{
public sealed partial class SetCredentialsUserControl
{
private SetCredentialsVm Model => (SetCredentialsVm)Grid.DataContext;
public string ButtonLabel
{
get { return (string)GetValue(ButtonLabelProperty); }
@@ -29,40 +22,5 @@ namespace ModernKeePass.Views.UserControls
{
InitializeComponent();
}
private async void KeyFileButton_Click(object sender, RoutedEventArgs e)
{
var picker =
new FileOpenPicker
{
ViewMode = PickerViewMode.List,
SuggestedStartLocation = PickerLocationId.DocumentsLibrary
};
picker.FileTypeFilter.Add("*");
// Application now has read/write access to the picked file
var file = await picker.PickSingleFileAsync();
if (file == null) return;
Model.KeyFilePath = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name);
Model.KeyFileText = file.Name;
}
private async void CreateKeyFileButton_Click(object sender, RoutedEventArgs e)
{
var savePicker = new FileSavePicker
{
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
SuggestedFileName = "Key"
};
savePicker.FileTypeChoices.Add("Key file", new List<string> { ".key" });
var file = await savePicker.PickSaveFileAsync();
if (file == null) return;
Model.KeyFilePath = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name);
Model.KeyFileText = file.Name;
await Model.GenerateKeyFile();
}
}
}