mirror of
https://github.com/KeyKeeperApp/KeyKeeper.git
synced 2026-05-17 13:56:31 +03:00
merge branch 'feature/confirmation-at-closing'
This commit is contained in:
@@ -8,6 +8,7 @@ namespace KeyKeeper.ViewModels;
|
|||||||
public class UnlockedRepositoryViewModel : ViewModelBase
|
public class UnlockedRepositoryViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
private IPassStore passStore;
|
private IPassStore passStore;
|
||||||
|
private bool hasUnsavedChanges;
|
||||||
|
|
||||||
public IEnumerable<PassStoreEntryPassword> Passwords
|
public IEnumerable<PassStoreEntryPassword> Passwords
|
||||||
{
|
{
|
||||||
@@ -19,9 +20,20 @@ public class UnlockedRepositoryViewModel : ViewModelBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool HasUnsavedChanges
|
||||||
|
{
|
||||||
|
get => hasUnsavedChanges;
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
hasUnsavedChanges = value;
|
||||||
|
OnPropertyChanged(nameof(HasUnsavedChanges));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public UnlockedRepositoryViewModel(IPassStore store)
|
public UnlockedRepositoryViewModel(IPassStore store)
|
||||||
{
|
{
|
||||||
passStore = store;
|
passStore = store;
|
||||||
|
HasUnsavedChanges = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddEntry(PassStoreEntry entry)
|
public void AddEntry(PassStoreEntry entry)
|
||||||
@@ -29,6 +41,7 @@ public class UnlockedRepositoryViewModel : ViewModelBase
|
|||||||
if (entry is PassStoreEntryPassword)
|
if (entry is PassStoreEntryPassword)
|
||||||
{
|
{
|
||||||
(passStore.GetRootDirectory() as PassStoreEntryGroup)!.ChildEntries.Add(entry);
|
(passStore.GetRootDirectory() as PassStoreEntryGroup)!.ChildEntries.Add(entry);
|
||||||
|
HasUnsavedChanges = true;
|
||||||
OnPropertyChanged(nameof(Passwords));
|
OnPropertyChanged(nameof(Passwords));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,6 +49,7 @@ public class UnlockedRepositoryViewModel : ViewModelBase
|
|||||||
public void DeleteEntry(Guid id)
|
public void DeleteEntry(Guid id)
|
||||||
{
|
{
|
||||||
(passStore.GetRootDirectory() as PassStoreEntryGroup)!.DeleteEntry(id);
|
(passStore.GetRootDirectory() as PassStoreEntryGroup)!.DeleteEntry(id);
|
||||||
|
HasUnsavedChanges = true;
|
||||||
OnPropertyChanged(nameof(Passwords));
|
OnPropertyChanged(nameof(Passwords));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,5 +66,6 @@ public class UnlockedRepositoryViewModel : ViewModelBase
|
|||||||
public void Save()
|
public void Save()
|
||||||
{
|
{
|
||||||
passStore.Save();
|
passStore.Save();
|
||||||
|
HasUnsavedChanges = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
29
src/KeyKeeper/Views/CloseConfirmationDialog.axaml
Normal file
29
src/KeyKeeper/Views/CloseConfirmationDialog.axaml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<Window xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
x:Class="KeyKeeper.Views.CloseConfirmationDialog"
|
||||||
|
Width="420"
|
||||||
|
Height="170"
|
||||||
|
CanResize="False"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
Title="Confirm close"
|
||||||
|
Background="White">
|
||||||
|
<Grid Margin="16" RowDefinitions="*,Auto">
|
||||||
|
<TextBlock Text="Save changes before closing the storage?"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Foreground="Black"
|
||||||
|
FontSize="16"/>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="1"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Spacing="8"
|
||||||
|
Margin="0,16,0,0">
|
||||||
|
<Button Content="Save"
|
||||||
|
Click="Save_Click" />
|
||||||
|
<Button Content="Do not save"
|
||||||
|
Click="Discard_Click" />
|
||||||
|
<Button Content="Cancel"
|
||||||
|
Click="Cancel_Click" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
||||||
52
src/KeyKeeper/Views/CloseConfirmationDialog.axaml.cs
Normal file
52
src/KeyKeeper/Views/CloseConfirmationDialog.axaml.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Interactivity;
|
||||||
|
|
||||||
|
namespace KeyKeeper.Views;
|
||||||
|
|
||||||
|
public enum CloseConfirmationResult
|
||||||
|
{
|
||||||
|
Save,
|
||||||
|
Discard,
|
||||||
|
Cancel,
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class CloseConfirmationDialog : Window
|
||||||
|
{
|
||||||
|
private bool closingWithResult;
|
||||||
|
|
||||||
|
public CloseConfirmationDialog()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnClosing(WindowClosingEventArgs e)
|
||||||
|
{
|
||||||
|
if (!closingWithResult)
|
||||||
|
{
|
||||||
|
e.Cancel = true;
|
||||||
|
closingWithResult = true;
|
||||||
|
Close(CloseConfirmationResult.Cancel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnClosing(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Save_Click(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
closingWithResult = true;
|
||||||
|
Close(CloseConfirmationResult.Save);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Discard_Click(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
closingWithResult = true;
|
||||||
|
Close(CloseConfirmationResult.Discard);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Cancel_Click(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
closingWithResult = true;
|
||||||
|
Close(CloseConfirmationResult.Cancel);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
xmlns:i="using:Avalonia.Interactivity"
|
xmlns:i="using:Avalonia.Interactivity"
|
||||||
xmlns:kkp="using:KeyKeeper.Views"
|
xmlns:kkp="using:KeyKeeper.Views"
|
||||||
x:Class="KeyKeeper.Views.RepositoryWindow"
|
x:Class="KeyKeeper.Views.RepositoryWindow"
|
||||||
|
Closing="RepositoryWindow_Closing"
|
||||||
Title="KeyKeeper - Password store"
|
Title="KeyKeeper - Password store"
|
||||||
CanResize="False"
|
CanResize="False"
|
||||||
Width="800"
|
Width="800"
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ namespace KeyKeeper.Views;
|
|||||||
|
|
||||||
public partial class RepositoryWindow : Window
|
public partial class RepositoryWindow : Window
|
||||||
{
|
{
|
||||||
|
private bool allowClose;
|
||||||
|
private bool closeConfirmationShown;
|
||||||
|
|
||||||
public RepositoryWindow(RepositoryWindowViewModel model)
|
public RepositoryWindow(RepositoryWindowViewModel model)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@@ -27,6 +30,45 @@ public partial class RepositoryWindow : Window
|
|||||||
base.OnOpened(e);
|
base.OnOpened(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void RepositoryWindow_Closing(object? sender, WindowClosingEventArgs e)
|
||||||
|
{
|
||||||
|
if (allowClose || closeConfirmationShown)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DataContext is RepositoryWindowViewModel checkVm &&
|
||||||
|
checkVm.CurrentPage is UnlockedRepositoryViewModel unlockedVm &&
|
||||||
|
!unlockedVm.HasUnsavedChanges)
|
||||||
|
{
|
||||||
|
allowClose = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Cancel = true;
|
||||||
|
closeConfirmationShown = true;
|
||||||
|
|
||||||
|
var dialog = new CloseConfirmationDialog();
|
||||||
|
var result = await dialog.ShowDialog<CloseConfirmationResult?>(this);
|
||||||
|
|
||||||
|
closeConfirmationShown = false;
|
||||||
|
|
||||||
|
if (result == null || result == CloseConfirmationResult.Cancel)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == CloseConfirmationResult.Save &&
|
||||||
|
DataContext is RepositoryWindowViewModel vm &&
|
||||||
|
vm.CurrentPage is UnlockedRepositoryViewModel pageVm)
|
||||||
|
{
|
||||||
|
pageVm.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
allowClose = true;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
private async void AddEntryButton_Click(object sender, RoutedEventArgs args)
|
private async void AddEntryButton_Click(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (DataContext is RepositoryWindowViewModel vm_ && vm_.CurrentPage is UnlockedRepositoryViewModel vm)
|
if (DataContext is RepositoryWindowViewModel vm_ && vm_.CurrentPage is UnlockedRepositoryViewModel vm)
|
||||||
|
|||||||
Reference in New Issue
Block a user