diff --git a/ModernKeePass/Common/DatabaseHelper.cs b/ModernKeePass/Common/DatabaseHelper.cs
index 7166d48..a759daa 100644
--- a/ModernKeePass/Common/DatabaseHelper.cs
+++ b/ModernKeePass/Common/DatabaseHelper.cs
@@ -16,13 +16,31 @@ namespace ModernKeePass.Common
Opening = 1,
Opened = 2
}
- private PwDatabase _pwDatabase = new PwDatabase();
+ private readonly PwDatabase _pwDatabase = new PwDatabase();
private StorageFile _databaseFile;
+ private GroupVm _recycleBin;
public GroupVm RootGroup { get; set; }
+
+ public GroupVm RecycleBin
+ {
+ get { return _recycleBin; }
+ set
+ {
+ _recycleBin = value;
+ _pwDatabase.RecycleBinUuid = _recycleBin.IdUuid;
+ }
+ }
+
public DatabaseStatus Status { get; private set; } = DatabaseStatus.Closed;
public string Name => DatabaseFile?.Name;
-
+
+ public bool RecycleBinEnabled
+ {
+ get { return _pwDatabase.RecycleBinEnabled; }
+ set { _pwDatabase.RecycleBinEnabled = value; }
+ }
+
public StorageFile DatabaseFile
{
get { return _databaseFile; }
@@ -52,7 +70,7 @@ namespace ModernKeePass.Common
if (_pwDatabase.IsOpen)
{
Status = DatabaseStatus.Opened;
- RootGroup = new GroupVm(_pwDatabase.RootGroup, null);
+ RootGroup = new GroupVm(_pwDatabase.RootGroup, null, RecycleBinEnabled ? _pwDatabase.RecycleBinUuid : null);
}
}
catch (ArgumentNullException)
diff --git a/ModernKeePass/Converters/TextToFontStyleConverter.cs b/ModernKeePass/Converters/BooleanToFontStyleConverter.cs
similarity index 52%
rename from ModernKeePass/Converters/TextToFontStyleConverter.cs
rename to ModernKeePass/Converters/BooleanToFontStyleConverter.cs
index 6cb62fb..e767a33 100644
--- a/ModernKeePass/Converters/TextToFontStyleConverter.cs
+++ b/ModernKeePass/Converters/BooleanToFontStyleConverter.cs
@@ -1,19 +1,15 @@
using System;
-using System.Runtime.InteropServices.WindowsRuntime;
using Windows.UI.Text;
using Windows.UI.Xaml.Data;
namespace ModernKeePass.Converters
{
- public class TextToFontStyleConverter : IValueConverter
+ public class BooleanToFontStyleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
- var compareValue = parameter as string;
- var text = value as string;
- return string.Compare(text, compareValue, StringComparison.OrdinalIgnoreCase) == 0
- ? FontStyle.Italic
- : FontStyle.Normal;
+ var boolean = value is bool ? (bool)value : false;
+ return boolean ? FontStyle.Italic : FontStyle.Normal;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
diff --git a/ModernKeePass/Interfaces/IPwEntity.cs b/ModernKeePass/Interfaces/IPwEntity.cs
index 3142f80..d595d47 100644
--- a/ModernKeePass/Interfaces/IPwEntity.cs
+++ b/ModernKeePass/Interfaces/IPwEntity.cs
@@ -11,9 +11,21 @@ namespace ModernKeePass.Interfaces
string Name { get; set; }
bool IsEditMode { get; }
+ ///
+ /// Delete from Model
+ ///
void CommitDelete();
+ ///
+ /// Restore ViewModel
+ ///
void UndoDelete();
+ ///
+ /// Save changes to Model
+ ///
void Save();
+ ///
+ /// Delete from ViewModel
+ ///
void MarkForDelete();
}
}
\ No newline at end of file
diff --git a/ModernKeePass/ModernKeePass.csproj b/ModernKeePass/ModernKeePass.csproj
index ab87ed5..d6b5387 100644
--- a/ModernKeePass/ModernKeePass.csproj
+++ b/ModernKeePass/ModernKeePass.csproj
@@ -123,6 +123,9 @@
+
+ SettingsDatabasePage.xaml
+
@@ -133,7 +136,7 @@
-
+
@@ -157,6 +160,7 @@
WelcomePage.xaml
+
@@ -177,11 +181,13 @@
+
+
@@ -245,6 +251,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
@@ -341,9 +351,7 @@
ModernKeePassLib
-
-
-
+
12.0
diff --git a/ModernKeePass/Pages/BasePages/LayoutAwarePageBase.cs b/ModernKeePass/Pages/BasePages/LayoutAwarePageBase.cs
index 68c2d0f..5e15942 100644
--- a/ModernKeePass/Pages/BasePages/LayoutAwarePageBase.cs
+++ b/ModernKeePass/Pages/BasePages/LayoutAwarePageBase.cs
@@ -5,7 +5,6 @@ using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Navigation;
using ModernKeePass.Common;
using ModernKeePass.Interfaces;
-using ModernKeePass.ViewModels;
namespace ModernKeePass.Pages.BasePages
{
diff --git a/ModernKeePass/Pages/EntryDetailPage.xaml b/ModernKeePass/Pages/EntryDetailPage.xaml
index 5802291..5a93cbc 100644
--- a/ModernKeePass/Pages/EntryDetailPage.xaml
+++ b/ModernKeePass/Pages/EntryDetailPage.xaml
@@ -379,13 +379,13 @@
-
+
diff --git a/ModernKeePass/Pages/EntryDetailPage.xaml.cs b/ModernKeePass/Pages/EntryDetailPage.xaml.cs
index ea701e7..9e1fbff 100644
--- a/ModernKeePass/Pages/EntryDetailPage.xaml.cs
+++ b/ModernKeePass/Pages/EntryDetailPage.xaml.cs
@@ -75,7 +75,11 @@ namespace ModernKeePass.Pages
private void DeleteButton_Click(object sender, RoutedEventArgs e)
{
- MessageDialogHelper.ShowDeleteConfirmationDialog("Are you sure you want to delete this entry?", Model, Frame);
+ var app = (App)Application.Current;
+ var message = app.Database.RecycleBinEnabled
+ ? "Are you sure you want to send this entry to the recycle bin?"
+ : "Are you sure you want to delete this entry?";
+ MessageDialogHelper.ShowDeleteConfirmationDialog(message, Model, Frame);
}
private async void UrlButton_Click(object sender, RoutedEventArgs e)
diff --git a/ModernKeePass/Pages/GroupDetailPage.xaml b/ModernKeePass/Pages/GroupDetailPage.xaml
index f180b7f..c1f3882 100644
--- a/ModernKeePass/Pages/GroupDetailPage.xaml
+++ b/ModernKeePass/Pages/GroupDetailPage.xaml
@@ -16,7 +16,7 @@
-
+
@@ -32,13 +32,13 @@
-
+
@@ -101,8 +101,7 @@
-
-
+
@@ -161,12 +160,12 @@
-
+
-
+
@@ -189,10 +188,7 @@
-
-
diff --git a/ModernKeePass/Pages/GroupDetailPage.xaml.cs b/ModernKeePass/Pages/GroupDetailPage.xaml.cs
index 582dbdd..3db3970 100644
--- a/ModernKeePass/Pages/GroupDetailPage.xaml.cs
+++ b/ModernKeePass/Pages/GroupDetailPage.xaml.cs
@@ -1,9 +1,6 @@
using System;
using System.Linq;
-using System.Threading.Tasks;
using Windows.Storage.Streams;
-using Windows.UI.Core;
-using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
@@ -115,7 +112,11 @@ namespace ModernKeePass.Pages
private void DeleteButton_Click(object sender, RoutedEventArgs e)
{
- MessageDialogHelper.ShowDeleteConfirmationDialog("Are you sure you want to delete the whole group and all its entries?", Model, Frame);
+ var app = (App) Application.Current;
+ var message = app.Database.RecycleBinEnabled
+ ? "Are you sure you want to send the whole group and all its entries to the recycle bin?"
+ : "Are you sure you want to delete the whole group and all its entries?";
+ MessageDialogHelper.ShowDeleteConfirmationDialog(message, Model, Frame);
}
private void SemanticZoom_ViewChangeStarted(object sender, SemanticZoomViewChangedEventArgs e)
diff --git a/ModernKeePass/Pages/MainPage.xaml b/ModernKeePass/Pages/MainPage.xaml
index eab0dc9..9f01e41 100644
--- a/ModernKeePass/Pages/MainPage.xaml
+++ b/ModernKeePass/Pages/MainPage.xaml
@@ -130,12 +130,6 @@
-
@@ -148,9 +142,6 @@
-
diff --git a/ModernKeePass/Pages/SettingsPage.xaml b/ModernKeePass/Pages/SettingsPage.xaml
index e4785f9..c217926 100644
--- a/ModernKeePass/Pages/SettingsPage.xaml
+++ b/ModernKeePass/Pages/SettingsPage.xaml
@@ -1,144 +1,111 @@
-
-
-
-
+
+
+
+
+
-
-
+
+
+
+
-
+
-
-
+
+
-
+
-
+
-
-
+
+
-
-
-
-
+ x:Name="MenuListView"
+ SelectionChanged="MenuListView_SelectionChanged"
+ Background="{ThemeResource AppBarBackgroundThemeBrush}"
+ ItemsSource="{Binding Source={StaticResource MenuItemsSource}}"
+ SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
+ IsSynchronizedWithCurrentItem="False"
+ ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}">
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
+
-
+
-
+
+
+
+
@@ -152,30 +119,27 @@
-->
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
-
-
-
-
+
+
-
+
diff --git a/ModernKeePass/Pages/SettingsPage.xaml.cs b/ModernKeePass/Pages/SettingsPage.xaml.cs
index 8763d08..20a2fac 100644
--- a/ModernKeePass/Pages/SettingsPage.xaml.cs
+++ b/ModernKeePass/Pages/SettingsPage.xaml.cs
@@ -1,20 +1,5 @@
-using ModernKeePass.Common;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Runtime.InteropServices.WindowsRuntime;
-using System.Windows.Input;
-using Windows.Foundation;
-using Windows.Foundation.Collections;
-using Windows.UI.ViewManagement;
-using Windows.UI.Xaml;
-using Windows.UI.Xaml.Controls;
-using Windows.UI.Xaml.Controls.Primitives;
-using Windows.UI.Xaml.Data;
-using Windows.UI.Xaml.Input;
-using Windows.UI.Xaml.Media;
-using Windows.UI.Xaml.Navigation;
+using Windows.UI.Xaml.Controls;
+using ModernKeePass.ViewModels;
// The Split Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234234
@@ -24,232 +9,23 @@ namespace ModernKeePass.Pages
/// A page that displays a group title, a list of items within the group, and details for
/// the currently selected item.
///
- public sealed partial class SettingsPage : Page
+ public sealed partial class SettingsPage
{
- private NavigationHelper navigationHelper;
- private ObservableDictionary defaultViewModel = new ObservableDictionary();
-
- ///
- /// This can be changed to a strongly typed view model.
- ///
- public ObservableDictionary DefaultViewModel
- {
- get { return this.defaultViewModel; }
- }
-
- ///
- /// NavigationHelper is used on each page to aid in navigation and
- /// process lifetime management
- ///
- public NavigationHelper NavigationHelper
- {
- get { return this.navigationHelper; }
- }
+ public new SettingsVM Model => (SettingsVM)DataContext;
public SettingsPage()
{
- this.InitializeComponent();
-
- // Setup the navigation helper
- this.navigationHelper = new NavigationHelper(this);
- this.navigationHelper.LoadState += navigationHelper_LoadState;
- this.navigationHelper.SaveState += navigationHelper_SaveState;
-
- // Setup the logical page navigation components that allow
- // the page to only show one pane at a time.
- this.navigationHelper.GoBackCommand = new ModernKeePass.Common.RelayCommand(() => this.GoBack(), () => this.CanGoBack());
- this.itemListView.SelectionChanged += itemListView_SelectionChanged;
-
- // Start listening for Window size changes
- // to change from showing two panes to showing a single pane
- Window.Current.SizeChanged += Window_SizeChanged;
- this.InvalidateVisualState();
+ InitializeComponent();
+ ListView = MenuListView;
+ ListViewSource = MenuItemsSource;
}
-
- void itemListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
+
+ private void MenuListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
- if (this.UsingLogicalPageNavigation())
- {
- this.navigationHelper.GoBackCommand.RaiseCanExecuteChanged();
- }
+ ListView_SelectionChanged(sender, e);
+ var selectedItem = Model.SelectedItem as ListMenuItemVm;
+ if (selectedItem == null) return;
+ MenuFrame?.Navigate(selectedItem.PageType);
}
-
- ///
- /// Populates the page with content passed during navigation. Any saved state is also
- /// provided when recreating a page from a prior session.
- ///
- ///
- /// The source of the event; typically
- ///
- /// Event data that provides both the navigation parameter passed to
- /// when this page was initially requested and
- /// a dictionary of state preserved by this page during an earlier
- /// session. The state will be null the first time a page is visited.
- private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
- {
- // TODO: Assign a bindable group to Me.DefaultViewModel("Group")
- // TODO: Assign a collection of bindable items to Me.DefaultViewModel("Items")
-
- if (e.PageState == null)
- {
- // When this is a new page, select the first item automatically unless logical page
- // navigation is being used (see the logical page navigation #region below.)
- if (!this.UsingLogicalPageNavigation() && this.itemsViewSource.View != null)
- {
- this.itemsViewSource.View.MoveCurrentToFirst();
- }
- }
- else
- {
- // Restore the previously saved state associated with this page
- if (e.PageState.ContainsKey("SelectedItem") && this.itemsViewSource.View != null)
- {
- // TODO: Invoke Me.itemsViewSource.View.MoveCurrentTo() with the selected
- // item as specified by the value of pageState("SelectedItem")
-
- }
- }
- }
-
- ///
- /// Preserves state associated with this page in case the application is suspended or the
- /// page is discarded from the navigation cache. Values must conform to the serialization
- /// requirements of .
- ///
- /// The source of the event; typically
- /// Event data that provides an empty dictionary to be populated with
- /// serializable state.
- private void navigationHelper_SaveState(object sender, SaveStateEventArgs e)
- {
- if (this.itemsViewSource.View != null)
- {
- // TODO: Derive a serializable navigation parameter and assign it to
- // pageState("SelectedItem")
-
- }
- }
-
- #region Logical page navigation
-
- // The split page is designed so that when the Window does have enough space to show
- // both the list and the details, only one pane will be shown at at time.
- //
- // This is all implemented with a single physical page that can represent two logical
- // pages. The code below achieves this goal without making the user aware of the
- // distinction.
-
- private const int MinimumWidthForSupportingTwoPanes = 768;
-
- ///
- /// Invoked to determine whether the page should act as one logical page or two.
- ///
- /// True if the window should show act as one logical page, false
- /// otherwise.
- private bool UsingLogicalPageNavigation()
- {
- return Window.Current.Bounds.Width < MinimumWidthForSupportingTwoPanes;
- }
-
- ///
- /// Invoked with the Window changes size
- ///
- /// The current Window
- /// Event data that describes the new size of the Window
- private void Window_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
- {
- this.InvalidateVisualState();
- }
-
- ///
- /// Invoked when an item within the list is selected.
- ///
- /// The GridView displaying the selected item.
- /// Event data that describes how the selection was changed.
- private void ItemListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- // Invalidate the view state when logical page navigation is in effect, as a change
- // in selection may cause a corresponding change in the current logical page. When
- // an item is selected this has the effect of changing from displaying the item list
- // to showing the selected item's details. When the selection is cleared this has the
- // opposite effect.
- if (this.UsingLogicalPageNavigation()) this.InvalidateVisualState();
- }
-
- private bool CanGoBack()
- {
- if (this.UsingLogicalPageNavigation() && this.itemListView.SelectedItem != null)
- {
- return true;
- }
- else
- {
- return this.navigationHelper.CanGoBack();
- }
- }
- private void GoBack()
- {
- if (this.UsingLogicalPageNavigation() && this.itemListView.SelectedItem != null)
- {
- // When logical page navigation is in effect and there's a selected item that
- // item's details are currently displayed. Clearing the selection will return to
- // the item list. From the user's point of view this is a logical backward
- // navigation.
- this.itemListView.SelectedItem = null;
- }
- else
- {
- this.navigationHelper.GoBack();
- }
- }
-
- private void InvalidateVisualState()
- {
- var visualState = DetermineVisualState();
- VisualStateManager.GoToState(this, visualState, false);
- this.navigationHelper.GoBackCommand.RaiseCanExecuteChanged();
- }
-
- ///
- /// Invoked to determine the name of the visual state that corresponds to an application
- /// view state.
- ///
- /// The name of the desired visual state. This is the same as the name of the
- /// view state except when there is a selected item in portrait and snapped views where
- /// this additional logical page is represented by adding a suffix of _Detail.
- private string DetermineVisualState()
- {
- if (!UsingLogicalPageNavigation())
- return "PrimaryView";
-
- // Update the back button's enabled state when the view state changes
- var logicalPageBack = this.UsingLogicalPageNavigation() && this.itemListView.SelectedItem != null;
-
- return logicalPageBack ? "SinglePane_Detail" : "SinglePane";
- }
-
- #endregion
-
- #region NavigationHelper registration
-
- /// The methods provided in this section are simply used to allow
- /// NavigationHelper to respond to the page's navigation methods.
- ///
- /// Page specific logic should be placed in event handlers for the
- ///
- /// and .
- /// The navigation parameter is available in the LoadState method
- /// in addition to page state preserved during an earlier session.
-
- protected override void OnNavigatedTo(NavigationEventArgs e)
- {
- navigationHelper.OnNavigatedTo(e);
- }
-
- protected override void OnNavigatedFrom(NavigationEventArgs e)
- {
- navigationHelper.OnNavigatedFrom(e);
- }
-
- #endregion
}
}
diff --git a/ModernKeePass/Pages/SettingsPageFrames/SettingsDatabasePage.xaml b/ModernKeePass/Pages/SettingsPageFrames/SettingsDatabasePage.xaml
new file mode 100644
index 0000000..f08249f
--- /dev/null
+++ b/ModernKeePass/Pages/SettingsPageFrames/SettingsDatabasePage.xaml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ModernKeePass/Pages/SettingsPageFrames/SettingsDatabasePage.xaml.cs b/ModernKeePass/Pages/SettingsPageFrames/SettingsDatabasePage.xaml.cs
new file mode 100644
index 0000000..ea905f2
--- /dev/null
+++ b/ModernKeePass/Pages/SettingsPageFrames/SettingsDatabasePage.xaml.cs
@@ -0,0 +1,15 @@
+// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
+
+namespace ModernKeePass.Pages
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class SettingsDatabasePage
+ {
+ public SettingsDatabasePage()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/ModernKeePass/ViewModels/EntryVm.cs b/ModernKeePass/ViewModels/EntryVm.cs
index 86e7996..1716830 100644
--- a/ModernKeePass/ViewModels/EntryVm.cs
+++ b/ModernKeePass/ViewModels/EntryVm.cs
@@ -14,13 +14,13 @@ namespace ModernKeePass.ViewModels
public class EntryVm : INotifyPropertyChanged, IPwEntity
{
public GroupVm ParentGroup { get; }
- public PwEntry Entry { get; }
- public System.Drawing.Color? BackgroundColor => Entry?.BackgroundColor;
- public System.Drawing.Color? ForegroundColor => Entry?.ForegroundColor;
+ public System.Drawing.Color? BackgroundColor => _pwEntry?.BackgroundColor;
+ public System.Drawing.Color? ForegroundColor => _pwEntry?.ForegroundColor;
public bool IsRevealPasswordEnabled => !string.IsNullOrEmpty(Password);
- public bool HasExpired => HasExpirationDate && Entry.ExpiryTime < DateTime.Now;
+ public bool HasExpired => HasExpirationDate && _pwEntry.ExpiryTime < DateTime.Now;
public double PasswordComplexityIndicator => QualityEstimation.EstimatePasswordBits(Password.ToCharArray());
+ public bool IsFirstItem => _pwEntry == null;
public double PasswordLength { get; set; } = 25;
public bool UpperCasePatternSelected { get; set; } = true;
@@ -38,12 +38,12 @@ namespace ModernKeePass.ViewModels
get
{
var title = GetEntryValue(PwDefs.TitleField);
- return title == null ? "New entry" : title;
+ return title == null ? "< New entry >" : title;
}
set { SetEntryValue(PwDefs.TitleField, value); }
}
- public string Id => Entry.Uuid.ToHexString();
+ public string Id => _pwEntry?.Uuid.ToHexString();
public string UserName
{
@@ -75,22 +75,22 @@ namespace ModernKeePass.ViewModels
{
get
{
- if (Entry == null) return Symbol.Add;
+ if (_pwEntry == null) return Symbol.Add;
if (HasExpired) return Symbol.Priority;
- var result = PwIconToSegoeMapping.GetSymbolFromIcon(Entry.IconId);
+ var result = PwIconToSegoeMapping.GetSymbolFromIcon(_pwEntry.IconId);
return result == Symbol.More ? Symbol.Permissions : result;
}
}
public DateTimeOffset ExpiryDate
{
- get { return new DateTimeOffset(Entry.ExpiryTime.Date); }
- set { if (HasExpirationDate) Entry.ExpiryTime = value.DateTime; }
+ get { return new DateTimeOffset(_pwEntry.ExpiryTime.Date); }
+ set { if (HasExpirationDate) _pwEntry.ExpiryTime = value.DateTime; }
}
public TimeSpan ExpiryTime
{
- get { return Entry.ExpiryTime.TimeOfDay; }
- set { if (HasExpirationDate) Entry.ExpiryTime = Entry.ExpiryTime.Date.Add(value); }
+ get { return _pwEntry.ExpiryTime.TimeOfDay; }
+ set { if (HasExpirationDate) _pwEntry.ExpiryTime = _pwEntry.ExpiryTime.Date.Add(value); }
}
public bool IsEditMode
@@ -114,16 +114,17 @@ namespace ModernKeePass.ViewModels
}
public bool HasExpirationDate
{
- get { return Entry.Expires; }
+ get { return _pwEntry.Expires; }
set
{
- Entry.Expires = value;
+ _pwEntry.Expires = value;
NotifyPropertyChanged("HasExpirationDate");
}
}
public event PropertyChangedEventHandler PropertyChanged;
+ private readonly PwEntry _pwEntry;
private bool _isEditMode;
private bool _isRevealPassword;
@@ -135,7 +136,7 @@ namespace ModernKeePass.ViewModels
public EntryVm() { }
public EntryVm(PwEntry entry, GroupVm parent)
{
- Entry = entry;
+ _pwEntry = entry;
ParentGroup = parent;
}
@@ -163,7 +164,7 @@ namespace ModernKeePass.ViewModels
ProtectedString password;
PwGenerator.Generate(out password, pwProfile, null, new CustomPwGeneratorPool());
- Entry?.Strings.Set(PwDefs.PasswordField, password);
+ _pwEntry?.Strings.Set(PwDefs.PasswordField, password);
NotifyPropertyChanged("Password");
NotifyPropertyChanged("IsRevealPasswordEnabled");
NotifyPropertyChanged("PasswordComplexityIndicator");
@@ -171,12 +172,12 @@ namespace ModernKeePass.ViewModels
private string GetEntryValue(string key)
{
- return Entry?.Strings.GetSafe(key).ReadString();
+ return _pwEntry?.Strings.GetSafe(key).ReadString();
}
private void SetEntryValue(string key, string newValue)
{
- Entry?.Strings.Set(key, new ProtectedString(true, newValue));
+ _pwEntry?.Strings.Set(key, new ProtectedString(true, newValue));
}
public void MarkForDelete()
@@ -187,7 +188,7 @@ namespace ModernKeePass.ViewModels
}
public void CommitDelete()
{
- Entry.ParentGroup.Entries.Remove(Entry);
+ _pwEntry.ParentGroup.Entries.Remove(_pwEntry);
}
public void UndoDelete()
diff --git a/ModernKeePass/ViewModels/GroupVm.cs b/ModernKeePass/ViewModels/GroupVm.cs
index a2f3a7e..5b15e13 100644
--- a/ModernKeePass/ViewModels/GroupVm.cs
+++ b/ModernKeePass/ViewModels/GroupVm.cs
@@ -7,11 +7,10 @@ using ModernKeePass.Common;
using ModernKeePass.Interfaces;
using ModernKeePass.Mappings;
using ModernKeePassLib;
-using System;
namespace ModernKeePass.ViewModels
{
- public class GroupVm : NotifyPropertyChangedBase, IPwEntity
+ public class GroupVm : NotifyPropertyChangedBase, IPwEntity, ISelectableModel
{
public GroupVm ParentGroup { get; }
public ObservableCollection Entries { get; set; } = new ObservableCollection();
@@ -19,26 +18,33 @@ namespace ModernKeePass.ViewModels
public ObservableCollection Groups { get; set; } = new ObservableCollection();
public int EntryCount => Entries.Count() - 1;
- public int GroupCount => Groups.Count - 1;
- public bool IsNotRoot => ParentGroup != null;
public FontWeight FontWeight => _pwGroup == null ? FontWeights.Bold : FontWeights.Normal;
- public string Id => _pwGroup.Uuid.ToHexString();
-
- public IOrderedEnumerable> EntriesZoomedOut
+ public int GroupCount => Groups.Count - 1;
+ public PwUuid IdUuid => _pwGroup?.Uuid;
+ public string Id => IdUuid?.ToHexString();
+ public bool IsNotRoot => ParentGroup != null;
+ ///
+ /// Is the Group the database Recycle Bin?
+ ///
+ public bool IsSelected
{
- get
+ get { return _app.Database.RecycleBinEnabled && _app.Database.RecycleBin.Id == Id; }
+ set
{
- return from e in Entries
- where e.Entry != null
- group e by e.Name.FirstOrDefault() into grp
- orderby grp.Key
- select grp;
+ // TODO: if _pwGroup is null, create a new group
+ if (value && _pwGroup != null) _app.Database.RecycleBin = this;
}
}
+ public IOrderedEnumerable> EntriesZoomedOut => from e in Entries
+ where !e.IsFirstItem
+ group e by e.Name.FirstOrDefault() into grp
+ orderby grp.Key
+ select grp;
+
public string Name
{
- get { return _pwGroup == null ? "New group" : _pwGroup.Name; }
+ get { return _pwGroup == null ? "< New group >" : _pwGroup.Name; }
set { _pwGroup.Name = value; }
}
@@ -59,18 +65,20 @@ namespace ModernKeePass.ViewModels
}
private readonly PwGroup _pwGroup;
- private bool _isLeftPaneOpen;
+ private readonly App _app = (App)Application.Current;
private bool _isEditMode;
public GroupVm() {}
- public GroupVm(PwGroup pwGroup, GroupVm parent)
+ public GroupVm(PwGroup pwGroup, GroupVm parent, PwUuid recycleBinId = null)
{
_pwGroup = pwGroup;
ParentGroup = parent;
+
+ if (recycleBinId != null && _pwGroup.Uuid.Equals(recycleBinId)) _app.Database.RecycleBin = this;
Entries = new ObservableCollection(pwGroup.Entries.Select(e => new EntryVm(e, this)).OrderBy(e => e.Name));
Entries.Insert(0, new EntryVm ());
- Groups = new ObservableCollection(pwGroup.Groups.Select(g => new GroupVm(g, this)).OrderBy(g => g.Name));
+ Groups = new ObservableCollection(pwGroup.Groups.Select(g => new GroupVm(g, this, recycleBinId)).OrderBy(g => g.Name));
Groups.Insert(0, new GroupVm ());
}
@@ -94,24 +102,31 @@ namespace ModernKeePass.ViewModels
public void MarkForDelete()
{
- var app = (App)Application.Current;
- app.PendingDeleteEntities.Add(Id, this);
+ _app.PendingDeleteEntities.Add(Id, this);
ParentGroup.Groups.Remove(this);
+ if (_app.Database.RecycleBinEnabled && !IsSelected) _app.Database.RecycleBin.Groups.Add(this);
}
public void CommitDelete()
{
_pwGroup.ParentGroup.Groups.Remove(_pwGroup);
+ if (_app.Database.RecycleBinEnabled && !IsSelected) _app.Database.RecycleBin._pwGroup.AddGroup(_pwGroup, true);
}
+
public void UndoDelete()
{
ParentGroup.Groups.Add(this);
+ if (_app.Database.RecycleBinEnabled && !IsSelected) _app.Database.RecycleBin.Groups.Remove(this);
}
public void Save()
{
- var app = (App)Application.Current;
- app.Database.Save();
+ _app.Database.Save();
+ }
+
+ public override string ToString()
+ {
+ return Name;
}
}
}
diff --git a/ModernKeePass/ViewModels/Items/ListMenuItemVm.cs b/ModernKeePass/ViewModels/Items/ListMenuItemVm.cs
new file mode 100644
index 0000000..abb49c1
--- /dev/null
+++ b/ModernKeePass/ViewModels/Items/ListMenuItemVm.cs
@@ -0,0 +1,30 @@
+using System;
+using Windows.UI.Xaml.Controls;
+using ModernKeePass.Common;
+using ModernKeePass.Interfaces;
+
+namespace ModernKeePass.ViewModels
+{
+ public class ListMenuItemVm : NotifyPropertyChangedBase, IIsEnabled, ISelectableModel
+ {
+ private bool _isSelected;
+
+ public string Title { get; set; }
+
+ public int Group { get; set; } = 0;
+ public Type PageType { get; set; }
+ public Symbol SymbolIcon { get; set; }
+ public bool IsEnabled { get; set; } = true;
+
+ public bool IsSelected
+ {
+ get { return _isSelected; }
+ set { SetProperty(ref _isSelected, value); }
+ }
+
+ public override string ToString()
+ {
+ return Title;
+ }
+ }
+}
diff --git a/ModernKeePass/ViewModels/Items/MainMenuItemVm.cs b/ModernKeePass/ViewModels/Items/MainMenuItemVm.cs
index f871336..f5b5ba2 100644
--- a/ModernKeePass/ViewModels/Items/MainMenuItemVm.cs
+++ b/ModernKeePass/ViewModels/Items/MainMenuItemVm.cs
@@ -1,32 +1,10 @@
-using System;
-using Windows.UI.Xaml.Controls;
-using ModernKeePass.Common;
-using ModernKeePass.Interfaces;
+using Windows.UI.Xaml.Controls;
namespace ModernKeePass.ViewModels
{
- public class MainMenuItemVm: NotifyPropertyChangedBase, IIsEnabled, ISelectableModel
+ public class MainMenuItemVm: ListMenuItemVm
{
- private bool _isSelected;
-
- public string Title { get; set; }
-
- public Type PageType { get; set; }
public object Parameter { get; set; }
public Frame Destination { get; set; }
- public int Group { get; set; } = 0;
- public Symbol SymbolIcon { get; set; }
- public bool IsEnabled { get; set; } = true;
-
- public bool IsSelected
- {
- get { return _isSelected; }
- set { SetProperty(ref _isSelected, value); }
- }
-
- public override string ToString()
- {
- return Title;
- }
}
}
diff --git a/ModernKeePass/ViewModels/Items/RecentItemVm.cs b/ModernKeePass/ViewModels/Items/RecentItemVm.cs
index 8091283..a970a36 100644
--- a/ModernKeePass/ViewModels/Items/RecentItemVm.cs
+++ b/ModernKeePass/ViewModels/Items/RecentItemVm.cs
@@ -1,5 +1,4 @@
-using System;
-using Windows.Storage;
+using Windows.Storage;
using ModernKeePass.Common;
using Windows.Storage.AccessCache;
diff --git a/ModernKeePass/ViewModels/Items/SettingsVM.cs b/ModernKeePass/ViewModels/Items/SettingsVM.cs
new file mode 100644
index 0000000..ef29685
--- /dev/null
+++ b/ModernKeePass/ViewModels/Items/SettingsVM.cs
@@ -0,0 +1,45 @@
+using System.Collections.ObjectModel;
+using System.Linq;
+using Windows.UI.Xaml.Controls;
+using ModernKeePass.Common;
+using ModernKeePass.Interfaces;
+using ModernKeePass.Pages;
+
+namespace ModernKeePass.ViewModels
+{
+ public class SettingsVM : NotifyPropertyChangedBase, IHasSelectableObject
+ {
+ private ListMenuItemVm _selectedItem;
+
+ public ObservableCollection MenuItems { get; set; }
+ public ISelectableModel SelectedItem
+ {
+ get { return _selectedItem; }
+ set
+ {
+ if (_selectedItem == value) return;
+ if (_selectedItem != null)
+ {
+ _selectedItem.IsSelected = false;
+ }
+
+ SetProperty(ref _selectedItem, (ListMenuItemVm)value);
+
+ if (_selectedItem != null)
+ {
+ _selectedItem.IsSelected = true;
+ }
+ }
+ }
+
+ public SettingsVM()
+ {
+ MenuItems = new ObservableCollection
+ {
+ new ListMenuItemVm { Title = "Database", SymbolIcon = Symbol.Setting, PageType = typeof(SettingsDatabasePage), IsSelected = true },
+ //new ListMenuItemVm { Title = "General", SymbolIcon = Symbol.Edit, PageType = typeof(SettingsGeneralPage) }
+ };
+ SelectedItem = MenuItems.FirstOrDefault(m => m.IsSelected);
+ }
+ }
+}
diff --git a/ModernKeePass/ViewModels/MainVm.cs b/ModernKeePass/ViewModels/MainVm.cs
index 4daef6d..f83890f 100644
--- a/ModernKeePass/ViewModels/MainVm.cs
+++ b/ModernKeePass/ViewModels/MainVm.cs
@@ -7,7 +7,6 @@ using Windows.UI.Xaml.Controls;
using ModernKeePass.Common;
using ModernKeePass.Interfaces;
using ModernKeePass.Pages;
-using ModernKeePass.Pages.BasePages;
namespace ModernKeePass.ViewModels
{
diff --git a/ModernKeePass/ViewModels/SettingsDatabaseVm.cs b/ModernKeePass/ViewModels/SettingsDatabaseVm.cs
new file mode 100644
index 0000000..9069fb4
--- /dev/null
+++ b/ModernKeePass/ViewModels/SettingsDatabaseVm.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Linq;
+using Windows.Storage;
+using Windows.UI.Xaml;
+using ModernKeePass.Common;
+using ModernKeePass.Interfaces;
+
+namespace ModernKeePass.ViewModels
+{
+ public class SettingsDatabaseVm: NotifyPropertyChangedBase, IHasSelectableObject
+ {
+ private readonly App _app = (App)Application.Current;
+ private readonly ApplicationDataContainer _localSettings = ApplicationData.Current.LocalSettings;
+ private GroupVm _selectedItem;
+
+ public bool HasRecycleBin
+ {
+ get { return _app.Database.RecycleBinEnabled; }
+ set
+ {
+ _app.Database.RecycleBinEnabled = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public ObservableCollection Groups { get; set; }
+
+ public ISelectableModel SelectedItem
+ {
+ get { return Groups.FirstOrDefault(g => g.IsSelected); }
+ set
+ {
+ if (_selectedItem == value) return;
+ if (_selectedItem != null)
+ {
+ _selectedItem.IsSelected = false;
+ }
+
+ SetProperty(ref _selectedItem, (GroupVm)value);
+
+ if (_selectedItem != null)
+ {
+ _selectedItem.IsSelected = true;
+ }
+ }
+ }
+
+ public SettingsDatabaseVm()
+ {
+ Groups = _app.Database.RootGroup.Groups;
+ }
+
+ // TODO: Move to another setting class (or a static class)
+ private T GetSetting(string property)
+ {
+ try
+ {
+ return (T) Convert.ChangeType(_localSettings.Values[property], typeof(T));
+ }
+ catch (InvalidCastException)
+ {
+ return default(T);
+ }
+ }
+ }
+}