diff --git a/ModernKeePass/Common/DatabaseHelper.cs b/ModernKeePass/Common/DatabaseHelper.cs index 5dca0e2..c708e23 100644 --- a/ModernKeePass/Common/DatabaseHelper.cs +++ b/ModernKeePass/Common/DatabaseHelper.cs @@ -1,6 +1,5 @@ using System; using Windows.Storage; -using Windows.Storage.AccessCache; using Windows.UI.Xaml.Controls; using ModernKeePass.Exceptions; using ModernKeePass.Interfaces; diff --git a/ModernKeePass/Common/ToastNotificationHelper.cs b/ModernKeePass/Common/ToastNotificationHelper.cs index 2da2b4e..8cd25a9 100644 --- a/ModernKeePass/Common/ToastNotificationHelper.cs +++ b/ModernKeePass/Common/ToastNotificationHelper.cs @@ -31,6 +31,19 @@ namespace ModernKeePass.Common }; ToastNotificationManager.CreateToastNotifier().Show(toast); } - + + public static void ShowGenericToast(string title, string text) + { + var notificationXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02); + var toastElements = notificationXml.GetElementsByTagName("text"); + toastElements[0].AppendChild(notificationXml.CreateTextNode(title)); + toastElements[1].AppendChild(notificationXml.CreateTextNode(text)); + + var toast = new ToastNotification(notificationXml) + { + ExpirationTime = DateTime.Now.AddSeconds(5) + }; + ToastNotificationManager.CreateToastNotifier().Show(toast); + } } } diff --git a/ModernKeePass/Controls/CompositeKeyUserControl.xaml.cs b/ModernKeePass/Controls/CompositeKeyUserControl.xaml.cs index a212610..2f45177 100644 --- a/ModernKeePass/Controls/CompositeKeyUserControl.xaml.cs +++ b/ModernKeePass/Controls/CompositeKeyUserControl.xaml.cs @@ -71,7 +71,11 @@ namespace ModernKeePass.Controls { ValidationChecking?.Invoke(this, new EventArgs()); - if (UpdateKey) Model.UpdateKey(); + if (UpdateKey) + { + Model.UpdateKey(); + ValidationChecked?.Invoke(this, new PasswordEventArgs(Model.RootGroup)); + } else { var oldLabel = ButtonLabel; diff --git a/ModernKeePass/Controls/TextBoxWithButton.cs b/ModernKeePass/Controls/TextBoxWithButton.cs index cb6f706..e0201f9 100644 --- a/ModernKeePass/Controls/TextBoxWithButton.cs +++ b/ModernKeePass/Controls/TextBoxWithButton.cs @@ -6,18 +6,6 @@ namespace ModernKeePass.Controls { public class TextBoxWithButton : TextBox { - /*public Symbol ButtonSymbol - { - get { return (Symbol)GetValue(ButtonSymbolProperty); } - set { SetValue(ButtonSymbolProperty, value); } - } - public static readonly DependencyProperty ButtonSymbolProperty = - DependencyProperty.Register( - "ButtonSymbol", - typeof(Symbol), - typeof(TextBoxWithButton), - new PropertyMetadata(Symbol.Delete, (o, args) => { }));*/ - public string ButtonSymbol { get { return (string)GetValue(ButtonSymbolProperty); } @@ -31,6 +19,18 @@ namespace ModernKeePass.Controls new PropertyMetadata("", (o, args) => { })); public event EventHandler ButtonClick; + public string ButtonTooltip + { + get { return (string)GetValue(ButtonTooltipProperty); } + set { SetValue(ButtonTooltipProperty, value); } + } + public static readonly DependencyProperty ButtonTooltipProperty = + DependencyProperty.Register( + "ButtonTooltip", + typeof(string), + typeof(TextBoxWithButton), + new PropertyMetadata(string.Empty, (o, args) => { })); + protected override void OnApplyTemplate() { base.OnApplyTemplate(); diff --git a/ModernKeePass/ModernKeePassApp.csproj b/ModernKeePass/ModernKeePassApp.csproj index 06212ef..d636b83 100644 --- a/ModernKeePass/ModernKeePassApp.csproj +++ b/ModernKeePass/ModernKeePassApp.csproj @@ -136,6 +136,9 @@ SettingsSecurityPage.xaml + + SettingsWelcomePage.xaml + @@ -268,6 +271,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/ModernKeePass/Pages/BasePages/LayoutAwarePageBase.cs b/ModernKeePass/Pages/BasePages/LayoutAwarePageBase.cs index 5e15942..bd691cb 100644 --- a/ModernKeePass/Pages/BasePages/LayoutAwarePageBase.cs +++ b/ModernKeePass/Pages/BasePages/LayoutAwarePageBase.cs @@ -69,17 +69,17 @@ namespace ModernKeePass.Pages.BasePages { // 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 (!UsingLogicalPageNavigation() && ListViewSource.View != null) + if (!UsingLogicalPageNavigation()) { - ListViewSource.View.MoveCurrentToFirst(); + ListViewSource.View?.MoveCurrentToFirst(); } } else { // Restore the previously saved state associated with this page - if (e.PageState.ContainsKey("SelectedItem") && ListViewSource.View != null) + if (e.PageState.ContainsKey("SelectedItem")) { - ListViewSource.View.MoveCurrentTo(e.PageState["SelectedItem"]); + ListViewSource.View?.MoveCurrentTo(e.PageState["SelectedItem"]); } } } diff --git a/ModernKeePass/Pages/EntryDetailPage.xaml b/ModernKeePass/Pages/EntryDetailPage.xaml index bd557ac..e07d084 100644 --- a/ModernKeePass/Pages/EntryDetailPage.xaml +++ b/ModernKeePass/Pages/EntryDetailPage.xaml @@ -428,7 +428,7 @@ - + @@ -437,7 +437,7 @@ - + @@ -447,7 +447,7 @@ - + @@ -467,14 +467,12 @@ - diff --git a/ModernKeePass/ViewModels/GroupVm.cs b/ModernKeePass/ViewModels/GroupVm.cs index 4e86f37..42b527a 100644 --- a/ModernKeePass/ViewModels/GroupVm.cs +++ b/ModernKeePass/ViewModels/GroupVm.cs @@ -1,7 +1,6 @@ using System.Collections.ObjectModel; using System.Linq; using System.Text; -using System.Threading.Tasks; using Windows.UI.Text; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; @@ -117,6 +116,7 @@ namespace ModernKeePass.ViewModels var pwEntry = new PwEntry(true, true); _pwGroup.AddEntry(pwEntry, true); var newEntry = new EntryVm(pwEntry, this) {IsEditMode = true}; + newEntry.GeneratePassword(); Entries.Add(newEntry); return newEntry; } diff --git a/ModernKeePass/ViewModels/Items/ListMenuItemVm.cs b/ModernKeePass/ViewModels/Items/ListMenuItemVm.cs index abb49c1..b707ce1 100644 --- a/ModernKeePass/ViewModels/Items/ListMenuItemVm.cs +++ b/ModernKeePass/ViewModels/Items/ListMenuItemVm.cs @@ -11,7 +11,7 @@ namespace ModernKeePass.ViewModels public string Title { get; set; } - public int Group { get; set; } = 0; + public string Group { get; set; } = "_"; public Type PageType { get; set; } public Symbol SymbolIcon { get; set; } public bool IsEnabled { get; set; } = true; diff --git a/ModernKeePass/ViewModels/MainVm.cs b/ModernKeePass/ViewModels/MainVm.cs index 4e72c21..8962e0a 100644 --- a/ModernKeePass/ViewModels/MainVm.cs +++ b/ModernKeePass/ViewModels/MainVm.cs @@ -12,12 +12,12 @@ namespace ModernKeePass.ViewModels { public class MainVm : NotifyPropertyChangedBase, IHasSelectableObject { - private IOrderedEnumerable> _mainMenuItems; + private IOrderedEnumerable> _mainMenuItems; private MainMenuItemVm _selectedItem; public string Name { get; } = Package.Current.DisplayName; - public IOrderedEnumerable> MainMenuItems + public IOrderedEnumerable> MainMenuItems { get { return _mainMenuItems; } set { SetProperty(ref _mainMenuItems, value); } @@ -86,7 +86,7 @@ namespace ModernKeePass.ViewModels PageType = typeof(GroupDetailPage), Destination = referenceFrame, Parameter = database.RootGroup, - Group = 1, + Group = "Databases", SymbolIcon = Symbol.ProtectedDocument }); diff --git a/ModernKeePass/ViewModels/OpenVm.cs b/ModernKeePass/ViewModels/OpenVm.cs index 1b30fae..a122b7f 100644 --- a/ModernKeePass/ViewModels/OpenVm.cs +++ b/ModernKeePass/ViewModels/OpenVm.cs @@ -1,5 +1,4 @@ -using System.ComponentModel; -using Windows.Storage; +using Windows.Storage; using Windows.Storage.AccessCache; using Windows.UI.Xaml; using ModernKeePass.Common; @@ -7,7 +6,7 @@ using ModernKeePass.Interfaces; namespace ModernKeePass.ViewModels { - public class OpenVm: INotifyPropertyChanged + public class OpenVm: NotifyPropertyChangedBase { public bool ShowPasswordBox => _database?.Status == (int) DatabaseHelper.DatabaseStatus.Opening; @@ -23,19 +22,12 @@ namespace ModernKeePass.ViewModels if (database == null || database.Status != (int) DatabaseHelper.DatabaseStatus.Opening) return; OpenFile(database.DatabaseFile); } - - public event PropertyChangedEventHandler PropertyChanged; - protected void NotifyPropertyChanged(string propertyName) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - public void OpenFile(StorageFile file) { _database.DatabaseFile = file; - NotifyPropertyChanged("Name"); - NotifyPropertyChanged("ShowPasswordBox"); + OnPropertyChanged("Name"); + OnPropertyChanged("ShowPasswordBox"); AddToRecentList(file); } diff --git a/ModernKeePass/ViewModels/SettingsVm.cs b/ModernKeePass/ViewModels/SettingsVm.cs index 9390003..3d71496 100644 --- a/ModernKeePass/ViewModels/SettingsVm.cs +++ b/ModernKeePass/ViewModels/SettingsVm.cs @@ -7,11 +7,19 @@ using ModernKeePass.Pages; namespace ModernKeePass.ViewModels { - public class SettingsVM : NotifyPropertyChangedBase, IHasSelectableObject + public class SettingsVm : NotifyPropertyChangedBase, IHasSelectableObject { private ListMenuItemVm _selectedItem; - public ObservableCollection MenuItems { get; set; } + //public ObservableCollection MenuItems { get; set; } + private IOrderedEnumerable> _menuItems; + + public IOrderedEnumerable> MenuItems + { + get { return _menuItems; } + set { SetProperty(ref _menuItems, value); } + } + public ISelectableModel SelectedItem { get { return _selectedItem; } @@ -32,15 +40,17 @@ namespace ModernKeePass.ViewModels } } - public SettingsVM() + public SettingsVm() { - MenuItems = new ObservableCollection + var menuItems = new ObservableCollection { - new ListMenuItemVm { Title = "Database", SymbolIcon = Symbol.Setting, PageType = typeof(SettingsDatabasePage), IsSelected = true }, - new ListMenuItemVm { Title = "Security", SymbolIcon = Symbol.Permissions, PageType = typeof(SettingsSecurityPage) }, + new ListMenuItemVm { Title = "General", Group = "Database", SymbolIcon = Symbol.Setting, PageType = typeof(SettingsDatabasePage), IsSelected = true }, + new ListMenuItemVm { Title = "Security", Group = "Database", SymbolIcon = Symbol.Permissions, PageType = typeof(SettingsSecurityPage) }, //new ListMenuItemVm { Title = "General", SymbolIcon = Symbol.Edit, PageType = typeof(SettingsGeneralPage) } }; - SelectedItem = MenuItems.FirstOrDefault(m => m.IsSelected); + SelectedItem = menuItems.FirstOrDefault(m => m.IsSelected); + + MenuItems = from item in menuItems group item by item.Group into grp orderby grp.Key select grp; } } } diff --git a/ModernKeePassApp.Test/Mock/DatabaseHelperMock.cs b/ModernKeePassApp.Test/Mock/DatabaseHelperMock.cs index 242d300..9a81391 100644 --- a/ModernKeePassApp.Test/Mock/DatabaseHelperMock.cs +++ b/ModernKeePassApp.Test/Mock/DatabaseHelperMock.cs @@ -35,7 +35,7 @@ namespace ModernKeePassApp.Test.Mock public void Close() { - throw new NotImplementedException(); + Status = 0; } public void CreateRecycleBin() @@ -45,7 +45,7 @@ namespace ModernKeePassApp.Test.Mock public void Open(CompositeKey key, bool createNew) { - throw new NotImplementedException(); + Status = 2; } public void Save() diff --git a/ModernKeePassApp.Test/ViewModelsTests.cs b/ModernKeePassApp.Test/ViewModelsTests.cs index c68cd15..4146660 100644 --- a/ModernKeePassApp.Test/ViewModelsTests.cs +++ b/ModernKeePassApp.Test/ViewModelsTests.cs @@ -1,5 +1,7 @@ -using System.Linq; +using System; +using System.Linq; using Windows.ApplicationModel; +using Windows.Storage.AccessCache; using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; using ModernKeePass.ViewModels; using ModernKeePassApp.Test.Mock; @@ -28,13 +30,74 @@ namespace ModernKeePassApp.Test database.Status = 1; mainVm = new MainVm(null, null, database); Assert.IsNotNull(mainVm.SelectedItem); - Assert.AreEqual("Open", ((MainMenuItemVm)mainVm.SelectedItem).Title); + Assert.AreEqual("Open", ((MainMenuItemVm) mainVm.SelectedItem).Title); database.Status = 2; mainVm = new MainVm(null, null, database); Assert.IsNotNull(mainVm.SelectedItem); Assert.AreEqual(2, mainVm.MainMenuItems.Count()); - Assert.AreEqual("Save", ((MainMenuItemVm)mainVm.SelectedItem).Title); + Assert.AreEqual("Save", ((MainMenuItemVm) mainVm.SelectedItem).Title); + } + + [TestMethod] + public void TestCompositeKeyVm() + { + var database = new DatabaseHelperMock(); + var compositeKeyVm = new CompositeKeyVm(database); + Assert.IsTrue(compositeKeyVm.OpenDatabase(false).GetAwaiter().GetResult()); + compositeKeyVm.StatusType = 1; + compositeKeyVm.Password = "test"; + Assert.AreEqual(0, compositeKeyVm.StatusType); + Assert.AreEqual(15.0, compositeKeyVm.PasswordComplexityIndicator); + } + + [TestMethod] + public void TestOpenVm() + { + var database = new DatabaseHelperMock + { + Status = 1, + DatabaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Databases\TestDatabase.kdbx") + .GetAwaiter().GetResult() + }; + var openVm = new OpenVm(database); + Assert.IsTrue(openVm.ShowPasswordBox); + Assert.AreEqual("MockDatabase", openVm.Name); + } + + /*[TestMethod] + public void TestNewVm() + { + }*/ + + [TestMethod] + public void TestRecentVm() + { + var mru = StorageApplicationPermissions.MostRecentlyUsedList; + mru.Add(Package.Current.InstalledLocation.GetFileAsync(@"Databases\TestDatabase.kdbx") + .GetAwaiter().GetResult(), "MockDatabase"); + var recentVm = new RecentVm(); + Assert.IsTrue(recentVm.RecentItems.Count == 1); + recentVm.SelectedItem = recentVm.RecentItems.FirstOrDefault(); + Assert.IsTrue(recentVm.SelectedItem.IsSelected); + mru.Clear(); + } + + /*[TestMethod] + public void TestSaveVm() + { + }*/ + + [TestMethod] + public void TestSettingsVm() + { + var settingsVm = new SettingsVm(); + Assert.AreEqual(1, settingsVm.MenuItems.Count()); + var firstGroup = settingsVm.MenuItems.FirstOrDefault(); + Assert.AreEqual(2, firstGroup.Count()); + Assert.IsNotNull(settingsVm.SelectedItem); + var selectedItem = (ListMenuItemVm) settingsVm.SelectedItem; + Assert.AreEqual("General", selectedItem.Title); } } }