WIP toast notifications

WIP layout and color changes
This commit is contained in:
2017-10-17 18:46:05 +02:00
committed by BONNEVILLE Geoffroy
parent 19008cdad2
commit 01ed1bc9c1
10 changed files with 211 additions and 28 deletions

View File

@@ -1,14 +1,15 @@
using System; using System;
using System.Collections.Generic;
using Windows.ApplicationModel; using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation; using Windows.ApplicationModel.Activation;
using Windows.ApplicationModel.Search;
using Windows.Foundation;
using Windows.Storage; using Windows.Storage;
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 Microsoft.QueryStringDotNET;
using ModernKeePass.Common; using ModernKeePass.Common;
using ModernKeePass.Interfaces;
using ModernKeePass.ViewModels;
// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227 // The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227
@@ -20,6 +21,7 @@ namespace ModernKeePass
sealed partial class App : Application sealed partial class App : Application
{ {
public DatabaseHelper Database { get; set; } = new DatabaseHelper(); public DatabaseHelper Database { get; set; } = new DatabaseHelper();
public Queue<IPwEntity> PendingDeleteQueue = new Queue<IPwEntity>();
/// <summary> /// <summary>
/// Initializes the singleton application object. This is the first line of authored code /// Initializes the singleton application object. This is the first line of authored code
@@ -38,6 +40,16 @@ namespace ModernKeePass
/// <param name="e">Details about the launch request and process.</param> /// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs e) protected override void OnLaunched(LaunchActivatedEventArgs e)
{ {
OnLaunchOrActivated(e);
}
protected override void OnActivated(IActivatedEventArgs args)
{
OnLaunchOrActivated(args);
}
private void OnLaunchOrActivated(IActivatedEventArgs e)
{
#if DEBUG #if DEBUG
if (System.Diagnostics.Debugger.IsAttached) if (System.Diagnostics.Debugger.IsAttached)
@@ -68,12 +80,34 @@ namespace ModernKeePass
Window.Current.Content = rootFrame; Window.Current.Content = rootFrame;
} }
if (rootFrame.Content == null) if (e is LaunchActivatedEventArgs)
{ {
// When the navigation stack isn't restored navigate to the first page, var lauchActivatedEventArgs = e as LaunchActivatedEventArgs;
// configuring the new page by passing required information as a navigation if (rootFrame.Content == null)
// parameter {
rootFrame.Navigate(typeof(MainPage), e.Arguments); // When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(MainPage), lauchActivatedEventArgs.Arguments);
}
}
//if (e is ToastNotificationActivatedEventArgs)
else
{
/*var toastActivationArgs = e as ToastNotificationActivatedEventArgs;
// Parse the query string (using QueryString.NET)
QueryString args = QueryString.Parse(toastActivationArgs.Argument);
// See what action is being requested
switch (args["action"])
{
}*/
var entity = PendingDeleteQueue.Dequeue();
if (entity is GroupVm)
{
entity.ParentGroup.Groups.Add(entity as GroupVm);
}
} }
// Ensure the current window is active // Ensure the current window is active
Window.Current.Activate(); Window.Current.Activate();
@@ -100,7 +134,7 @@ namespace ModernKeePass
{ {
var deferral = e.SuspendingOperation.GetDeferral(); var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity //TODO: Save application state and stop any background activity
//Database.Save(); Database.Save();
deferral.Complete(); deferral.Complete();
} }

View File

@@ -0,0 +1,16 @@
using Windows.UI.Xaml.Controls;
using ModernKeePass.ViewModels;
namespace ModernKeePass.Interfaces
{
public interface IPwEntity
{
GroupVm ParentGroup { get; }
Symbol IconSymbol { get; }
string Id { get; }
string Name { get; set; }
bool IsEditMode { get; }
void CommitDelete();
}
}

View File

@@ -130,6 +130,7 @@
<Compile Include="Converters\ProgressBarLegalValuesConverter.cs" /> <Compile Include="Converters\ProgressBarLegalValuesConverter.cs" />
<Compile Include="Events\PasswordEventArgs.cs" /> <Compile Include="Events\PasswordEventArgs.cs" />
<Compile Include="Interfaces\IIsEnabled.cs" /> <Compile Include="Interfaces\IIsEnabled.cs" />
<Compile Include="Interfaces\IPwEntity.cs" />
<Compile Include="MainPage.xaml.cs"> <Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon> <DependentUpon>MainPage.xaml</DependentUpon>
</Compile> </Compile>
@@ -243,10 +244,18 @@
<HintPath>..\packages\Portable.BouncyCastle.1.8.1.3\lib\netstandard1.0\BouncyCastle.Crypto.dll</HintPath> <HintPath>..\packages\Portable.BouncyCastle.1.8.1.3\lib\netstandard1.0\BouncyCastle.Crypto.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="Microsoft.Toolkit.Uwp.Notifications, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Toolkit.Uwp.Notifications.2.0.0\lib\dotnet\Microsoft.Toolkit.Uwp.Notifications.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ModernKeePassLib, Version=2.28.1.4000, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="ModernKeePassLib, Version=2.28.1.4000, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ModernKeePassLib.2.28.4000\lib\netstandard1.2\ModernKeePassLib.dll</HintPath> <HintPath>..\packages\ModernKeePassLib.2.28.4000\lib\netstandard1.2\ModernKeePassLib.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="QueryString.NETCore, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\QueryString.NET.1.0.0\lib\dotnet\QueryString.NETCore.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Splat.2.0.0\lib\Portable-Win81+Wpa81\Splat.dll</HintPath> <HintPath>..\packages\Splat.2.0.0\lib\Portable-Win81+Wpa81\Splat.dll</HintPath>
<Private>True</Private> <Private>True</Private>

View File

@@ -51,23 +51,23 @@
</ObjectAnimationUsingKeyFrames> </ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" <ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
Storyboard.TargetProperty="Foreground"> Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverForegroundThemeBrush}" /> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames> </ObjectAnimationUsingKeyFrames>
</Storyboard> </Storyboard>
</VisualState> </VisualState>
<VisualState x:Name="Pressed"> <VisualState x:Name="Pressed">
<Storyboard> <Storyboard>
<!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement" <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Background"> Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBackgroundThemeBrush}" /> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>--> </ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="BorderBrush"> Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}" /> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames> </ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" <ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
Storyboard.TargetProperty="Foreground"> Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBackgroundThemeBrush}" /> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames> </ObjectAnimationUsingKeyFrames>
</Storyboard> </Storyboard>
</VisualState> </VisualState>
@@ -406,7 +406,7 @@
<TextBox <TextBox
Grid.Column="1" Grid.Column="1"
x:Name="TitleTextBox" x:Name="TitleTextBox"
Text="{Binding Title, Mode=TwoWay}" Text="{Binding Name, Mode=TwoWay}"
Style="{StaticResource HeaderTextBoxStyle}" Style="{StaticResource HeaderTextBoxStyle}"
Foreground="{ThemeResource DefaultTextForegroundThemeBrush}" Foreground="{ThemeResource DefaultTextForegroundThemeBrush}"
IsHitTestVisible="{Binding IsEditMode}" IsHitTestVisible="{Binding IsEditMode}"

View File

@@ -68,7 +68,7 @@
<CompositeTransform ScaleX="2" TranslateX="0" TranslateY="0" ScaleY="2"/> <CompositeTransform ScaleX="2" TranslateX="0" TranslateY="0" ScaleY="2"/>
</SymbolIcon.RenderTransform> </SymbolIcon.RenderTransform>
</SymbolIcon> </SymbolIcon>
<TextBlock Grid.Column="1" Text="{Binding Title}" FontWeight="Bold" Style="{ThemeResource TitleTextBlockStyle}" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="13,0,0,5"/> <TextBlock Grid.Column="1" Text="{Binding Name}" FontWeight="Bold" Style="{ThemeResource TitleTextBlockStyle}" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="13,0,0,5"/>
</Grid> </Grid>
</Border> </Border>
</DataTemplate> </DataTemplate>
@@ -90,7 +90,7 @@
</SymbolIcon> </SymbolIcon>
</Border> </Border>
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,10,0,0" > <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,10,0,0" >
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" Foreground="{Binding ForegroundColor, ConverterParameter={StaticResource TextBoxForegroundThemeBrush}, Converter={StaticResource ColorToBrushConverter}}"/> <TextBlock Text="{Binding Name}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" Foreground="{Binding ForegroundColor, ConverterParameter={StaticResource TextBoxForegroundThemeBrush}, Converter={StaticResource ColorToBrushConverter}}"/>
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/> <TextBlock Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
<!--<TextBlock Text="{Binding EntryCount, ConverterParameter=entry\,entries, Converter={StaticResource PluralizationConverter}}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" /> <!--<TextBlock Text="{Binding EntryCount, ConverterParameter=entry\,entries, Converter={StaticResource PluralizationConverter}}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
<TextBlock Text="{Binding GroupCount, ConverterParameter=group\,groups, Converter={StaticResource PluralizationConverter}}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />--> <TextBlock Text="{Binding GroupCount, ConverterParameter=group\,groups, Converter={StaticResource PluralizationConverter}}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />-->
@@ -185,7 +185,7 @@
<ListView.ItemTemplate> <ListView.ItemTemplate>
<DataTemplate> <DataTemplate>
<StackPanel Orientation="Vertical"> <StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/> <TextBlock Text="{Binding Name}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/>
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
</ListView.ItemTemplate> </ListView.ItemTemplate>

View File

@@ -1,13 +1,19 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
using Windows.Data.Xml.Dom;
using Windows.Storage.Streams; using Windows.Storage.Streams;
using Windows.UI.Core; using Windows.UI.Core;
using Windows.UI.Notifications;
using Windows.UI.Popups; using Windows.UI.Popups;
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 Microsoft.QueryStringDotNET;
using Microsoft.Toolkit.Uwp.Notifications;
using ModernKeePass.Common; using ModernKeePass.Common;
using ModernKeePass.Interfaces;
using ModernKeePass.ViewModels; using ModernKeePass.ViewModels;
// The Group Detail Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234229 // The Group Detail Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234229
@@ -114,7 +120,7 @@ namespace ModernKeePass.Pages
Frame.Navigate(typeof(EntryDetailPage), entry); Frame.Navigate(typeof(EntryDetailPage), entry);
} }
private async void DeleteButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e) private async void DeleteButton_Click(object sender, RoutedEventArgs e)
{ {
// Create the message dialog and set its content // Create the message dialog and set its content
var messageDialog = new MessageDialog("Are you sure you want to delete the whole group and all its entries?"); var messageDialog = new MessageDialog("Are you sure you want to delete the whole group and all its entries?");
@@ -122,7 +128,8 @@ namespace ModernKeePass.Pages
// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers // Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
messageDialog.Commands.Add(new UICommand("Delete", delete => messageDialog.Commands.Add(new UICommand("Delete", delete =>
{ {
Model.RemoveGroup(); ShowToast("Group", Model);
Model.MarkForDelete();
if (Frame.CanGoBack) Frame.GoBack(); if (Frame.CanGoBack) Frame.GoBack();
})); }));
messageDialog.Commands.Add(new UICommand("Cancel")); messageDialog.Commands.Add(new UICommand("Cancel"));
@@ -149,10 +156,10 @@ namespace ModernKeePass.Pages
private void SearchBox_OnSuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args) private void SearchBox_OnSuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args)
{ {
var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx://Assets/Logo.scale-80.png")); var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx://Assets/Logo.scale-80.png"));
var results = Model.Entries.Skip(1).Where(e => e.Title.IndexOf(args.QueryText, StringComparison.OrdinalIgnoreCase) >= 0).Take(5); var results = Model.Entries.Skip(1).Where(e => e.Name.IndexOf(args.QueryText, StringComparison.OrdinalIgnoreCase) >= 0).Take(5);
foreach (var result in results) foreach (var result in results)
{ {
args.Request.SearchSuggestionCollection.AppendResultSuggestion(result.Title, result.ParentGroup.Name, result.Id, imageUri, string.Empty); args.Request.SearchSuggestionCollection.AppendResultSuggestion(result.Name, result.ParentGroup.Name, result.Id, imageUri, string.Empty);
} }
} }
@@ -164,5 +171,90 @@ namespace ModernKeePass.Pages
#endregion #endregion
private async void ShowToast(string entityType, IPwEntity entity)
{
// Construct the visuals of the toast
var visual = new ToastVisual
{
BindingGeneric = new ToastBindingGeneric
{
Children =
{
new AdaptiveText
{
Text = $"{entityType} {entity.Name} deleted."
}
}/*,
AppLogoOverride = new ToastGenericAppLogo()
{
Source = logo,
HintCrop = ToastGenericAppLogoCrop.Circle
}*/
}
};
// Construct the actions for the toast (inputs and buttons)
var actions = new ToastActionsCustom
{
Buttons =
{
new ToastButton("Undo", new QueryString
{
{ "action", "undo" },
{ "entityType", entityType },
{ "entityId", entity.Id }
}.ToString())
}
};
// Now we can construct the final toast content
var toastContent = new ToastContent
{
Visual = visual,
Actions = actions,
// Arguments when the user taps body of toast
Launch = new QueryString()
{
{ "action", "undo" },
{ "entityType", "group" },
{ "entityId", entity.Id }
}.ToString()
};
// And create the toast notification
var toastXml = new XmlDocument();
toastXml.LoadXml(toastContent.GetContent());
var visualXml = toastXml.GetElementsByTagName("visual")[0];
((XmlElement)visualXml.ChildNodes[0]).SetAttribute("template", "ToastText02");
var toast = new ToastNotification(toastXml) {ExpirationTime = DateTime.Now.AddSeconds(5)};
toast.Dismissed += Toast_Dismissed;
/*var notificationXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
var toastElements = notificationXml.GetElementsByTagName("text");
toastElements[0].AppendChild(notificationXml.CreateTextNode($"{entityType} deleted"));
toastElements[1].AppendChild(notificationXml.CreateTextNode("Click me to undo"));
var toast = new ToastNotification(notificationXml)
{
ExpirationTime = DateTime.Now.AddSeconds(5)
};*/
ToastNotificationManager.CreateToastNotifier().Show(toast);
}
private void Toast_Dismissed(ToastNotification sender, ToastDismissedEventArgs args)
{
var app = (App)Application.Current;
if (app.PendingDeleteQueue.Count == 0) return;
var entity = app.PendingDeleteQueue.Dequeue();
if (entity is GroupVm)
{
entity.CommitDelete();
}
}
} }
} }

View File

@@ -25,7 +25,14 @@
<TextBlock Margin="25,10,0,10" Text="{Binding Name}" /> <TextBlock Margin="25,10,0,10" Text="{Binding Name}" />
<local:OpenDatabaseUserControl Password="{Binding Password, Mode=TwoWay}" CreateNew="True" ValidationChecked="PasswordUserControl_PasswordChecked" /> <local:OpenDatabaseUserControl Password="{Binding Password, Mode=TwoWay}" CreateNew="True" ValidationChecked="PasswordUserControl_PasswordChecked" />
<TextBlock Margin="25,0,0,10">Password complexity</TextBlock> <TextBlock Margin="25,0,0,10">Password complexity</TextBlock>
<ProgressBar Margin="25,0,0,10" Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}, Mode=OneWay}" Maximum="128" Width="300" HorizontalAlignment="Left" /> <ProgressBar Margin="25,0,0,10" Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}, Mode=OneWay}" Maximum="128" Width="300" HorizontalAlignment="Left" >
<ProgressBar.Background>
<LinearGradientBrush EndPoint="1,1" StartPoint="0,0">
<GradientStop Color="#FFFD0000"/>
<GradientStop Color="#FF2EFF00" Offset="1"/>
</LinearGradientBrush>
</ProgressBar.Background>
</ProgressBar>
</StackPanel> </StackPanel>
</Border> </Border>
</StackPanel> </StackPanel>

View File

@@ -1,13 +1,15 @@
using System.ComponentModel; using System.ComponentModel;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using ModernKeePass.Interfaces;
using ModernKeePass.Mappings; using ModernKeePass.Mappings;
using ModernKeePassLib; using ModernKeePassLib;
using ModernKeePassLib.Cryptography.PasswordGenerator; using ModernKeePassLib.Cryptography.PasswordGenerator;
using ModernKeePassLib.Security; using ModernKeePassLib.Security;
using System;
namespace ModernKeePass.ViewModels namespace ModernKeePass.ViewModels
{ {
public class EntryVm : INotifyPropertyChanged public class EntryVm : INotifyPropertyChanged, IPwEntity
{ {
public GroupVm ParentGroup { get; } public GroupVm ParentGroup { get; }
public PwEntry Entry { get; } public PwEntry Entry { get; }
@@ -27,7 +29,7 @@ namespace ModernKeePass.ViewModels
public bool BracketsPatternSelected { get; set; } public bool BracketsPatternSelected { get; set; }
public string CustomChars { get; set; } = string.Empty; public string CustomChars { get; set; } = string.Empty;
public string Title public string Name
{ {
get get
{ {
@@ -152,5 +154,10 @@ namespace ModernKeePass.ViewModels
{ {
Entry?.Strings.Set(key, new ProtectedString(true, newValue)); Entry?.Strings.Set(key, new ProtectedString(true, newValue));
} }
public void CommitDelete()
{
throw new NotImplementedException();
}
} }
} }

View File

@@ -1,14 +1,17 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using Windows.UI.Text; using Windows.UI.Text;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using ModernKeePass.Common; using ModernKeePass.Common;
using ModernKeePass.Interfaces;
using ModernKeePass.Mappings; using ModernKeePass.Mappings;
using ModernKeePassLib; using ModernKeePassLib;
using System;
namespace ModernKeePass.ViewModels namespace ModernKeePass.ViewModels
{ {
public class GroupVm : NotifyPropertyChangedBase public class GroupVm : NotifyPropertyChangedBase, IPwEntity
{ {
public GroupVm ParentGroup { get; } public GroupVm ParentGroup { get; }
public ObservableCollection<EntryVm> Entries { get; set; } = new ObservableCollection<EntryVm>(); public ObservableCollection<EntryVm> Entries { get; set; } = new ObservableCollection<EntryVm>();
@@ -19,6 +22,7 @@ namespace ModernKeePass.ViewModels
public int GroupCount => Groups.Count - 1; public int GroupCount => Groups.Count - 1;
public bool IsNotRoot => ParentGroup != null; public bool IsNotRoot => ParentGroup != null;
public FontWeight FontWeight => _pwGroup == null ? FontWeights.Bold : FontWeights.Normal; public FontWeight FontWeight => _pwGroup == null ? FontWeights.Bold : FontWeights.Normal;
public string Id => _pwGroup.Uuid.ToHexString();
public IOrderedEnumerable<IGrouping<char, EntryVm>> EntriesZoomedOut public IOrderedEnumerable<IGrouping<char, EntryVm>> EntriesZoomedOut
{ {
@@ -26,7 +30,7 @@ namespace ModernKeePass.ViewModels
{ {
return from e in Entries return from e in Entries
where e.Entry != null where e.Entry != null
group e by e.Title.FirstOrDefault() into grp group e by e.Name.FirstOrDefault() into grp
orderby grp.Key orderby grp.Key
select grp; select grp;
} }
@@ -70,7 +74,7 @@ namespace ModernKeePass.ViewModels
{ {
_pwGroup = pwGroup; _pwGroup = pwGroup;
ParentGroup = parent; ParentGroup = parent;
Entries = new ObservableCollection<EntryVm>(pwGroup.Entries.Select(e => new EntryVm(e, this)).OrderBy(e => e.Title)); Entries = new ObservableCollection<EntryVm>(pwGroup.Entries.Select(e => new EntryVm(e, this)).OrderBy(e => e.Name));
Entries.Insert(0, new EntryVm ()); Entries.Insert(0, new EntryVm ());
Groups = new ObservableCollection<GroupVm>(pwGroup.Groups.Select(g => new GroupVm(g, this)).OrderBy(g => g.Name)); Groups = new ObservableCollection<GroupVm>(pwGroup.Groups.Select(g => new GroupVm(g, this)).OrderBy(g => g.Name));
Groups.Insert(0, new GroupVm ()); Groups.Insert(0, new GroupVm ());
@@ -105,5 +109,17 @@ namespace ModernKeePass.ViewModels
_pwGroup.Entries.Remove(entry.Entry); _pwGroup.Entries.Remove(entry.Entry);
Entries.Remove(entry); Entries.Remove(entry);
} }
public void MarkForDelete()
{
var app = (App)Application.Current;
app.PendingDeleteQueue.Enqueue(this);
ParentGroup.Groups.Remove(this);
}
public void CommitDelete()
{
_pwGroup.ParentGroup.Groups.Remove(_pwGroup);
}
} }
} }

View File

@@ -2,9 +2,11 @@
<packages> <packages>
<package id="Microsoft.NETCore.Platforms" version="2.0.0" targetFramework="win81" /> <package id="Microsoft.NETCore.Platforms" version="2.0.0" targetFramework="win81" />
<package id="Microsoft.NETCore.Portable.Compatibility" version="1.0.2" targetFramework="win81" /> <package id="Microsoft.NETCore.Portable.Compatibility" version="1.0.2" targetFramework="win81" />
<package id="Microsoft.Toolkit.Uwp.Notifications" version="2.0.0" targetFramework="win81" />
<package id="ModernKeePassLib" version="2.28.4000" targetFramework="win81" /> <package id="ModernKeePassLib" version="2.28.4000" targetFramework="win81" />
<package id="NETStandard.Library" version="2.0.0" targetFramework="win81" /> <package id="NETStandard.Library" version="2.0.0" targetFramework="win81" />
<package id="Portable.BouncyCastle" version="1.8.1.3" targetFramework="win81" /> <package id="Portable.BouncyCastle" version="1.8.1.3" targetFramework="win81" />
<package id="QueryString.NET" version="1.0.0" targetFramework="win81" />
<package id="Splat" version="2.0.0" targetFramework="win81" /> <package id="Splat" version="2.0.0" targetFramework="win81" />
<package id="System.Collections" version="4.0.11" targetFramework="win81" /> <package id="System.Collections" version="4.0.11" targetFramework="win81" />
<package id="System.Diagnostics.Debug" version="4.0.11" targetFramework="win81" /> <package id="System.Diagnostics.Debug" version="4.0.11" targetFramework="win81" />