mirror of
https://github.com/wismna/ModernKeePass.git
synced 2025-10-03 15:40:18 -04:00
WIP toast notifications
WIP layout and color changes
This commit is contained in:
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
ModernKeePass/Interfaces/IPwEntity.cs
Normal file
16
ModernKeePass/Interfaces/IPwEntity.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
@@ -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>
|
||||||
|
@@ -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}"
|
||||||
|
@@ -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>
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,6 +170,91 @@ 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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>
|
||||||
|
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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" />
|
||||||
|
Reference in New Issue
Block a user