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

@@ -27,7 +27,6 @@ namespace ModernKeePass.Application.Common.Interfaces
Task ReOpen(byte[] file); Task ReOpen(byte[] file);
Task Create(Credentials credentials, string name, DatabaseVersion version = DatabaseVersion.V4); Task Create(Credentials credentials, string name, DatabaseVersion version = DatabaseVersion.V4);
Task<byte[]> SaveDatabase(); Task<byte[]> SaveDatabase();
Task<byte[]> SaveDatabase(byte[] newFileContents);
void UpdateCredentials(Credentials credentials); void UpdateCredentials(Credentials credentials);
void CloseDatabase(); void CloseDatabase();

View File

@@ -1,12 +1,15 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using ModernKeePass.Domain.Dtos;
namespace ModernKeePass.Application.Common.Interfaces namespace ModernKeePass.Application.Common.Interfaces
{ {
public interface IFileProxy public interface IFileProxy
{ {
Task<byte[]> OpenBinaryFile(string path); Task<FileInfo> OpenFile(string name, string extension, bool addToRecent);
Task<IList<string>> OpenTextFile(string path); Task<FileInfo> CreateFile(string name, string extension, string description, bool addToRecent);
Task<byte[]> ReadBinaryFile(string path);
Task<IList<string>> ReadTextFile(string path);
Task WriteBinaryContentsToFile(string path, byte[] contents); Task WriteBinaryContentsToFile(string path, byte[] contents);
void ReleaseFile(string path); void ReleaseFile(string path);
} }

View File

@@ -44,7 +44,7 @@ namespace ModernKeePass.Application.Database.Commands.CreateDatabase
await _database.Create(new Credentials await _database.Create(new Credentials
{ {
KeyFileContents = !string.IsNullOrEmpty(message.KeyFilePath) ? await _file.OpenBinaryFile(message.KeyFilePath) : null, KeyFileContents = !string.IsNullOrEmpty(message.KeyFilePath) ? await _file.ReadBinaryFile(message.KeyFilePath) : null,
Password = message.Password Password = message.Password
}, message.Name, version); }, message.Name, version);
_database.FileAccessToken = message.FilePath; _database.FileAccessToken = message.FilePath;

View File

@@ -27,27 +27,20 @@ namespace ModernKeePass.Application.Database.Commands.SaveDatabase
try try
{ {
byte[] contents; if (!string.IsNullOrEmpty(message.FilePath))
if (string.IsNullOrEmpty(message.FilePath))
{ {
contents = await _database.SaveDatabase(); _database.FileAccessToken = message.FilePath;
}
// Test DB integrity before writing changes to file var contents = await _database.SaveDatabase();
// Test DB integrity
_database.CloseDatabase(); _database.CloseDatabase();
await _database.ReOpen(contents); await _database.ReOpen(contents);
// Transactional write to file
await _file.WriteBinaryContentsToFile(_database.FileAccessToken, contents); await _file.WriteBinaryContentsToFile(_database.FileAccessToken, contents);
} }
else
{
var newFileContents = await _file.OpenBinaryFile(message.FilePath);
contents = await _database.SaveDatabase(newFileContents);
await _file.WriteBinaryContentsToFile(message.FilePath, contents);
_file.ReleaseFile(_database.FileAccessToken);
_database.FileAccessToken = message.FilePath;
}
}
catch (Exception exception) catch (Exception exception)
{ {
throw new SaveException(exception); throw new SaveException(exception);

View File

@@ -27,7 +27,7 @@ namespace ModernKeePass.Application.Database.Commands.UpdateCredentials
if (!_database.IsOpen) throw new DatabaseClosedException(); if (!_database.IsOpen) throw new DatabaseClosedException();
_database.UpdateCredentials(new Credentials _database.UpdateCredentials(new Credentials
{ {
KeyFileContents = !string.IsNullOrEmpty(message.KeyFilePath) ? await _file.OpenBinaryFile(message.KeyFilePath) : null, KeyFileContents = !string.IsNullOrEmpty(message.KeyFilePath) ? await _file.ReadBinaryFile(message.KeyFilePath) : null,
Password = message.Password Password = message.Password
}); });
} }

View File

@@ -27,11 +27,11 @@ namespace ModernKeePass.Application.Database.Queries.OpenDatabase
{ {
if (_database.IsDirty) throw new DatabaseOpenException(); if (_database.IsDirty) throw new DatabaseOpenException();
var file = await _file.OpenBinaryFile(message.FilePath); var file = await _file.ReadBinaryFile(message.FilePath);
var hasKeyFile = !string.IsNullOrEmpty(message.KeyFilePath); var hasKeyFile = !string.IsNullOrEmpty(message.KeyFilePath);
await _database.Open(file, new Credentials await _database.Open(file, new Credentials
{ {
KeyFileContents = hasKeyFile ? await _file.OpenBinaryFile(message.KeyFilePath): null, KeyFileContents = hasKeyFile ? await _file.ReadBinaryFile(message.KeyFilePath): null,
Password = message.Password Password = message.Password
}); });
if (hasKeyFile) _file.ReleaseFile(message.KeyFilePath); if (hasKeyFile) _file.ReleaseFile(message.KeyFilePath);

View File

@@ -23,7 +23,7 @@ namespace ModernKeePass.Application.Database.Queries.ReOpenDatabase
if (_database.IsOpen) throw new DatabaseOpenException(); if (_database.IsOpen) throw new DatabaseOpenException();
if (string.IsNullOrEmpty(_database.FileAccessToken)) throw new DatabaseClosedException(); if (string.IsNullOrEmpty(_database.FileAccessToken)) throw new DatabaseClosedException();
var file = await _file.OpenBinaryFile(_database.FileAccessToken); var file = await _file.ReadBinaryFile(_database.FileAccessToken);
await _database.ReOpen(file); await _database.ReOpen(file);
} }
} }

View File

@@ -3,5 +3,11 @@
public static class Constants public static class Constants
{ {
public static string EmptyId => "00000000000000000000000000000000"; public static string EmptyId => "00000000000000000000000000000000";
public static class Extensions
{
public static string Any => "*";
public static string Kdbx => ".kdbx";
}
} }
} }

View File

@@ -152,15 +152,6 @@ namespace ModernKeePass.Infrastructure.KeePass
}); });
} }
public async Task<byte[]> SaveDatabase(byte[] newFileContents)
{
return await Task.Run(() =>
{
_pwDatabase.SaveAs(IOConnectionInfo.FromByteArray(newFileContents), true, new NullStatusLogger());
return _pwDatabase.IOConnectionInfo.Bytes;
});
}
public void CloseDatabase() public void CloseDatabase()
{ {
_pwDatabase?.Close(); _pwDatabase?.Close();

View File

@@ -5,20 +5,69 @@ using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks; using System.Threading.Tasks;
using Windows.Storage; using Windows.Storage;
using Windows.Storage.AccessCache; using Windows.Storage.AccessCache;
using Windows.Storage.Pickers;
using ModernKeePass.Application.Common.Interfaces; using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.Dtos;
namespace ModernKeePass.Infrastructure.UWP namespace ModernKeePass.Infrastructure.UWP
{ {
public class StorageFileClient: IFileProxy public class StorageFileClient: IFileProxy
{ {
public async Task<byte[]> OpenBinaryFile(string path) public async Task<FileInfo> OpenFile(string name, string extension, bool addToRecent)
{
var picker = new FileOpenPicker
{
ViewMode = PickerViewMode.List,
SuggestedStartLocation = PickerLocationId.DocumentsLibrary
};
picker.FileTypeFilter.Add(extension);
// Application now has read/write access to the picked file
var file = await picker.PickSingleFileAsync().AsTask();
if (file == null) return null;
var token = addToRecent
? StorageApplicationPermissions.MostRecentlyUsedList.Add(file, file.Path)
: StorageApplicationPermissions.FutureAccessList.Add(file, file.Name);
return new FileInfo
{
Id = token,
Name = file.Name,
Path = file.Path
};
}
public async Task<FileInfo> CreateFile(string name, string extension, string description, bool addToRecent)
{
var savePicker = new FileSavePicker
{
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
SuggestedFileName = name
};
savePicker.FileTypeChoices.Add(description, new List<string> { extension });
var file = await savePicker.PickSaveFileAsync().AsTask();
if (file == null) return null;
var token = addToRecent
? StorageApplicationPermissions.MostRecentlyUsedList.Add(file, file.Path)
: StorageApplicationPermissions.FutureAccessList.Add(file, file.Name);
return new FileInfo
{
Id = token,
Name = file.Name,
Path = file.Path
};
}
public async Task<byte[]> ReadBinaryFile(string path)
{ {
var file = await GetFile(path); var file = await GetFile(path);
var result = await FileIO.ReadBufferAsync(file).AsTask(); var result = await FileIO.ReadBufferAsync(file).AsTask();
return result.ToArray(); return result.ToArray();
} }
public async Task<IList<string>> OpenTextFile(string path) public async Task<IList<string>> ReadTextFile(string path)
{ {
var file = await GetFile(path); var file = await GetFile(path);
var result = await FileIO.ReadLinesAsync(file).AsTask(); var result = await FileIO.ReadLinesAsync(file).AsTask();

View File

@@ -1,17 +1,16 @@
using System; using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Windows.ApplicationModel; using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation; using Windows.ApplicationModel.Activation;
using Windows.Storage; using Windows.Storage;
using Windows.Storage.AccessCache; using Windows.Storage.AccessCache;
using Windows.Storage.Pickers;
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;
using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Views; using GalaSoft.MvvmLight.Views;
using MediatR; using MediatR;
using Messages;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.HockeyApp; using Microsoft.HockeyApp;
using ModernKeePass.Application; using ModernKeePass.Application;
@@ -41,6 +40,7 @@ namespace ModernKeePass
private readonly IHockeyClient _hockey; private readonly IHockeyClient _hockey;
private readonly IDialogService _dialog; private readonly IDialogService _dialog;
private readonly INotificationService _notification; private readonly INotificationService _notification;
private readonly IFileProxy _file;
public static IServiceProvider Services { get; private set; } public static IServiceProvider Services { get; private set; }
@@ -66,57 +66,33 @@ namespace ModernKeePass
_dialog = Services.GetService<IDialogService>(); _dialog = Services.GetService<IDialogService>();
_notification = Services.GetService<INotificationService>(); _notification = Services.GetService<INotificationService>();
_hockey = Services.GetService<IHockeyClient>(); _hockey = Services.GetService<IHockeyClient>();
_file = Services.GetService<IFileProxy>();
var messenger = Services.GetService<IMessenger>();
InitializeComponent(); InitializeComponent();
Suspending += OnSuspending; Suspending += OnSuspending;
Resuming += OnResuming; Resuming += OnResuming;
UnhandledException += OnUnhandledException; 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 #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 _hockey.TrackException(e.Exception);
var exception = unhandledExceptionEventArgs.Exception; _hockey.Flush();
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});
}
}
});
}
} }
/// <summary> /// <summary>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -13,7 +13,7 @@
</Page.Resources> </Page.Resources>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <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" /> <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}}"> <Border HorizontalAlignment="Left" BorderThickness="1" BorderBrush="AliceBlue" Width="550" Visibility="{Binding IsFileSelected, Converter={StaticResource BooleanToVisibilityConverter}}">
<StackPanel Margin="25,0,25,0"> <StackPanel Margin="25,0,25,0">

View File

@@ -1,11 +1,4 @@
using System; // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
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
namespace ModernKeePass.Views namespace ModernKeePass.Views
{ {
@@ -14,28 +7,9 @@ namespace ModernKeePass.Views
/// </summary> /// </summary>
public sealed partial class NewDatabasePage public sealed partial class NewDatabasePage
{ {
private NewVm Model => (NewVm)DataContext;
public NewDatabasePage() public NewDatabasePage()
{ {
InitializeComponent(); 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> </Page.Resources>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <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" /> <TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" x:Uid="OpenBrowseDesc" />
<!--<HyperlinkButton x:Uid="OpenUrlButton" IsEnabled="False" Foreground="{StaticResource MainColor}" Style="{StaticResource MainColorHyperlinkButton}" /> <!--<HyperlinkButton x:Uid="OpenUrlButton" IsEnabled="False" Foreground="{StaticResource MainColor}" Style="{StaticResource MainColorHyperlinkButton}" />
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" x:Uid="OpenUrlDesc" />--> <TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" x:Uid="OpenUrlDesc" />-->

View File

@@ -1,8 +1,4 @@
using System; using Windows.UI.Xaml.Navigation;
using Windows.Storage.AccessCache;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Navigation;
using ModernKeePass.Domain.Dtos; using ModernKeePass.Domain.Dtos;
using ModernKeePass.ViewModels; using ModernKeePass.ViewModels;
@@ -26,31 +22,7 @@ namespace ModernKeePass.Views
{ {
base.OnNavigatedTo(e); base.OnNavigatedTo(e);
var file = e.Parameter as FileInfo; var file = e.Parameter as FileInfo;
if (file != null) Model.SetFileInformation(file);
{
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;
} }
} }
} }

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 // 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 namespace ModernKeePass.Views
{ {
/// <summary> /// <summary>

View File

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

View File

@@ -1,10 +1,4 @@
using System; // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
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
namespace ModernKeePass.Views namespace ModernKeePass.Views
{ {
@@ -13,24 +7,9 @@ namespace ModernKeePass.Views
/// </summary> /// </summary>
public sealed partial class SaveDatabasePage public sealed partial class SaveDatabasePage
{ {
public SaveVm Model => (SaveVm)DataContext;
public SaveDatabasePage() public SaveDatabasePage()
{ {
InitializeComponent(); 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" <HyperlinkButton Grid.Row="1" Grid.Column="1" Margin="-15,0,0,0"
x:Name="HyperlinkButton" x:Name="HyperlinkButton"
Content="{Binding KeyFileText}" Content="{Binding KeyFileText}"
Click="KeyFileButton_Click" /> Command="{Binding OpenKeyFileCommand}" />
<Button Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2" <Button Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2"
x:Uid="OpenDatabaseControlButton" x:Uid="OpenDatabaseControlButton"

View File

@@ -1,7 +1,4 @@
using System; using Windows.System;
using Windows.Storage.AccessCache;
using Windows.Storage.Pickers;
using Windows.System;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Input;
using ModernKeePass.ViewModels; using ModernKeePass.ViewModels;
@@ -38,24 +35,5 @@ namespace ModernKeePass.Views.UserControls
// Stop the event from triggering twice // Stop the event from triggering twice
e.Handled = true; 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:DoubleToSolidColorBrushConverter x:Key="DoubleToSolidColorBrushConverter"/>
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/> <converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
</UserControl.Resources> </UserControl.Resources>
<Grid x:Name="Grid" DataContext="{Binding Source={StaticResource Locator}, Path=SetCredentials}"> <Grid DataContext="{Binding Source={StaticResource Locator}, Path=SetCredentials}">
<Grid.Resources> <Grid.Resources>
<SolidColorBrush x:Key="ErrorBrush" Color="Red" /> <SolidColorBrush x:Key="ErrorBrush" Color="Red" />
<SolidColorBrush x:Key="ValidBrush" Color="Green" /> <SolidColorBrush x:Key="ValidBrush" Color="Green" />
@@ -57,11 +57,9 @@
<HyperlinkButton Grid.Row="3" Grid.Column="1" Margin="-15,0,0,0" <HyperlinkButton Grid.Row="3" Grid.Column="1" Margin="-15,0,0,0"
x:Name="HyperlinkButton" x:Name="HyperlinkButton"
Content="{Binding KeyFileText}" Content="{Binding KeyFileText}"
IsEnabled="{Binding HasKeyFile}" Command="{Binding OpenKeyFileCommand}" />
Click="KeyFileButton_Click" />
<HyperlinkButton Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" <HyperlinkButton Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right"
IsEnabled="{Binding HasKeyFile}" Command="{Binding CreateKeyFileCommand}">
Click="CreateKeyFileButton_Click">
<SymbolIcon Symbol="Add"> <SymbolIcon Symbol="Add">
<ToolTipService.ToolTip> <ToolTipService.ToolTip>
<ToolTip x:Uid="CompositeKeyNewKeyFileTooltip" /> <ToolTip x:Uid="CompositeKeyNewKeyFileTooltip" />

View File

@@ -1,9 +1,4 @@
using System; using Windows.UI.Xaml;
using System.Collections.Generic;
using Windows.Storage.AccessCache;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using ModernKeePass.ViewModels;
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 // 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 public sealed partial class SetCredentialsUserControl
{ {
private SetCredentialsVm Model => (SetCredentialsVm)Grid.DataContext;
public string ButtonLabel public string ButtonLabel
{ {
get { return (string)GetValue(ButtonLabelProperty); } get { return (string)GetValue(ButtonLabelProperty); }
@@ -29,40 +22,5 @@ namespace ModernKeePass.Views.UserControls
{ {
InitializeComponent(); 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();
}
} }
} }

View File

@@ -1,4 +1,5 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Views; using GalaSoft.MvvmLight.Views;
using MediatR; using MediatR;
using Messages; using Messages;
@@ -15,16 +16,31 @@ namespace ModernKeePass.ViewModels
private readonly IMediator _mediator; private readonly IMediator _mediator;
private readonly ISettingsProxy _settings; private readonly ISettingsProxy _settings;
private readonly INavigationService _navigation; private readonly INavigationService _navigation;
private readonly IFileProxy _file;
public NewVm(IMediator mediator, IRecentProxy recent, ISettingsProxy settings, INavigationService navigation) public RelayCommand CreateDatabaseFileCommand { get; }
public NewVm(IMediator mediator, ISettingsProxy settings, INavigationService navigation, IFileProxy file): base(file)
{ {
_mediator = mediator; _mediator = mediator;
_settings = settings; _settings = settings;
_navigation = navigation; _navigation = navigation;
_file = file;
CreateDatabaseFileCommand = new RelayCommand(async () => await CreateDatabaseFile());
MessengerInstance.Register<CredentialsSetMessage>(this, async m => await TryCreateDatabase(m)); MessengerInstance.Register<CredentialsSetMessage>(this, async m => await TryCreateDatabase(m));
} }
private async Task CreateDatabaseFile()
{
// TODO: get these from resource
var file = await _file.CreateFile("New Database", Domain.Common.Constants.Extensions.Kdbx, "KeePass 2.x database", true);
Token = file.Id;
Path = file.Path;
Name = file.Name;
}
private async Task TryCreateDatabase(CredentialsSetMessage message) private async Task TryCreateDatabase(CredentialsSetMessage message)
{ {
var database = await _mediator.Send(new GetDatabaseQuery()); var database = await _mediator.Send(new GetDatabaseQuery());
@@ -45,7 +61,7 @@ namespace ModernKeePass.ViewModels
Password = message.Password, Password = message.Password,
Name = "ModernKeePass", Name = "ModernKeePass",
Version = _settings.GetSetting(Constants.Settings.DefaultFileFormat, "4"), Version = _settings.GetSetting(Constants.Settings.DefaultFileFormat, "4"),
CreateSampleData = _settings.GetSetting<bool>(Constants.Settings.Sample, true) CreateSampleData = _settings.GetSetting(Constants.Settings.Sample, true)
}); });
var database = await _mediator.Send(new GetDatabaseQuery()); var database = await _mediator.Send(new GetDatabaseQuery());

View File

@@ -1,9 +1,15 @@
using GalaSoft.MvvmLight; using System.Threading.Tasks;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.Common;
using ModernKeePass.Domain.Dtos;
namespace ModernKeePass.ViewModels namespace ModernKeePass.ViewModels
{ {
public class OpenVm: ViewModelBase public class OpenVm: ViewModelBase
{ {
private readonly IFileProxy _file;
private string _name; private string _name;
private string _path; private string _path;
private string _token; private string _token;
@@ -30,5 +36,27 @@ namespace ModernKeePass.ViewModels
get { return _path; } get { return _path; }
set { Set(() => Path, ref _path, value); } set { Set(() => Path, ref _path, value); }
} }
public RelayCommand OpenDatabaseFileCommand { get; }
public OpenVm(IFileProxy file)
{
_file = file;
OpenDatabaseFileCommand = new RelayCommand(async () => await OpenDatabaseFile());
}
public void SetFileInformation(FileInfo file)
{
if (file == null) return;
Token = file.Id;
Path = file.Path;
Name = file.Name;
}
private async Task OpenDatabaseFile()
{
var file = await _file.OpenFile(string.Empty, Constants.Extensions.Kdbx, true);
SetFileInformation(file);
}
} }
} }

View File

@@ -1,46 +1,61 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Windows.Storage; using GalaSoft.MvvmLight;
using Windows.Storage.AccessCache; using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Views; using GalaSoft.MvvmLight.Views;
using MediatR; using MediatR;
using Messages;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Database.Commands.CloseDatabase; using ModernKeePass.Application.Database.Commands.CloseDatabase;
using ModernKeePass.Application.Database.Commands.SaveDatabase; using ModernKeePass.Application.Database.Commands.SaveDatabase;
using ModernKeePass.Application.Database.Queries.GetDatabase; using ModernKeePass.Application.Database.Queries.GetDatabase;
using ModernKeePass.Common; using ModernKeePass.Common;
using RelayCommand = GalaSoft.MvvmLight.Command.RelayCommand; using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.ViewModels namespace ModernKeePass.ViewModels
{ {
public class SaveVm public class SaveVm: ViewModelBase
{ {
public bool IsSaveEnabled => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult().IsDirty; public bool IsSaveEnabled => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult().IsDirty;
public RelayCommand SaveAsCommand { get; }
public RelayCommand SaveCommand { get; } public RelayCommand SaveCommand { get; }
public RelayCommand CloseCommand { get; } public RelayCommand CloseCommand { get; }
private readonly IMediator _mediator; private readonly IMediator _mediator;
private readonly INavigationService _navigation; private readonly INavigationService _navigation;
private readonly IFileProxy _file;
public SaveVm(IMediator mediator, INavigationService navigation) public SaveVm(IMediator mediator, INavigationService navigation, IFileProxy file)
{ {
_mediator = mediator; _mediator = mediator;
_navigation = navigation; _navigation = navigation;
_file = file;
SaveAsCommand = new RelayCommand(async () => await SaveAs());
SaveCommand = new RelayCommand(async () => await Save(), () => IsSaveEnabled); SaveCommand = new RelayCommand(async () => await Save(), () => IsSaveEnabled);
CloseCommand = new RelayCommand(async () => await Close()); CloseCommand = new RelayCommand(async () => await Close());
} }
public async Task Save(bool close = true) private async Task SaveAs()
{ {
await _mediator.Send(new SaveDatabaseCommand()); // TODO: get these from resource
if (close) await _mediator.Send(new CloseDatabaseCommand()); var file = await _file.CreateFile("New Database", Domain.Common.Constants.Extensions.Kdbx, "KeePass 2.x database", true);
await _mediator.Send(new SaveDatabaseCommand { FilePath = file.Id });
_navigation.NavigateTo(Constants.Navigation.MainPage); _navigation.NavigateTo(Constants.Navigation.MainPage);
} }
public async Task Save(StorageFile file) public async Task Save()
{ {
var token = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name); try
await _mediator.Send(new SaveDatabaseCommand { FilePath = token }); {
_navigation.NavigateTo(Constants.Navigation.MainPage); await _mediator.Send(new SaveDatabaseCommand());
await Close();
}
catch (SaveException e)
{
MessengerInstance.Send(new SaveErrorMessage { Message = e.Message });
}
} }
public async Task Close() public async Task Close()

View File

@@ -9,6 +9,7 @@ using Messages;
using ModernKeePass.Application.Common.Interfaces; using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Database.Queries.GetDatabase; using ModernKeePass.Application.Database.Queries.GetDatabase;
using ModernKeePass.Application.Database.Queries.OpenDatabase; using ModernKeePass.Application.Database.Queries.OpenDatabase;
using ModernKeePass.Domain.Common;
namespace ModernKeePass.ViewModels namespace ModernKeePass.ViewModels
{ {
@@ -85,11 +86,13 @@ namespace ModernKeePass.ViewModels
public bool IsValid => !IsOpening && (HasPassword || HasKeyFile && !string.IsNullOrEmpty(KeyFilePath)); public bool IsValid => !IsOpening && (HasPassword || HasKeyFile && !string.IsNullOrEmpty(KeyFilePath));
public RelayCommand OpenKeyFileCommand { get; }
public RelayCommand<string> OpenDatabaseCommand { get; } public RelayCommand<string> OpenDatabaseCommand { get; }
private readonly IMediator _mediator; private readonly IMediator _mediator;
private readonly IResourceProxy _resource; private readonly IResourceProxy _resource;
private readonly INotificationService _notification; private readonly INotificationService _notification;
private readonly IFileProxy _file;
private bool _hasPassword; private bool _hasPassword;
private bool _hasKeyFile; private bool _hasKeyFile;
private bool _isOpening; private bool _isOpening;
@@ -99,15 +102,26 @@ namespace ModernKeePass.ViewModels
private string _keyFileText; private string _keyFileText;
private bool _isError; private bool _isError;
public OpenDatabaseControlVm(IMediator mediator, IResourceProxy resource, INotificationService notification) public OpenDatabaseControlVm(IMediator mediator, IResourceProxy resource, INotificationService notification, IFileProxy file)
{ {
_mediator = mediator; _mediator = mediator;
_resource = resource; _resource = resource;
_notification = notification; _notification = notification;
_file = file;
OpenKeyFileCommand = new RelayCommand(async () => await OpenKeyFile());
OpenDatabaseCommand = new RelayCommand<string>(async databaseFilePath => await TryOpenDatabase(databaseFilePath), _ => IsValid); OpenDatabaseCommand = new RelayCommand<string>(async databaseFilePath => await TryOpenDatabase(databaseFilePath), _ => IsValid);
_keyFileText = _resource.GetResourceValue("CompositeKeyDefaultKeyFile"); _keyFileText = _resource.GetResourceValue("CompositeKeyDefaultKeyFile");
} }
private async Task OpenKeyFile()
{
var file = await _file.OpenFile(string.Empty, Constants.Extensions.Any, false);
if (file == null) return;
KeyFilePath = file.Id;
KeyFileText = file.Name;
HasKeyFile = true;
}
public async Task TryOpenDatabase(string databaseFilePath) public async Task TryOpenDatabase(string databaseFilePath)
{ {
MessengerInstance.Send(new DatabaseOpeningMessage {Token = databaseFilePath}); MessengerInstance.Send(new DatabaseOpeningMessage {Token = databaseFilePath});

View File

@@ -5,6 +5,8 @@ using MediatR;
using Messages; using Messages;
using ModernKeePass.Application.Common.Interfaces; using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Security.Commands.GenerateKeyFile; using ModernKeePass.Application.Security.Commands.GenerateKeyFile;
using ModernKeePass.Domain.Common;
using ModernKeePass.Domain.Dtos;
namespace ModernKeePass.ViewModels namespace ModernKeePass.ViewModels
{ {
@@ -12,6 +14,7 @@ namespace ModernKeePass.ViewModels
{ {
private readonly IMediator _mediator; private readonly IMediator _mediator;
private readonly ICredentialsProxy _credentials; private readonly ICredentialsProxy _credentials;
private readonly IFileProxy _file;
public bool HasPassword public bool HasPassword
{ {
@@ -33,6 +36,8 @@ namespace ModernKeePass.ViewModels
Set(() => HasKeyFile, ref _hasKeyFile, value); Set(() => HasKeyFile, ref _hasKeyFile, value);
RaisePropertyChanged(nameof(IsKeyFileValid)); RaisePropertyChanged(nameof(IsKeyFileValid));
RaisePropertyChanged(nameof(IsValid)); RaisePropertyChanged(nameof(IsValid));
OpenKeyFileCommand.RaiseCanExecuteChanged();
CreateKeyFileCommand.RaiseCanExecuteChanged();
GenerateCredentialsCommand.RaiseCanExecuteChanged(); GenerateCredentialsCommand.RaiseCanExecuteChanged();
} }
} }
@@ -85,6 +90,8 @@ namespace ModernKeePass.ViewModels
public bool IsKeyFileValid => HasKeyFile && !string.IsNullOrEmpty(KeyFilePath) || !HasKeyFile; public bool IsKeyFileValid => HasKeyFile && !string.IsNullOrEmpty(KeyFilePath) || !HasKeyFile;
public bool IsValid => HasPassword && Password == ConfirmPassword || HasKeyFile && !string.IsNullOrEmpty(KeyFilePath) && (HasPassword || HasKeyFile); public bool IsValid => HasPassword && Password == ConfirmPassword || HasKeyFile && !string.IsNullOrEmpty(KeyFilePath) && (HasPassword || HasKeyFile);
public RelayCommand OpenKeyFileCommand { get; }
public RelayCommand CreateKeyFileCommand { get; }
public RelayCommand GenerateCredentialsCommand{ get; } public RelayCommand GenerateCredentialsCommand{ get; }
private bool _hasPassword; private bool _hasPassword;
@@ -94,18 +101,39 @@ namespace ModernKeePass.ViewModels
private string _keyFilePath; private string _keyFilePath;
private string _keyFileText; private string _keyFileText;
public SetCredentialsVm(IMediator mediator, ICredentialsProxy credentials, IResourceProxy resource) public SetCredentialsVm(IMediator mediator, ICredentialsProxy credentials, IResourceProxy resource, IFileProxy file)
{ {
_mediator = mediator; _mediator = mediator;
_credentials = credentials; _credentials = credentials;
_file = file;
OpenKeyFileCommand = new RelayCommand(async () => await OpenKeyFile(), () => HasKeyFile);
CreateKeyFileCommand = new RelayCommand(async () => await CreateKeyFile(), () => HasKeyFile);
GenerateCredentialsCommand = new RelayCommand(GenerateCredentials, () => IsValid); GenerateCredentialsCommand = new RelayCommand(GenerateCredentials, () => IsValid);
_keyFileText = resource.GetResourceValue("CompositeKeyDefaultKeyFile"); _keyFileText = resource.GetResourceValue("CompositeKeyDefaultKeyFile");
} }
public async Task GenerateKeyFile() private async Task OpenKeyFile()
{ {
await _mediator.Send(new GenerateKeyFileCommand {KeyFilePath = KeyFilePath}); var file = await _file.OpenFile(string.Empty, Constants.Extensions.Any, false);
SetKeyFileInfo(file);
}
private async Task CreateKeyFile()
{
var file = await _file.CreateFile("Key", Constants.Extensions.Any, "Key file", false);
SetKeyFileInfo(file);
await _mediator.Send(new GenerateKeyFileCommand { KeyFilePath = KeyFilePath });
}
private void SetKeyFileInfo(FileInfo file)
{
if (file == null) return;
KeyFilePath = file.Id;
KeyFileText = file.Name;
HasKeyFile = true;
} }
private void GenerateCredentials() private void GenerateCredentials()

View File

@@ -50,6 +50,7 @@ namespace ModernKeePass.ViewModels
SimpleIoc.Default.Register(() => App.Services.GetRequiredService<IRecentProxy>()); SimpleIoc.Default.Register(() => App.Services.GetRequiredService<IRecentProxy>());
SimpleIoc.Default.Register(() => App.Services.GetRequiredService<IResourceProxy>()); SimpleIoc.Default.Register(() => App.Services.GetRequiredService<IResourceProxy>());
SimpleIoc.Default.Register(() => App.Services.GetRequiredService<ISettingsProxy>()); SimpleIoc.Default.Register(() => App.Services.GetRequiredService<ISettingsProxy>());
SimpleIoc.Default.Register(() => App.Services.GetRequiredService<IFileProxy>());
SimpleIoc.Default.Register(() => App.Services.GetRequiredService<ICredentialsProxy>()); SimpleIoc.Default.Register(() => App.Services.GetRequiredService<ICredentialsProxy>());
SimpleIoc.Default.Register(() => App.Services.GetRequiredService<IDialogService>()); SimpleIoc.Default.Register(() => App.Services.GetRequiredService<IDialogService>());
SimpleIoc.Default.Register(() => App.Services.GetRequiredService<INavigationService>()); SimpleIoc.Default.Register(() => App.Services.GetRequiredService<INavigationService>());