32 Commits

Author SHA1 Message Date
Geoffroy BONNEVILLE
2ebd952982 Minor refactoring 2021-06-15 15:33:15 +02:00
Geoffroy BONNEVILLE
5387f1c5a1 Fix navigation issue
Applied some syntax style
2021-06-15 10:16:58 +02:00
Geoffroy BONNEVILLE
77b5927d46 Refactor NavigationHelper 2021-06-14 19:38:48 +02:00
Geoffroy BONNEVILLE
e917bd249f Unregister the messenger everywhere on unload/navigate from 2021-05-10 20:28:13 +02:00
Geoffroy BONNEVILLE
dec59b2378 Update certificates 2021-04-30 17:18:50 +02:00
Geoffroy BONNEVILLE
4153dc7344 Update store association
Update CommonServiceLocator
2021-04-30 16:37:54 +02:00
Geoffroy BONNEVILLE
a589e1c5b7 Fix multiple messenger instance registrations in entry view models 2021-04-27 15:48:45 +02:00
Geoffroy BONNEVILLE
fc8dde32cd Remove sonarqube files from source control 2020-06-26 15:37:10 +02:00
Geoffroy BONNEVILLE
80a255aa6f Restored stackpanel in breadcrumb 2020-06-26 15:21:06 +02:00
Geoffroy BONNEVILLE
1f06bf3ba7 Root group up button disabled
Going back to home when opening a file from explorer no longer displays open file
Inverted Breadcrumb order to avoid reordering items
Update release notes
Code cleanup
2020-06-26 01:16:44 +02:00
Geoffroy BONNEVILLE
7dcd5a4a57 Removed Breadcrumb service
Breadcrumb control handles breadcrumb status
Layout improvements
Added the ability to delete an entry from the group menu
2020-06-10 13:38:04 +02:00
Geoffroy BONNEVILLE
c62ed584dc New Breadcrumb user control
New Breadcrumb service
WIP icons and back button behavior
2020-06-09 20:18:17 +02:00
d6b17fe696 WIP Return of the Breadcrumb
Entry Title field added as part of the entry page
Code cleanup
2020-06-08 19:17:11 +02:00
f477828628 Changed some observable collections types for HamburgerMenu binding (issue with WinRT 8.1)
Restored CollectionViewSource for recent (issue with WinRT 8.1)
Forbid horizontal scrolling in Main Menu
Fixed an incorrect SetupFocusAction target object binding
2020-06-08 14:16:54 +02:00
Geoffroy BONNEVILLE
4a0bc1cb86 Add ARM debug target 2020-06-08 11:52:12 +02:00
Geoffroy BONNEVILLE
4e7aca5517 CSV Import command created 2020-06-05 19:08:29 +02:00
Geoffroy BONNEVILLE
1f04f941c2 Corrected issue in color picker user control when changing history
Use of commands instead of events in code-behind
Some refactoring
2020-06-04 16:29:26 +02:00
Geoffroy BONNEVILLE
5c1dfa1b0e Update version to 1.20
Clicking new group button while collapsed will expand the menu
Use of space freed by hidden hamburger menu
2020-06-04 15:31:38 +02:00
Geoffroy BONNEVILLE
1c6fb0f2bb Removed useless collectionviewsource
Updated some packages
2020-06-02 15:57:14 +02:00
Geoffroy BONNEVILLE
e5b35dc6ab SemanticView zoomed out layout and design improvements 2020-06-02 13:16:36 +02:00
Geoffroy BONNEVILLE
ce48850566 Fix Sonar issues 2020-06-01 23:03:57 +02:00
Geoffroy BONNEVILLE
5d8d996f44 Working ColorPickerUserControl 2020-06-01 10:32:06 +02:00
Geoffroy BONNEVILLE
4000d51f70 Update PasswordLength property on password generation 2020-05-26 19:06:59 +02:00
Geoffroy BONNEVILLE
0c70b5146f Create entry history only if DB is open
Fix issues in entry field names
Entry field names cleanup and refactoring
2020-05-26 13:38:07 +02:00
Geoffroy BONNEVILLE
3ecee4a821 Fix ClipboardAction so that it only clears Clipboard when Window is active 2020-05-26 12:30:52 +02:00
Geoffroy BONNEVILLE
3d436c56fa Password generation button with display toggle and indicator is now a user control
SetCredentials user controls now uses PasswordGenerationBox user control
Some layout improvements in EntryDetailsPage
WIP Clipboard suspend issues
2020-05-25 19:23:32 +02:00
Geoffroy BONNEVILLE
0e05e3fbca Fix Sonar issues 2020-05-20 19:03:31 +02:00
Geoffroy BONNEVILLE
45b5ae5630 ColorPickerControl finally doesn't set database to dirty when there is an initial value 2020-05-20 17:40:06 +02:00
Geoffroy BONNEVILLE
643fb9a3f2 Working protected fields (warning: check performance) 2020-05-20 11:59:40 +02:00
Geoffroy BONNEVILLE
b7f8853ef2 WIP Protect/Unprotect Additional Field on selection 2020-05-18 22:20:31 +02:00
Geoffroy BONNEVILLE
9126307b4c Cryptography service now handles random byte generation
Protected strings are now protected in memory
2020-05-18 14:14:28 +02:00
Geoffroy BONNEVILLE
ceaf7dabd3 Fix Sonar issues 2020-05-14 17:06:39 +02:00
121 changed files with 1994 additions and 33321 deletions

2
.gitignore vendored
View File

@@ -39,4 +39,6 @@ project.lock.json
AppPackages/ AppPackages/
BundleArtifacts/ BundleArtifacts/
*.DotSettings *.DotSettings
/ModernKeePass/Win81App_TemporaryKey.pfx
/ModernKeePass/Win81App_StoreKey.pfx /ModernKeePass/Win81App_StoreKey.pfx
.sonarqube/

View File

@@ -36,6 +36,16 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget> <PlatformTarget>x64</PlatformTarget>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>ARM</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
@@ -81,14 +91,15 @@
<Compile Include="Common\Interfaces\IDatabaseProxy.cs" /> <Compile Include="Common\Interfaces\IDatabaseProxy.cs" />
<Compile Include="Common\Interfaces\IEntityVm.cs" /> <Compile Include="Common\Interfaces\IEntityVm.cs" />
<Compile Include="Common\Interfaces\IFileProxy.cs" /> <Compile Include="Common\Interfaces\IFileProxy.cs" />
<Compile Include="Common\Interfaces\IImportFormat.cs" />
<Compile Include="Common\Interfaces\ICredentialsProxy.cs" /> <Compile Include="Common\Interfaces\ICredentialsProxy.cs" />
<Compile Include="Common\Interfaces\ILogger.cs" />
<Compile Include="Common\Interfaces\INotificationService.cs" /> <Compile Include="Common\Interfaces\INotificationService.cs" />
<Compile Include="Common\Interfaces\IRecentProxy.cs" /> <Compile Include="Common\Interfaces\IRecentProxy.cs" />
<Compile Include="Common\Interfaces\IResourceProxy.cs" /> <Compile Include="Common\Interfaces\IResourceProxy.cs" />
<Compile Include="Common\Interfaces\ISettingsProxy.cs" /> <Compile Include="Common\Interfaces\ISettingsProxy.cs" />
<Compile Include="Common\Mappings\IMapFrom.cs" /> <Compile Include="Common\Mappings\IMapFrom.cs" />
<Compile Include="Common\Mappings\MappingProfile.cs" /> <Compile Include="Common\Mappings\MappingProfile.cs" />
<Compile Include="Common\Models\BreadcrumbItem.cs" />
<Compile Include="Entry\Commands\AddAttachment\AddAttachmentCommand.cs" /> <Compile Include="Entry\Commands\AddAttachment\AddAttachmentCommand.cs" />
<Compile Include="Entry\Commands\AddHistory\AddHistoryCommand.cs" /> <Compile Include="Entry\Commands\AddHistory\AddHistoryCommand.cs" />
<Compile Include="Entry\Commands\DeleteAttachment\DeleteAttachmentCommand.cs" /> <Compile Include="Entry\Commands\DeleteAttachment\DeleteAttachmentCommand.cs" />
@@ -104,6 +115,8 @@
<Compile Include="Group\Queries\GetAllGroups\GetAllGroupsQuery.cs" /> <Compile Include="Group\Queries\GetAllGroups\GetAllGroupsQuery.cs" />
<Compile Include="Group\Queries\GetGroup\GetGroupQuery.cs" /> <Compile Include="Group\Queries\GetGroup\GetGroupQuery.cs" />
<Compile Include="Group\Queries\SearchEntries\SearchEntriesQuery.cs" /> <Compile Include="Group\Queries\SearchEntries\SearchEntriesQuery.cs" />
<Compile Include="Import\Commands\ImportFromCsv\ImportFromCsvCommand.cs" />
<Compile Include="Import\Commands\ImportFromCsv\ImportFromCsvCommandValidator.cs" />
<Compile Include="Parameters\Commands\SetCipher\SetCipherCommand.cs" /> <Compile Include="Parameters\Commands\SetCipher\SetCipherCommand.cs" />
<Compile Include="Parameters\Commands\SetCompression\SetCompressionCommand.cs" /> <Compile Include="Parameters\Commands\SetCompression\SetCompressionCommand.cs" />
<Compile Include="Parameters\Commands\SetHasRecycleBin\SetHasRecycleBinCommand.cs" /> <Compile Include="Parameters\Commands\SetHasRecycleBin\SetHasRecycleBinCommand.cs" />
@@ -118,7 +131,7 @@
<Compile Include="Parameters\Queries\GetKeyDerivations\GetKeyDerivationsQuery.cs" /> <Compile Include="Parameters\Queries\GetKeyDerivations\GetKeyDerivationsQuery.cs" />
<Compile Include="Database\Commands\CloseDatabase\CloseDatabaseCommand.cs" /> <Compile Include="Database\Commands\CloseDatabase\CloseDatabaseCommand.cs" />
<Compile Include="Database\Commands\CreateDatabase\CreateDatabaseCommand.cs" /> <Compile Include="Database\Commands\CreateDatabase\CreateDatabaseCommand.cs" />
<Compile Include="Database\Commands\CreateDatabase\CreateDatabaseQueryValidator.cs" /> <Compile Include="Database\Commands\CreateDatabase\CreateDatabaseCommandValidator.cs" />
<Compile Include="Database\Commands\SaveDatabase\SaveDatabaseCommand.cs" /> <Compile Include="Database\Commands\SaveDatabase\SaveDatabaseCommand.cs" />
<Compile Include="Database\Commands\UpdateCredentials\UpdateCredentialsCommand.cs" /> <Compile Include="Database\Commands\UpdateCredentials\UpdateCredentialsCommand.cs" />
<Compile Include="Database\Models\DatabaseVm.cs" /> <Compile Include="Database\Models\DatabaseVm.cs" />

View File

@@ -6,5 +6,6 @@ namespace ModernKeePass.Application.Common.Interfaces
{ {
Task<string> Protect(string value); Task<string> Protect(string value);
Task<string> UnProtect(string value); Task<string> UnProtect(string value);
byte[] Random(uint length);
} }
} }

View File

@@ -35,7 +35,7 @@ namespace ModernKeePass.Application.Common.Interfaces
EntryEntity GetEntry(string id); EntryEntity GetEntry(string id);
Task AddEntry(string parentGroupId, string entryId); Task AddEntry(string parentGroupId, string entryId);
Task MoveEntry(string parentGroupId, string entryId, int index); Task MoveEntry(string parentGroupId, string entryId, int index);
void UpdateEntry(string entryId, string fieldName, object fieldValue, bool isProtected); Task UpdateEntry(string entryId, string fieldName, object fieldValue, bool isProtected);
void DeleteField(string entryId, string fieldName); void DeleteField(string entryId, string fieldName);
Task RemoveEntry(string parentGroupId, string entryId); Task RemoveEntry(string parentGroupId, string entryId);
EntryEntity CreateEntry(string parentGroupId); EntryEntity CreateEntry(string parentGroupId);

View File

@@ -10,6 +10,7 @@ namespace ModernKeePass.Application.Common.Interfaces
Task<FileInfo> CreateFile(string name, string extension, string description, bool addToRecent); Task<FileInfo> CreateFile(string name, string extension, string description, bool addToRecent);
Task<byte[]> ReadBinaryFile(string path); Task<byte[]> ReadBinaryFile(string path);
Task<IList<string>> ReadTextFile(string path); Task<IList<string>> ReadTextFile(string path);
Task WriteToLogFile(IEnumerable<string> data);
Task WriteBinaryContentsToFile(string path, byte[] contents); Task WriteBinaryContentsToFile(string path, byte[] contents);
void ReleaseFile(string path); void ReleaseFile(string path);
} }

View File

@@ -1,9 +0,0 @@
using System.Collections.Generic;
namespace ModernKeePass.Application.Common.Interfaces
{
public interface IImportFormat
{
List<Dictionary<string, string>> Import(IList<string> fileContents);
}
}

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace ModernKeePass.Application.Common.Interfaces
{
public interface ILogger
{
Task LogError(Exception exception);
void LogTrace(string message, Dictionary<string, string> values);
}
}

View File

@@ -0,0 +1,12 @@
using ModernKeePass.Domain.Enums;
namespace ModernKeePass.Application.Common.Models
{
public class BreadcrumbItem
{
public string Path { get; set; }
public string Name { get; set; }
public Icon Icon { get; set; }
}
}

View File

@@ -64,17 +64,17 @@ namespace ModernKeePass.Application.Database.Commands.CreateDatabase
_database.UpdateGroup(internetGroup); _database.UpdateGroup(internetGroup);
var sample1 = _database.CreateEntry(_database.RootGroupId); var sample1 = _database.CreateEntry(_database.RootGroupId);
_database.UpdateEntry(sample1.Id, EntryFieldName.Title, "Sample Entry", false); await _database.UpdateEntry(sample1.Id, EntryFieldName.Title, "Sample Entry", false);
_database.UpdateEntry(sample1.Id, EntryFieldName.UserName, "Username", false); await _database.UpdateEntry(sample1.Id, EntryFieldName.UserName, "Username", false);
_database.UpdateEntry(sample1.Id, EntryFieldName.Password, "Password", true); await _database.UpdateEntry(sample1.Id, EntryFieldName.Password, "Password", true);
_database.UpdateEntry(sample1.Id, EntryFieldName.Url, "https://keepass.info/", false); await _database.UpdateEntry(sample1.Id, EntryFieldName.Url, "https://keepass.info/", false);
_database.UpdateEntry(sample1.Id, EntryFieldName.Notes, "You may safely delete this sample", false); await _database.UpdateEntry(sample1.Id, EntryFieldName.Notes, "You may safely delete this sample", false);
var sample2 = _database.CreateEntry(_database.RootGroupId); var sample2 = _database.CreateEntry(_database.RootGroupId);
_database.UpdateEntry(sample2.Id, EntryFieldName.Title, "Sample Entry #2", false); await _database.UpdateEntry(sample2.Id, EntryFieldName.Title, "Sample Entry #2", false);
_database.UpdateEntry(sample2.Id, EntryFieldName.UserName, "Michael321", false); await _database.UpdateEntry(sample2.Id, EntryFieldName.UserName, "Michael321", false);
_database.UpdateEntry(sample2.Id, EntryFieldName.Password, "12345", true); await _database.UpdateEntry(sample2.Id, EntryFieldName.Password, "12345", true);
_database.UpdateEntry(sample2.Id, EntryFieldName.Url, "https://keepass.info/help/kb/testform.html", false); await _database.UpdateEntry(sample2.Id, EntryFieldName.Url, "https://keepass.info/help/kb/testform.html", false);
} }
} }
} }

View File

@@ -2,9 +2,9 @@
namespace ModernKeePass.Application.Database.Commands.CreateDatabase namespace ModernKeePass.Application.Database.Commands.CreateDatabase
{ {
public class CreateDatabaseQueryValidator : AbstractValidator<CreateDatabaseCommand> public class CreateDatabaseCommandValidator : AbstractValidator<CreateDatabaseCommand>
{ {
public CreateDatabaseQueryValidator() public CreateDatabaseCommandValidator()
{ {
RuleFor(v => v.FilePath) RuleFor(v => v.FilePath)
.NotNull() .NotNull()

View File

@@ -1,4 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics;
using MediatR; using MediatR;
using System.Threading.Tasks; using System.Threading.Tasks;
using ModernKeePass.Application.Common.Interfaces; using ModernKeePass.Application.Common.Interfaces;
@@ -14,11 +16,13 @@ namespace ModernKeePass.Application.Database.Commands.SaveDatabase
{ {
private readonly IDatabaseProxy _database; private readonly IDatabaseProxy _database;
private readonly IFileProxy _file; private readonly IFileProxy _file;
private readonly ILogger _logger;
public SaveDatabaseCommandHandler(IDatabaseProxy database, IFileProxy file) public SaveDatabaseCommandHandler(IDatabaseProxy database, IFileProxy file, ILogger logger)
{ {
_database = database; _database = database;
_file = file; _file = file;
_logger = logger;
} }
public async Task Handle(SaveDatabaseCommand message) public async Task Handle(SaveDatabaseCommand message)
@@ -27,6 +31,7 @@ namespace ModernKeePass.Application.Database.Commands.SaveDatabase
try try
{ {
var timeToSave = Stopwatch.StartNew();
if (!string.IsNullOrEmpty(message.FilePath)) if (!string.IsNullOrEmpty(message.FilePath))
{ {
_database.FileAccessToken = message.FilePath; _database.FileAccessToken = message.FilePath;
@@ -40,6 +45,13 @@ namespace ModernKeePass.Application.Database.Commands.SaveDatabase
// Transactional write to file // Transactional write to file
await _file.WriteBinaryContentsToFile(_database.FileAccessToken, contents); await _file.WriteBinaryContentsToFile(_database.FileAccessToken, contents);
timeToSave.Stop();
_logger.LogTrace("SaveCommand", new Dictionary<string, string>
{
{ "duration", timeToSave.ElapsedMilliseconds.ToString()},
{ "size", _database.Size.ToString()}
});
} }
catch (Exception exception) catch (Exception exception)
{ {

View File

@@ -12,7 +12,7 @@ namespace ModernKeePass.Application
var assembly = typeof(DependencyInjection).GetTypeInfo().Assembly; var assembly = typeof(DependencyInjection).GetTypeInfo().Assembly;
services.AddMediatR(assembly); services.AddMediatR(assembly);
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(DirtyStatusBehavior<,>)); services.AddTransient(typeof(IPipelineBehavior<,>), typeof(DirtyStatusBehavior<,>));
return services; return services;
} }
} }

View File

@@ -1,4 +1,5 @@
using MediatR; using System.Threading.Tasks;
using MediatR;
using ModernKeePass.Application.Common.Interfaces; using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.Exceptions; using ModernKeePass.Domain.Exceptions;
@@ -11,7 +12,7 @@ namespace ModernKeePass.Application.Entry.Commands.UpsertField
public object FieldValue { get; set; } public object FieldValue { get; set; }
public bool IsProtected { get; set; } = true; public bool IsProtected { get; set; } = true;
public class UpsertFieldCommandHandler : IRequestHandler<UpsertFieldCommand> public class UpsertFieldCommandHandler : IAsyncRequestHandler<UpsertFieldCommand>
{ {
private readonly IDatabaseProxy _database; private readonly IDatabaseProxy _database;
@@ -20,11 +21,11 @@ namespace ModernKeePass.Application.Entry.Commands.UpsertField
_database = database; _database = database;
} }
public void Handle(UpsertFieldCommand message) public async Task Handle(UpsertFieldCommand message)
{ {
if (!_database.IsOpen) throw new DatabaseClosedException(); if (!_database.IsOpen) throw new DatabaseClosedException();
_database.UpdateEntry(message.EntryId, message.FieldName, message.FieldValue, message.IsProtected); await _database.UpdateEntry(message.EntryId, message.FieldName, message.FieldValue, message.IsProtected);
} }
} }
} }

View File

@@ -39,29 +39,20 @@ namespace ModernKeePass.Application.Entry.Models
public void Mapping(Profile profile) public void Mapping(Profile profile)
{ {
profile.CreateMap<EntryEntity, EntryVm>() profile.CreateMap<EntryEntity, EntryVm>()
.ForMember(d => d.ParentGroupId, opts => opts.MapFrom(s => s.ParentId))
.ForMember(d => d.ParentGroupName, opts => opts.MapFrom(s => s.ParentName))
.ForMember(d => d.Id, opts => opts.MapFrom(s => s.Id))
.ForMember(d => d.Title, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f => .ForMember(d => d.Title, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f =>
f.Name.Equals(EntryFieldName.Title, StringComparison.OrdinalIgnoreCase)) ?? new FieldEntity { Name = EntryFieldName.Title, IsProtected = true } )) f.Name.Equals(EntryFieldName.Title, StringComparison.Ordinal)) ?? new FieldEntity { Name = EntryFieldName.Title, IsProtected = false } ))
.ForMember(d => d.Username, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f => .ForMember(d => d.Username, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f =>
f.Name.Equals(EntryFieldName.UserName, StringComparison.OrdinalIgnoreCase)) ?? new FieldEntity { Name = EntryFieldName.UserName, IsProtected = true } )) f.Name.Equals(EntryFieldName.UserName, StringComparison.Ordinal)) ?? new FieldEntity { Name = EntryFieldName.UserName, IsProtected = false } ))
.ForMember(d => d.Password, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f => .ForMember(d => d.Password, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f =>
f.Name.Equals(EntryFieldName.Password, StringComparison.OrdinalIgnoreCase)) ?? new FieldEntity { Name = EntryFieldName.Password, IsProtected = true } )) f.Name.Equals(EntryFieldName.Password, StringComparison.Ordinal)) ?? new FieldEntity { Name = EntryFieldName.Password, IsProtected = true } ))
.ForMember(d => d.Url, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f => .ForMember(d => d.Url, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f =>
f.Name.Equals(EntryFieldName.Url, StringComparison.OrdinalIgnoreCase)) ?? new FieldEntity { Name = EntryFieldName.Url, IsProtected = true } )) f.Name.Equals(EntryFieldName.Url, StringComparison.Ordinal)) ?? new FieldEntity { Name = EntryFieldName.Url, IsProtected = false } ))
.ForMember(d => d.Notes, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f => .ForMember(d => d.Notes, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f =>
f.Name.Equals(EntryFieldName.Notes, StringComparison.OrdinalIgnoreCase)) ?? new FieldEntity { Name = EntryFieldName.Notes, IsProtected = true } )) f.Name.Equals(EntryFieldName.Notes, StringComparison.Ordinal)) ?? new FieldEntity { Name = EntryFieldName.Notes, IsProtected = false } ))
.ForMember(d => d.AdditionalFields, opts => opts.MapFrom(s => .ForMember(d => d.AdditionalFields, opts => opts.MapFrom(s =>
s.Fields.Where(f => !EntryFieldName.StandardFieldNames.Contains(f.Name, StringComparer.OrdinalIgnoreCase)))) s.Fields.Where(f => !EntryFieldName.StandardFieldNames.Contains(f.Name, StringComparer.Ordinal))))
.ForMember(d => d.History, opts => opts.MapFrom(s => s.History.Reverse())) .ForMember(d => d.History, opts => opts.MapFrom(s => s.History.Reverse()))
.ForMember(d => d.HasExpirationDate, opts => opts.MapFrom(s => s.HasExpirationDate)) .ForMember(d => d.Icon, opts => opts.MapFrom(s => s.HasExpirationDate && s.ExpirationDate < DateTimeOffset.Now ? Icon.ReportHacked : s.Icon));
.ForMember(d => d.ExpirationDate, opts => opts.MapFrom(s => s.ExpirationDate))
.ForMember(d => d.ModificationDate, opts => opts.MapFrom(s => s.LastModificationDate))
.ForMember(d => d.Icon, opts => opts.MapFrom(s => s.HasExpirationDate && s.ExpirationDate < DateTimeOffset.Now ? Icon.ReportHacked : s.Icon))
.ForMember(d => d.ForegroundColor, opts => opts.MapFrom(s => s.ForegroundColor))
.ForMember(d => d.BackgroundColor, opts => opts.MapFrom(s => s.BackgroundColor))
.ForMember(d => d.Attachments, opts => opts.MapFrom(s => s.Attachments));
} }
} }
} }

View File

@@ -29,7 +29,7 @@ namespace ModernKeePass.Application.Group.Commands.CreateGroup
var group = _database.CreateGroup(message.ParentGroup.Id, message.Name, message.IsRecycleBin); var group = _database.CreateGroup(message.ParentGroup.Id, message.Name, message.IsRecycleBin);
var groupVm = _mapper.Map<GroupVm>(group); var groupVm = _mapper.Map<GroupVm>(group);
message.ParentGroup.SubGroups.Add(groupVm); message.ParentGroup.Groups.Add(groupVm);
return groupVm; return groupVm;
} }
} }

View File

@@ -26,7 +26,7 @@ namespace ModernKeePass.Application.Group.Commands.MoveGroup
if (!_database.IsOpen) throw new DatabaseClosedException(); if (!_database.IsOpen) throw new DatabaseClosedException();
await _database.MoveGroup(message.ParentGroup.Id, message.Group.Id, message.Index); await _database.MoveGroup(message.ParentGroup.Id, message.Group.Id, message.Index);
message.ParentGroup.SubGroups.Insert(message.Index, message.Group); message.ParentGroup.Groups.Insert(message.Index, message.Group);
} }
} }
} }

View File

@@ -24,7 +24,7 @@ namespace ModernKeePass.Application.Group.Commands.SortGroups
if (!_database.IsOpen) throw new DatabaseClosedException(); if (!_database.IsOpen) throw new DatabaseClosedException();
_database.SortSubGroups(message.Group.Id); _database.SortSubGroups(message.Group.Id);
message.Group.SubGroups = message.Group.SubGroups.OrderBy(g => g.Title).ToList(); message.Group.Groups = message.Group.Groups.OrderBy(g => g.Title).ToList();
} }
} }
} }

View File

@@ -15,7 +15,7 @@ namespace ModernKeePass.Application.Group.Models
public string Id { get; set; } public string Id { get; set; }
public string Title { get; set; } public string Title { get; set; }
public Icon Icon { get; set; } public Icon Icon { get; set; }
public List<GroupVm> SubGroups { get; set; } public List<GroupVm> Groups { get; set; }
public List<EntryVm> Entries { get; set; } public List<EntryVm> Entries { get; set; }
public override string ToString() public override string ToString()
@@ -26,13 +26,7 @@ namespace ModernKeePass.Application.Group.Models
public void Mapping(Profile profile) public void Mapping(Profile profile)
{ {
profile.CreateMap<GroupEntity, GroupVm>() profile.CreateMap<GroupEntity, GroupVm>()
.ForMember(d => d.ParentGroupId, opts => opts.MapFrom(s => s.ParentId))
.ForMember(d => d.ParentGroupName, opts => opts.MapFrom(s => s.ParentName))
.ForMember(d => d.Id, opts => opts.MapFrom(s => s.Id))
.ForMember(d => d.Title, opts => opts.MapFrom(s => s.Name)) .ForMember(d => d.Title, opts => opts.MapFrom(s => s.Name))
.ForMember(d => d.Icon, opts => opts.MapFrom(s => s.Icon))
.ForMember(d => d.Entries, opts => opts.MapFrom(s => s.Entries))
.ForMember(d => d.SubGroups, opts => opts.MapFrom(s => s.SubGroups))
.MaxDepth(2); .MaxDepth(2);
} }
} }

View File

@@ -0,0 +1,50 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.Enums;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Import.Commands.ImportFromCsv
{
public class ImportFromCsvCommand : IRequest
{
public string FilePath { get; set; }
public string DestinationGroupId { get; set; }
public bool HasHeaderRow { get; set; }
public char Delimiter { get; set; } = ';';
public Dictionary<int, string> FieldMappings { get; set; }
public class CreateDatabaseCommandHandler : IAsyncRequestHandler<ImportFromCsvCommand>
{
private readonly IDatabaseProxy _database;
private readonly IFileProxy _file;
public CreateDatabaseCommandHandler(IDatabaseProxy database, IFileProxy file)
{
_database = database;
_file = file;
}
public async Task Handle(ImportFromCsvCommand message)
{
if (!_database.IsOpen) throw new DatabaseClosedException();
var fileContents = await _file.ReadTextFile(message.FilePath);
for (var index = message.HasHeaderRow ? 1 : 0; index < fileContents.Count; index++)
{
var line = fileContents[index];
var fields = line.Split(message.Delimiter);
var entry = _database.CreateEntry(message.DestinationGroupId);
for (var i = 0; i < fields.Length; i++)
{
var fieldMapping = message.FieldMappings[i];
await _database.UpdateEntry(entry.Id, fieldMapping, fields[i], fieldMapping == EntryFieldName.Password);
}
}
}
}
}
}

View File

@@ -0,0 +1,17 @@
using FluentValidation;
namespace ModernKeePass.Application.Import.Commands.ImportFromCsv
{
public class ImportFromCsvCommandValidator : AbstractValidator<ImportFromCsvCommand>
{
public ImportFromCsvCommandValidator()
{
RuleFor(v => v.FilePath)
.NotNull()
.NotEmpty();
RuleFor(v => v.DestinationGroupId)
.NotNull()
.NotEmpty();
}
}
}

View File

@@ -1,5 +1,4 @@
using System; using System.Threading.Tasks;
using System.Threading.Tasks;
using MediatR; using MediatR;
using ModernKeePass.Application.Common.Interfaces; using ModernKeePass.Application.Common.Interfaces;
@@ -14,11 +13,13 @@ namespace ModernKeePass.Application.Security.Commands.GenerateKeyFile
{ {
private readonly ICredentialsProxy _security; private readonly ICredentialsProxy _security;
private readonly IFileProxy _file; private readonly IFileProxy _file;
private readonly ICryptographyClient _cryptography;
public GenerateKeyFileCommandHandler(ICredentialsProxy security, IFileProxy file) public GenerateKeyFileCommandHandler(ICredentialsProxy security, IFileProxy file, ICryptographyClient cryptography)
{ {
_security = security; _security = security;
_file = file; _file = file;
_cryptography = cryptography;
} }
public async Task Handle(GenerateKeyFileCommand message) public async Task Handle(GenerateKeyFileCommand message)
@@ -26,9 +27,7 @@ namespace ModernKeePass.Application.Security.Commands.GenerateKeyFile
byte[] entropy = null; byte[] entropy = null;
if (message.AddAdditionalEntropy) if (message.AddAdditionalEntropy)
{ {
entropy = new byte[10]; entropy = _cryptography.Random(10);
var random = new Random();
random.NextBytes(entropy);
} }
var keyFile = _security.GenerateKeyFile(entropy); var keyFile = _security.GenerateKeyFile(entropy);
await _file.WriteBinaryContentsToFile(message.KeyFilePath, keyFile); await _file.WriteBinaryContentsToFile(message.KeyFilePath, keyFile);

View File

@@ -6,7 +6,7 @@
"MediatR": "3.0.1", "MediatR": "3.0.1",
"MediatR.Extensions.Microsoft.DependencyInjection": "2.0.0", "MediatR.Extensions.Microsoft.DependencyInjection": "2.0.0",
"Microsoft.Extensions.DependencyInjection": "1.1.1", "Microsoft.Extensions.DependencyInjection": "1.1.1",
"Microsoft.NETCore.Portable.Compatibility": "1.0.1", "Microsoft.NETCore.Portable.Compatibility": "1.0.2",
"NETStandard.Library": "2.0.3", "NETStandard.Library": "2.0.3",
"Splat": "3.0.0" "Splat": "3.0.0"
}, },

View File

@@ -36,6 +36,16 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget> <PlatformTarget>x64</PlatformTarget>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>ARM</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>

View File

@@ -6,8 +6,8 @@ namespace ModernKeePass.Domain.Entities
{ {
public string Id { get; set; } public string Id { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string ParentId { get; set; } public string ParentGroupId { get; set; }
public string ParentName { get; set; } public string ParentGroupName { get; set; }
public DateTimeOffset LastModificationDate { get; set; } public DateTimeOffset ModificationDate { get; set; }
} }
} }

View File

@@ -5,7 +5,7 @@ namespace ModernKeePass.Domain.Entities
{ {
public class GroupEntity : BaseEntity public class GroupEntity : BaseEntity
{ {
public List<GroupEntity> SubGroups { get; set; } = new List<GroupEntity>(); public List<GroupEntity> Groups { get; set; } = new List<GroupEntity>();
public List<EntryEntity> Entries { get; set; } = new List<EntryEntity>(); public List<EntryEntity> Entries { get; set; } = new List<EntryEntity>();
public Icon Icon { get; set; } public Icon Icon { get; set; }
} }

View File

@@ -7,7 +7,7 @@ namespace ModernKeePass.Domain.Enums
public const string Title = nameof(Title); public const string Title = nameof(Title);
public const string UserName = nameof(UserName); public const string UserName = nameof(UserName);
public const string Password = nameof(Password); public const string Password = nameof(Password);
public const string Url = nameof(Url); public const string Url = "URL";
public const string Notes = nameof(Notes); public const string Notes = nameof(Notes);
public const string Icon = nameof(Icon); public const string Icon = nameof(Icon);
public const string ExpirationDate = nameof(ExpirationDate); public const string ExpirationDate = nameof(ExpirationDate);
@@ -15,7 +15,7 @@ namespace ModernKeePass.Domain.Enums
public const string BackgroundColor = nameof(BackgroundColor); public const string BackgroundColor = nameof(BackgroundColor);
public const string ForegroundColor = nameof(ForegroundColor); public const string ForegroundColor = nameof(ForegroundColor);
public static IEnumerable<string> StandardFieldNames = new[] public static IEnumerable<string> StandardFieldNames => new[]
{ {
Title, Title,
UserName, UserName,

View File

@@ -1,7 +1,7 @@
{ {
"supports": {}, "supports": {},
"dependencies": { "dependencies": {
"Microsoft.NETCore.Portable.Compatibility": "1.0.1", "Microsoft.NETCore.Portable.Compatibility": "1.0.2",
"NETStandard.Library": "2.0.3", "NETStandard.Library": "2.0.3",
"Splat": "3.0.0" "Splat": "3.0.0"
}, },

View File

@@ -1,31 +0,0 @@
using System.Collections.Generic;
using ModernKeePass.Application.Common.Interfaces;
namespace ModernKeePass.Infrastructure.File
{
public class CsvImportFormat: IImportFormat
{
private const bool HasHeaderRow = true;
private const char Delimiter = ';';
private const char LineDelimiter = '\n';
public List<Dictionary<string, string>> Import(IList<string> fileContents)
{
var parsedResult = new List<Dictionary<string, string>>();
foreach (var line in fileContents)
{
var fields = line.Split(Delimiter);
var recordItem = new Dictionary<string, string>();
var i = 0;
foreach (var field in fields)
{
recordItem.Add(i.ToString(), field);
i++;
}
parsedResult.Add(recordItem);
}
return parsedResult;
}
}
}

View File

@@ -44,6 +44,16 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget> <PlatformTarget>x64</PlatformTarget>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>ARM</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
@@ -78,8 +88,6 @@
<ItemGroup> <ItemGroup>
<Compile Include="Common\MachineDateTime.cs" /> <Compile Include="Common\MachineDateTime.cs" />
<Compile Include="DependencyInjection.cs" /> <Compile Include="DependencyInjection.cs" />
<Compile Include="File\CsvImportFormat.cs" />
<Compile Include="KeePass\EntryFieldMapper.cs" />
<Compile Include="KeePass\MappingProfiles.cs" /> <Compile Include="KeePass\MappingProfiles.cs" />
<Compile Include="KeePass\IconMapper.cs" /> <Compile Include="KeePass\IconMapper.cs" />
<Compile Include="KeePass\KeePassDatabaseSettingsProxy.cs" /> <Compile Include="KeePass\KeePassDatabaseSettingsProxy.cs" />

View File

@@ -1,33 +0,0 @@
using ModernKeePass.Domain.Enums;
using ModernKeePassLib;
namespace ModernKeePass.Infrastructure.KeePass
{
public static class EntryFieldMapper
{
public static string MapPwDefsToField(string value)
{
switch (value)
{
case PwDefs.TitleField: return EntryFieldName.Title;
case PwDefs.UserNameField: return EntryFieldName.UserName;
case PwDefs.PasswordField: return EntryFieldName.Password;
case PwDefs.NotesField: return EntryFieldName.Notes;
case PwDefs.UrlField: return EntryFieldName.Url;
default: return value;
}
}
public static string MapFieldToPwDef(string value)
{
switch (value)
{
case EntryFieldName.Title: return PwDefs.TitleField;
case EntryFieldName.UserName: return PwDefs.UserNameField;
case EntryFieldName.Password: return PwDefs.PasswordField;
case EntryFieldName.Notes: return PwDefs.NotesField;
case EntryFieldName.Url: return PwDefs.UrlField;
default: return value;
}
}
}
}

View File

@@ -25,6 +25,7 @@ namespace ModernKeePass.Infrastructure.KeePass
{ {
private readonly IMapper _mapper; private readonly IMapper _mapper;
private readonly IDateTime _dateTime; private readonly IDateTime _dateTime;
private readonly ICryptographyClient _cryptography;
private readonly PwDatabase _pwDatabase = new PwDatabase(); private readonly PwDatabase _pwDatabase = new PwDatabase();
private Credentials _credentials; private Credentials _credentials;
// Flag: Has Dispose already been called? // Flag: Has Dispose already been called?
@@ -94,10 +95,11 @@ namespace ModernKeePass.Infrastructure.KeePass
set { _pwDatabase.Compression = (PwCompressionAlgorithm) Enum.Parse(typeof(PwCompressionAlgorithm), value); } set { _pwDatabase.Compression = (PwCompressionAlgorithm) Enum.Parse(typeof(PwCompressionAlgorithm), value); }
} }
public KeePassDatabaseClient(IMapper mapper, IDateTime dateTime) public KeePassDatabaseClient(IMapper mapper, IDateTime dateTime, ICryptographyClient cryptography)
{ {
_mapper = mapper; _mapper = mapper;
_dateTime = dateTime; _dateTime = dateTime;
_cryptography = cryptography;
} }
public async Task Open(byte[] file, Credentials credentials) public async Task Open(byte[] file, Credentials credentials)
@@ -240,19 +242,12 @@ namespace ModernKeePass.Infrastructure.KeePass
_pwDatabase.DeletedObjects.Add(new PwDeletedObject(BuildIdFromString(entityId), _dateTime.Now)); _pwDatabase.DeletedObjects.Add(new PwDeletedObject(BuildIdFromString(entityId), _dateTime.Now));
} }
public void UpdateEntry(string entryId, string fieldName, object fieldValue, bool isProtected) public async Task UpdateEntry(string entryId, string fieldName, object fieldValue, bool isProtected)
{ {
var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true); var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
switch (fieldName) switch (fieldName)
{ {
case EntryFieldName.Title:
case EntryFieldName.UserName:
case EntryFieldName.Password:
case EntryFieldName.Notes:
case EntryFieldName.Url:
pwEntry.Strings.Set(EntryFieldMapper.MapFieldToPwDef(fieldName), new ProtectedString(isProtected, fieldValue.ToString()));
break;
case EntryFieldName.HasExpirationDate: case EntryFieldName.HasExpirationDate:
pwEntry.Expires = (bool)fieldValue; pwEntry.Expires = (bool)fieldValue;
break; break;
@@ -268,8 +263,10 @@ namespace ModernKeePass.Infrastructure.KeePass
case EntryFieldName.ForegroundColor: case EntryFieldName.ForegroundColor:
pwEntry.ForegroundColor = (Color)fieldValue; pwEntry.ForegroundColor = (Color)fieldValue;
break; break;
default: default:
pwEntry.Strings.Set(fieldName, new ProtectedString(isProtected, fieldValue.ToString())); var stringValue = fieldValue == null ? string.Empty: fieldValue.ToString();
var unprotectedFieldValue = isProtected ? await _cryptography.UnProtect(stringValue) : stringValue;
pwEntry.Strings.Set(fieldName, new ProtectedString(isProtected, unprotectedFieldValue));
break; break;
} }
} }
@@ -394,7 +391,7 @@ namespace ModernKeePass.Infrastructure.KeePass
{ {
Id = g.Uuid.ToHexString(), Id = g.Uuid.ToHexString(),
Name = g.Name, Name = g.Name,
ParentName = g.ParentGroup?.Name ParentGroupName = g.ParentGroup?.Name
}); });
return groups; return groups;
} }

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using AutoMapper; using AutoMapper;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.Entities; using ModernKeePass.Domain.Entities;
using ModernKeePassLib; using ModernKeePassLib;
using ModernKeePassLib.Security; using ModernKeePassLib.Security;
@@ -14,32 +15,42 @@ namespace ModernKeePass.Infrastructure.KeePass
{ {
CreateMap<KeyValuePair<string, ProtectedString>, FieldEntity>() CreateMap<KeyValuePair<string, ProtectedString>, FieldEntity>()
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Key)) .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Key))
.ForMember(dest => dest.Value, opt => opt.MapFrom(src => src.Value.ReadString())) .ForMember(dest => dest.Value, opt => opt.ResolveUsing<ProtectedStringResolver>())
.ForMember(dest => dest.IsProtected, opt => opt.MapFrom(src => src.Value.IsProtected)); .ForMember(dest => dest.IsProtected, opt => opt.MapFrom(src => src.Value.IsProtected));
CreateMap<PwEntry, EntryEntity>() CreateMap<PwEntry, EntryEntity>()
.ForMember(dest => dest.ParentId, opt => opt.MapFrom(src => src.ParentGroup.Uuid.ToHexString())) .ForMember(dest => dest.ParentGroupId, opt => opt.MapFrom(src => src.ParentGroup.Uuid.ToHexString()))
.ForMember(dest => dest.ParentName, opt => opt.MapFrom(src => src.ParentGroup.Name))
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Uuid.ToHexString())) .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Uuid.ToHexString()))
.ForMember(dest => dest.Fields, opt => opt.MapFrom(src => src.Strings)) .ForMember(dest => dest.Fields, opt => opt.MapFrom(src => src.Strings))
.ForMember(dest => dest.ForegroundColor, opt => opt.MapFrom(src => src.ForegroundColor))
.ForMember(dest => dest.BackgroundColor, opt => opt.MapFrom(src => src.BackgroundColor))
.ForMember(dest => dest.ExpirationDate, opt => opt.MapFrom(src => new DateTimeOffset(src.ExpiryTime))) .ForMember(dest => dest.ExpirationDate, opt => opt.MapFrom(src => new DateTimeOffset(src.ExpiryTime)))
.ForMember(dest => dest.HasExpirationDate, opt => opt.MapFrom(src => src.Expires)) .ForMember(dest => dest.HasExpirationDate, opt => opt.MapFrom(src => src.Expires))
.ForMember(dest => dest.Icon, opt => opt.MapFrom(src => IconMapper.MapPwIconToIcon(src.IconId))) .ForMember(dest => dest.Icon, opt => opt.MapFrom(src => IconMapper.MapPwIconToIcon(src.IconId)))
.ForMember(dest => dest.LastModificationDate, opt => opt.MapFrom(src => new DateTimeOffset(src.LastModificationTime))) .ForMember(dest => dest.ModificationDate, opt => opt.MapFrom(src => new DateTimeOffset(src.LastModificationTime)))
.ForMember(dest => dest.Attachments, opt => opt.MapFrom(src => src.Binaries.Select(b => new KeyValuePair<string, byte[]> (b.Key, b.Value.ReadData()) ))); .ForMember(dest => dest.Attachments, opt => opt.MapFrom(src => src.Binaries.Select(b => new KeyValuePair<string, byte[]> (b.Key, b.Value.ReadData()) )));
CreateMap<PwGroup, GroupEntity>() CreateMap<PwGroup, GroupEntity>()
.ForMember(d => d.ParentId, opts => opts.MapFrom(s => s.ParentGroup.Uuid.ToHexString())) .ForMember(d => d.ParentGroupId, opts => opts.MapFrom(s => s.ParentGroup.Uuid.ToHexString()))
.ForMember(d => d.ParentName, opts => opts.MapFrom(s => s.ParentGroup.Name))
.ForMember(d => d.Id, opts => opts.MapFrom(s => s.Uuid.ToHexString())) .ForMember(d => d.Id, opts => opts.MapFrom(s => s.Uuid.ToHexString()))
.ForMember(d => d.Name, opts => opts.MapFrom(s => s.Name))
.ForMember(d => d.Icon, opts => opts.MapFrom(s => IconMapper.MapPwIconToIcon(s.IconId))) .ForMember(d => d.Icon, opts => opts.MapFrom(s => IconMapper.MapPwIconToIcon(s.IconId)))
.ForMember(d => d.LastModificationDate, opts => opts.MapFrom(s => s.LastModificationTime)) .ForMember(d => d.ModificationDate, opts => opts.MapFrom(s => s.LastModificationTime))
.ForMember(d => d.Entries, opts => opts.MapFrom(s => s.Entries))
.ForMember(d => d.SubGroups, opts => opts.MapFrom(s => s.Groups))
.MaxDepth(2); .MaxDepth(2);
} }
} }
public class ProtectedStringResolver : IValueResolver<KeyValuePair<string, ProtectedString>, FieldEntity, string>
{
private readonly ICryptographyClient _cryptography;
public ProtectedStringResolver(ICryptographyClient cryptography)
{
_cryptography = cryptography;
}
public string Resolve(KeyValuePair<string, ProtectedString> source, FieldEntity destination, string destMember, ResolutionContext context)
{
// TODO: this variable will contain (temporarily) the decrypted string
var decryptedString = source.Value.ReadString();
return source.Value.IsProtected ? _cryptography.Protect(decryptedString).GetAwaiter().GetResult() : decryptedString;
}
}
} }

View File

@@ -74,6 +74,24 @@ namespace ModernKeePass.Infrastructure.UWP
return result; return result;
} }
public async Task WriteToLogFile(IEnumerable<string> data)
{
var local = ApplicationData.Current.LocalFolder;
var logFile = await local.CreateFileAsync("LogFile.txt", CreationCollisionOption.OpenIfExists).AsTask();
if (logFile != null)
{
try
{
await FileIO.AppendLinesAsync(logFile, data);
}
catch (Exception)
{
// If another option is available to the app to log error(i.e. Azure Mobile Service, etc...) then try that here
}
}
}
public void ReleaseFile(string path) public void ReleaseFile(string path)
{ {
StorageApplicationPermissions.FutureAccessList.Remove(path); StorageApplicationPermissions.FutureAccessList.Remove(path);

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks; using System.Threading.Tasks;
using Windows.Security.Cryptography; using Windows.Security.Cryptography;
using Windows.Security.Cryptography.DataProtection; using Windows.Security.Cryptography.DataProtection;
@@ -10,24 +11,28 @@ namespace ModernKeePass.Infrastructure.UWP
{ {
public async Task<string> Protect(string value) public async Task<string> Protect(string value)
{ {
// Create a DataProtectionProvider object for the specified descriptor. if (string.IsNullOrEmpty(value)) return value;
var provider = new DataProtectionProvider();
// Create a DataProtectionProvider object for the specified descriptor.
var provider = new DataProtectionProvider("LOCAL=user");
// Encode the plaintext input message to a buffer. // Encode the plaintext input message to a buffer.
var buffMsg = CryptographicBuffer.ConvertStringToBinary(value, BinaryStringEncoding.Utf8); var buffMsg = CryptographicBuffer.ConvertStringToBinary(value, BinaryStringEncoding.Utf8);
// Encrypt the message. // Encrypt the message.
var buffProtected = await provider.ProtectAsync(buffMsg); var buffProtected = await provider.ProtectAsync(buffMsg).AsTask().ConfigureAwait(false);
// Encode buffer to Base64 // Encode buffer to Base64
var stringProtected = CryptographicBuffer.EncodeToBase64String(buffProtected); var protectedValue = CryptographicBuffer.EncodeToBase64String(buffProtected);
// Return the encrypted string. // Return the encrypted string.
return stringProtected; return protectedValue;
} }
public async Task<string> UnProtect(string value) public async Task<string> UnProtect(string value)
{ {
if (string.IsNullOrEmpty(value)) return value;
// Create a DataProtectionProvider object. // Create a DataProtectionProvider object.
var provider = new DataProtectionProvider(); var provider = new DataProtectionProvider();
@@ -35,13 +40,18 @@ namespace ModernKeePass.Infrastructure.UWP
var buffProtected = CryptographicBuffer.DecodeFromBase64String(value); var buffProtected = CryptographicBuffer.DecodeFromBase64String(value);
// Decrypt the protected message specified on input. // Decrypt the protected message specified on input.
var buffUnprotected = await provider.UnprotectAsync(buffProtected); var buffUnprotected = await provider.UnprotectAsync(buffProtected).AsTask().ConfigureAwait(false);
// Convert the unprotected message from an IBuffer object to a string. // Convert the unprotected message from an IBuffer object to a string.
var strClearText = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, buffUnprotected); var clearText = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, buffUnprotected);
// Return the plaintext string. // Return the plaintext string.
return strClearText; return clearText;
}
public byte[] Random(uint length)
{
return CryptographicBuffer.GenerateRandom(length).ToArray();
} }
} }
} }

View File

@@ -2,7 +2,7 @@
"supports": {}, "supports": {},
"dependencies": { "dependencies": {
"AutoMapper": "5.2.0", "AutoMapper": "5.2.0",
"Microsoft.NETCore.Portable.Compatibility": "1.0.1", "Microsoft.NETCore.Portable.Compatibility": "1.0.2",
"ModernKeePassLib": "2.45.1", "ModernKeePassLib": "2.45.1",
"NETStandard.Library": "2.0.3" "NETStandard.Library": "2.0.3"
}, },

View File

@@ -1 +0,0 @@
C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\out\0

View File

@@ -1,171 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<AnalysisConfig xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.sonarsource.com/msbuild/integration/2015/1">
<SonarConfigDir>C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\conf</SonarConfigDir>
<SonarOutputDir>C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\out</SonarOutputDir>
<SonarBinDir>C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\bin</SonarBinDir>
<SonarScannerWorkingDirectory>C:\Sources\Other\ModernKeePass\ModernKeePass</SonarScannerWorkingDirectory>
<HasBeginStepCommandLineCredentials>true</HasBeginStepCommandLineCredentials>
<SonarQubeHostUrl>https://sonarcloud.io</SonarQubeHostUrl>
<SonarQubeVersion>7.2.0.12953</SonarQubeVersion>
<SonarProjectKey>ModernKeePass</SonarProjectKey>
<AdditionalConfig>
<ConfigSetting Id="BuildUri" />
<ConfigSetting Id="TfsUri" />
<ConfigSetting Id="settings.file.path" Value="c:\sonar\SonarQube.Analysis.xml" />
</AdditionalConfig>
<ServerSettings>
<Property Name="sonaranalyzer-cs.nuget.packageVersion">7.1.0.5212</Property>
<Property Name="sonar.editions.jsonUrl">https://update.sonarsource.org/editions.json</Property>
<Property Name="sonar.cs.ignoreHeaderComments">true</Property>
<Property Name="sonar.cfamily.useSema">true</Property>
<Property Name="sonar.c.file.suffixes">.c,.h</Property>
<Property Name="sonar.typescript.file.suffixes">.ts,.tsx</Property>
<Property Name="email.fromName">SonarQube</Property>
<Property Name="sonar.python.xunit.skipDetails">false</Property>
<Property Name="sonar.auth.bitbucket.loginStrategy">Unique</Property>
<Property Name="sonar.plsql.jdbc.driver.class">oracle.jdbc.OracleDriver</Property>
<Property Name="sonar.go.exclusions">**/vendor/**</Property>
<Property Name="sonar.forceAuthentication">false</Property>
<Property Name="sonar.notifications.delay">60</Property>
<Property Name="sonar.cpp.file.suffixes">.cc,.cpp,.cxx,.c++,.hh,.hpp,.hxx,.h++,.ipp</Property>
<Property Name="sonaranalyzer-cs.ruleNamespace">SonarAnalyzer.CSharp</Property>
<Property Name="sonar.web.file.suffixes">.html,.xhtml,.rhtml,.shtml</Property>
<Property Name="sonar.builtInQualityProfiles.disableNotificationOnUpdate">false</Property>
<Property Name="sonar.java.failOnException">false</Property>
<Property Name="sonar.organizations.createPersonalOrg">true</Property>
<Property Name="sonar.cpd.abap.minimumTokens">100</Property>
<Property Name="sonar.jacoco.reportPaths">target/jacoco.exec, target/jacoco-it.exec</Property>
<Property Name="sonar.cpd.cross_project">false</Property>
<Property Name="sonar.vbnet.ignoreHeaderComments">true</Property>
<Property Name="sonar.leak.period">30</Property>
<Property Name="sonar.auth.github.groupsSync">false</Property>
<Property Name="sonar.dbcleaner.daysBeforeDeletingInactiveShortLivingBranches">30</Property>
<Property Name="sonar.auth.github.loginStrategy">Unique</Property>
<Property Name="sonar.auth.microsoft.enabled">true</Property>
<Property Name="sonaranalyzer-vbnet.ruleNamespace">SonarAnalyzer.VisualBasic</Property>
<Property Name="sonar.auth.microsoft.allowsUsersToSignUp">true</Property>
<Property Name="sonar.javascript.ignoreHeaderComments">true</Property>
<Property Name="sonar.dbcleaner.daysBeforeDeletingClosedIssues">730</Property>
<Property Name="sonar.dbcleaner.weeksBeforeKeepingOnlyOneSnapshotByMonth">4</Property>
<Property Name="sonar.lf.gravatarServerUrl">https://secure.gravatar.com/avatar/{EMAIL_MD5}.jpg?s={SIZE}&amp;d=identicon</Property>
<Property Name="sonar.notifications.runningDelayBeforeReportingStatus">600</Property>
<Property Name="sonar.javascript.environments">amd, applescript, atomtest, browser, commonjs, couch, embertest, flow, greasemonkey, jasmine, jest, jquery, meteor, mocha, mongo, nashorn, node, phantomjs, prototypejs, protractor, qunit, rhino, serviceworker, shared-node-browser, shelljs, webextensions, worker, wsh, yui</Property>
<Property Name="sonar.scm.disabled">false</Property>
<Property Name="sonar.typescript.exclusions">**/node_modules/**,**/bower_components/**</Property>
<Property Name="sonar.vbnet.file.suffixes">.vb</Property>
<Property Name="sonar.abap.file.suffixes">.abap,.ab4,.flow,.asprog</Property>
<Property Name="sonar.cfamily.ignoreHeaderComments">true</Property>
<Property Name="sonar.technicalDebt.developmentCost">30</Property>
<Property Name="sonar.python.file.suffixes">py</Property>
<Property Name="sonar.cs.file.suffixes">.cs</Property>
<Property Name="sonar.plsql.file.suffixes">sql,tab,pkb</Property>
<Property Name="sonaranalyzer-vbnet.staticResourceName">SonarAnalyzer-7.1.0.5212.zip</Property>
<Property Name="sonar.java.file.suffixes">.java,.jav</Property>
<Property Name="sonar.php.file.suffixes">php,php3,php4,php5,phtml,inc</Property>
<Property Name="sonar.xml.file.suffixes">.xml,.xsd,.xsl</Property>
<Property Name="sonar.dbcleaner.weeksBeforeDeletingAllSnapshots">480</Property>
<Property Name="sonar.auth.bitbucket.allowUsersToSignUp">true</Property>
<Property Name="sonar.auth.github.enabled">true</Property>
<Property Name="sonar.javascript.jQueryObjectAliases">$, jQuery</Property>
<Property Name="sonaranalyzer-vbnet.nuget.packageVersion">7.1.0.5212</Property>
<Property Name="sonar.go.file.suffixes">.go</Property>
<Property Name="sonar.dbcleaner.weeksBeforeKeepingOnlyAnalysesWithVersion">104</Property>
<Property Name="sonar.swift.file.suffixes">.swift</Property>
<Property Name="sonar.github.endpoint">https://api.github.com</Property>
<Property Name="sonar.plsql.ignoreHeaderComments">false</Property>
<Property Name="sonar.flex.file.suffixes">as</Property>
<Property Name="sonar.auth.github.apiUrl">https://api.github.com/</Property>
<Property Name="sonar.auth.github.allowUsersToSignUp">true</Property>
<Property Name="sonar.python.xunit.reportPath">xunit-reports/xunit-result-*.xml</Property>
<Property Name="sonar.javascript.globals">angular,goog,google,OpenLayers,d3,dojo,dojox,dijit,Backbone,moment,casper</Property>
<Property Name="sonar.dbcleaner.hoursBeforeKeepingOnlyOneSnapshotByDay">24</Property>
<Property Name="sonar.auth.bitbucket.enabled">true</Property>
<Property Name="sonar.javascript.exclusions">**/node_modules/**,**/bower_components/**</Property>
<Property Name="sonar.auth.github.webUrl">https://github.com/</Property>
<Property Name="sonar.dbcleaner.cleanDirectory">true</Property>
<Property Name="sonar.onboardingTutorial.showToNewUsers">false</Property>
<Property Name="sonaranalyzer-vbnet.nuget.packageId">SonarAnalyzer.VisualBasic</Property>
<Property Name="email.from">noreply@sonarcloud.io</Property>
<Property Name="sonaranalyzer-vbnet.pluginVersion">7.1.0.5212</Property>
<Property Name="sonar.typescript.node">node</Property>
<Property Name="sonar.dbcleaner.weeksBeforeKeepingOnlyOneSnapshotByWeek">1</Property>
<Property Name="sonaranalyzer-vbnet.analyzerId">SonarAnalyzer.VisualBasic</Property>
<Property Name="email.prefix">[SonarCloud]</Property>
<Property Name="sonar.c.std">c11</Property>
<Property Name="sonaranalyzer-cs.pluginKey">csharp</Property>
<Property Name="sonar.cfamily.useCache">true</Property>
<Property Name="sonar.branch.longLivedBranches.regex">(branch|release)-.*</Property>
<Property Name="sonar.objc.file.suffixes">.m</Property>
<Property Name="sonar.go.coverage.reportPaths">coverage.out</Property>
<Property Name="sonaranalyzer-cs.staticResourceName">SonarAnalyzer-7.1.0.5212.zip</Property>
<Property Name="sonaranalyzer-cs.nuget.packageId">SonarAnalyzer.CSharp</Property>
<Property Name="sonar.auth.bitbucket.apiUrl">https://api.bitbucket.org/</Property>
<Property Name="sonar.authenticator.downcase">false</Property>
<Property Name="sonar.github.disableInlineComments">false</Property>
<Property Name="sonar.python.coverage.reportPath">coverage-reports/*coverage-*.xml</Property>
<Property Name="sonaranalyzer-cs.analyzerId">SonarAnalyzer.CSharp</Property>
<Property Name="sonar.organizations.anyoneCanCreate">true</Property>
<Property Name="sonar.technicalDebt.ratingGrid">0.05,0.1,0.2,0.5</Property>
<Property Name="sonar.lf.enableGravatar">true</Property>
<Property Name="sonar.preview.excludePlugins">devcockpit,pdfreport,governance,ldap,authaad,authgithub,authbitbucket,googleanalytics</Property>
<Property Name="sonaranalyzer-cs.pluginVersion">7.1.0.5212</Property>
<Property Name="sonar.javascript.file.suffixes">.js,.jsx,.vue</Property>
<Property Name="sonar.cpd.abap.minimumLines">20</Property>
<Property Name="sonaranalyzer-vbnet.pluginKey">vbnet</Property>
<Property Name="sonar.java.collectAnalysisErrors">true</Property>
<Property Name="sonar.updatecenter.url">https://update.sonarsource.org/update-center.properties</Property>
<Property Name="sonar.tsql.file.suffixes">.tsql</Property>
<Property Name="sonar.cpp.std">c++11</Property>
<Property Name="sonar.core.serverBaseURL">https://sonarcloud.io</Property>
<Property Name="sonar.lf.logoUrl">https://about.sonarcloud.io/images/SonarCloud-white-210px.png</Property>
<Property Name="sonar.lf.logoWidthPx">105</Property>
<Property Name="sonar.lf.aboutText">&lt;div class="boxed-group" style="border: none; border-radius: 3px;"&gt;
&lt;div class="boxed-group-inner clearfix" style="padding: 30px; border-radius: 3px; border: #e6e6e6 1px solid; background: #f3f3f3;"&gt;
&lt;div style="overflow: hidden; line-height: 1.5; font-size: 16px;"&gt;
&lt;p&gt;
Analyze your open source and private projects on SonarCloud.
Select your &lt;a href="https://about.sonarcloud.io"&gt;plan&lt;/a&gt; and start improving.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</Property>
<Property Name="sonar.core.id">AWHW8ct9-T_TB3XqouNu</Property>
<Property Name="sonar.core.startTime">07/06/2018 12:32:21</Property>
</ServerSettings>
<LocalSettings>
<Property Name="sonar.organization">geogeob</Property>
<Property Name="sonar.host.url">https://sonarcloud.io</Property>
</LocalSettings>
<AnalyzersSettings>
<AnalyzerSettings>
<Language>cs</Language>
<RuleSetFilePath>C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\conf\SonarQubeRoslyn-cs.ruleset</RuleSetFilePath>
<AnalyzerAssemblyPaths>
<Path>C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\0\Google.Protobuf.dll</Path>
<Path>C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\0\SonarAnalyzer.CSharp.dll</Path>
<Path>C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\0\SonarAnalyzer.dll</Path>
</AnalyzerAssemblyPaths>
<AdditionalFilePaths>
<Path>C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\conf\cs\SonarLint.xml</Path>
</AdditionalFilePaths>
</AnalyzerSettings>
<AnalyzerSettings>
<Language>vbnet</Language>
<RuleSetFilePath>C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\conf\SonarQubeRoslyn-vbnet.ruleset</RuleSetFilePath>
<AnalyzerAssemblyPaths>
<Path>C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\SonarAnalyzer.VisualBasic.nuspec</Path>
<Path>C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\[Content_Types].xml</Path>
<Path>C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\analyzers\Google.Protobuf.dll</Path>
<Path>C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\analyzers\SonarAnalyzer.dll</Path>
<Path>C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\analyzers\SonarAnalyzer.VisualBasic.dll</Path>
<Path>C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\package\services\metadata\core-properties\f124441cdae948bb922ac980ea59570c.psmdcp</Path>
<Path>C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\tools\install.ps1</Path>
<Path>C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\tools\uninstall.ps1</Path>
<Path>C:\Users\GBE\AppData\Local\Temp\.sonarqube\resources\1\_rels\.rels</Path>
</AnalyzerAssemblyPaths>
<AdditionalFilePaths>
<Path>C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\conf\vbnet\SonarLint.xml</Path>
</AdditionalFilePaths>
</AnalyzerSettings>
</AnalyzersSettings>
</AnalysisConfig>

View File

@@ -1,348 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="Rules for SonarQube" Description="This rule set was automatically generated from SonarQube" ToolsVersion="14.0">
<Rules AnalyzerId="SonarAnalyzer.CSharp" RuleNamespace="SonarAnalyzer.CSharp">
<Rule Id="S2589" Action="Warning" />
<Rule Id="S3433" Action="Warning" />
<Rule Id="S4061" Action="Warning" />
<Rule Id="S1121" Action="Warning" />
<Rule Id="S1854" Action="Warning" />
<Rule Id="S4457" Action="Warning" />
<Rule Id="S4456" Action="Warning" />
<Rule Id="S2278" Action="Warning" />
<Rule Id="S4211" Action="Warning" />
<Rule Id="S3923" Action="Warning" />
<Rule Id="S4426" Action="Warning" />
<Rule Id="S2486" Action="Warning" />
<Rule Id="S4433" Action="Warning" />
<Rule Id="S2758" Action="Warning" />
<Rule Id="S1751" Action="Warning" />
<Rule Id="S1871" Action="Warning" />
<Rule Id="S4586" Action="Warning" />
<Rule Id="S4581" Action="Warning" />
<Rule Id="S2737" Action="Warning" />
<Rule Id="S3400" Action="Warning" />
<Rule Id="S3649" Action="Warning" />
<Rule Id="S1144" Action="Warning" />
<Rule Id="S1264" Action="Warning" />
<Rule Id="S2201" Action="Warning" />
<Rule Id="S1118" Action="Warning" />
<Rule Id="S1006" Action="Warning" />
<Rule Id="S4214" Action="Warning" />
<Rule Id="S4210" Action="Warning" />
<Rule Id="S3241" Action="Warning" />
<Rule Id="S4428" Action="Warning" />
<Rule Id="S1048" Action="Warning" />
<Rule Id="S2183" Action="Warning" />
<Rule Id="S3168" Action="Warning" />
<Rule Id="S4220" Action="Warning" />
<Rule Id="S3261" Action="Warning" />
<Rule Id="S4260" Action="Warning" />
<Rule Id="S4159" Action="Warning" />
<Rule Id="S4277" Action="Warning" />
<Rule Id="S2583" Action="Warning" />
<Rule Id="S3440" Action="Warning" />
<Rule Id="S3776" Action="Warning" />
<Rule Id="S2326" Action="Warning" />
<Rule Id="S1116" Action="Warning" />
<Rule Id="S3358" Action="Warning" />
<Rule Id="S4200" Action="Warning" />
<Rule Id="S1172" Action="Warning" />
<Rule Id="S1862" Action="Warning" />
<Rule Id="S2275" Action="Warning" />
<Rule Id="S3457" Action="Warning" />
<Rule Id="S3459" Action="Warning" />
<Rule Id="S3464" Action="Warning" />
<Rule Id="S3343" Action="Warning" />
<Rule Id="S818" Action="Warning" />
<Rule Id="S1656" Action="Warning" />
<Rule Id="S2184" Action="Warning" />
<Rule Id="S1764" Action="Warning" />
<Rule Id="S2971" Action="Warning" />
<Rule Id="S3060" Action="Warning" />
<Rule Id="S101" Action="Warning" />
<Rule Id="S1066" Action="Warning" />
<Rule Id="S107" Action="Warning" />
<Rule Id="S1075" Action="Warning" />
<Rule Id="S108" Action="Warning" />
<Rule Id="S110" Action="Warning" />
<Rule Id="S1104" Action="Warning" />
<Rule Id="S1110" Action="Warning" />
<Rule Id="S1117" Action="Warning" />
<Rule Id="S112" Action="Warning" />
<Rule Id="S1123" Action="Warning" />
<Rule Id="S1125" Action="Warning" />
<Rule Id="S1134" Action="Warning" />
<Rule Id="S1135" Action="Warning" />
<Rule Id="S1155" Action="Warning" />
<Rule Id="S1163" Action="Warning" />
<Rule Id="S1168" Action="Warning" />
<Rule Id="S1185" Action="Warning" />
<Rule Id="S1186" Action="Warning" />
<Rule Id="S1206" Action="Warning" />
<Rule Id="S1210" Action="Warning" />
<Rule Id="S1215" Action="Warning" />
<Rule Id="S125" Action="Warning" />
<Rule Id="S1450" Action="Warning" />
<Rule Id="S1479" Action="Warning" />
<Rule Id="S1481" Action="Warning" />
<Rule Id="S1607" Action="Warning" />
<Rule Id="S1643" Action="Warning" />
<Rule Id="S1699" Action="Warning" />
<Rule Id="S1848" Action="Warning" />
<Rule Id="S1905" Action="Warning" />
<Rule Id="S1939" Action="Warning" />
<Rule Id="S1940" Action="Warning" />
<Rule Id="S1944" Action="Warning" />
<Rule Id="S2068" Action="Warning" />
<Rule Id="S2114" Action="Warning" />
<Rule Id="S2123" Action="Warning" />
<Rule Id="S2178" Action="Warning" />
<Rule Id="S2187" Action="Warning" />
<Rule Id="S2190" Action="Warning" />
<Rule Id="S2219" Action="Warning" />
<Rule Id="S2223" Action="Warning" />
<Rule Id="S2225" Action="Warning" />
<Rule Id="S2234" Action="Warning" />
<Rule Id="S2259" Action="Warning" />
<Rule Id="S2290" Action="Warning" />
<Rule Id="S2291" Action="Warning" />
<Rule Id="S2292" Action="Warning" />
<Rule Id="S2306" Action="Warning" />
<Rule Id="S2328" Action="Warning" />
<Rule Id="S2342" Action="Warning" />
<Rule Id="S2344" Action="Warning" />
<Rule Id="S2345" Action="Warning" />
<Rule Id="S2346" Action="Warning" />
<Rule Id="S2365" Action="Warning" />
<Rule Id="S2368" Action="Warning" />
<Rule Id="S2372" Action="Warning" />
<Rule Id="S2376" Action="Warning" />
<Rule Id="S2386" Action="Warning" />
<Rule Id="S2436" Action="Warning" />
<Rule Id="S2437" Action="Warning" />
<Rule Id="S2681" Action="Warning" />
<Rule Id="S2688" Action="Warning" />
<Rule Id="S2692" Action="Warning" />
<Rule Id="S2696" Action="Warning" />
<Rule Id="S2743" Action="Warning" />
<Rule Id="S2757" Action="Warning" />
<Rule Id="S2761" Action="Warning" />
<Rule Id="S2930" Action="Warning" />
<Rule Id="S2933" Action="Warning" />
<Rule Id="S2934" Action="Warning" />
<Rule Id="S2953" Action="Warning" />
<Rule Id="S2995" Action="Warning" />
<Rule Id="S2996" Action="Warning" />
<Rule Id="S2997" Action="Warning" />
<Rule Id="S3005" Action="Warning" />
<Rule Id="S3010" Action="Warning" />
<Rule Id="S3169" Action="Warning" />
<Rule Id="S3172" Action="Warning" />
<Rule Id="S3217" Action="Warning" />
<Rule Id="S3218" Action="Warning" />
<Rule Id="S3220" Action="Warning" />
<Rule Id="S3236" Action="Warning" />
<Rule Id="S3237" Action="Warning" />
<Rule Id="S3244" Action="Warning" />
<Rule Id="S3246" Action="Warning" />
<Rule Id="S3247" Action="Warning" />
<Rule Id="S3249" Action="Warning" />
<Rule Id="S3251" Action="Warning" />
<Rule Id="S3256" Action="Warning" />
<Rule Id="S3262" Action="Warning" />
<Rule Id="S3263" Action="Warning" />
<Rule Id="S3264" Action="Warning" />
<Rule Id="S3265" Action="Warning" />
<Rule Id="S3346" Action="Warning" />
<Rule Id="S3376" Action="Warning" />
<Rule Id="S3397" Action="Warning" />
<Rule Id="S3415" Action="Warning" />
<Rule Id="S3427" Action="Warning" />
<Rule Id="S3442" Action="Warning" />
<Rule Id="S3443" Action="Warning" />
<Rule Id="S3444" Action="Warning" />
<Rule Id="S3445" Action="Warning" />
<Rule Id="S3447" Action="Warning" />
<Rule Id="S3449" Action="Warning" />
<Rule Id="S3450" Action="Warning" />
<Rule Id="S3451" Action="Warning" />
<Rule Id="S3453" Action="Warning" />
<Rule Id="S3456" Action="Warning" />
<Rule Id="S3458" Action="Warning" />
<Rule Id="S3466" Action="Warning" />
<Rule Id="S3597" Action="Warning" />
<Rule Id="S3598" Action="Warning" />
<Rule Id="S3600" Action="Warning" />
<Rule Id="S3603" Action="Warning" />
<Rule Id="S3604" Action="Warning" />
<Rule Id="S3610" Action="Warning" />
<Rule Id="S3626" Action="Warning" />
<Rule Id="S3655" Action="Warning" />
<Rule Id="S3693" Action="Warning" />
<Rule Id="S3869" Action="Warning" />
<Rule Id="S3871" Action="Warning" />
<Rule Id="S3875" Action="Warning" />
<Rule Id="S3877" Action="Warning" />
<Rule Id="S3881" Action="Warning" />
<Rule Id="S3884" Action="Warning" />
<Rule Id="S3885" Action="Warning" />
<Rule Id="S3887" Action="Warning" />
<Rule Id="S3889" Action="Warning" />
<Rule Id="S3897" Action="Warning" />
<Rule Id="S3903" Action="Warning" />
<Rule Id="S3904" Action="Warning" />
<Rule Id="S3925" Action="Warning" />
<Rule Id="S3926" Action="Warning" />
<Rule Id="S3927" Action="Warning" />
<Rule Id="S3928" Action="Warning" />
<Rule Id="S3966" Action="Warning" />
<Rule Id="S3971" Action="Warning" />
<Rule Id="S3972" Action="Warning" />
<Rule Id="S3981" Action="Warning" />
<Rule Id="S3984" Action="Warning" />
<Rule Id="S3998" Action="Warning" />
<Rule Id="S4015" Action="Warning" />
<Rule Id="S4016" Action="Warning" />
<Rule Id="S4019" Action="Warning" />
<Rule Id="S4035" Action="Warning" />
<Rule Id="S4144" Action="Warning" />
<Rule Id="S4158" Action="Warning" />
<Rule Id="S907" Action="Warning" />
<Rule Id="S927" Action="Warning" />
<Rule Id="S4524" Action="None" />
<Rule Id="S2228" Action="None" />
<Rule Id="S881" Action="None" />
<Rule Id="S4564" Action="None" />
<Rule Id="S4212" Action="None" />
<Rule Id="S2245" Action="None" />
<Rule Id="S131" Action="None" />
<Rule Id="S3330" Action="None" />
<Rule Id="S2255" Action="None" />
<Rule Id="S4432" Action="None" />
<Rule Id="S109" Action="None" />
<Rule Id="S2070" Action="None" />
<Rule Id="S4462" Action="None" />
<Rule Id="S1192" Action="None" />
<Rule Id="S2302" Action="None" />
<Rule Id="S1694" Action="None" />
<Rule Id="S4040" Action="None" />
<Rule Id="S4142" Action="None" />
<Rule Id="S2092" Action="None" />
<Rule Id="S3900" Action="None" />
<Rule Id="S1821" Action="None" />
<Rule Id="S3235" Action="None" />
<Rule Id="S3366" Action="None" />
<Rule Id="S1151" Action="None" />
<Rule Id="S4041" Action="None" />
<Rule Id="S4261" Action="None" />
<Rule Id="S1147" Action="None" />
<Rule Id="S3532" Action="None" />
<Rule Id="S3353" Action="None" />
<Rule Id="S126" Action="None" />
<Rule Id="S138" Action="None" />
<Rule Id="S1659" Action="None" />
<Rule Id="S2197" Action="None" />
<Rule Id="S100" Action="None" />
<Rule Id="S103" Action="None" />
<Rule Id="S104" Action="None" />
<Rule Id="S105" Action="None" />
<Rule Id="S1067" Action="None" />
<Rule Id="S1109" Action="None" />
<Rule Id="S113" Action="None" />
<Rule Id="S1145" Action="None" />
<Rule Id="S1200" Action="None" />
<Rule Id="S121" Action="None" />
<Rule Id="S122" Action="None" />
<Rule Id="S1226" Action="None" />
<Rule Id="S1227" Action="None" />
<Rule Id="S1244" Action="None" />
<Rule Id="S127" Action="None" />
<Rule Id="S1301" Action="None" />
<Rule Id="S1309" Action="None" />
<Rule Id="S1313" Action="None" />
<Rule Id="S134" Action="None" />
<Rule Id="S1449" Action="None" />
<Rule Id="S1451" Action="None" />
<Rule Id="S1541" Action="None" />
<Rule Id="S1696" Action="None" />
<Rule Id="S1697" Action="None" />
<Rule Id="S1698" Action="None" />
<Rule Id="S1858" Action="None" />
<Rule Id="S1994" Action="None" />
<Rule Id="S2156" Action="None" />
<Rule Id="S2221" Action="None" />
<Rule Id="S2325" Action="None" />
<Rule Id="S2330" Action="None" />
<Rule Id="S2333" Action="None" />
<Rule Id="S2339" Action="None" />
<Rule Id="S2357" Action="None" />
<Rule Id="S2360" Action="None" />
<Rule Id="S2387" Action="None" />
<Rule Id="S2551" Action="None" />
<Rule Id="S2674" Action="None" />
<Rule Id="S2699" Action="None" />
<Rule Id="S2701" Action="None" />
<Rule Id="S2760" Action="None" />
<Rule Id="S2931" Action="None" />
<Rule Id="S2952" Action="None" />
<Rule Id="S2955" Action="None" />
<Rule Id="S3052" Action="None" />
<Rule Id="S3215" Action="None" />
<Rule Id="S3216" Action="None" />
<Rule Id="S3234" Action="None" />
<Rule Id="S3240" Action="None" />
<Rule Id="S3242" Action="None" />
<Rule Id="S3253" Action="None" />
<Rule Id="S3254" Action="None" />
<Rule Id="S3257" Action="None" />
<Rule Id="S3431" Action="None" />
<Rule Id="S3441" Action="None" />
<Rule Id="S3717" Action="None" />
<Rule Id="S3872" Action="None" />
<Rule Id="S3874" Action="None" />
<Rule Id="S3876" Action="None" />
<Rule Id="S3880" Action="None" />
<Rule Id="S3898" Action="None" />
<Rule Id="S3902" Action="None" />
<Rule Id="S3906" Action="None" />
<Rule Id="S3908" Action="None" />
<Rule Id="S3909" Action="None" />
<Rule Id="S3956" Action="None" />
<Rule Id="S3962" Action="None" />
<Rule Id="S3963" Action="None" />
<Rule Id="S3967" Action="None" />
<Rule Id="S3990" Action="None" />
<Rule Id="S3992" Action="None" />
<Rule Id="S3993" Action="None" />
<Rule Id="S3994" Action="None" />
<Rule Id="S3995" Action="None" />
<Rule Id="S3996" Action="None" />
<Rule Id="S3997" Action="None" />
<Rule Id="S4000" Action="None" />
<Rule Id="S4002" Action="None" />
<Rule Id="S4004" Action="None" />
<Rule Id="S4005" Action="None" />
<Rule Id="S4017" Action="None" />
<Rule Id="S4018" Action="None" />
<Rule Id="S4022" Action="None" />
<Rule Id="S4023" Action="None" />
<Rule Id="S4025" Action="None" />
<Rule Id="S4026" Action="None" />
<Rule Id="S4027" Action="None" />
<Rule Id="S4039" Action="None" />
<Rule Id="S4047" Action="None" />
<Rule Id="S4049" Action="None" />
<Rule Id="S4050" Action="None" />
<Rule Id="S4052" Action="None" />
<Rule Id="S4055" Action="None" />
<Rule Id="S4056" Action="None" />
<Rule Id="S4057" Action="None" />
<Rule Id="S4058" Action="None" />
<Rule Id="S4059" Action="None" />
<Rule Id="S4060" Action="None" />
<Rule Id="S4069" Action="None" />
<Rule Id="S4070" Action="None" />
<Rule Id="S4225" Action="None" />
<Rule Id="S4226" Action="None" />
</Rules>
</RuleSet>

View File

@@ -1,74 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="Rules for SonarQube" Description="This rule set was automatically generated from SonarQube" ToolsVersion="14.0">
<Rules AnalyzerId="SonarAnalyzer.VisualBasic" RuleNamespace="SonarAnalyzer.VisualBasic">
<Rule Id="S1751" Action="Warning" />
<Rule Id="S1871" Action="Warning" />
<Rule Id="S1656" Action="Warning" />
<Rule Id="S1862" Action="Warning" />
<Rule Id="S1764" Action="Warning" />
<Rule Id="S2178" Action="Warning" />
<Rule Id="S101" Action="Warning" />
<Rule Id="S1075" Action="Warning" />
<Rule Id="S112" Action="Warning" />
<Rule Id="S114" Action="Warning" />
<Rule Id="S117" Action="Warning" />
<Rule Id="S1197" Action="Warning" />
<Rule Id="S1542" Action="Warning" />
<Rule Id="S1643" Action="Warning" />
<Rule Id="S1645" Action="Warning" />
<Rule Id="S1654" Action="Warning" />
<Rule Id="S2304" Action="Warning" />
<Rule Id="S2340" Action="Warning" />
<Rule Id="S2342" Action="Warning" />
<Rule Id="S2344" Action="Warning" />
<Rule Id="S2345" Action="Warning" />
<Rule Id="S2346" Action="Warning" />
<Rule Id="S2347" Action="Warning" />
<Rule Id="S2349" Action="Warning" />
<Rule Id="S2352" Action="Warning" />
<Rule Id="S2355" Action="Warning" />
<Rule Id="S2358" Action="Warning" />
<Rule Id="S2359" Action="Warning" />
<Rule Id="S2365" Action="Warning" />
<Rule Id="S2368" Action="Warning" />
<Rule Id="S2372" Action="Warning" />
<Rule Id="S2375" Action="Warning" />
<Rule Id="S2376" Action="Warning" />
<Rule Id="S2951" Action="Warning" />
<Rule Id="S3385" Action="Warning" />
<Rule Id="S3981" Action="Warning" />
<Rule Id="S4144" Action="Warning" />
<Rule Id="S4142" Action="None" />
<Rule Id="S1659" Action="None" />
<Rule Id="S131" Action="None" />
<Rule Id="S103" Action="None" />
<Rule Id="S104" Action="None" />
<Rule Id="S105" Action="None" />
<Rule Id="S1067" Action="None" />
<Rule Id="S1147" Action="None" />
<Rule Id="S122" Action="None" />
<Rule Id="S1226" Action="None" />
<Rule Id="S134" Action="None" />
<Rule Id="S139" Action="None" />
<Rule Id="S1541" Action="None" />
<Rule Id="S2339" Action="None" />
<Rule Id="S2343" Action="None" />
<Rule Id="S2348" Action="None" />
<Rule Id="S2353" Action="None" />
<Rule Id="S2354" Action="None" />
<Rule Id="S2357" Action="None" />
<Rule Id="S2360" Action="None" />
<Rule Id="S2362" Action="None" />
<Rule Id="S2363" Action="None" />
<Rule Id="S2364" Action="None" />
<Rule Id="S2366" Action="None" />
<Rule Id="S2367" Action="None" />
<Rule Id="S2369" Action="None" />
<Rule Id="S2370" Action="None" />
<Rule Id="S2373" Action="None" />
<Rule Id="S2374" Action="None" />
<Rule Id="S2429" Action="None" />
<Rule Id="S3860" Action="None" />
<Rule Id="S3866" Action="None" />
</Rules>
</RuleSet>

View File

@@ -1,695 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<AnalysisInput>
<Settings>
<Setting>
<Key>sonar.cs.ignoreHeaderComments</Key>
<Value>true</Value>
</Setting>
<Setting>
<Key>sonar.cs.file.suffixes</Key>
<Value>.cs</Value>
</Setting>
</Settings>
<Rules>
<Rule>
<Key>S2589</Key>
</Rule>
<Rule>
<Key>S3433</Key>
</Rule>
<Rule>
<Key>S4061</Key>
</Rule>
<Rule>
<Key>S1121</Key>
</Rule>
<Rule>
<Key>S1854</Key>
</Rule>
<Rule>
<Key>S4457</Key>
</Rule>
<Rule>
<Key>S4456</Key>
</Rule>
<Rule>
<Key>S2278</Key>
</Rule>
<Rule>
<Key>S4211</Key>
</Rule>
<Rule>
<Key>S3923</Key>
</Rule>
<Rule>
<Key>S4426</Key>
</Rule>
<Rule>
<Key>S2486</Key>
</Rule>
<Rule>
<Key>S4433</Key>
</Rule>
<Rule>
<Key>S2758</Key>
</Rule>
<Rule>
<Key>S1751</Key>
</Rule>
<Rule>
<Key>S1871</Key>
</Rule>
<Rule>
<Key>S4586</Key>
</Rule>
<Rule>
<Key>S4581</Key>
</Rule>
<Rule>
<Key>S2737</Key>
</Rule>
<Rule>
<Key>S3400</Key>
</Rule>
<Rule>
<Key>S3649</Key>
</Rule>
<Rule>
<Key>S1144</Key>
</Rule>
<Rule>
<Key>S1264</Key>
</Rule>
<Rule>
<Key>S2201</Key>
</Rule>
<Rule>
<Key>S1118</Key>
</Rule>
<Rule>
<Key>S1006</Key>
</Rule>
<Rule>
<Key>S4214</Key>
</Rule>
<Rule>
<Key>S4210</Key>
</Rule>
<Rule>
<Key>S3241</Key>
</Rule>
<Rule>
<Key>S4428</Key>
</Rule>
<Rule>
<Key>S1048</Key>
</Rule>
<Rule>
<Key>S2183</Key>
</Rule>
<Rule>
<Key>S3168</Key>
</Rule>
<Rule>
<Key>S4220</Key>
</Rule>
<Rule>
<Key>S3261</Key>
</Rule>
<Rule>
<Key>S4260</Key>
</Rule>
<Rule>
<Key>S4159</Key>
</Rule>
<Rule>
<Key>S4277</Key>
</Rule>
<Rule>
<Key>S2583</Key>
</Rule>
<Rule>
<Key>S3440</Key>
</Rule>
<Rule>
<Key>S3776</Key>
<Parameters>
<Parameter>
<Key>threshold</Key>
<Value>15</Value>
</Parameter>
<Parameter>
<Key>propertyThreshold</Key>
<Value>3</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S2326</Key>
</Rule>
<Rule>
<Key>S1116</Key>
</Rule>
<Rule>
<Key>S3358</Key>
</Rule>
<Rule>
<Key>S4200</Key>
</Rule>
<Rule>
<Key>S1172</Key>
</Rule>
<Rule>
<Key>S1862</Key>
</Rule>
<Rule>
<Key>S2275</Key>
</Rule>
<Rule>
<Key>S3457</Key>
</Rule>
<Rule>
<Key>S3459</Key>
</Rule>
<Rule>
<Key>S3464</Key>
</Rule>
<Rule>
<Key>S3343</Key>
</Rule>
<Rule>
<Key>S818</Key>
</Rule>
<Rule>
<Key>S1656</Key>
</Rule>
<Rule>
<Key>S2184</Key>
</Rule>
<Rule>
<Key>S1764</Key>
</Rule>
<Rule>
<Key>S2971</Key>
</Rule>
<Rule>
<Key>S3060</Key>
</Rule>
<Rule>
<Key>S101</Key>
</Rule>
<Rule>
<Key>S1066</Key>
</Rule>
<Rule>
<Key>S107</Key>
<Parameters>
<Parameter>
<Key>max</Key>
<Value>7</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S1075</Key>
</Rule>
<Rule>
<Key>S108</Key>
</Rule>
<Rule>
<Key>S110</Key>
<Parameters>
<Parameter>
<Key>max</Key>
<Value>5</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S1104</Key>
</Rule>
<Rule>
<Key>S1110</Key>
</Rule>
<Rule>
<Key>S1117</Key>
</Rule>
<Rule>
<Key>S112</Key>
</Rule>
<Rule>
<Key>S1123</Key>
</Rule>
<Rule>
<Key>S1125</Key>
</Rule>
<Rule>
<Key>S1134</Key>
</Rule>
<Rule>
<Key>S1135</Key>
</Rule>
<Rule>
<Key>S1155</Key>
</Rule>
<Rule>
<Key>S1163</Key>
</Rule>
<Rule>
<Key>S1168</Key>
</Rule>
<Rule>
<Key>S1185</Key>
</Rule>
<Rule>
<Key>S1186</Key>
</Rule>
<Rule>
<Key>S1206</Key>
</Rule>
<Rule>
<Key>S1210</Key>
</Rule>
<Rule>
<Key>S1215</Key>
</Rule>
<Rule>
<Key>S125</Key>
</Rule>
<Rule>
<Key>S1450</Key>
</Rule>
<Rule>
<Key>S1479</Key>
<Parameters>
<Parameter>
<Key>maximum</Key>
<Value>30</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S1481</Key>
</Rule>
<Rule>
<Key>S1607</Key>
</Rule>
<Rule>
<Key>S1643</Key>
</Rule>
<Rule>
<Key>S1699</Key>
</Rule>
<Rule>
<Key>S1848</Key>
</Rule>
<Rule>
<Key>S1905</Key>
</Rule>
<Rule>
<Key>S1939</Key>
</Rule>
<Rule>
<Key>S1940</Key>
</Rule>
<Rule>
<Key>S1944</Key>
</Rule>
<Rule>
<Key>S2068</Key>
<Parameters>
<Parameter>
<Key>credentialWords</Key>
<Value>password, passwd, pwd</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S2114</Key>
</Rule>
<Rule>
<Key>S2123</Key>
</Rule>
<Rule>
<Key>S2178</Key>
</Rule>
<Rule>
<Key>S2187</Key>
</Rule>
<Rule>
<Key>S2190</Key>
</Rule>
<Rule>
<Key>S2219</Key>
</Rule>
<Rule>
<Key>S2223</Key>
</Rule>
<Rule>
<Key>S2225</Key>
</Rule>
<Rule>
<Key>S2234</Key>
</Rule>
<Rule>
<Key>S2259</Key>
</Rule>
<Rule>
<Key>S2290</Key>
</Rule>
<Rule>
<Key>S2291</Key>
</Rule>
<Rule>
<Key>S2292</Key>
</Rule>
<Rule>
<Key>S2306</Key>
</Rule>
<Rule>
<Key>S2328</Key>
</Rule>
<Rule>
<Key>S2342</Key>
<Parameters>
<Parameter>
<Key>format</Key>
<Value>^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$</Value>
</Parameter>
<Parameter>
<Key>flagsAttributeFormat</Key>
<Value>^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?s$</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S2344</Key>
</Rule>
<Rule>
<Key>S2345</Key>
</Rule>
<Rule>
<Key>S2346</Key>
</Rule>
<Rule>
<Key>S2365</Key>
</Rule>
<Rule>
<Key>S2368</Key>
</Rule>
<Rule>
<Key>S2372</Key>
</Rule>
<Rule>
<Key>S2376</Key>
</Rule>
<Rule>
<Key>S2386</Key>
</Rule>
<Rule>
<Key>S2436</Key>
<Parameters>
<Parameter>
<Key>max</Key>
<Value>2</Value>
</Parameter>
<Parameter>
<Key>maxMethod</Key>
<Value>3</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S2437</Key>
</Rule>
<Rule>
<Key>S2681</Key>
</Rule>
<Rule>
<Key>S2688</Key>
</Rule>
<Rule>
<Key>S2692</Key>
</Rule>
<Rule>
<Key>S2696</Key>
</Rule>
<Rule>
<Key>S2743</Key>
</Rule>
<Rule>
<Key>S2757</Key>
</Rule>
<Rule>
<Key>S2761</Key>
</Rule>
<Rule>
<Key>S2930</Key>
</Rule>
<Rule>
<Key>S2933</Key>
</Rule>
<Rule>
<Key>S2934</Key>
</Rule>
<Rule>
<Key>S2953</Key>
</Rule>
<Rule>
<Key>S2995</Key>
</Rule>
<Rule>
<Key>S2996</Key>
</Rule>
<Rule>
<Key>S2997</Key>
</Rule>
<Rule>
<Key>S3005</Key>
</Rule>
<Rule>
<Key>S3010</Key>
</Rule>
<Rule>
<Key>S3169</Key>
</Rule>
<Rule>
<Key>S3172</Key>
</Rule>
<Rule>
<Key>S3217</Key>
</Rule>
<Rule>
<Key>S3218</Key>
</Rule>
<Rule>
<Key>S3220</Key>
</Rule>
<Rule>
<Key>S3236</Key>
</Rule>
<Rule>
<Key>S3237</Key>
</Rule>
<Rule>
<Key>S3244</Key>
</Rule>
<Rule>
<Key>S3246</Key>
</Rule>
<Rule>
<Key>S3247</Key>
</Rule>
<Rule>
<Key>S3249</Key>
</Rule>
<Rule>
<Key>S3251</Key>
</Rule>
<Rule>
<Key>S3256</Key>
</Rule>
<Rule>
<Key>S3262</Key>
</Rule>
<Rule>
<Key>S3263</Key>
</Rule>
<Rule>
<Key>S3264</Key>
</Rule>
<Rule>
<Key>S3265</Key>
</Rule>
<Rule>
<Key>S3346</Key>
</Rule>
<Rule>
<Key>S3376</Key>
</Rule>
<Rule>
<Key>S3397</Key>
</Rule>
<Rule>
<Key>S3415</Key>
</Rule>
<Rule>
<Key>S3427</Key>
</Rule>
<Rule>
<Key>S3442</Key>
</Rule>
<Rule>
<Key>S3443</Key>
</Rule>
<Rule>
<Key>S3444</Key>
</Rule>
<Rule>
<Key>S3445</Key>
</Rule>
<Rule>
<Key>S3447</Key>
</Rule>
<Rule>
<Key>S3449</Key>
</Rule>
<Rule>
<Key>S3450</Key>
</Rule>
<Rule>
<Key>S3451</Key>
</Rule>
<Rule>
<Key>S3453</Key>
</Rule>
<Rule>
<Key>S3456</Key>
</Rule>
<Rule>
<Key>S3458</Key>
</Rule>
<Rule>
<Key>S3466</Key>
</Rule>
<Rule>
<Key>S3597</Key>
</Rule>
<Rule>
<Key>S3598</Key>
</Rule>
<Rule>
<Key>S3600</Key>
</Rule>
<Rule>
<Key>S3603</Key>
</Rule>
<Rule>
<Key>S3604</Key>
</Rule>
<Rule>
<Key>S3610</Key>
</Rule>
<Rule>
<Key>S3626</Key>
</Rule>
<Rule>
<Key>S3655</Key>
</Rule>
<Rule>
<Key>S3693</Key>
</Rule>
<Rule>
<Key>S3869</Key>
</Rule>
<Rule>
<Key>S3871</Key>
</Rule>
<Rule>
<Key>S3875</Key>
</Rule>
<Rule>
<Key>S3877</Key>
</Rule>
<Rule>
<Key>S3881</Key>
</Rule>
<Rule>
<Key>S3884</Key>
</Rule>
<Rule>
<Key>S3885</Key>
</Rule>
<Rule>
<Key>S3887</Key>
</Rule>
<Rule>
<Key>S3889</Key>
</Rule>
<Rule>
<Key>S3897</Key>
</Rule>
<Rule>
<Key>S3903</Key>
</Rule>
<Rule>
<Key>S3904</Key>
</Rule>
<Rule>
<Key>S3925</Key>
</Rule>
<Rule>
<Key>S3926</Key>
</Rule>
<Rule>
<Key>S3927</Key>
</Rule>
<Rule>
<Key>S3928</Key>
</Rule>
<Rule>
<Key>S3966</Key>
</Rule>
<Rule>
<Key>S3971</Key>
</Rule>
<Rule>
<Key>S3972</Key>
</Rule>
<Rule>
<Key>S3981</Key>
</Rule>
<Rule>
<Key>S3984</Key>
</Rule>
<Rule>
<Key>S3998</Key>
</Rule>
<Rule>
<Key>S4015</Key>
</Rule>
<Rule>
<Key>S4016</Key>
</Rule>
<Rule>
<Key>S4019</Key>
</Rule>
<Rule>
<Key>S4035</Key>
</Rule>
<Rule>
<Key>S4144</Key>
</Rule>
<Rule>
<Key>S4158</Key>
</Rule>
<Rule>
<Key>S907</Key>
</Rule>
<Rule>
<Key>S927</Key>
</Rule>
</Rules>
<Files>
</Files>
</AnalysisInput>

View File

@@ -1,186 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<AnalysisInput>
<Settings>
<Setting>
<Key>sonar.vbnet.ignoreHeaderComments</Key>
<Value>true</Value>
</Setting>
<Setting>
<Key>sonar.vbnet.file.suffixes</Key>
<Value>.vb</Value>
</Setting>
</Settings>
<Rules>
<Rule>
<Key>S1751</Key>
</Rule>
<Rule>
<Key>S1871</Key>
</Rule>
<Rule>
<Key>S1656</Key>
</Rule>
<Rule>
<Key>S1862</Key>
</Rule>
<Rule>
<Key>S1764</Key>
</Rule>
<Rule>
<Key>S2178</Key>
</Rule>
<Rule>
<Key>S101</Key>
<Parameters>
<Parameter>
<Key>format</Key>
<Value>^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S1075</Key>
</Rule>
<Rule>
<Key>S112</Key>
</Rule>
<Rule>
<Key>S114</Key>
<Parameters>
<Parameter>
<Key>format</Key>
<Value>^I([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S117</Key>
<Parameters>
<Parameter>
<Key>format</Key>
<Value>^[a-z][a-z0-9]*([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S1197</Key>
</Rule>
<Rule>
<Key>S1542</Key>
<Parameters>
<Parameter>
<Key>format</Key>
<Value>^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S1643</Key>
</Rule>
<Rule>
<Key>S1645</Key>
</Rule>
<Rule>
<Key>S1654</Key>
<Parameters>
<Parameter>
<Key>format</Key>
<Value>^[a-z][a-z0-9]*([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S2304</Key>
<Parameters>
<Parameter>
<Key>format</Key>
<Value>^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?(\.([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?)*$</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S2340</Key>
</Rule>
<Rule>
<Key>S2342</Key>
<Parameters>
<Parameter>
<Key>format</Key>
<Value>^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$</Value>
</Parameter>
<Parameter>
<Key>flagsAttributeFormat</Key>
<Value>^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?s$</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S2344</Key>
</Rule>
<Rule>
<Key>S2345</Key>
</Rule>
<Rule>
<Key>S2346</Key>
</Rule>
<Rule>
<Key>S2347</Key>
<Parameters>
<Parameter>
<Key>format</Key>
<Value>^(([a-z][a-z0-9]*)?([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?_)?([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S2349</Key>
</Rule>
<Rule>
<Key>S2352</Key>
</Rule>
<Rule>
<Key>S2355</Key>
</Rule>
<Rule>
<Key>S2358</Key>
</Rule>
<Rule>
<Key>S2359</Key>
</Rule>
<Rule>
<Key>S2365</Key>
</Rule>
<Rule>
<Key>S2368</Key>
</Rule>
<Rule>
<Key>S2372</Key>
</Rule>
<Rule>
<Key>S2375</Key>
<Parameters>
<Parameter>
<Key>minimumSeriesLength</Key>
<Value>6</Value>
</Parameter>
</Parameters>
</Rule>
<Rule>
<Key>S2376</Key>
</Rule>
<Rule>
<Key>S2951</Key>
</Rule>
<Rule>
<Key>S3385</Key>
</Rule>
<Rule>
<Key>S3981</Key>
</Rule>
<Rule>
<Key>S4144</Key>
</Rule>
</Rules>
<Files>
</Files>
</AnalysisInput>

View File

@@ -1,7 +0,0 @@
organization=geogeob
projectKey=ModernKeePass
serverUrl=https://sonarcloud.io
serverVersion=7.2.0.12953
dashboardUrl=https://sonarcloud.io/dashboard/index/ModernKeePass
ceTaskId=AWQER9hfTzX59Iu7A6N0
ceTaskUrl=https://sonarcloud.io/api/ce/task?id=AWQER9hfTzX59Iu7A6N0

View File

@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ProjectInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.sonarsource.com/msbuild/integration/2015/1">
<ProjectName>ModernKeePass.App</ProjectName>
<ProjectLanguage>C#</ProjectLanguage>
<ProjectType>Product</ProjectType>
<ProjectGuid>a0cfc681-769b-405a-8482-0cdee595a91f</ProjectGuid>
<FullPath>C:\Sources\Other\ModernKeePass\ModernKeePass\ModernKeePass.App.csproj</FullPath>
<IsExcluded>false</IsExcluded>
<AnalysisResults>
<AnalysisResult Id="FilesToAnalyze" Location="C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\out\0\FilesToAnalyze.txt" />
</AnalysisResults>
<AnalysisSettings>
<Property Name="sonar.cs.roslyn.reportFilePath">C:\Sources\Other\ModernKeePass\ModernKeePass\bin\Debug\ModernKeePass.exe.RoslynCA.json</Property>
<Property Name="sonar.cs.analyzer.projectOutPath">C:\Sources\Other\ModernKeePass\ModernKeePass\.sonarqube\out\0</Property>
</AnalysisSettings>
<Configuration>Debug</Configuration>
<Platform>AnyCPU</Platform>
</ProjectInfo>

View File

@@ -1,85 +0,0 @@
P
GC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\ClipboardAction.csutf-8T
KC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\NavigateToUrlAction.csutf-8Q
HC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\SetupFocusAction.csutf-8A
8C:\Sources\Other\ModernKeePass\ModernKeePass\App.xaml.csutf-8X
OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\IntToSymbolConverter.csutf-8[
RC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\DatabaseOpenedException.csutf-8S
JC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ILicenseService.csutf-8[
RC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IProxyInvocationHandler.csutf-8R
IC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentService.csutf-8O
FC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentItem.csutf-8T
KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IResourceService.csutf-8V
MC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SingletonServiceBase.csutf-8i
`C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\SelectableDataTemplateSelector.csutf-8X
OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsSaveVm.csutf-8]
TC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\DonatePage.xaml.csutf-8Q
HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\DatabaseService.csutf-8T
KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISettingsService.csutf-8S
JC:\Sources\Other\ModernKeePass\ModernKeePass\Common\MessageDialogHelper.csutf-8P
GC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NavigationHelper.csutf-8Y
PC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NotifyPropertyChangedBase.csutf-8T
KC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ObservableDictionary.csutf-8L
CC:\Sources\Other\ModernKeePass\ModernKeePass\Common\RelayCommand.csutf-8Q
HC:\Sources\Other\ModernKeePass\ModernKeePass\Common\SuspensionManager.csutf-8P
GC:\Sources\Other\ModernKeePass\ModernKeePass\Services\LicenseService.csutf-8O
FC:\Sources\Other\ModernKeePass\ModernKeePass\Services\RecentService.csutf-8R
IC:\Sources\Other\ModernKeePass\ModernKeePass\Services\ResourcesService.csutf-8Q
HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SettingsService.csutf-8W
NC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ToastNotificationHelper.csutf-8i
`C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DiscreteIntToSolidColorBrushConverter.csutf-8d
[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\EmptyStringToVisibilityConverter.csutf-8Z
QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\NullToBooleanConverter.csutf-8Q
HC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\SaveException.csutf-8\
SC:\Sources\Other\ModernKeePass\ModernKeePass\Extensions\DispatcherTaskExtensions.csutf-8T
KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IDatabaseService.csutf-8X
OC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IHasSelectableObject.csutf-8T
KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISelectableModel.csutf-8\
SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\BasePages\LayoutAwarePageBase.csutf-8k
bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsDatabasePage.xaml.csutf-8n
eC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsNewDatabasePage.xaml.csutf-8g
^C:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSavePage.xaml.csutf-8k
bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSecurityPage.xaml.csutf-8j
aC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsWelcomePage.xaml.csutf-8h
_C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\FirstItemDataTemplateSelector.csutf-8U
LC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\ListViewWithDisable.csutf-8f
]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\BreadCrumbUserControl.xaml.csutf-8h
_C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\CompositeKeyUserControl.xaml.csutf-8S
JC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\TextBoxWithButton.csutf-8`
WC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\BooleanToVisibilityConverter.csutf-8Y
PC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ColorToBrushConverter.csutf-8d
[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DoubleToSolidColorBrushConverter.csutf-8g
^C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\InverseBooleanToVisibilityConverter.csutf-8Z
QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\PluralizationConverter.csutf-8c
ZC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ProgressBarLegalValuesConverter.csutf-8X
OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\TextToWidthConverter.csutf-8Q
HC:\Sources\Other\ModernKeePass\ModernKeePass\Events\PasswordEventArgs.csutf-8N
EC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IIsEnabled.csutf-8M
DC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IPwEntity.csutf-8L
CC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPage.xaml.csutf-8\
SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\AboutPage.xaml.csutf-8b
YC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\NewDatabasePage.xaml.csutf-8P
GC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPage.xaml.csutf-8^
UC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\WelcomePage.xaml.csutf-8K
BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\AboutVm.csutf-8R
IC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\CompositeKeyVm.csutf-8X
OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\ListMenuItemVm.csutf-8X
OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\MainMenuItemVm.csutf-8V
MC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\RecentItemVm.csutf-8S
JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\EntryDetailPage.xaml.csutf-8S
JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\GroupDetailPage.xaml.csutf-8c
ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\OpenDatabasePage.xaml.csutf-8f
]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\RecentDatabasesPage.xaml.csutf-8c
ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\SaveDatabasePage.xaml.csutf-8P
GC:\Sources\Other\ModernKeePass\ModernKeePass\Properties\AssemblyInfo.csutf-8K
BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\EntryVm.csutf-8K
BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\GroupVm.csutf-8W
NC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsNewVm.csutf-8N
EC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SettingsVm.csutf-8J
AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\MainVm.csutf-8I
@C:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\NewVm.csutf-8J
AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\OpenVm.csutf-8L
CC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\RecentVm.csutf-8J
AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SaveVm.csutf-8\
SC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsDatabaseVm.csutf-8i
`C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\HamburgerMenuUserControl.xaml.csutf-8

View File

@@ -1,139 +0,0 @@
I
GC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\ClipboardAction.csM
KC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\NavigateToUrlAction.csJ
HC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\SetupFocusAction.cs:
8C:\Sources\Other\ModernKeePass\ModernKeePass\App.xaml.csQ
OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\IntToSymbolConverter.csT
RC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\DatabaseOpenedException.csL
JC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ILicenseService.csT
RC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IProxyInvocationHandler.csK
IC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentService.csH
FC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentItem.csM
KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IResourceService.csO
MC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SingletonServiceBase.csb
`C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\SelectableDataTemplateSelector.csQ
OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsSaveVm.csV
TC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\DonatePage.xaml.csJ
HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\DatabaseService.csM
KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISettingsService.csL
JC:\Sources\Other\ModernKeePass\ModernKeePass\Common\MessageDialogHelper.csI
GC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NavigationHelper.csR
PC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NotifyPropertyChangedBase.csM
KC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ObservableDictionary.csE
CC:\Sources\Other\ModernKeePass\ModernKeePass\Common\RelayCommand.csJ
HC:\Sources\Other\ModernKeePass\ModernKeePass\Common\SuspensionManager.csI
GC:\Sources\Other\ModernKeePass\ModernKeePass\Services\LicenseService.csH
FC:\Sources\Other\ModernKeePass\ModernKeePass\Services\RecentService.csK
IC:\Sources\Other\ModernKeePass\ModernKeePass\Services\ResourcesService.csJ
HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SettingsService.csP
NC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ToastNotificationHelper.csb
`C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DiscreteIntToSolidColorBrushConverter.cs]
[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\EmptyStringToVisibilityConverter.csS
QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\NullToBooleanConverter.csJ
HC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\SaveException.csU
SC:\Sources\Other\ModernKeePass\ModernKeePass\Extensions\DispatcherTaskExtensions.csM
KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IDatabaseService.csQ
OC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IHasSelectableObject.csM
KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISelectableModel.csU
SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\BasePages\LayoutAwarePageBase.csd
bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsDatabasePage.xaml.csg
eC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsNewDatabasePage.xaml.cs`
^C:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSavePage.xaml.csd
bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSecurityPage.xaml.csc
aC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsWelcomePage.xaml.csa
_C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\FirstItemDataTemplateSelector.csN
LC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\ListViewWithDisable.cs_
]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\BreadCrumbUserControl.xaml.csa
_C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\CompositeKeyUserControl.xaml.csL
JC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\TextBoxWithButton.csY
WC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\BooleanToVisibilityConverter.csR
PC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ColorToBrushConverter.cs]
[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DoubleToSolidColorBrushConverter.cs`
^C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\InverseBooleanToVisibilityConverter.csS
QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\PluralizationConverter.cs\
ZC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ProgressBarLegalValuesConverter.csQ
OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\TextToWidthConverter.csJ
HC:\Sources\Other\ModernKeePass\ModernKeePass\Events\PasswordEventArgs.csG
EC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IIsEnabled.csF
DC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IPwEntity.csE
CC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPage.xaml.csU
SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\AboutPage.xaml.cs[
YC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\NewDatabasePage.xaml.csI
GC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPage.xaml.csW
UC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\WelcomePage.xaml.csD
BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\AboutVm.csK
IC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\CompositeKeyVm.csQ
OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\ListMenuItemVm.csQ
OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\MainMenuItemVm.csO
MC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\RecentItemVm.csL
JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\EntryDetailPage.xaml.csL
JC:\Sources\Other\ModernKeePass\ModernKeePass\Views\GroupDetailPage.xaml.cs\
ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\OpenDatabasePage.xaml.cs_
]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\RecentDatabasesPage.xaml.cs\
ZC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\SaveDatabasePage.xaml.csI
GC:\Sources\Other\ModernKeePass\ModernKeePass\Properties\AssemblyInfo.csD
BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\EntryVm.csD
BC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\GroupVm.csP
NC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsNewVm.csG
EC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SettingsVm.csC
AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\MainVm.csB
@C:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\NewVm.csC
AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\OpenVm.csE
CC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\RecentVm.csC
AC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\SaveVm.csU
SC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsDatabaseVm.csb
`C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\HamburgerMenuUserControl.xaml.csE
AC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\App.g.i.csC
?C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\App.g.csO
KC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\Colors.g.i.csM
IC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\Colors.g.csk
gC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsSavePage.g.i.csi
eC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsSavePage.g.csj
fC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\UserControls\BreadCrumbUserControl.g.i.csh
dC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\UserControls\BreadCrumbUserControl.g.csl
hC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\UserControls\CompositeKeyUserControl.g.i.csj
fC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\UserControls\CompositeKeyUserControl.g.csP
LC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPage.g.i.csN
JC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPage.g.cs`
\C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\AboutPage.g.i.cs^
ZC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\AboutPage.g.csW
SC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\EntryDetailPage.g.i.csU
QC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\EntryDetailPage.g.csW
SC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\GroupDetailPage.g.i.csU
QC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\GroupDetailPage.g.csa
]C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\DonatePage.g.i.cs_
[C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\DonatePage.g.csf
bC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\NewDatabasePage.g.i.csd
`C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\NewDatabasePage.g.csg
cC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\OpenDatabasePage.g.i.cse
aC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\OpenDatabasePage.g.csj
fC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\RecentDatabasesPage.g.i.csh
dC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\RecentDatabasesPage.g.csg
cC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\SaveDatabasePage.g.i.cse
aC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\SaveDatabasePage.g.csT
PC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPage.g.i.csR
NC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPage.g.csb
^C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\WelcomePage.g.i.cs`
\C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\MainPageFrames\WelcomePage.g.cso
kC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsDatabasePage.g.i.csm
iC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsDatabasePage.g.csr
nC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsNewDatabasePage.g.i.csp
lC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsNewDatabasePage.g.cso
kC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsSecurityPage.g.i.csm
iC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsSecurityPage.g.csn
jC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsWelcomePage.g.i.csl
hC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\SettingsPageFrames\SettingsWelcomePage.g.cs]
YC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\HamburgerButtonStyle.g.i.cs[
WC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\HamburgerButtonStyle.g.csc
_C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\ListViewLeftIndicatorStyle.g.i.csa
]C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\ListViewLeftIndicatorStyle.g.cs\
XC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\NoBorderButtonStyle.g.i.csZ
VC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\NoBorderButtonStyle.g.csO
KC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\Styles.g.i.csM
IC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\Styles.g.cs_
[C:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\TextBoxWithButtonStyle.g.i.cs]
YC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Styles\TextBoxWithButtonStyle.g.csm
iC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\UserControls\HamburgerMenuUserControl.g.i.csk
gC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\Views\UserControls\HamburgerMenuUserControl.g.csL
HC:\Sources\Other\ModernKeePass\ModernKeePass\obj\Debug\XamlTypeInfo.g.csQ
MC:\Users\GBE\AppData\Local\Temp\.NETCore,Version=v4.5.1.AssemblyAttributes.cs

View File

@@ -1,180 +0,0 @@
<EFBFBD>
GC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\ClipboardAction.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=3;2=0;4=0;6=0;8=0;10=0;12=0r
<1A> <17>
KC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\NavigateToUrlAction.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=3;2=0;4=0;6=0;8=0;10=0;12=0r
 !x<01>
<1D>
HC:\Sources\Other\ModernKeePass\ModernKeePass\Actions\SetupFocusAction.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=2;2=1;4=0;6=0;8=0;10=0;12=0r
<1B>
<18>
8C:\Sources\Other\ModernKeePass\ModernKeePass\App.xaml.cs7 8@HR 0=0;5=0;10=0;20=1;30=0;60=0;90=0Z1=5;2=1;4=2;6=1;8=0;10=0;12=0jH*>?@ABFTZ[^`fluvwz|}<7D><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01>r<>
 !"#()+,-./023456789:;<CDEFGIJKLNORSUX\]_bdehjmnpqrstxy<79><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01>x<10>I !"+-./24579:EFKRX\_bdhmpsx<73><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01>
OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\IntToSymbolConverter.cs7 (08;@;H;R 0=0;5=0;10=0;20=0;30=1;60=0;90=0Z1=0;2=1;4=0;6=0;8=0;10=0;12=1j<31>+,08<@JKLMZ[\]^_`abcdefgjklmnopqrstuvwxyz{|}~<><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03>r[
 !"#$%&'()*-./12345679:;=>?ABCDEFGHINOPQRSUVWXYhi<68><03><03><03><03><03>x<02>?
 !"#$%&'()*-./12345679:;=>?ABCDEFGHINOPQXhi<68><03>
RC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\DatabaseOpenedException.cs(0R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r <09>
JC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ILicenseService.cs(08@R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r 
<0C>
RC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IProxyInvocationHandler.cs(0R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r <09>
IC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentService.cs(08@R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r
<0F>
FC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IRecentItem.cs(08@R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r

<0B>
KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IResourceService.cs(0R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r<07>
MC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SingletonServiceBase.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0r

<0C>
<EFBFBD>
`C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\SelectableDataTemplateSelector.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=4;2=1;4=0;6=0;8=0;10=0;12=0r
x<02><0F>
OC:\Sources\Other\ModernKeePass\ModernKeePass\ViewModels\Items\SettingsSaveVm.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=4;2=0;4=0;6=0;8=0;10=0;12=0r
<18>
<15>
TC:\Sources\Other\ModernKeePass\ModernKeePass\Views\MainPageFrames\DonatePage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0jr

<0F> <0C>
HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\DatabaseService.csQ (082@2H2R 0=0;5=0;10=0;20=0;30=1;60=0;90=0Z1=25;2=5;4=0;6=2;8=0;10=0;12=0j$cdefghky<6B><01><01><01><01><01><01><01><01><01><01><01><01><01>r<>
 !"#$%')*+,-/0123456789:<=>?@BCDEFHIJKLNOPQRTUVWYZ[]^_`ijlmnopqstuvwz{|}~<><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><02><02><02><02><02>x<16><01>"#'+,1468>?DEJKPQTUY_npstuwz{|<><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><02><02>
KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISettingsService.cs(0R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r<08>
JC:\Sources\Other\ModernKeePass\ModernKeePass\Common\MessageDialogHelper.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=4;2=2;4=0;6=0;8=0;10=0;12=0j 9<DJMPSr?
 !"$%&')*+,-./01234678:=>@ABEFHIKNQTVWXYx<03> "$%+-.028:=BENQTV<54>
GC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NavigationHelper.csD (8>@>H>R 0=0;5=0;10=0;20=0;30=0;60=1;90=0Z1=12;2=8;4=1;6=1;8=0;10=0;12=1j<31> !"#&(*,-./02579:ABCDEFKLMSW`stuvxyz<79><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03>r<>
;<=>?GHINOTUVXYZ[\^abfghiklpq{|}~<><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03><03>x*<2A><01>?INTUXZ[afhi<69><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><02><03><03><03>
PC:\Sources\Other\ModernKeePass\ModernKeePass\Common\NotifyPropertyChangedBase.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=2;4=0;6=0;8=0;10=0;12=0r
x<01>
<19>
KC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ObservableDictionary.cs( (08!@&H!R 0=0;5=0;10=0;20=0;30=1;60=0;90=0Z1=18;2=5;4=1;6=0;8=0;10=0;12=0j
r<>
 !"#$&'()*,-./12345679:;<=>?@ACDEFGHIJKLMOPQRSTUVWXYZ\]^_`abcdfghiklmnpqrsuvwxz{|}<><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01>x <09>. "().35;=>@FGIJLSWX^_`bhmrw|<7C><01><01><01><01><01><01><01><01>
CC:\Sources\Other\ModernKeePass\ModernKeePass\Common\RelayCommand.cs (8@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=2;2=3;4=0;6=0;8=0;10=0;12=0j%
$%&'(1234567=>?@ABHIJKLr*  !")*+,-./89:;CDEFMNOPQRSTUVx<03>+,-.:EPR<50>
HC:\Sources\Other\ModernKeePass\ModernKeePass\Common\SuspensionManager.cs8 (08@HR 0=0;5=0;10=0;20=1;30=0;60=0;90=0Z1=5;2=3;4=3;6=0;8=0;10=0;12=0j~ !"#)*+,-3456789>HIN\]^_`abcdefmqv<71><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01>r<>
$%&'./01:;<=?@ABCDEFJKLOPQRSTUVWXYZghiklnoprstwxyz{|}~<><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><02><02><02><02><02><02><02><02><02><02><02>x<15>S&0?BDLOPRSXinoswz|}<7D><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01>
GC:\Sources\Other\ModernKeePass\ModernKeePass\Services\LicenseService.cs (08 @ H R 0=0;5=0;10=1;20=0;30=0;60=0;90=0Z1=5;2=0;4=0;6=1;8=0;10=0;12=0j*+r?
!"#$%&'(),-./012345678:;<=>@ABCEFGHIJx<03>#$&'(),.012346<=BG<42>
FC:\Sources\Other\ModernKeePass\ModernKeePass\Services\RecentService.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=4;2=1;4=0;6=0;8=0;10=0;12=0r,
 !#$%&()*+-./012x<06>
 %*/<2F>
IC:\Sources\Other\ModernKeePass\ModernKeePass\Services\ResourcesService.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0r
<11>
<0E>
HC:\Sources\Other\ModernKeePass\ModernKeePass\Services\SettingsService.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=1;4=0;6=0;8=0;10=0;12=0r
x<03>
<1C>
NC:\Sources\Other\ModernKeePass\ModernKeePass\Common\ToastNotificationHelper.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=2;2=1;4=0;6=0;8=0;10=0;12=0r0
 !#$%&'(*+,-./123456x<01> %&'(,.3<EFBFBD>
`C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DiscreteIntToSolidColorBrushConverter.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=1;6=0;8=0;10=0;12=0r
x<01>
<18>
[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\EmptyStringToVisibilityConverter.cs 8@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=1;4=0;6=0;8=0;10=0;12=0r
x<02> <11>
QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\NullToBooleanConverter.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=2;2=0;4=0;6=0;8=0;10=0;12=0r
<12>
<0F>
HC:\Sources\Other\ModernKeePass\ModernKeePass\Exceptions\SaveException.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=2;2=0;4=0;6=0;8=0;10=0;12=0r 
<0E> <0B>
SC:\Sources\Other\ModernKeePass\ModernKeePass\Extensions\DispatcherTaskExtensions.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=2;2=0;4=0;6=0;8=0;10=0;12=0jr
 x<03>
<1E>
KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IDatabaseService.cs(08@R 0=0;5=0;10=0;20=1;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0jr 
 !"#<23>
OC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IHasSelectableObject.cs(08@R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r<07>
KC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\ISelectableModel.cs(08@R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r<07>
SC:\Sources\Other\ModernKeePass\ModernKeePass\Views\BasePages\LayoutAwarePageBase.cs" (08#@#H#R 0=0;5=0;10=0;20=0;30=1;60=0;90=0Z1=13;2=4;4=1;6=1;8=0;10=0;12=0j\
"#*+,-.456789:;<=>ABFGOWXYZ[\]^ijlmnrstuv|}~<><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01>r<>
 $%&()/012?@DEHIJKLMNPQRSTU_`abcdepwxyz<79><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01>x<10>1 $%/01DHJPRacy<63><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01><01>
bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsDatabasePage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0jr

<0F> <0C>
eC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsNewDatabasePage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0jr

<0F> <0C>
^C:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSavePage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0jr

<0F> <0C>
bC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsSecurityPage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=2;2=0;4=0;6=0;8=0;10=0;12=0j
r
<17><14>
aC:\Sources\Other\ModernKeePass\ModernKeePass\Views\SettingsPageFrames\SettingsWelcomePage.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=0;8=0;10=0;12=0jr

<0F> <0C>
_C:\Sources\Other\ModernKeePass\ModernKeePass\TemplateSelectors\FirstItemDataTemplateSelector.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=4;2=1;4=0;6=0;8=0;10=0;12=0r
x<01>
<0F>
LC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\ListViewWithDisable.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=1;4=0;6=0;8=0;10=0;12=0r
x<02> <11>
]C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\BreadCrumbUserControl.xaml.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=3;2=0;4=0;6=0;8=0;10=0;12=0jr
<1D>
<1B>
_C:\Sources\Other\ModernKeePass\ModernKeePass\Views\UserControls\CompositeKeyUserControl.xaml.cs
(08@HR 0=0;5=0;10=0;20=1;30=0;60=0;90=0Z1=8;2=4;4=0;6=1;8=0;10=0;12=0j `ort
 !"#$%&'()*,-./01234569;<=>@ABCEFGIJKLMNOPQRSTUVWXY[\]^_abcefghijklmpqrsuvwxyz{|~<><01><01><01>x <09>%"#&*./26=GIKLRSUW]_ajkmpqry|~<><01>
JC:\Sources\Other\ModernKeePass\ModernKeePass\Controls\TextBoxWithButton.cs (
0
8 @ H R 0=0;5=0;10=1;20=0;30=0;60=0;90=0Z1=8;2=1;4=0;6=0;8=0;10=0;12=0r@
 !#$%&'()*+,-/0123456789;<=>?@ABCDEx<01>
!%&)-1259=>?A<>
WC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\BooleanToVisibilityConverter.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=0;2=1;4=1;6=0;8=0;10=0;12=0jr
x<04> <18>
PC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ColorToBrushConverter.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=1;6=0;8=0;10=0;12=0r
x<03>
<17>
[C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\DoubleToSolidColorBrushConverter.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=2;2=0;4=0;6=0;8=0;10=0;12=0r
x<01><1C>
^C:\Sources\Other\ModernKeePass\ModernKeePass\Converters\InverseBooleanToVisibilityConverter.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=0;2=1;4=1;6=0;8=0;10=0;12=0jr
x<04> <18>
QC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\PluralizationConverter.cs (08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=1;8=0;10=0;12=0jr
x<04>
<15>
ZC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\ProgressBarLegalValuesConverter.cs
(08@HR 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=1;2=0;4=0;6=1;8=0;10=0;12=0r
x<05> <18>
OC:\Sources\Other\ModernKeePass\ModernKeePass\Converters\TextToWidthConverter.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=1;2=1;4=0;6=0;8=0;10=0;12=0r
<14>
<11>
HC:\Sources\Other\ModernKeePass\ModernKeePass\Events\PasswordEventArgs.cs (08@HR 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=3;2=0;4=0;6=0;8=0;10=0;12=0r

<0F> <0C>
EC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IIsEnabled.cs(08@R 0=1;5=0;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0r<07>
DC:\Sources\Other\ModernKeePass\ModernKeePass\Interfaces\IPwEntity.cs(08 @ R 0=0;5=1;10=0;20=0;30=0;60=0;90=0Z1=0;2=0;4=0;6=0;8=0;10=0;12=0j "#$r

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,210 +0,0 @@
sonar.projectKey=ModernKeePass
sonar.working.directory=C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\.sonarqube\\out\\.sonar
sonar.projectBaseDir=C:\\Sources\\Other\\ModernKeePass\\ModernKeePass
A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.projectKey=ModernKeePass:A0CFC681-769B-405A-8482-0CDEE595A91F
A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.projectName=ModernKeePass.App
A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.projectBaseDir=C:\\Sources\\Other\\ModernKeePass\\ModernKeePass
A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.sourceEncoding=utf-8
A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.sources=\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Actions\\ClipboardAction.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Actions\\NavigateToUrlAction.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Actions\\SetupFocusAction.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\App.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\IntToSymbolConverter.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Exceptions\\DatabaseOpenedException.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\ILicenseService.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IProxyInvocationHandler.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IRecentService.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IRecentItem.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IResourceService.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Services\\SingletonServiceBase.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\TemplateSelectors\\SelectableDataTemplateSelector.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\Items\\SettingsSaveVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\DonatePage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Services\\DatabaseService.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\ISettingsService.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Common\\MessageDialogHelper.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Common\\NavigationHelper.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Common\\NotifyPropertyChangedBase.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Common\\ObservableDictionary.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Common\\RelayCommand.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Common\\SuspensionManager.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Services\\LicenseService.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Services\\RecentService.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Services\\ResourcesService.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Services\\SettingsService.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Common\\ToastNotificationHelper.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\DiscreteIntToSolidColorBrushConverter.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\EmptyStringToVisibilityConverter.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\NullToBooleanConverter.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Exceptions\\SaveException.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Extensions\\DispatcherTaskExtensions.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IDatabaseService.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IHasSelectableObject.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\ISelectableModel.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\BasePages\\LayoutAwarePageBase.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsDatabasePage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsNewDatabasePage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsSavePage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsSecurityPage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsWelcomePage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\TemplateSelectors\\FirstItemDataTemplateSelector.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Controls\\ListViewWithDisable.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\UserControls\\BreadCrumbUserControl.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\UserControls\\CompositeKeyUserControl.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Controls\\TextBoxWithButton.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\BooleanToVisibilityConverter.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\ColorToBrushConverter.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\DoubleToSolidColorBrushConverter.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\InverseBooleanToVisibilityConverter.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\PluralizationConverter.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\ProgressBarLegalValuesConverter.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Converters\\TextToWidthConverter.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Events\\PasswordEventArgs.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IIsEnabled.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Interfaces\\IPwEntity.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\AboutPage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\NewDatabasePage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\WelcomePage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\AboutVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\CompositeKeyVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\Items\\ListMenuItemVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\Items\\MainMenuItemVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\Items\\RecentItemVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\EntryDetailPage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\GroupDetailPage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\OpenDatabasePage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\RecentDatabasesPage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\SaveDatabasePage.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Properties\\AssemblyInfo.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\EntryVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\GroupVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\Items\\SettingsNewVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\SettingsVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\MainVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\NewVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\OpenVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\RecentVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\SaveVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\ViewModels\\Items\\SettingsDatabaseVm.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\UserControls\\HamburgerMenuUserControl.xaml.cs",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\description.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.Entry.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.Filter.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.Group.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.New.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.Open.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.Recent.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.Semantic.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\description.Settings.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\Entry.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\Filter.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\Group.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\New.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\Open.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\Recent.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\Semantic.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\images\\Screenshot\\Settings.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\keywords.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\privacyPolicy.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\releaseNotes.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\en-us\\baselisting\\websiteUrl.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\description.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.Entry.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.Filter.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.Group.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.New.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.Open.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.Recent.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.Semantic.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\description.Settings.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\Entry.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\Filter.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\Group.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\New.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\Open.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\Recent.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\Semantic.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\images\\Screenshot\\Settings.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\keywords.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\privacyPolicy.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\releaseNotes.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\appMetadata\\fr-fr\\baselisting\\websiteUrl.txt",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Logo.scale-100.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Logo.scale-140.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Logo.scale-180.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Logo.scale-80.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.scale-100.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.scale-140.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.scale-180.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.scale-80.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.targetsize-16.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.targetsize-256.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.targetsize-32.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SmallLogo.targetsize-48.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SplashScreen.scale-100.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SplashScreen.scale-140.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\ModernKeePass-SplashScreen.scale-180.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square310x310Logo.scale-100.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square310x310Logo.scale-140.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square310x310Logo.scale-180.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square310x310Logo.scale-80.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square70x70Logo.scale-100.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square70x70Logo.scale-140.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square70x70Logo.scale-180.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Square70x70Logo.scale-80.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\StoreLogo.scale-100.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\StoreLogo.scale-140.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\StoreLogo.scale-180.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Wide310x150Logo.scale-100.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Wide310x150Logo.scale-140.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Wide310x150Logo.scale-180.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Assets\\Wide310x150Logo.scale-80.png",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\packages.config",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Strings\\fr-FR\\Resources.resw",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Strings\\fr-FR\\CodeBehind.resw",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Strings\\en-US\\CodeBehind.resw",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Strings\\en-US\\Resources.resw",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Styles\\Colors.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsSavePage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\UserControls\\BreadCrumbUserControl.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\UserControls\\CompositeKeyUserControl.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\AboutPage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\EntryDetailPage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\GroupDetailPage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\DonatePage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\NewDatabasePage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\OpenDatabasePage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\RecentDatabasesPage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\SaveDatabasePage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\MainPageFrames\\WelcomePage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsDatabasePage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsNewDatabasePage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsSecurityPage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\SettingsPageFrames\\SettingsWelcomePage.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Styles\\HamburgerButtonStyle.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Styles\\ListViewLeftIndicatorStyle.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Styles\\NoBorderButtonStyle.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Styles\\Styles.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Styles\\TextBoxWithButtonStyle.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\Views\\UserControls\\HamburgerMenuUserControl.xaml",\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\App.xaml"
A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.cs.roslyn.reportFilePath=C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\bin\\Debug\\ModernKeePass.exe.RoslynCA.json
A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.cs.analyzer.projectOutPath=C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\.sonarqube\\out\\0
A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.cs.analyzer.projectOutPaths=\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\.sonarqube\\out\\0"
A0CFC681-769B-405A-8482-0CDEE595A91F.sonar.cs.roslyn.reportFilePaths=\
"C:\\Sources\\Other\\ModernKeePass\\ModernKeePass\\bin\\Debug\\ModernKeePass.exe.RoslynCA.json"
sonar.organization=geogeob
sonar.host.url=https://sonarcloud.io
sonar.visualstudio.enable=false
sonar.modules=A0CFC681-769B-405A-8482-0CDEE595A91F

View File

@@ -1,3 +0,0 @@
Analysis succeeded for SonarQube project "", version [Analysis results](https://sonarcloud.io/dashboard/index/ModernKeePass)
- Product projects: 1, test projects: 0
- Invalid projects: 0, skipped projects: 0, excluded projects: 0

View File

@@ -38,11 +38,12 @@ namespace ModernKeePass
private readonly IMediator _mediator; private readonly IMediator _mediator;
private readonly ISettingsProxy _settings; private readonly ISettingsProxy _settings;
private readonly INavigationService _navigation; private readonly INavigationService _navigation;
private readonly IHockeyClient _hockey;
private readonly INotificationService _notification; private readonly INotificationService _notification;
private readonly IFileProxy _file; private readonly IFileProxy _file;
private readonly IMessenger _messenger; private readonly IMessenger _messenger;
private readonly ILogger _log;
private readonly IHockeyClient _hockey;
/// <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
/// executed, and as such is the logical equivalent of main() or WinMain(). /// executed, and as such is the logical equivalent of main() or WinMain().
@@ -63,6 +64,7 @@ namespace ModernKeePass
_settings = Services.GetService<ISettingsProxy>(); _settings = Services.GetService<ISettingsProxy>();
_navigation = Services.GetService<INavigationService>(); _navigation = Services.GetService<INavigationService>();
_notification = Services.GetService<INotificationService>(); _notification = Services.GetService<INotificationService>();
_log = Services.GetService<ILogger>();
_hockey = Services.GetService<IHockeyClient>(); _hockey = Services.GetService<IHockeyClient>();
_file = Services.GetService<IFileProxy>(); _file = Services.GetService<IFileProxy>();
_messenger = Services.GetService<IMessenger>(); _messenger = Services.GetService<IMessenger>();
@@ -93,8 +95,7 @@ namespace ModernKeePass
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e) private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{ {
_hockey.TrackException(e.Exception); _log.LogError(e.Exception);
_hockey.Flush();
} }
/// <summary> /// <summary>
@@ -209,8 +210,7 @@ namespace ModernKeePass
} }
catch (Exception ex) catch (Exception ex)
{ {
_hockey.TrackException(ex); await _log.LogError(ex);
_hockey.Flush();
} }
finally finally
{ {

View File

@@ -4,8 +4,10 @@ using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Views; using GalaSoft.MvvmLight.Views;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.HockeyApp; using Microsoft.HockeyApp;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Common; using ModernKeePass.Common;
using ModernKeePass.Views; using ModernKeePass.Views;
using ModernKeePass.Log;
namespace ModernKeePass namespace ModernKeePass
{ {
@@ -37,6 +39,7 @@ namespace ModernKeePass
#endif #endif
return HockeyClient.Current; return HockeyClient.Current;
}); });
services.AddSingleton(typeof(ILogger), typeof(HockeyAppLog));
return services; return services;
} }

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using ModernKeePass.Application.Common.Interfaces;
using Microsoft.HockeyApp;
using ModernKeePass.Domain.Interfaces;
namespace ModernKeePass.Log
{
public class HockeyAppLog : ILogger
{
private readonly IHockeyClient _hockey;
private readonly IFileProxy _file;
private readonly IDateTime _dateTime;
public HockeyAppLog(IHockeyClient hockey, IFileProxy file, IDateTime dateTime)
{
_hockey = hockey;
_file = file;
_dateTime = dateTime;
}
public async Task LogError(Exception exception)
{
_hockey.TrackException(exception);
_hockey.Flush();
var time = _dateTime.Now.ToLocalTime();
var data = new List<string>
{
$"{time} - {exception.Message}",
$"{time} - {exception.StackTrace}"
};
await _file.WriteToLogFile(data);
}
public void LogTrace(string message, Dictionary<string, string> values)
{
_hockey.TrackTrace(message, values);
_hockey.Flush();
}
}
}

View File

@@ -368,23 +368,33 @@
<BundleInfo> <BundleInfo>
<PackageInfo> <PackageInfo>
<OsMinVersion>6.3.0.0</OsMinVersion> <OsMinVersion>6.3.0.0</OsMinVersion>
<PackageArchitecture>Neutral</PackageArchitecture> <PackageArchitecture>X64</PackageArchitecture>
<PackageMaxArchitectureVersion>1.15.2557.0</PackageMaxArchitectureVersion> <PackageMaxArchitectureVersion>1.20.640.0</PackageMaxArchitectureVersion>
</PackageInfo>
<PackageInfo>
<OsMinVersion>6.3.0.0</OsMinVersion>
<PackageArchitecture>X86</PackageArchitecture>
<PackageMaxArchitectureVersion>1.20.640.0</PackageMaxArchitectureVersion>
</PackageInfo>
<PackageInfo>
<OsMinVersion>6.3.0.0</OsMinVersion>
<PackageArchitecture>Arm</PackageArchitecture>
<PackageMaxArchitectureVersion>1.20.640.0</PackageMaxArchitectureVersion>
</PackageInfo> </PackageInfo>
<PackageInfo> <PackageInfo>
<OsMinVersion>6.3.0.0</OsMinVersion> <OsMinVersion>6.3.0.0</OsMinVersion>
<PackageArchitecture>Neutral</PackageArchitecture> <PackageArchitecture>Neutral</PackageArchitecture>
<PackageMaxArchitectureVersion>1.15.2557.0</PackageMaxArchitectureVersion> <PackageMaxArchitectureVersion>1.20.640.0</PackageMaxArchitectureVersion>
</PackageInfo> </PackageInfo>
<PackageInfo> <PackageInfo>
<OsMinVersion>6.3.0.0</OsMinVersion> <OsMinVersion>6.3.0.0</OsMinVersion>
<PackageArchitecture>Neutral</PackageArchitecture> <PackageArchitecture>Neutral</PackageArchitecture>
<PackageMaxArchitectureVersion>1.15.2557.0</PackageMaxArchitectureVersion> <PackageMaxArchitectureVersion>1.20.640.0</PackageMaxArchitectureVersion>
</PackageInfo> </PackageInfo>
<PackageInfo> <PackageInfo>
<OsMinVersion>6.3.0.0</OsMinVersion> <OsMinVersion>6.3.0.0</OsMinVersion>
<PackageArchitecture>Neutral</PackageArchitecture> <PackageArchitecture>Neutral</PackageArchitecture>
<PackageMaxArchitectureVersion>1.15.2557.0</PackageMaxArchitectureVersion> <PackageMaxArchitectureVersion>1.20.640.0</PackageMaxArchitectureVersion>
</PackageInfo> </PackageInfo>
</BundleInfo> </BundleInfo>
</PackageInfoList> </PackageInfoList>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest"> <Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest">
<Identity Name="wismna.ModernKeePass" Publisher="CN=0719A91A-C322-4EE0-A257-E60733EECF06" Version="1.18.0.12" /> <Identity Name="wismna.ModernKeePass" Publisher="CN=0719A91A-C322-4EE0-A257-E60733EECF06" Version="1.21.0.22" />
<Properties> <Properties>
<DisplayName>ModernKeePass</DisplayName> <DisplayName>ModernKeePass</DisplayName>
<PublisherDisplayName>wismna</PublisherDisplayName> <PublisherDisplayName>wismna</PublisherDisplayName>

View File

@@ -8,14 +8,11 @@
<Setter Property="BorderBrush" Value="{ThemeResource ComboBoxBorderThemeBrush}" /> <Setter Property="BorderBrush" Value="{ThemeResource ComboBoxBorderThemeBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" /> <Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" /> <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource SearchBoxContentThemeFontSize}" /> <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="FontWeight" Value="{ThemeResource SearchBoxContentThemeFontWeight}"/> <Setter Property="FontWeight" Value="{ThemeResource SearchBoxContentThemeFontWeight}"/>
<Setter Property="Foreground" Value="{ThemeResource SearchBoxForegroundThemeBrush}" /> <Setter Property="Foreground" Value="{ThemeResource SearchBoxForegroundThemeBrush}" />
<Setter Property="Padding" Value="{ThemeResource SearchBoxThemePadding}"/> <Setter Property="Padding" Value="{ThemeResource SearchBoxThemePadding}"/>
<Setter Property="IsTabStop" Value="False" /> <Setter Property="IsTabStop" Value="False" />
<Setter Property="Width" Value="350" />
<Setter Property="Height" Value="32" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Typography.StylisticSet20" Value="True"/> <Setter Property="Typography.StylisticSet20" Value="True"/>
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
@@ -299,7 +296,7 @@
FontSize="{TemplateBinding FontSize}" FontSize="{TemplateBinding FontSize}"
Grid.Column="1" Grid.Column="1"
Style="{StaticResource ActionButtonStyle}" Style="{StaticResource ActionButtonStyle}"
Content="{TemplateBinding ButtonSymbol}" Content="{TemplateBinding ButtonContent}"
Command="{TemplateBinding ButtonCommand}" Command="{TemplateBinding ButtonCommand}"
CommandParameter="{TemplateBinding ButtonCommandParameter}"> CommandParameter="{TemplateBinding ButtonCommandParameter}">
<ToolTipService.ToolTip> <ToolTipService.ToolTip>

View File

@@ -26,13 +26,12 @@ using ModernKeePass.Application.Group.Commands.AddEntry;
using ModernKeePass.Application.Group.Commands.DeleteEntry; using ModernKeePass.Application.Group.Commands.DeleteEntry;
using ModernKeePass.Application.Group.Commands.RemoveEntry; using ModernKeePass.Application.Group.Commands.RemoveEntry;
using ModernKeePass.Application.Group.Queries.GetGroup; using ModernKeePass.Application.Group.Queries.GetGroup;
using ModernKeePass.Application.Security.Commands.GeneratePassword;
using ModernKeePass.Application.Security.Queries.EstimatePasswordComplexity;
using ModernKeePass.Domain.Enums; using ModernKeePass.Domain.Enums;
using ModernKeePass.Application.Group.Models; using ModernKeePass.Application.Group.Models;
using ModernKeePass.Common; using ModernKeePass.Common;
using ModernKeePass.Domain.Dtos; using ModernKeePass.Domain.Dtos;
using ModernKeePass.Domain.Exceptions; using ModernKeePass.Domain.Exceptions;
using ModernKeePass.Domain.Interfaces;
using ModernKeePass.Extensions; using ModernKeePass.Extensions;
using ModernKeePass.Models; using ModernKeePass.Models;
using ModernKeePass.ViewModels.ListItems; using ModernKeePass.ViewModels.ListItems;
@@ -41,73 +40,22 @@ namespace ModernKeePass.ViewModels
{ {
public class EntryDetailVm : ViewModelBase public class EntryDetailVm : ViewModelBase
{ {
public bool HasExpired => HasExpirationDate && ExpiryDate < DateTime.Now; public bool HasExpired => HasExpirationDate && ExpiryDate < _dateTime.Now;
public double PasswordComplexityIndicator => _mediator.Send(new EstimatePasswordComplexityQuery {Password = Password}).GetAwaiter().GetResult();
public double PasswordLength public string Id => _current.Id;
{
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.PasswordLength, 25); }
set
{
_settings.PutSetting(Constants.Settings.PasswordGenerationOptions.PasswordLength, value);
RaisePropertyChanged(nameof(PasswordLength));
}
}
public bool UpperCasePatternSelected
{
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.UpperCasePattern, true); }
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.UpperCasePattern, value); }
}
public bool LowerCasePatternSelected
{
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.LowerCasePattern, true); }
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.LowerCasePattern, value); }
}
public bool DigitsPatternSelected
{
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.DigitsPattern, true); }
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.DigitsPattern, value); }
}
public bool MinusPatternSelected
{
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.MinusPattern, false); }
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.MinusPattern, value); }
}
public bool UnderscorePatternSelected
{
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.UnderscorePattern, false); }
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.UnderscorePattern, value); }
}
public bool SpacePatternSelected
{
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.SpacePattern, false); }
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.SpacePattern, value); }
}
public bool SpecialPatternSelected
{
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.SpecialPattern, true); }
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.SpecialPattern, value); }
}
public bool BracketsPatternSelected
{
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.BracketsPattern, false); }
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.BracketsPattern, value); }
}
public string CustomChars { get; set; } = string.Empty;
public string Id => SelectedItem.Id; public GroupVm Parent { get; private set; }
public string ParentGroupName => _parent.Title;
public bool IsRecycleOnDelete public bool IsRecycleOnDelete
{ {
get get
{ {
var database = Database; var database = Database;
return database.IsRecycleBinEnabled && _parent.Id != database.RecycleBinId; return database.IsRecycleBinEnabled && Parent.Id != database.RecycleBinId;
} }
} }
public ObservableCollection<EntryVm> History { get; private set; } public ObservableCollection<IEntityVm> History { get; private set; }
public ObservableCollection<EntryFieldVm> AdditionalFields { get; private set; } public ObservableCollection<EntryFieldVm> AdditionalFields { get; private set; }
public ObservableCollection<Attachment> Attachments { get; private set; } public ObservableCollection<Attachment> Attachments { get; private set; }
@@ -115,31 +63,6 @@ namespace ModernKeePass.ViewModels
/// Determines if the Entry is current or from history /// Determines if the Entry is current or from history
/// </summary> /// </summary>
public bool IsCurrentEntry => SelectedIndex == 0; public bool IsCurrentEntry => SelectedIndex == 0;
public EntryVm SelectedItem
{
get { return _selectedItem; }
set
{
Set(() => SelectedItem, ref _selectedItem, value, true);
if (value != null)
{
AdditionalFields =
new ObservableCollection<EntryFieldVm>(
SelectedItem.AdditionalFields.Select(f => new EntryFieldVm(f.Name, f.Value, f.IsProtected)));
Attachments = new ObservableCollection<Attachment>(SelectedItem.Attachments.Select(f => new Attachment
{
Name = f.Key,
Content = f.Value
}));
Attachments.CollectionChanged += (sender, args) =>
{
UpdateDirtyStatus(true);
};
RaisePropertyChanged(string.Empty);
}
}
}
public int SelectedIndex public int SelectedIndex
{ {
@@ -161,151 +84,137 @@ namespace ModernKeePass.ViewModels
DeleteAdditionalField.RaiseCanExecuteChanged(); DeleteAdditionalField.RaiseCanExecuteChanged();
} }
} }
public string Title public string Title
{ {
get { return SelectedItem.Title.Value; } get { return _current.Title.Value; }
set set
{ {
SelectedItem.Title.Value = value; _current.Title.Value = value;
SetFieldValue(nameof(Title), value, false).Wait(); SetFieldValue(_current.Title.Name, value, false).ConfigureAwait(false).GetAwaiter();
} }
} }
public string UserName public string UserName
{ {
get { return SelectedItem.Username.Value; } get { return _current.Username.Value; }
set set
{ {
SelectedItem.Username.Value = value; _current.Username.Value = value;
SetFieldValue(nameof(UserName), value, false).Wait(); SetFieldValue(_current.Username.Name, value, false).ConfigureAwait(false).GetAwaiter();
RaisePropertyChanged(nameof(UserName)); RaisePropertyChanged(nameof(UserName));
} }
} }
public string Password public string Password
{ {
get { return SelectedItem.Password.Value; } get { return _cryptography.UnProtect(_current.Password.Value).GetAwaiter().GetResult(); }
set set
{ {
SelectedItem.Password.Value = value; var protectedPassword = _cryptography.Protect(value).ConfigureAwait(false).GetAwaiter().GetResult();
SetFieldValue(nameof(Password), value, true).Wait(); _current.Password.Value = protectedPassword;
SetFieldValue(_current.Password.Name, protectedPassword, true).ConfigureAwait(false).GetAwaiter();
RaisePropertyChanged(nameof(Password)); RaisePropertyChanged(nameof(Password));
RaisePropertyChanged(nameof(PasswordComplexityIndicator));
} }
} }
public string Url public string Url
{ {
get { return SelectedItem.Url.Value; } get { return _current.Url.Value; }
set set
{ {
SelectedItem.Url.Value = value; _current.Url.Value = value;
SetFieldValue(nameof(Url), value, false).Wait(); SetFieldValue(_current.Url.Name, value, false).ConfigureAwait(false).GetAwaiter();
RaisePropertyChanged(nameof(Url)); RaisePropertyChanged(nameof(Url));
} }
} }
public string Notes public string Notes
{ {
get { return SelectedItem.Notes.Value; } get { return _current.Notes.Value; }
set set
{ {
SelectedItem.Notes.Value = value; _current.Notes.Value = value;
SetFieldValue(nameof(Notes), value, false).Wait(); SetFieldValue(_current.Notes.Name, value, false).ConfigureAwait(false).GetAwaiter();
} }
} }
public Symbol Icon public Symbol Icon
{ {
get { return (Symbol)Enum.Parse(typeof(Symbol), SelectedItem.Icon.ToString()); } get { return (Symbol)Enum.Parse(typeof(Symbol), _current.Icon.ToString()); }
set set
{ {
SelectedItem.Icon = (Icon)Enum.Parse(typeof(Icon), value.ToString()); _current.Icon = (Icon)Enum.Parse(typeof(Icon), value.ToString());
SetFieldValue(nameof(Icon), SelectedItem.Icon, false).Wait(); SetFieldValue(EntryFieldName.Icon, _current.Icon, false).ConfigureAwait(false).GetAwaiter();
} }
} }
public DateTimeOffset ExpiryDate public DateTimeOffset ExpiryDate
{ {
get { return SelectedItem.ExpirationDate; } get { return _current.ExpirationDate; }
set set
{ {
if (!HasExpirationDate) return; if (!HasExpirationDate) return;
SelectedItem.ExpirationDate = value.Date; _current.ExpirationDate = value.Date;
SetFieldValue("ExpirationDate", SelectedItem.ExpirationDate, false).Wait(); SetFieldValue(EntryFieldName.ExpirationDate, _current.ExpirationDate, false).ConfigureAwait(false).GetAwaiter();
} }
} }
public TimeSpan ExpiryTime public TimeSpan ExpiryTime
{ {
get { return SelectedItem.ExpirationDate.TimeOfDay; } get { return _current.ExpirationDate.TimeOfDay; }
set set
{ {
if (!HasExpirationDate) return; if (!HasExpirationDate) return;
SelectedItem.ExpirationDate = SelectedItem.ExpirationDate.Date.Add(value); _current.ExpirationDate = _current.ExpirationDate.Date.Add(value);
SetFieldValue("ExpirationDate", SelectedItem.ExpirationDate, false).Wait(); SetFieldValue(EntryFieldName.ExpirationDate, _current.ExpirationDate, false).ConfigureAwait(false).GetAwaiter();
} }
} }
public bool HasExpirationDate public bool HasExpirationDate
{ {
get { return SelectedItem.HasExpirationDate; } get { return _current.HasExpirationDate; }
set set
{ {
SelectedItem.HasExpirationDate = value; _current.HasExpirationDate = value;
SetFieldValue(nameof(HasExpirationDate), value, false).Wait(); SetFieldValue(EntryFieldName.HasExpirationDate, value, false).ConfigureAwait(false).GetAwaiter();
RaisePropertyChanged(nameof(HasExpirationDate)); RaisePropertyChanged(nameof(HasExpirationDate));
} }
} }
public SolidColorBrush BackgroundColor public SolidColorBrush BackgroundColor
{ {
get { return SelectedItem?.BackgroundColor.ToSolidColorBrush(); } get { return _current?.BackgroundColor.ToSolidColorBrush(); }
set set
{ {
SelectedItem.BackgroundColor = value.ToColor(); _current.BackgroundColor = value.ToColor();
SetFieldValue(nameof(BackgroundColor), SelectedItem.BackgroundColor, false).Wait(); SetFieldValue(EntryFieldName.BackgroundColor, _current.BackgroundColor, false).ConfigureAwait(false).GetAwaiter();
} }
} }
public SolidColorBrush ForegroundColor public SolidColorBrush ForegroundColor
{ {
get { return SelectedItem?.ForegroundColor.ToSolidColorBrush(); } get { return _current?.ForegroundColor.ToSolidColorBrush(); }
set set
{ {
SelectedItem.ForegroundColor = value.ToColor(); _current.ForegroundColor = value.ToColor();
SetFieldValue(nameof(ForegroundColor), SelectedItem.ForegroundColor, false).Wait(); SetFieldValue(EntryFieldName.ForegroundColor, _current.ForegroundColor, false).ConfigureAwait(false).GetAwaiter();
} }
} }
public bool IsEditMode
{
get { return IsCurrentEntry && _isEditMode; }
set { Set(() => IsEditMode, ref _isEditMode, value); }
}
public bool IsRevealPassword
{
get { return _isRevealPassword; }
set { Set(() => IsRevealPassword, ref _isRevealPassword, value); }
}
public RelayCommand SaveCommand { get; } public RelayCommand SaveCommand { get; }
public RelayCommand GeneratePasswordCommand { get; }
public RelayCommand<string> MoveCommand { get; } public RelayCommand<string> MoveCommand { get; }
public RelayCommand RestoreCommand { get; } public RelayCommand RestoreCommand { get; }
public RelayCommand DeleteCommand { get; } public RelayCommand DeleteCommand { get; }
public RelayCommand GoBackCommand { get; } public RelayCommand AddAdditionalField { get; }
public RelayCommand GoToParentCommand { get; set; } public RelayCommand<EntryFieldVm> DeleteAdditionalField { get; }
public RelayCommand AddAdditionalField { get; set; } public RelayCommand<Attachment> OpenAttachmentCommand { get; }
public RelayCommand<EntryFieldVm> DeleteAdditionalField { get; set; } public RelayCommand AddAttachmentCommand { get; }
public RelayCommand<Attachment> OpenAttachmentCommand { get; set; } public RelayCommand<Attachment> DeleteAttachmentCommand { get; }
public RelayCommand AddAttachmentCommand { get; set; } public RelayCommand<EntryVm> SetCurrentEntryCommand { get; }
public RelayCommand<Attachment> DeleteAttachmentCommand { get; set; }
private DatabaseVm Database => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult(); private DatabaseVm Database => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
@@ -315,16 +224,14 @@ namespace ModernKeePass.ViewModels
private readonly IDialogService _dialog; private readonly IDialogService _dialog;
private readonly INotificationService _notification; private readonly INotificationService _notification;
private readonly IFileProxy _file; private readonly IFileProxy _file;
private readonly ISettingsProxy _settings; private readonly ICryptographyClient _cryptography;
private GroupVm _parent; private readonly IDateTime _dateTime;
private EntryVm _selectedItem; private EntryVm _current;
private int _selectedIndex; private int _selectedIndex;
private int _additionalFieldSelectedIndex = -1; private int _additionalFieldSelectedIndex = -1;
private bool _isEditMode;
private bool _isRevealPassword;
private bool _isDirty; private bool _isDirty;
public EntryDetailVm(IMediator mediator, INavigationService navigation, IResourceProxy resource, IDialogService dialog, INotificationService notification, IFileProxy file, ISettingsProxy settings) public EntryDetailVm(IMediator mediator, INavigationService navigation, IResourceProxy resource, IDialogService dialog, INotificationService notification, IFileProxy file, ICryptographyClient cryptography, IDateTime dateTime)
{ {
_mediator = mediator; _mediator = mediator;
_navigation = navigation; _navigation = navigation;
@@ -332,33 +239,34 @@ namespace ModernKeePass.ViewModels
_dialog = dialog; _dialog = dialog;
_notification = notification; _notification = notification;
_file = file; _file = file;
_settings = settings; _cryptography = cryptography;
_dateTime = dateTime;
SaveCommand = new RelayCommand(async () => await SaveChanges(), () => Database.IsDirty); SaveCommand = new RelayCommand(async () => await SaveChanges(), () => Database.IsDirty);
GeneratePasswordCommand = new RelayCommand(async () => await GeneratePassword()); MoveCommand = new RelayCommand<string>(async destination => await Move(destination), destination => Parent != null && !string.IsNullOrEmpty(destination) && destination != Parent.Id);
MoveCommand = new RelayCommand<string>(async destination => await Move(destination), destination => _parent != null && !string.IsNullOrEmpty(destination) && destination != _parent.Id);
RestoreCommand = new RelayCommand(async () => await RestoreHistory()); RestoreCommand = new RelayCommand(async () => await RestoreHistory());
DeleteCommand = new RelayCommand(async () => await AskForDelete()); DeleteCommand = new RelayCommand(async () => await AskForDelete());
GoBackCommand = new RelayCommand(() => _navigation.GoBack());
GoToParentCommand = new RelayCommand(() => GoToGroup(_parent.Id));
AddAdditionalField = new RelayCommand(AddField, () => IsCurrentEntry); AddAdditionalField = new RelayCommand(AddField, () => IsCurrentEntry);
DeleteAdditionalField = new RelayCommand<EntryFieldVm>(async field => await DeleteField(field), field => field != null && IsCurrentEntry); DeleteAdditionalField = new RelayCommand<EntryFieldVm>(async field => await DeleteField(field), field => field != null && IsCurrentEntry);
OpenAttachmentCommand = new RelayCommand<Attachment>(async attachment => await OpenAttachment(attachment)); OpenAttachmentCommand = new RelayCommand<Attachment>(async attachment => await OpenAttachment(attachment));
AddAttachmentCommand = new RelayCommand(async () => await AddAttachment(), () => IsCurrentEntry); AddAttachmentCommand = new RelayCommand(async () => await AddAttachment(), () => IsCurrentEntry);
DeleteAttachmentCommand = new RelayCommand<Attachment>(async attachment => await DeleteAttachment(attachment), _ => IsCurrentEntry); DeleteAttachmentCommand = new RelayCommand<Attachment>(async attachment => await DeleteAttachment(attachment), _ => IsCurrentEntry);
SetCurrentEntryCommand = new RelayCommand<EntryVm>(SetCurrentEntry, entry => entry != null);
MessengerInstance.Register<DatabaseSavedMessage>(this, _ => SaveCommand.RaiseCanExecuteChanged()); MessengerInstance.Register<DatabaseSavedMessage>(this, _ => SaveCommand.RaiseCanExecuteChanged());
MessengerInstance.Register<EntryFieldValueChangedMessage>(this, async message => await SetFieldValue(message.FieldName, message.FieldValue, message.IsProtected)); MessengerInstance.Register<EntryFieldValueChangedMessage>(this, async message => await SetFieldValue(message.FieldName, message.FieldValue, message.IsProtected));
MessengerInstance.Register<EntryFieldNameChangedMessage>(this, async message => await UpdateFieldName(message.OldName, message.NewName, message.Value, message.IsProtected)); MessengerInstance.Register<EntryFieldNameChangedMessage>(this, async message => await UpdateFieldName(message.OldName, message.NewName, message.Value, message.IsProtected));
MessengerInstance.Register<PasswordGeneratedMessage>(this, message => Password = message.Password);
} }
public async Task Initialize(string entryId) public async Task Initialize(string entryId)
{ {
SelectedIndex = 0; SelectedIndex = 0;
SelectedItem = await _mediator.Send(new GetEntryQuery { Id = entryId }); _current = await _mediator.Send(new GetEntryQuery { Id = entryId });
_parent = await _mediator.Send(new GetGroupQuery { Id = SelectedItem.ParentGroupId }); SetCurrentEntry(_current);
History = new ObservableCollection<EntryVm> { SelectedItem }; Parent = await _mediator.Send(new GetGroupQuery { Id = _current.ParentGroupId });
foreach (var entry in SelectedItem.History.Skip(1)) History = new ObservableCollection<IEntityVm> { _current };
foreach (var entry in _current.History.Skip(1))
{ {
History.Add(entry); History.Add(entry);
} }
@@ -369,26 +277,9 @@ namespace ModernKeePass.ViewModels
}; };
} }
public async Task GeneratePassword()
{
Password = await _mediator.Send(new GeneratePasswordCommand
{
BracketsPatternSelected = BracketsPatternSelected,
CustomChars = CustomChars,
DigitsPatternSelected = DigitsPatternSelected,
LowerCasePatternSelected = LowerCasePatternSelected,
MinusPatternSelected = MinusPatternSelected,
PasswordLength = (int)PasswordLength,
SpacePatternSelected = SpacePatternSelected,
SpecialPatternSelected = SpecialPatternSelected,
UnderscorePatternSelected = UnderscorePatternSelected,
UpperCasePatternSelected = UpperCasePatternSelected
});
}
public async Task AddHistory() public async Task AddHistory()
{ {
if (_isDirty) await _mediator.Send(new AddHistoryCommand { Entry = History[0] }); if (_isDirty && Database.IsOpen) await _mediator.Send(new AddHistoryCommand { Entry = History[0] as EntryVm });
} }
public void GoToGroup(string groupId) public void GoToGroup(string groupId)
@@ -399,7 +290,7 @@ namespace ModernKeePass.ViewModels
private async Task Move(string destination) private async Task Move(string destination)
{ {
await _mediator.Send(new AddEntryCommand { ParentGroupId = destination, EntryId = Id }); await _mediator.Send(new AddEntryCommand { ParentGroupId = destination, EntryId = Id });
await _mediator.Send(new RemoveEntryCommand { ParentGroupId = _parent.Id, EntryId = Id }); await _mediator.Send(new RemoveEntryCommand { ParentGroupId = Parent.Id, EntryId = Id });
GoToGroup(destination); GoToGroup(destination);
} }
@@ -417,7 +308,7 @@ namespace ModernKeePass.ViewModels
private void AddField() private void AddField()
{ {
AdditionalFields.Add(new EntryFieldVm(string.Empty, string.Empty, false)); AdditionalFields.Add(new EntryFieldVm(_cryptography));
AdditionalFieldSelectedIndex = AdditionalFields.Count - 1; AdditionalFieldSelectedIndex = AdditionalFields.Count - 1;
} }
@@ -461,7 +352,7 @@ namespace ModernKeePass.ViewModels
_resource.GetResourceValue("EntityDeleteCancelButton"), async isOk => _resource.GetResourceValue("EntityDeleteCancelButton"), async isOk =>
{ {
if (!isOk) return; if (!isOk) return;
await _mediator.Send(new DeleteHistoryCommand { Entry = History[0], HistoryIndex = History.Count - SelectedIndex - 1 }); await _mediator.Send(new DeleteHistoryCommand { Entry = History[0] as EntryVm, HistoryIndex = History.Count - SelectedIndex - 1 });
History.RemoveAt(SelectedIndex); History.RemoveAt(SelectedIndex);
}); });
} }
@@ -469,8 +360,8 @@ namespace ModernKeePass.ViewModels
private async Task RestoreHistory() private async Task RestoreHistory()
{ {
await _mediator.Send(new RestoreHistoryCommand { Entry = History[0], HistoryIndex = History.Count - SelectedIndex - 1 }); await _mediator.Send(new RestoreHistoryCommand { Entry = History[0] as EntryVm, HistoryIndex = History.Count - SelectedIndex - 1 });
History.Insert(0, SelectedItem); History.Insert(0, _current);
} }
private async Task SaveChanges() private async Task SaveChanges()
@@ -492,7 +383,7 @@ namespace ModernKeePass.ViewModels
await _mediator.Send(new DeleteEntryCommand await _mediator.Send(new DeleteEntryCommand
{ {
EntryId = Id, EntryId = Id,
ParentGroupId = SelectedItem.ParentGroupId, ParentGroupId = _current.ParentGroupId,
RecycleBinName = _resource.GetResourceValue("RecycleBinTitle") RecycleBinName = _resource.GetResourceValue("RecycleBinTitle")
}); });
_isDirty = false; _isDirty = false;
@@ -515,13 +406,13 @@ namespace ModernKeePass.ViewModels
var fileInfo = await _file.OpenFile(string.Empty, Domain.Common.Constants.Extensions.Any, false); var fileInfo = await _file.OpenFile(string.Empty, Domain.Common.Constants.Extensions.Any, false);
if (fileInfo == null) return; if (fileInfo == null) return;
var contents = await _file.ReadBinaryFile(fileInfo.Id); var contents = await _file.ReadBinaryFile(fileInfo.Id);
await _mediator.Send(new AddAttachmentCommand { Entry = SelectedItem, AttachmentName = fileInfo.Name, AttachmentContent = contents }); await _mediator.Send(new AddAttachmentCommand { Entry = _current, AttachmentName = fileInfo.Name, AttachmentContent = contents });
Attachments.Add(new Attachment { Name = fileInfo.Name, Content = contents }); Attachments.Add(new Attachment { Name = fileInfo.Name, Content = contents });
} }
private async Task DeleteAttachment(Attachment attachment) private async Task DeleteAttachment(Attachment attachment)
{ {
await _mediator.Send(new DeleteAttachmentCommand { Entry = SelectedItem, AttachmentName = attachment.Name }); await _mediator.Send(new DeleteAttachmentCommand { Entry = _current, AttachmentName = attachment.Name });
Attachments.Remove(attachment); Attachments.Remove(attachment);
} }
@@ -530,5 +421,35 @@ namespace ModernKeePass.ViewModels
SaveCommand.RaiseCanExecuteChanged(); SaveCommand.RaiseCanExecuteChanged();
_isDirty = isDirty; _isDirty = isDirty;
} }
private void SetCurrentEntry(EntryVm entry)
{
_current = entry;
AdditionalFields =
new ObservableCollection<EntryFieldVm>(
entry.AdditionalFields.Select(f =>
{
var field = new EntryFieldVm(_cryptography);
field.Initialize(f.Name, f.Value, f.IsProtected);
return field;
}));
Attachments = new ObservableCollection<Attachment>(entry.Attachments.Select(f => new Attachment
{
Name = f.Key,
Content = f.Value
}));
Attachments.CollectionChanged += (sender, args) =>
{
UpdateDirtyStatus(true);
};
RaisePropertyChanged(string.Empty);
}
public override void Cleanup()
{
MessengerInstance.Unregister(this);
base.Cleanup();
}
} }
} }

View File

@@ -18,6 +18,7 @@ using ModernKeePass.Application.Group.Commands.AddEntry;
using ModernKeePass.Application.Group.Commands.AddGroup; using ModernKeePass.Application.Group.Commands.AddGroup;
using ModernKeePass.Application.Group.Commands.CreateEntry; using ModernKeePass.Application.Group.Commands.CreateEntry;
using ModernKeePass.Application.Group.Commands.CreateGroup; using ModernKeePass.Application.Group.Commands.CreateGroup;
using ModernKeePass.Application.Group.Commands.DeleteEntry;
using ModernKeePass.Application.Group.Commands.DeleteGroup; using ModernKeePass.Application.Group.Commands.DeleteGroup;
using ModernKeePass.Application.Group.Commands.MoveEntry; using ModernKeePass.Application.Group.Commands.MoveEntry;
using ModernKeePass.Application.Group.Commands.MoveGroup; using ModernKeePass.Application.Group.Commands.MoveGroup;
@@ -38,10 +39,12 @@ namespace ModernKeePass.ViewModels
{ {
public ObservableCollection<EntryVm> Entries { get; private set; } public ObservableCollection<EntryVm> Entries { get; private set; }
public ObservableCollection<GroupVm> Groups { get; private set; } public ObservableCollection<IEntityVm> Groups { get; private set; }
public bool IsNotRoot => Database.RootGroupId != _group.Id; public bool IsNotRoot => Database.RootGroupId != _group.Id;
public GroupVm Parent { get; private set; }
public IOrderedEnumerable<IGrouping<char, EntryVm>> EntriesZoomedOut => from e in Entries public IOrderedEnumerable<IGrouping<char, EntryVm>> EntriesZoomedOut => from e in Entries
group e by (e.Title.Value ?? string.Empty).ToUpper().FirstOrDefault() into grp group e by (e.Title.Value ?? string.Empty).ToUpper().FirstOrDefault() into grp
orderby grp.Key orderby grp.Key
@@ -80,11 +83,11 @@ namespace ModernKeePass.ViewModels
} }
} }
public string ParentGroupName => _parent?.Title; public string ParentGroupName => Parent == null ? Database.Name : Parent.Title;
public bool IsRecycleOnDelete => Database.IsRecycleBinEnabled && !IsInRecycleBin; public bool IsRecycleOnDelete => Database.IsRecycleBinEnabled && !IsInRecycleBin;
public bool IsInRecycleBin => _parent != null && _parent.Id == Database.RecycleBinId; public bool IsInRecycleBin => Parent != null && Parent.Id == Database.RecycleBinId;
public RelayCommand SaveCommand { get; } public RelayCommand SaveCommand { get; }
public RelayCommand SortEntriesCommand { get; } public RelayCommand SortEntriesCommand { get; }
@@ -92,9 +95,12 @@ namespace ModernKeePass.ViewModels
public RelayCommand<string> MoveCommand { get; } public RelayCommand<string> MoveCommand { get; }
public RelayCommand CreateEntryCommand { get; } public RelayCommand CreateEntryCommand { get; }
public RelayCommand<string> CreateGroupCommand { get; } public RelayCommand<string> CreateGroupCommand { get; }
public RelayCommand DeleteCommand { get; set; } public RelayCommand DeleteCommand { get; }
public RelayCommand GoBackCommand { get; set; } public RelayCommand GoBackCommand { get; }
public RelayCommand GoToParentCommand { get; set; } public RelayCommand GoToParentCommand { get; }
public RelayCommand<GroupVm> GoToGroupCommand { get; }
public RelayCommand<EntryVm> GoToEntryCommand { get; }
public RelayCommand<EntryVm> DeleteEntryCommand { get; }
private DatabaseVm Database => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult(); private DatabaseVm Database => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
@@ -104,7 +110,6 @@ namespace ModernKeePass.ViewModels
private readonly IDialogService _dialog; private readonly IDialogService _dialog;
private readonly INotificationService _notification; private readonly INotificationService _notification;
private GroupVm _group; private GroupVm _group;
private GroupVm _parent;
private bool _isEditMode; private bool _isEditMode;
private EntryVm _reorderedEntry; private EntryVm _reorderedEntry;
private GroupVm _reorderedGroup; private GroupVm _reorderedGroup;
@@ -125,7 +130,10 @@ namespace ModernKeePass.ViewModels
CreateGroupCommand = new RelayCommand<string>(async newGroupName => await AddNewGroup(newGroupName), _ => !IsInRecycleBin && Database.RecycleBinId != Id); CreateGroupCommand = new RelayCommand<string>(async newGroupName => await AddNewGroup(newGroupName), _ => !IsInRecycleBin && Database.RecycleBinId != Id);
DeleteCommand = new RelayCommand(async () => await AskForDelete(),() => IsNotRoot); DeleteCommand = new RelayCommand(async () => await AskForDelete(),() => IsNotRoot);
GoBackCommand = new RelayCommand(() => _navigation.GoBack()); GoBackCommand = new RelayCommand(() => _navigation.GoBack());
GoToParentCommand= new RelayCommand(() => GoToGroup(_parent.Id), () => _parent != null); GoToParentCommand = new RelayCommand(() => GoToGroup(Parent.Id), () => Parent != null);
GoToGroupCommand = new RelayCommand<GroupVm>(group => GoToGroup(group.Id), group => group != null);
GoToEntryCommand = new RelayCommand<EntryVm>(entry => GoToEntry(entry.Id), entry => entry != null);
DeleteEntryCommand = new RelayCommand<EntryVm>(async entry => await AskForDeleteEntry(entry), entry => entry != null);
MessengerInstance.Register<DatabaseSavedMessage>(this, _ => SaveCommand.RaiseCanExecuteChanged()); MessengerInstance.Register<DatabaseSavedMessage>(this, _ => SaveCommand.RaiseCanExecuteChanged());
} }
@@ -135,12 +143,13 @@ namespace ModernKeePass.ViewModels
_group = await _mediator.Send(new GetGroupQuery { Id = groupId }); _group = await _mediator.Send(new GetGroupQuery { Id = groupId });
if (!string.IsNullOrEmpty(_group.ParentGroupId)) if (!string.IsNullOrEmpty(_group.ParentGroupId))
{ {
_parent = await _mediator.Send(new GetGroupQuery { Id = _group.ParentGroupId }); Parent = await _mediator.Send(new GetGroupQuery {Id = _group.ParentGroupId});
} }
else Parent = null;
Entries = new ObservableCollection<EntryVm>(_group.Entries); Entries = new ObservableCollection<EntryVm>(_group.Entries);
Entries.CollectionChanged += Entries_CollectionChanged; Entries.CollectionChanged += Entries_CollectionChanged;
Groups = new ObservableCollection<GroupVm>(_group.SubGroups); Groups = new ObservableCollection<IEntityVm>(_group.Groups);
Groups.CollectionChanged += Groups_CollectionChanged; Groups.CollectionChanged += Groups_CollectionChanged;
} }
@@ -176,7 +185,7 @@ namespace ModernKeePass.ViewModels
public async Task Move(string destinationId) public async Task Move(string destinationId)
{ {
await _mediator.Send(new AddGroupCommand {ParentGroupId = destinationId, GroupId = Id }); await _mediator.Send(new AddGroupCommand {ParentGroupId = destinationId, GroupId = Id });
await _mediator.Send(new RemoveGroupCommand {ParentGroupId = _parent.Id, GroupId = Id }); await _mediator.Send(new RemoveGroupCommand {ParentGroupId = Parent.Id, GroupId = Id });
GoToGroup(destinationId); GoToGroup(destinationId);
} }
@@ -222,7 +231,7 @@ namespace ModernKeePass.ViewModels
{ {
case NotifyCollectionChangedAction.Remove: case NotifyCollectionChangedAction.Remove:
var oldIndex = e.OldStartingIndex; var oldIndex = e.OldStartingIndex;
_reorderedGroup = _group.SubGroups[oldIndex]; _reorderedGroup = _group.Groups[oldIndex];
break; break;
case NotifyCollectionChangedAction.Add: case NotifyCollectionChangedAction.Add:
if (_reorderedGroup == null) if (_reorderedGroup == null)
@@ -251,7 +260,7 @@ namespace ModernKeePass.ViewModels
private async Task SortGroupsAsync() private async Task SortGroupsAsync()
{ {
await _mediator.Send(new SortGroupsCommand {Group = _group}); await _mediator.Send(new SortGroupsCommand {Group = _group});
Groups = new ObservableCollection<GroupVm>(_group.SubGroups); Groups = new ObservableCollection<IEntityVm>(_group.Groups);
RaisePropertyChanged(nameof(Groups)); RaisePropertyChanged(nameof(Groups));
SaveCommand.RaiseCanExecuteChanged(); SaveCommand.RaiseCanExecuteChanged();
} }
@@ -285,7 +294,39 @@ namespace ModernKeePass.ViewModels
ParentGroupId = _group.ParentGroupId, ParentGroupId = _group.ParentGroupId,
RecycleBinName = _resource.GetResourceValue("RecycleBinTitle") RecycleBinName = _resource.GetResourceValue("RecycleBinTitle")
}); });
_navigation.GoBack(); _navigation.GoBack();
} }
private async Task AskForDeleteEntry(EntryVm entry)
{
if (IsRecycleOnDelete)
{
await DeleteEntry(entry);
_notification.Show(_resource.GetResourceValue("EntityDeleting"), string.Format(_resource.GetResourceValue("EntryRecycled"), entry.Title));
}
else
{
await _dialog.ShowMessage(
string.Format(_resource.GetResourceValue("EntryDeletingConfirmation"), entry.Title),
_resource.GetResourceValue("EntityDeleting"),
_resource.GetResourceValue("EntityDeleteActionButton"),
_resource.GetResourceValue("EntityDeleteCancelButton"),
async isOk =>
{
if (isOk) await DeleteEntry(entry);
});
}
}
private async Task DeleteEntry(EntryVm entry)
{
await _mediator.Send(new DeleteEntryCommand
{
EntryId = entry.Id,
ParentGroupId = Id,
RecycleBinName = _resource.GetResourceValue("RecycleBinTitle")
});
Entries.Remove(entry);
}
} }
} }

View File

@@ -193,5 +193,11 @@ namespace ModernKeePass.ViewModels
MessengerInstance.Send(new DatabaseClosedMessage { Parameter = message.Parameter }); MessengerInstance.Send(new DatabaseClosedMessage { Parameter = message.Parameter });
}); });
} }
public override void Cleanup()
{
MessengerInstance.Unregister(this);
base.Cleanup();
}
} }
} }

View File

@@ -85,7 +85,7 @@ namespace ModernKeePass.Views.BasePages
/// <summary> /// <summary>
/// Preserves state associated with this page in case the application is suspended or the /// 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 /// page is discarded from the navigation cache. Values must conform to the serialization
/// requirements of <see cref="Common.SuspensionManager.SessionState"/>. /// requirements of <see cref="SuspensionManager.SessionState"/>.
/// </summary> /// </summary>
/// <param name="sender">The source of the event; typically <see cref="Common.NavigationHelper"/></param> /// <param name="sender">The source of the event; typically <see cref="Common.NavigationHelper"/></param>
/// <param name="e">Event data that provides an empty dictionary to be populated with /// <param name="e">Event data that provides an empty dictionary to be populated with

View File

@@ -8,7 +8,7 @@
xmlns:interactivity="using:Microsoft.Xaml.Interactivity" xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core" xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:actions="using:ModernKeePass.Actions" xmlns:actions="using:ModernKeePass.Actions"
xmlns:userControls="using:ModernKeePass.Views.UserControls" xmlns:controls="using:ModernKeePass.Views.UserControls"
x:Class="ModernKeePass.Views.EntryDetailPage" x:Class="ModernKeePass.Views.EntryDetailPage"
mc:Ignorable="d" mc:Ignorable="d"
SizeChanged="EntryDetailPage_OnSizeChanged" SizeChanged="EntryDetailPage_OnSizeChanged"
@@ -16,347 +16,6 @@
<Page.Resources> <Page.Resources>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter" /> <converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter" />
<converters:ProgressBarLegalValuesConverter x:Key="ProgressBarLegalValuesConverter" />
<converters:DoubleToSolidColorBrushConverter x:Key="DoubleToForegroundBrushComplexityConverter" />
<Style TargetType="local:PasswordBoxWithButton" x:Key="PasswordBoxWithButtonStyle">
<Setter Property="Background" Value="{ThemeResource SearchBoxBackgroundThemeBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource ComboBoxBorderThemeBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource SearchBoxContentThemeFontSize}" />
<Setter Property="FontWeight" Value="{ThemeResource SearchBoxContentThemeFontWeight}"/>
<Setter Property="Foreground" Value="{ThemeResource SearchBoxForegroundThemeBrush}" />
<Setter Property="Padding" Value="{ThemeResource SearchBoxThemePadding}"/>
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Width" Value="350" />
<Setter Property="Height" Value="32" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Typography.StylisticSet20" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:PasswordBoxWithButton">
<Grid x:Name="SearchBoxGrid">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Foreground}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxPointerOverBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxPointerOverBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxPointerOverTextThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledTextThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PasswordBox" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource MainColor}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="FocusedDropDown">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedTextThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.Resources>
<Style x:Key="ActionButtonStyle" TargetType="Button">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonPointerOverForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButtonBackground" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonPointerOverBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedTextThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButtonBackground" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled" />
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused" />
<VisualState x:Name="Unfocused" />
<VisualState x:Name="PointerFocused" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="ActionButtonBackground" Background="{TemplateBinding Background}">
<TextBlock x:Name="SearchGlyph"
AutomationProperties.AccessibilityView="Raw"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
Foreground="{TemplateBinding Foreground}"
HorizontalAlignment="Center"
FontStyle="Normal"
Padding="4,0,4,0"
Text="{TemplateBinding Content}"
VerticalAlignment="Center" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="PasswordBoxStyle" TargetType="PasswordBox">
<Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
<Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
<Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}" />
<Setter Property="Background" Value="{ThemeResource TextBoxBackgroundThemeBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource TextBoxBorderThemeBrush}" />
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextSelectionHighlightColorThemeBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="PasswordBox">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="{ThemeResource TextControlBackgroundThemeOpacity}" />
<DoubleAnimation Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="{ThemeResource TextControlBorderThemeOpacity}" />
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="{ThemeResource TextControlPointerOverBackgroundThemeOpacity}" />
<DoubleAnimation Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="{ThemeResource TextControlPointerOverBorderThemeOpacity}" />
</Storyboard>
</VisualState>
<VisualState x:Name="Focused" />
</VisualStateGroup>
<VisualStateGroup x:Name="ButtonStates" />
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border x:Name="BackgroundElement"
Grid.Row="1"
Background="{TemplateBinding Background}"
Margin="{TemplateBinding BorderThickness}" />
<Border x:Name="BorderElement"
Grid.Row="1"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" />
<ContentPresenter x:Name="HeaderContentPresenter"
Grid.Row="0"
Foreground="{ThemeResource TextBoxForegroundHeaderThemeBrush}"
Margin="0,4,0,4"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
FontWeight="Semilight" />
<ScrollViewer x:Name="ContentElement"
Grid.Row="1"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
IsTabStop="False"
AutomationProperties.AccessibilityView="Raw"
ZoomMode="Disabled" />
<ContentControl x:Name="PlaceholderTextContentPresenter"
Grid.Row="1"
Foreground="{ThemeResource TextBoxPlaceholderTextThemeBrush}"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
IsTabStop="False"
Grid.ColumnSpan="2"
Content="{TemplateBinding PlaceholderText}"
IsHitTestVisible="False" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Border x:Name="SearchBoxBorder"
Background="Transparent"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<PasswordBox x:Name="PasswordBox"
BorderThickness="0"
Background="Transparent"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
Foreground="{TemplateBinding Foreground}"
MaxLength="2048"
MinHeight="{ThemeResource SearchBoxTextBoxThemeMinHeight}"
Padding="{TemplateBinding Padding}"
PlaceholderText="{TemplateBinding PlaceholderText}"
Style="{StaticResource PasswordBoxStyle}"
VerticalAlignment="Stretch"
Margin="0"
Password="{Binding RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, Path=Password}"
IsPasswordRevealButtonEnabled="{TemplateBinding IsPasswordRevealEnabled}"/>
<Button x:Name="ActionButton"
AutomationProperties.AccessibilityView="Raw"
Background="Transparent"
FontWeight="{ThemeResource SearchBoxButtonThemeFontWeight}"
FontSize="{TemplateBinding FontSize}"
Grid.Column="1"
Style="{StaticResource ActionButtonStyle}"
Content="{TemplateBinding ButtonSymbol}"
IsEnabled="{TemplateBinding IsButtonEnabled}">
<Button.Flyout>
<Flyout>
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding Password}" ComparisonCondition="NotEqual" Value="" >
<!--<actions:CloseFlyoutAction />-->
<core:CallMethodAction MethodName="Hide" />
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
<StackPanel>
<TextBlock>
<Run x:Uid="PasswordGeneratorLength" />
<Run Text="{Binding PasswordLength}" />
</TextBlock>
<Slider Value="{Binding PasswordLength, Mode=TwoWay}" Margin="0,-10,0,-20" />
<CheckBox IsChecked="{Binding UpperCasePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorUpper" />
<CheckBox IsChecked="{Binding LowerCasePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorLower" />
<CheckBox IsChecked="{Binding DigitsPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorDigits" />
<CheckBox IsChecked="{Binding MinusPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorMinus" />
<CheckBox IsChecked="{Binding UnderscorePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorUnderscore" />
<CheckBox IsChecked="{Binding SpacePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorSpace" />
<CheckBox IsChecked="{Binding SpecialPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorSpecial" />
<CheckBox IsChecked="{Binding BracketsPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorBrackets" />
<TextBlock x:Uid="PasswordGeneratorAlso" Margin="0,5,0,0"/>
<TextBox Text="{Binding CustomChars, Mode=TwoWay}" />
<Button x:Uid="PasswordGeneratorButton" Command="{Binding GeneratePasswordCommand}" />
</StackPanel>
</Flyout>
</Button.Flyout>
<ToolTipService.ToolTip>
<ToolTip x:Uid="PasswordGeneratorTooltip" />
</ToolTipService.ToolTip>
</Button>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources> </Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ChildrenTransitions> <Grid.ChildrenTransitions>
@@ -373,14 +32,8 @@
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<userControls:HamburgerMenuUserControl
x:Name="HamburgerMenu"
x:Uid="HistoryLeftListView"
ItemsSource="{Binding History}"
SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
<Grid Grid.Column="1"> <Grid Grid.Column="1">
<Hub Padding="0"> <Hub x:Name="Hub" Padding="0">
<Hub.Resources> <Hub.Resources>
<Style TargetType="TextBlock" x:Key="EntryTextBlockStyle"> <Style TargetType="TextBlock" x:Key="EntryTextBlockStyle">
<Setter Property="Margin" Value="0,20,0,0"/> <Setter Property="Margin" Value="0,20,0,0"/>
@@ -391,15 +44,24 @@
<HubSection x:Uid="EntryHubMain"> <HubSection x:Uid="EntryHubMain">
<DataTemplate> <DataTemplate>
<ScrollViewer VerticalScrollBarVisibility="Auto"> <ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Margin="20,0,0,20" MinWidth="400"> <StackPanel Width="350" Margin="0,0,25,0">
<StackPanel.Resources> <StackPanel.Resources>
<Style TargetType="CheckBox"> <Style TargetType="CheckBox">
<Setter Property="Margin" Value="0,20,0,0"/> <Setter Property="Margin" Value="0,20,0,0"/>
<Setter Property="FontSize" Value="18"/> <Setter Property="FontSize" Value="18"/>
</Style> </Style>
</StackPanel.Resources> </StackPanel.Resources>
<TextBlock x:Uid="EntryTitle" Style="{StaticResource EntryTextBlockStyle}" />
<local:TextBoxWithButton x:Uid="TitleTextBox" Text="{Binding Title, Mode=TwoWay}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonContent="&#xE16F;" IsEnabled="{Binding IsCurrentEntry}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:ClipboardAction Text="{Binding Title}" />
<actions:ToastAction x:Uid="ToastCopyTitle" Title="{Binding Title}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</local:TextBoxWithButton>
<TextBlock x:Uid="EntryLogin" Style="{StaticResource EntryTextBlockStyle}" /> <TextBlock x:Uid="EntryLogin" Style="{StaticResource EntryTextBlockStyle}" />
<local:TextBoxWithButton x:Uid="LoginTextBox" Text="{Binding UserName, Mode=TwoWay}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonSymbol="&#xE16F;" IsEnabled="{Binding IsCurrentEntry}"> <local:TextBoxWithButton x:Uid="LoginTextBox" Text="{Binding UserName, Mode=TwoWay}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonContent="&#xE16F;" IsEnabled="{Binding IsCurrentEntry}">
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick"> <core:EventTriggerBehavior EventName="ButtonClick">
<actions:ClipboardAction Text="{Binding UserName}" /> <actions:ClipboardAction Text="{Binding UserName}" />
@@ -408,19 +70,9 @@
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
</local:TextBoxWithButton> </local:TextBoxWithButton>
<TextBlock x:Uid="EntryPassword" Style="{StaticResource EntryTextBlockStyle}" /> <TextBlock x:Uid="EntryPassword" Style="{StaticResource EntryTextBlockStyle}" />
<local:PasswordBoxWithButton Password="{Binding Password, Mode=TwoWay}" IsPasswordRevealEnabled="True" Visibility="{Binding IsRevealPassword, Converter={StaticResource InverseBooleanToVisibilityConverter}}" Style="{StaticResource PasswordBoxWithButtonStyle}" IsEnabled="{Binding IsCurrentEntry}" ButtonSymbol="&#xE15E;" /> <controls:PasswordGenerationBox Password="{Binding Password, Mode=TwoWay}" IsEnabled="{Binding IsCurrentEntry}" />
<local:TextBoxWithButton x:Uid="PasswordTextBox" Text="{Binding Password, Mode=TwoWay}" Visibility="{Binding IsRevealPassword, Converter={StaticResource BooleanToVisibilityConverter}}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonSymbol="&#xE16F;" IsEnabled="{Binding IsCurrentEntry}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:ClipboardAction Text="{Binding Password}" />
<actions:ToastAction x:Uid="ToastCopyPassword" Title="{Binding Title}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</local:TextBoxWithButton>
<ProgressBar Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}" Maximum="128" Width="350" HorizontalAlignment="Left" Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroundBrushComplexityConverter}}" />
<CheckBox x:Uid="EntryShowPassword" HorizontalAlignment="Left" Margin="-3,0,0,0" IsChecked="{Binding IsRevealPassword, Mode=TwoWay}" />
<TextBlock Text="URL" Style="{StaticResource EntryTextBlockStyle}"/> <TextBlock Text="URL" Style="{StaticResource EntryTextBlockStyle}"/>
<local:TextBoxWithButton x:Uid="UrlTextBox" Text="{Binding Url, Mode=TwoWay}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonSymbol="&#xE111;" IsEnabled="{Binding IsCurrentEntry}"> <local:TextBoxWithButton x:Uid="UrlTextBox" Text="{Binding Url, Mode=TwoWay}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonContent="&#xE111;" IsEnabled="{Binding IsCurrentEntry}">
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick"> <core:EventTriggerBehavior EventName="ButtonClick">
<actions:NavigateToUrlAction Url="{Binding Url}" /> <actions:NavigateToUrlAction Url="{Binding Url}" />
@@ -428,8 +80,8 @@
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
</local:TextBoxWithButton> </local:TextBoxWithButton>
<TextBlock x:Uid="EntryNotes" Style="{StaticResource EntryTextBlockStyle}" /> <TextBlock x:Uid="EntryNotes" Style="{StaticResource EntryTextBlockStyle}" />
<TextBox HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding Notes, Mode=TwoWay}" Width="350" Height="200" AcceptsReturn="True" IsSpellCheckEnabled="True" IsEnabled="{Binding IsCurrentEntry}" /> <TextBox TextWrapping="Wrap" Text="{Binding Notes, Mode=TwoWay}" Width="350" Height="200" AcceptsReturn="True" IsSpellCheckEnabled="True" IsEnabled="{Binding IsCurrentEntry}" />
<CheckBox x:Uid="EntryExpirationDate" IsChecked="{Binding HasExpirationDate, Mode=TwoWay}" IsEnabled="{Binding IsCurrentEntry}" /> <CheckBox x:Uid="EntryExpirationDate" Margin="-3,0,0,0" IsChecked="{Binding HasExpirationDate, Mode=TwoWay}" IsEnabled="{Binding IsCurrentEntry}" />
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
@@ -471,11 +123,11 @@
<DataTemplate> <DataTemplate>
<StackPanel Orientation="Vertical"> <StackPanel Orientation="Vertical">
<TextBlock x:Uid="EntryIcon" Style="{StaticResource EntryTextBlockStyle}" /> <TextBlock x:Uid="EntryIcon" Style="{StaticResource EntryTextBlockStyle}" />
<userControls:SymbolPickerUserControl SelectedSymbol="{Binding Icon, Mode=TwoWay}" HorizontalAlignment="Left" IsEnabled="{Binding IsCurrentEntry}" /> <controls:SymbolPickerUserControl SelectedSymbol="{Binding Icon, Mode=TwoWay}" HorizontalAlignment="Left" IsEnabled="{Binding IsCurrentEntry}" />
<TextBlock x:Uid="EntryBackgroundColor" Style="{StaticResource EntryTextBlockStyle}" /> <TextBlock x:Uid="EntryBackgroundColor" Style="{StaticResource EntryTextBlockStyle}" />
<userControls:ColorPickerUserControl SelectedColor="{Binding BackgroundColor, Mode=TwoWay}" IsEnabled="{Binding IsCurrentEntry}" Width="250" /> <controls:ColorPickerUserControl SelectedColor="{Binding BackgroundColor, Mode=TwoWay}" IsEnabled="{Binding IsCurrentEntry}" Width="250" />
<TextBlock x:Uid="EntryForegroundColor" Style="{StaticResource EntryTextBlockStyle}" /> <TextBlock x:Uid="EntryForegroundColor" Style="{StaticResource EntryTextBlockStyle}" />
<userControls:ColorPickerUserControl SelectedColor="{Binding ForegroundColor, Mode=TwoWay}" IsEnabled="{Binding IsCurrentEntry}" Width="250" /> <controls:ColorPickerUserControl SelectedColor="{Binding ForegroundColor, Mode=TwoWay}" IsEnabled="{Binding IsCurrentEntry}" Width="250" />
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
</HubSection> </HubSection>
@@ -520,8 +172,7 @@
<DataTemplate> <DataTemplate>
<StackPanel Orientation="Vertical" Margin="5"> <StackPanel Orientation="Vertical" Margin="5">
<TextBlock Text="{Binding Name}" Style="{StaticResource EntryTextBlockStyle}" FontWeight="SemiBold" /> <TextBlock Text="{Binding Name}" Style="{StaticResource EntryTextBlockStyle}" FontWeight="SemiBold" />
<TextBlock HorizontalAlignment="Left" MaxLines="3" FontSize="12" Margin="2,0,2,5" Text="*****" Visibility="{Binding IsProtected, Converter={StaticResource BooleanToVisibilityConverter}}" Style="{StaticResource EntryTextBlockStyle}"/> <TextBlock HorizontalAlignment="Left" MaxLines="3" FontSize="12" Margin="2,0,2,5" Text="{Binding DisplayValue}" Style="{StaticResource EntryTextBlockStyle}"/>
<TextBlock HorizontalAlignment="Left" MaxLines="3" FontSize="12" Margin="2,0,2,5" Text="{Binding Value}" Visibility="{Binding IsProtected, Converter={StaticResource InverseBooleanToVisibilityConverter}}" Style="{StaticResource EntryTextBlockStyle}"/>
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
</local:SelectableTemplateListView.ItemTemplate> </local:SelectableTemplateListView.ItemTemplate>
@@ -561,62 +212,28 @@
</HubSection> </HubSection>
</Hub> </Hub>
</Grid> </Grid>
<controls:HamburgerMenuUserControl
Grid.Column="0"
x:Name="HamburgerMenu"
x:Uid="HistoryLeftListView"
ItemsSource="{Binding History}"
SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="SelectionChanged">
<core:InvokeCommandAction Command="{Binding SetCurrentEntryCommand}" CommandParameter="{Binding SelectedItem, ElementName=HamburgerMenu}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</controls:HamburgerMenuUserControl>
</Grid> </Grid>
<!-- Bouton Précédent et titre de la page --> <!-- Bouton Précédent et titre de la page -->
<Grid Grid.Row="0" Background="{ThemeResource AppBarBackgroundThemeBrush}"> <Grid Grid.Row="0" Background="{ThemeResource AppBarBackgroundThemeBrush}">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="{StaticResource MenuWidthGridLength}"/>
<ColumnDefinition Width="{StaticResource MenuWidthGridLength}"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Button Grid.Column="0" <controls:BreadcrumbUserControl x:Name="Breadcrumb" Group="{Binding Parent}" />
Command="{Binding GoBackCommand}" <controls:TopMenuUserControl
Height="{StaticResource MenuHeight}" x:Name="TopMenu" Grid.Column="1"
Width="{StaticResource MenuWidth}"
AutomationProperties.Name="Back"
AutomationProperties.AutomationId="BackButton"
AutomationProperties.ItemType="Navigation Button"
Style="{StaticResource NoBorderButtonStyle}">
<SymbolIcon Symbol="Back" />
</Button>
<Button Grid.Column="1"
Height="{StaticResource MenuHeight}"
Width="{StaticResource MenuWidth}"
Command="{Binding GoToParentCommand}"
Style="{StaticResource NoBorderButtonStyle}">
<SymbolIcon Symbol="Up" />
<ToolTipService.ToolTip>
<ToolTip Content="{Binding ParentGroupName}" />
</ToolTipService.ToolTip>
</Button>
<Viewbox Grid.Column="2" MaxHeight="200">
<SymbolIcon Symbol="{Binding Icon}" Width="100" Height="70" />
</Viewbox>
<TextBox Grid.Column="3"
x:Uid="EntryTitle"
x:Name="TitleTextBox"
Text="{Binding Title, Mode=TwoWay}"
Background="Transparent"
IsHitTestVisible="{Binding IsEditMode}"
FontSize="20"
FontWeight="Light"
TextWrapping="NoWrap"
VerticalAlignment="Center">
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="True">
<actions:SetupFocusAction TargetObject="{Binding ElementName=TitleTextBox}" />
<core:ChangePropertyAction TargetObject="{Binding ElementName=TitleTextBox}" PropertyName="BorderThickness" Value="2" />
</core:DataTriggerBehavior>
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="False">
<core:ChangePropertyAction TargetObject="{Binding ElementName=TitleTextBox}" PropertyName="BorderThickness" Value="0" />
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
</TextBox>
<userControls:TopMenuUserControl
x:Name="TopMenu" Grid.Column="4"
IsEditButtonChecked="{Binding IsEditMode, Mode=TwoWay}"
MoveButtonVisibility="{Binding IsCurrentEntry, Converter={StaticResource BooleanToVisibilityConverter}}" MoveButtonVisibility="{Binding IsCurrentEntry, Converter={StaticResource BooleanToVisibilityConverter}}"
RestoreButtonVisibility="{Binding IsCurrentEntry, Converter={StaticResource InverseBooleanToVisibilityConverter}}" RestoreButtonVisibility="{Binding IsCurrentEntry, Converter={StaticResource InverseBooleanToVisibilityConverter}}"
SaveCommand="{Binding SaveCommand}" SaveCommand="{Binding SaveCommand}"
@@ -628,7 +245,32 @@
<actions:SetupFocusAction TargetObject="{Binding ElementName=TitleTextBox}" /> <actions:SetupFocusAction TargetObject="{Binding ElementName=TitleTextBox}" />
</core:EventTriggerBehavior> </core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
</userControls:TopMenuUserControl> </controls:TopMenuUserControl>
</Grid> </Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="PageLayout">
<VisualState x:Name="Small">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Hub" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="-30,0,0,0"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Medium">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Hub" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,0"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Large">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Hub" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,0"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid> </Grid>
</Page> </Page>

View File

@@ -14,7 +14,7 @@ namespace ModernKeePass.Views
public sealed partial class EntryDetailPage public sealed partial class EntryDetailPage
{ {
public EntryDetailVm Model => (EntryDetailVm) DataContext; public EntryDetailVm Model => (EntryDetailVm) DataContext;
public EntryDetailPage() public EntryDetailPage()
{ {
InitializeComponent(); InitializeComponent();
@@ -28,14 +28,13 @@ namespace ModernKeePass.Views
if (args != null) if (args != null)
{ {
await Model.Initialize(args.Id); await Model.Initialize(args.Id);
Model.IsEditMode = args.IsNew;
if (args.IsNew) await Model.GeneratePassword();
} }
} }
protected override async void OnNavigatedFrom(NavigationEventArgs e) protected override async void OnNavigatedFrom(NavigationEventArgs e)
{ {
await Model.AddHistory(); await Model.AddHistory();
Model.Cleanup();
} }
#endregion #endregion
@@ -47,18 +46,21 @@ namespace ModernKeePass.Views
VisualStateManager.GoToState(this, "Small", true); VisualStateManager.GoToState(this, "Small", true);
VisualStateManager.GoToState(TopMenu, "Collapsed", true); VisualStateManager.GoToState(TopMenu, "Collapsed", true);
VisualStateManager.GoToState(HamburgerMenu, "Hidden", true); VisualStateManager.GoToState(HamburgerMenu, "Hidden", true);
VisualStateManager.GoToState(Breadcrumb, "Small", true);
} }
else if (e.NewSize.Width > 640 && e.NewSize.Width <= 1008) else if (e.NewSize.Width > 640 && e.NewSize.Width <= 1008)
{ {
VisualStateManager.GoToState(this, "Medium", true); VisualStateManager.GoToState(this, "Medium", true);
VisualStateManager.GoToState(TopMenu, "Overflowed", true); VisualStateManager.GoToState(TopMenu, "Overflowed", true);
VisualStateManager.GoToState(HamburgerMenu, "Collapsed", true); VisualStateManager.GoToState(HamburgerMenu, "Collapsed", true);
VisualStateManager.GoToState(Breadcrumb, "Medium", true);
} }
else else
{ {
VisualStateManager.GoToState(this, "Large", true); VisualStateManager.GoToState(this, "Large", true);
VisualStateManager.GoToState(TopMenu, "Overflowed", true); VisualStateManager.GoToState(TopMenu, "Overflowed", true);
VisualStateManager.GoToState(HamburgerMenu, "Collapsed", true); VisualStateManager.GoToState(HamburgerMenu, "Collapsed", true);
VisualStateManager.GoToState(Breadcrumb, "Large", true);
} }
} }
} }

View File

@@ -1,4 +1,4 @@
<Page <Page x:Name="Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
@@ -15,14 +15,10 @@
<Page.Resources> <Page.Resources>
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/> <converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/> <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
<converters:IconToSymbolConverter x:Key="IconToSymbolConverter"/> <converters:IconToSymbolConverter x:Key="IconToSymbolConverter"/>
</Page.Resources> </Page.Resources>
<Grid> <Grid>
<Grid.Resources> <Grid.Resources>
<CollectionViewSource
x:Name="EntriesViewSource"
Source="{Binding Entries}" />
<CollectionViewSource <CollectionViewSource
x:Name="EntriesZoomedOutViewSource" x:Name="EntriesZoomedOutViewSource"
Source="{Binding EntriesZoomedOut}" IsSourceGrouped="True" /> Source="{Binding EntriesZoomedOut}" IsSourceGrouped="True" />
@@ -44,14 +40,6 @@
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<userControls:HamburgerMenuUserControl
x:Name="HamburgerMenu"
x:Uid="GroupsLeftListView"
ItemsSource="{Binding Groups}"
CanDragItems="{Binding IsEditMode}"
SelectionChanged="groups_SelectionChanged"
ActionButtonCommand="{Binding CreateGroupCommand}"
IsButtonVisible="Visible" />
<Grid Grid.Column="1"> <Grid Grid.Column="1">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
@@ -74,16 +62,15 @@
</StackPanel> </StackPanel>
</HyperlinkButton> </HyperlinkButton>
<SemanticZoom Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="1" ViewChangeStarted="SemanticZoom_ViewChangeStarted" ScrollViewer.HorizontalScrollBarVisibility="Visible"> <SemanticZoom x:Name="SemanticZoom" Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="1" ViewChangeStarted="SemanticZoom_ViewChangeStarted" ScrollViewer.HorizontalScrollBarVisibility="Visible">
<SemanticZoom.ZoomedInView> <SemanticZoom.ZoomedInView>
<!-- Horizontal scrolling grid --> <!-- Horizontal scrolling grid -->
<GridView <GridView
x:Name="GridView" x:Name="GridView"
ItemsSource="{Binding Source={StaticResource EntriesViewSource}}" ItemsSource="{Binding Entries}"
AutomationProperties.AutomationId="ItemGridView" AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Entries" AutomationProperties.Name="Entries"
TabIndex="1" TabIndex="1"
SelectionChanged="entries_SelectionChanged"
IsSynchronizedWithCurrentItem="False" IsSynchronizedWithCurrentItem="False"
BorderBrush="{StaticResource ListViewItemSelectedBackgroundThemeBrush}" BorderBrush="{StaticResource ListViewItemSelectedBackgroundThemeBrush}"
AllowDrop="True" AllowDrop="True"
@@ -91,8 +78,11 @@
CanDragItems="{Binding IsEditMode}"> CanDragItems="{Binding IsEditMode}">
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="False"> <core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="False">
<actions:SetupFocusAction TargetObject="{Binding}" /> <actions:SetupFocusAction TargetObject="{Binding ElementName=GridView}" />
</core:DataTriggerBehavior> </core:DataTriggerBehavior>
<core:EventTriggerBehavior EventName="SelectionChanged">
<core:InvokeCommandAction Command="{Binding GoToEntryCommand}" CommandParameter="{Binding SelectedItem, ElementName=GridView}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
<GridView.ItemTemplate> <GridView.ItemTemplate>
<DataTemplate> <DataTemplate>
@@ -128,7 +118,7 @@
<MenuFlyoutItem x:Uid="EntryItemCopyPassword"> <MenuFlyoutItem x:Uid="EntryItemCopyPassword">
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click"> <core:EventTriggerBehavior EventName="Click">
<actions:ClipboardAction Text="{Binding Password}" /> <actions:ClipboardAction Text="{Binding Password}" IsProtected="True" />
<actions:ToastAction x:Uid="ToastCopyPassword" Title="{Binding Title}" /> <actions:ToastAction x:Uid="ToastCopyPassword" Title="{Binding Title}" />
</core:EventTriggerBehavior> </core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
@@ -140,6 +130,7 @@
</core:EventTriggerBehavior> </core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
</MenuFlyoutItem> </MenuFlyoutItem>
<MenuFlyoutItem x:Uid="EntryItemDelete" Command="{Binding DataContext.DeleteEntryCommand, ElementName=Page}" CommandParameter="{Binding}" />
</MenuFlyout> </MenuFlyout>
</Button.Flyout> </Button.Flyout>
</Button> </Button>
@@ -151,23 +142,26 @@
<SemanticZoom.ZoomedOutView> <SemanticZoom.ZoomedOutView>
<GridView <GridView
ItemsSource="{Binding Source={StaticResource EntriesZoomedOutViewSource}}" ItemsSource="{Binding Source={StaticResource EntriesZoomedOutViewSource}}"
SelectionChanged="groups_SelectionChanged"
SelectionMode="None" SelectionMode="None"
IsSynchronizedWithCurrentItem="False"> IsSynchronizedWithCurrentItem="False">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical" ItemWidth="140" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate> <GridView.ItemTemplate>
<DataTemplate> <DataTemplate>
<StackPanel Orientation="Vertical"> <TextBlock Width="100" Margin="5,0,0,0" Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/>
<TextBlock Width="100" Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/>
</StackPanel>
</DataTemplate> </DataTemplate>
</GridView.ItemTemplate> </GridView.ItemTemplate>
<GridView.GroupStyle> <GridView.GroupStyle>
<GroupStyle HidesIfEmpty="True"> <GroupStyle HidesIfEmpty="True">
<GroupStyle.HeaderTemplate> <GroupStyle.HeaderTemplate>
<DataTemplate> <DataTemplate>
<Grid Background="LightGray" HorizontalAlignment="Left"> <StackPanel Orientation="Vertical" HorizontalAlignment="Left">
<TextBlock Text="{Binding Key}" Width="50" Margin="30" Foreground="{StaticResource MainColorBrush}" Style="{StaticResource HeaderTextBlockStyle}" TextAlignment="Center" /> <TextBlock Text="{Binding Key}" Width="50" Margin="20" Foreground="{StaticResource MainColorBrush}" Style="{StaticResource SubheaderTextBlockStyle}" TextAlignment="Center" />
</Grid> <Border BorderBrush="DarkGray" BorderThickness="0,0,0,1" />
</StackPanel>
</DataTemplate> </DataTemplate>
</GroupStyle.HeaderTemplate> </GroupStyle.HeaderTemplate>
</GroupStyle> </GroupStyle>
@@ -176,64 +170,32 @@
</SemanticZoom.ZoomedOutView> </SemanticZoom.ZoomedOutView>
</SemanticZoom> </SemanticZoom>
</Grid> </Grid>
<userControls:HamburgerMenuUserControl
Grid.Column="0"
x:Name="HamburgerMenu"
x:Uid="GroupsLeftListView"
HeaderLabel="{Binding Title}"
ItemsSource="{Binding Groups}"
CanDragItems="{Binding IsEditMode}"
ActionButtonCommand="{Binding CreateGroupCommand}"
IsButtonVisible="Visible">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="SelectionChanged">
<core:InvokeCommandAction Command="{Binding GoToGroupCommand}" CommandParameter="{Binding SelectedItem, ElementName=HamburgerMenu}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</userControls:HamburgerMenuUserControl>
</Grid> </Grid>
<!-- Back button and page title --> <!-- Back button and page title -->
<Grid Grid.Row="0" Background="{ThemeResource AppBarBackgroundThemeBrush}"> <Grid Grid.Row="0" Background="{ThemeResource AppBarBackgroundThemeBrush}">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="{StaticResource MenuWidthGridLength}"/>
<ColumnDefinition Width="{StaticResource MenuWidthGridLength}"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Button Grid.Column="0" <userControls:BreadcrumbUserControl x:Name="Breadcrumb" Group="{Binding Parent}" />
Command="{Binding GoBackCommand}" <userControls:TopMenuUserControl x:Name="TopMenu" Grid.Column="1"
Height="{StaticResource MenuHeight}"
Width="{StaticResource MenuWidth}"
AutomationProperties.Name="Back"
AutomationProperties.AutomationId="BackButton"
AutomationProperties.ItemType="Navigation Button"
Style="{StaticResource NoBorderButtonStyle}">
<SymbolIcon Symbol="Back" />
</Button>
<Button Grid.Column="1"
Height="{StaticResource MenuHeight}"
Width="{StaticResource MenuWidth}"
Command="{Binding GoToParentCommand}"
Style="{StaticResource NoBorderButtonStyle}">
<SymbolIcon Symbol="Up" />
<ToolTipService.ToolTip>
<ToolTip Content="{Binding ParentGroupName}" />
</ToolTipService.ToolTip>
</Button>
<Viewbox Grid.Column="2" MaxHeight="200" Visibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}">
<userControls:SymbolPickerUserControl Width="100" Height="70" SelectedSymbol="{Binding Icon, Mode=TwoWay}" />
</Viewbox>
<Viewbox Grid.Column="2" MaxHeight="200" Visibility="{Binding IsEditMode, Converter={StaticResource InverseBooleanToVisibilityConverter}}">
<SymbolIcon Symbol="{Binding Icon}" Width="100" Height="70" />
</Viewbox>
<TextBox Grid.Column="3"
x:Uid="GroupTitle"
x:Name="TitleTextBox"
Text="{Binding Title, Mode=TwoWay}"
Background="Transparent"
IsHitTestVisible="{Binding IsEditMode}"
FontSize="20"
FontWeight="Light"
TextWrapping="NoWrap"
VerticalAlignment="Center">
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="True">
<actions:SetupFocusAction TargetObject="{Binding ElementName=TitleTextBox}" />
<core:ChangePropertyAction TargetObject="{Binding ElementName=TitleTextBox}" PropertyName="BorderThickness" Value="2" />
</core:DataTriggerBehavior>
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="False">
<core:ChangePropertyAction TargetObject="{Binding ElementName=TitleTextBox}" PropertyName="BorderThickness" Value="0" />
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
</TextBox>
<userControls:TopMenuUserControl x:Name="TopMenu" Grid.Column="4"
SortButtonVisibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}" SortButtonVisibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}"
EditButtonVisibility="Visible"
IsEditButtonChecked="{Binding IsEditMode, Mode=TwoWay}" IsEditButtonChecked="{Binding IsEditMode, Mode=TwoWay}"
SaveCommand="{Binding SaveCommand}" SaveCommand="{Binding SaveCommand}"
MoveCommand="{Binding MoveCommand}" MoveCommand="{Binding MoveCommand}"
@@ -246,7 +208,6 @@
</core:EventTriggerBehavior> </core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
</userControls:TopMenuUserControl> </userControls:TopMenuUserControl>
</Grid> </Grid>
<VisualStateManager.VisualStateGroups> <VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="PageLayout"> <VisualStateGroup x:Name="PageLayout">
@@ -258,6 +219,9 @@
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HamburgerMenu" Storyboard.TargetProperty="IsOpen"> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HamburgerMenu" Storyboard.TargetProperty="IsOpen">
<DiscreteObjectKeyFrame KeyTime="0" Value="False"/> <DiscreteObjectKeyFrame KeyTime="0" Value="False"/>
</ObjectAnimationUsingKeyFrames> </ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SemanticZoom" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="-60,0,0,0"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard> </Storyboard>
</VisualState> </VisualState>
<VisualState x:Name="Medium"> <VisualState x:Name="Medium">
@@ -265,6 +229,9 @@
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HamburgerMenu" Storyboard.TargetProperty="IsOpen"> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HamburgerMenu" Storyboard.TargetProperty="IsOpen">
<DiscreteObjectKeyFrame KeyTime="0" Value="False"/> <DiscreteObjectKeyFrame KeyTime="0" Value="False"/>
</ObjectAnimationUsingKeyFrames> </ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SemanticZoom" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,0"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard> </Storyboard>
</VisualState> </VisualState>
<VisualState x:Name="Large"> <VisualState x:Name="Large">
@@ -275,6 +242,9 @@
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HamburgerMenu" Storyboard.TargetProperty="IsOpen"> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HamburgerMenu" Storyboard.TargetProperty="IsOpen">
<DiscreteObjectKeyFrame KeyTime="0" Value="True"/> <DiscreteObjectKeyFrame KeyTime="0" Value="True"/>
</ObjectAnimationUsingKeyFrames> </ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SemanticZoom" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,0"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard> </Storyboard>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>

View File

@@ -1,7 +1,6 @@
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 ModernKeePass.Application.Entry.Models;
using ModernKeePass.Models; using ModernKeePass.Models;
using ModernKeePass.ViewModels; using ModernKeePass.ViewModels;
@@ -37,33 +36,6 @@ namespace ModernKeePass.Views
#endregion #endregion
#region Event Handlers #region Event Handlers
private void groups_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listView = sender as ListView;
switch (listView?.SelectedIndex)
{
case -1:
return;
default:
var group = listView?.SelectedItem as Application.Group.Models.GroupVm;
Model.GoToGroup(group?.Id);
break;
}
}
private void entries_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
switch (GridView.SelectedIndex)
{
case -1:
return;
default:
var entry = GridView.SelectedItem as EntryVm;
Model.GoToEntry(entry?.Id);
break;
}
}
private void SemanticZoom_ViewChangeStarted(object sender, SemanticZoomViewChangedEventArgs e) private void SemanticZoom_ViewChangeStarted(object sender, SemanticZoomViewChangedEventArgs e)
{ {
@@ -81,18 +53,21 @@ namespace ModernKeePass.Views
VisualStateManager.GoToState(this, "Small", true); VisualStateManager.GoToState(this, "Small", true);
VisualStateManager.GoToState(TopMenu, "Collapsed", true); VisualStateManager.GoToState(TopMenu, "Collapsed", true);
VisualStateManager.GoToState(HamburgerMenu, "Hidden", true); VisualStateManager.GoToState(HamburgerMenu, "Hidden", true);
VisualStateManager.GoToState(Breadcrumb, "Small", true);
} }
else if (e.NewSize.Width > 640 && e.NewSize.Width <= 1008) else if (e.NewSize.Width > 640 && e.NewSize.Width <= 1008)
{ {
VisualStateManager.GoToState(this, "Medium", true); VisualStateManager.GoToState(this, "Medium", true);
VisualStateManager.GoToState(TopMenu, "Overflowed", true); VisualStateManager.GoToState(TopMenu, "Overflowed", true);
VisualStateManager.GoToState(HamburgerMenu, "Collapsed", true); VisualStateManager.GoToState(HamburgerMenu, "Collapsed", true);
VisualStateManager.GoToState(Breadcrumb, "Medium", true);
} }
else else
{ {
VisualStateManager.GoToState(this, "Large", true); VisualStateManager.GoToState(this, "Large", true);
VisualStateManager.GoToState(TopMenu, "Overflowed", true); VisualStateManager.GoToState(TopMenu, "Overflowed", true);
VisualStateManager.GoToState(HamburgerMenu, "Expanded", true); VisualStateManager.GoToState(HamburgerMenu, "Expanded", true);
VisualStateManager.GoToState(Breadcrumb, "Large", true);
} }
} }

View File

@@ -57,6 +57,7 @@
Grid.Column="0" Grid.Column="0"
Grid.Row="1" Grid.Row="1"
x:Name="MenuListView" x:Name="MenuListView"
ScrollViewer.VerticalScrollMode="Disabled"
SelectionChanged="ListView_SelectionChanged" SelectionChanged="ListView_SelectionChanged"
Background="{ThemeResource AppBarBackgroundThemeBrush}" Background="{ThemeResource AppBarBackgroundThemeBrush}"
ItemsSource="{Binding Source={StaticResource MenuItemsSource}}" ItemsSource="{Binding Source={StaticResource MenuItemsSource}}"

View File

@@ -13,35 +13,50 @@ namespace ModernKeePass.Views
/// </summary> /// </summary>
public sealed partial class MainPage public sealed partial class MainPage
{ {
public new MainVm Model => (MainVm)DataContext; public new MainVm Model => (MainVm) DataContext;
public MainPage() public MainPage()
{ {
InitializeComponent(); InitializeComponent();
Unloaded += MainPage_Unloaded; ListView = MenuListView;
ListView = MenuListView;
ListViewSource = MenuItemsSource; ListViewSource = MenuItemsSource;
} }
private void MainPage_Unloaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
Model.Cleanup();
}
private new void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) private new void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
base.ListView_SelectionChanged(sender, e); base.ListView_SelectionChanged(sender, e);
var selectedItem = Model.SelectedItem as MainMenuItemVm; var selectedItem = Model.SelectedItem as MainMenuItemVm;
if (selectedItem == null) MenuFrame.Navigate(typeof(WelcomePage)); if (selectedItem == null)
else selectedItem.Destination.Navigate(selectedItem.PageType, selectedItem.Parameter); {
MenuFrame.Navigate(typeof(WelcomePage));
}
else
{
selectedItem.Destination.Navigate(selectedItem.PageType, selectedItem.Parameter);
}
} }
protected override async void OnNavigatedTo(NavigationEventArgs e) protected override async void OnNavigatedTo(NavigationEventArgs e)
{ {
base.OnNavigatedTo(e); base.OnNavigatedTo(e);
var file = e.Parameter as FileInfo; FileInfo file;
if (e.NavigationMode == NavigationMode.Back)
{
file = null;
}
else
{
file = e.Parameter as FileInfo;
}
await Model.Initialize(Frame, MenuFrame, file); await Model.Initialize(Frame, MenuFrame, file);
} }
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
Model.Cleanup();
}
} }
} }

View File

@@ -1,5 +1,5 @@
<Page <Page
x:Class="ModernKeePass.Views.ImportExportPage" x:Class="ModernKeePass.Views.ImportPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

View File

@@ -5,9 +5,9 @@ namespace ModernKeePass.Views
/// <summary> /// <summary>
/// The import/export page. /// The import/export page.
/// </summary> /// </summary>
public sealed partial class ImportExportPage public sealed partial class ImportPage
{ {
public ImportExportPage() public ImportPage()
{ {
InitializeComponent(); InitializeComponent();
} }

View File

@@ -1,5 +1,8 @@
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
using Windows.UI.Xaml.Navigation;
using ModernKeePass.ViewModels;
namespace ModernKeePass.Views namespace ModernKeePass.Views
{ {
/// <summary> /// <summary>
@@ -7,9 +10,16 @@ namespace ModernKeePass.Views
/// </summary> /// </summary>
public sealed partial class NewDatabasePage public sealed partial class NewDatabasePage
{ {
public NewVm Model => (NewVm)DataContext;
public NewDatabasePage() public NewDatabasePage()
{ {
InitializeComponent(); InitializeComponent();
} }
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
Model.Cleanup();
}
} }
} }

View File

@@ -9,6 +9,11 @@
mc:Ignorable="d" mc:Ignorable="d"
DataContext="{Binding Source={StaticResource Locator}, Path=Recent}"> DataContext="{Binding Source={StaticResource Locator}, Path=Recent}">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.Resources>
<CollectionViewSource
x:Name="RecentItemsSource"
Source="{Binding RecentItems}" />
</Grid.Resources>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="40" /> <RowDefinition Height="40" />
<RowDefinition Height="*" /> <RowDefinition Height="*" />
@@ -21,7 +26,7 @@
</HyperlinkButton> </HyperlinkButton>
<controls:SelectableTemplateListView Grid.Row="1" <controls:SelectableTemplateListView Grid.Row="1"
SelectedIndex="{Binding SelectedIndex}" SelectedIndex="{Binding SelectedIndex}"
ItemsSource="{Binding RecentItems}" ItemsSource="{Binding Source={StaticResource RecentItemsSource}}"
ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}"> ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}">
<controls:SelectableTemplateListView.SelectedItemTemplate> <controls:SelectableTemplateListView.SelectedItemTemplate>
<DataTemplate> <DataTemplate>

View File

@@ -1,5 +1,8 @@
// Pour en savoir plus sur le modèle d'élément Page vierge, consultez la page http://go.microsoft.com/fwlink/?LinkId=234238 // Pour en savoir plus sur le modèle d'élément Page vierge, consultez la page http://go.microsoft.com/fwlink/?LinkId=234238
using Windows.UI.Xaml.Navigation;
using ModernKeePass.ViewModels;
namespace ModernKeePass.Views namespace ModernKeePass.Views
{ {
/// <summary> /// <summary>
@@ -7,9 +10,16 @@ namespace ModernKeePass.Views
/// </summary> /// </summary>
public sealed partial class RecentDatabasesPage public sealed partial class RecentDatabasesPage
{ {
public RecentVm Model => (RecentVm)DataContext;
public RecentDatabasesPage() public RecentDatabasesPage()
{ {
InitializeComponent(); InitializeComponent();
} }
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
Model.Cleanup();
}
} }
} }

View File

@@ -1,5 +1,8 @@
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
using Windows.UI.Xaml.Navigation;
using ModernKeePass.ViewModels;
namespace ModernKeePass.Views namespace ModernKeePass.Views
{ {
/// <summary> /// <summary>
@@ -7,9 +10,16 @@ namespace ModernKeePass.Views
/// </summary> /// </summary>
public sealed partial class SaveDatabasePage public sealed partial class SaveDatabasePage
{ {
public SaveVm Model => (SaveVm)DataContext;
public SaveDatabasePage() public SaveDatabasePage()
{ {
InitializeComponent(); InitializeComponent();
} }
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
Model.Cleanup();
}
} }
} }

View File

@@ -17,7 +17,7 @@ namespace ModernKeePass.Views
private void UIElement_OnKeyDown(object sender, KeyRoutedEventArgs e) private void UIElement_OnKeyDown(object sender, KeyRoutedEventArgs e)
{ {
if ((e.Key < VirtualKey.NumberPad0 || e.Key > VirtualKey.NumberPad9) & (e.Key < VirtualKey.Number0 || e.Key > VirtualKey.Number9)) if ((e.Key < VirtualKey.NumberPad0 || e.Key > VirtualKey.NumberPad9) && (e.Key < VirtualKey.Number0 || e.Key > VirtualKey.Number9))
{ {
e.Handled = true; e.Handled = true;
} }

View File

@@ -17,7 +17,7 @@ namespace ModernKeePass.Views.SettingsPageFrames
private void UIElement_OnKeyDown(object sender, KeyRoutedEventArgs e) private void UIElement_OnKeyDown(object sender, KeyRoutedEventArgs e)
{ {
if ((e.Key < VirtualKey.NumberPad0 || e.Key > VirtualKey.NumberPad9) & (e.Key < VirtualKey.Number0 || e.Key > VirtualKey.Number9)) if ((e.Key < VirtualKey.NumberPad0 || e.Key > VirtualKey.NumberPad9) && (e.Key < VirtualKey.Number0 || e.Key > VirtualKey.Number9))
{ {
e.Handled = true; e.Handled = true;
} }

View File

@@ -1,30 +1,15 @@
using System; // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
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;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace ModernKeePass.Views.SettingsPageFrames namespace ModernKeePass.Views.SettingsPageFrames
{ {
/// <summary> /// <summary>
/// An empty page that can be used on its own or navigated to within a Frame. /// An empty page that can be used on its own or navigated to within a Frame.
/// </summary> /// </summary>
public sealed partial class SettingsRecycleBinPage : Page public sealed partial class SettingsRecycleBinPage
{ {
public SettingsRecycleBinPage() public SettingsRecycleBinPage()
{ {
this.InitializeComponent(); InitializeComponent();
} }
} }
} }

View File

@@ -0,0 +1,117 @@
<UserControl
x:Class="ModernKeePass.Views.UserControls.BreadcrumbUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:converters="using:ModernKeePass.Converters"
xmlns:templateSelectors="using:ModernKeePass.TemplateSelectors"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
mc:Ignorable="d">
<StackPanel x:Name="StackPanel" DataContext="{Binding Source={StaticResource Locator}, Path=Breadcrumb}" Orientation="Horizontal">
<StackPanel.Resources>
<converters:IconToSymbolConverter x:Key="IconToSymbolConverter"/>
<DataTemplate x:Key="FirstItemTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="10,5,10,0" Text="{Binding Name}" FontStyle="Italic" HorizontalAlignment="Center" />
<SymbolIcon Symbol="{Binding Icon, Converter={StaticResource IconToSymbolConverter}, ConverterParameter=33}" Margin="0,3,0,0" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="OtherItemTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="10,5,10,0" Text="&lt;" HorizontalAlignment="Center" />
<TextBlock Margin="10,5,10,0" Text="{Binding Name}" FontStyle="Italic" HorizontalAlignment="Center" />
<SymbolIcon Symbol="{Binding Icon, Converter={StaticResource IconToSymbolConverter}, ConverterParameter=33}" Margin="0,3,0,0" />
</StackPanel>
</DataTemplate>
</StackPanel.Resources>
<Button
Command="{Binding GoBackCommand}"
Height="{StaticResource MenuHeight}"
Width="{StaticResource MenuWidth}"
AutomationProperties.Name="Back"
AutomationProperties.AutomationId="BackButton"
AutomationProperties.ItemType="Navigation Button"
Style="{StaticResource NoBorderButtonStyle}">
<SymbolIcon Symbol="Back" />
</Button>
<Button
Height="{StaticResource MenuHeight}"
Command="{Binding GoUpCommand}"
Style="{StaticResource NoBorderButtonStyle}">
<StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="Up" />
<SymbolIcon x:Name="UpButtonIcon" Symbol="{Binding ParentGroupIcon, Converter={StaticResource IconToSymbolConverter}, ConverterParameter=33}" Margin="16,0,0,0" />
<TextBlock x:Name="UpButtonText" Margin="10,2,0,0" Text="{Binding ParentGroupName}" FontStyle="Italic" FontWeight="Normal" HorizontalAlignment="Center" />
</StackPanel>
<ToolTipService.ToolTip>
<ToolTip Content="{Binding ParentGroupName}" />
</ToolTipService.ToolTip>
</Button>
<ListView x:Name="ListView" ItemsSource="{Binding BreadcrumbItems}" ScrollViewer.HorizontalScrollMode="Auto">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel FlowDirection="RightToLeft" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplateSelector>
<templateSelectors:FirstItemDataTemplateSelector FirstItem="{StaticResource FirstItemTemplate}" OtherItem="{StaticResource OtherItemTemplate}" />
</ListView.ItemTemplateSelector>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Margin" Value="0"/>
<Setter Property="Height" Value="{StaticResource MenuHeight}" />
</Style>
</ListView.ItemContainerStyle>
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="SelectionChanged">
<core:InvokeCommandAction Command="{Binding GoToCommand}" CommandParameter="{Binding SelectedIndex, ElementName=ListView}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</ListView>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="PageLayout">
<VisualState x:Name="Small">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="UpButtonIcon" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="UpButtonText" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ListView" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Medium">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="UpButtonIcon" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="UpButtonText" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ListView" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Large">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="UpButtonIcon" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="UpButtonText" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ListView" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,36 @@
using System.Linq;
using Windows.UI.Xaml;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.ViewModels;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace ModernKeePass.Views.UserControls
{
public sealed partial class BreadcrumbUserControl
{
public GroupVm Group
{
get { return (GroupVm)GetValue(GroupProperty); }
set { SetValue(GroupProperty, value); }
}
public static readonly DependencyProperty GroupProperty =
DependencyProperty.Register(
nameof(Group),
typeof(GroupVm),
typeof(BreadcrumbUserControl),
new PropertyMetadata(null, async (o, args) =>
{
var userControl = o as BreadcrumbUserControl;
var vm = userControl?.StackPanel.DataContext as BreadcrumbControlVm;
if (vm == null) return;
await vm.Initialize(args.NewValue as GroupVm).ConfigureAwait(false);
userControl?.ListView.ScrollIntoView(vm.BreadcrumbItems.Last());
}));
public BreadcrumbUserControl()
{
InitializeComponent();
}
}
}

View File

@@ -6,10 +6,13 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> mc:Ignorable="d">
<ComboBox x:Name="ComboBox" <ComboBox x:Name="ComboBox"
ItemsSource="{Binding Colors, ElementName=UserControl}" DataContext="{Binding Source={StaticResource Locator}, Path=ColorPicker}"
SelectionChanged="Selector_OnSelectionChanged" ItemsSource="{Binding Colors}"
Loaded="ComboBox_Loaded" SelectedItem="{Binding SelectedItem}"
IsEnabled="{Binding IsEnabled, ElementName=UserControl}"> SelectedValue="{Binding SelectedColor, ElementName=UserControl}"
SelectedValuePath="ColorBrush"
SelectionChanged="ComboBox_OnSelectionChanged"
IsEnabled="{Binding IsEnabled, ElementName=UserControl}">
<ComboBox.ItemTemplate> <ComboBox.ItemTemplate>
<DataTemplate> <DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,10,0"> <StackPanel Orientation="Horizontal" Margin="0,0,10,0">

View File

@@ -1,9 +1,8 @@
using System.Collections.Generic; using System.Linq;
using System.Linq;
using System.Reflection;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media;
using ModernKeePass.ViewModels;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236 // The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
@@ -11,14 +10,6 @@ namespace ModernKeePass.Views.UserControls
{ {
public sealed partial class ColorPickerUserControl public sealed partial class ColorPickerUserControl
{ {
public struct Color
{
public string ColorName { get; set; }
public SolidColorBrush ColorBrush { get; set; }
}
public List<Color> Colors { get; }
public SolidColorBrush SelectedColor public SolidColorBrush SelectedColor
{ {
get { return (SolidColorBrush)GetValue(SelectedColorProperty); } get { return (SolidColorBrush)GetValue(SelectedColorProperty); }
@@ -29,33 +20,22 @@ namespace ModernKeePass.Views.UserControls
nameof(SelectedColor), nameof(SelectedColor),
typeof(SolidColorBrush), typeof(SolidColorBrush),
typeof(ColorPickerUserControl), typeof(ColorPickerUserControl),
new PropertyMetadata(new SolidColorBrush(), (o, args) => { })); new PropertyMetadata(new SolidColorBrush(), (o, args) =>
{
var colorPickerUserControl = o as ColorPickerUserControl;
var vm = colorPickerUserControl?.ComboBox.DataContext as ColorPickerControlVm;
vm?.Initialize(args.NewValue as SolidColorBrush);
}));
public ColorPickerUserControl() public ColorPickerUserControl()
{ {
InitializeComponent(); InitializeComponent();
Colors = new List<Color>();
var type = typeof(Windows.UI.Colors);
var properties = type.GetRuntimeProperties().ToArray();
foreach (var propertyInfo in properties)
{
Colors.Add(new Color
{
ColorName = propertyInfo.Name,
ColorBrush = new SolidColorBrush((Windows.UI.Color)propertyInfo.GetValue(null, null))
});
}
} }
private void ComboBox_Loaded(object sender, RoutedEventArgs e) private void ComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
ComboBox.SelectedItem = Colors.Find(c => c.ColorBrush.Color.Equals(SelectedColor.Color)); if (e.AddedItems.Any())
} SelectedColor = (e.AddedItems[0] as ColorPickerControlVm.Color)?.ColorBrush;
private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var selectedItem = ComboBox.SelectedItem as Color? ?? new Color();
SelectedColor = selectedItem.ColorBrush;
} }
} }
} }

View File

@@ -60,7 +60,10 @@
<RowDefinition Height="*" /> <RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<ToggleButton Style="{StaticResource HamburgerToggleButton}" IsChecked="{Binding IsOpen, ElementName=UserControl}" Unchecked="ToggleButton_OnUnchecked"> <ToggleButton Style="{StaticResource HamburgerToggleButton}" IsChecked="{Binding IsOpen, ElementName=UserControl, Mode=TwoWay}" Unchecked="ToggleButton_OnUnchecked">
<ToolTipService.ToolTip>
<ToolTip Content="{Binding HeaderLabel, ElementName=UserControl}" />
</ToolTipService.ToolTip>
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Checked"> <core:EventTriggerBehavior EventName="Checked">
<core:GoToStateAction StateName="Expanded" /> <core:GoToStateAction StateName="Expanded" />
@@ -94,7 +97,7 @@
<ListView.ItemTemplate> <ListView.ItemTemplate>
<DataTemplate x:Name="IsNormal"> <DataTemplate x:Name="IsNormal">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="{Binding Icon, Converter={StaticResource IconToSymbolConverter}, ConverterParameter=48}" Margin="7,10,0,15"> <SymbolIcon Symbol="{Binding Icon, Converter={StaticResource IconToSymbolConverter}, ConverterParameter=33}" Margin="7,10,0,15">
<ToolTipService.ToolTip> <ToolTipService.ToolTip>
<ToolTip Content="{Binding Path={Binding DisplayMemberPath, ElementName=UserControl}}" /> <ToolTip Content="{Binding Path={Binding DisplayMemberPath, ElementName=UserControl}}" />
</ToolTipService.ToolTip> </ToolTipService.ToolTip>
@@ -125,6 +128,7 @@
</StackPanel> </StackPanel>
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click"> <core:EventTriggerBehavior EventName="Click">
<core:ChangePropertyAction TargetObject="{Binding ElementName=UserControl}" PropertyName="IsOpen" Value="True" />
<core:ChangePropertyAction TargetObject="{Binding ElementName=NewGroupTextBox}" PropertyName="Visibility" Value="Visible" /> <core:ChangePropertyAction TargetObject="{Binding ElementName=NewGroupTextBox}" PropertyName="Visibility" Value="Visible" />
<core:ChangePropertyAction TargetObject="{Binding ElementName=NewGroupButton}" PropertyName="Visibility" Value="Collapsed" /> <core:ChangePropertyAction TargetObject="{Binding ElementName=NewGroupButton}" PropertyName="Visibility" Value="Collapsed" />
<actions:SetupFocusAction TargetObject="{Binding ElementName=NewGroupTextBox}" /> <actions:SetupFocusAction TargetObject="{Binding ElementName=NewGroupTextBox}" />
@@ -142,7 +146,7 @@
ButtonCommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Text}" ButtonCommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Text}"
Style="{StaticResource TextBoxWithButtonStyle}" Style="{StaticResource TextBoxWithButtonStyle}"
KeyDown="NewGroupTextBox_OnKeyDown" KeyDown="NewGroupTextBox_OnKeyDown"
ButtonSymbol="&#xE109;"> ButtonContent="&#xE109;">
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="LostFocus"> <core:EventTriggerBehavior EventName="LostFocus">
<core:ChangePropertyAction TargetObject="{Binding ElementName=NewGroupButton}" PropertyName="Visibility" Value="Visible" /> <core:ChangePropertyAction TargetObject="{Binding ElementName=NewGroupButton}" PropertyName="Visibility" Value="Visible" />

View File

@@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Windows.Input; using System.Windows.Input;
using Windows.System; using Windows.System;
using Windows.UI.Xaml; using Windows.UI.Xaml;
@@ -7,6 +6,7 @@ using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Input;
using ModernKeePass.Application.Common.Interfaces; using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Controls; using ModernKeePass.Controls;
using System.Collections.ObjectModel;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236 // The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
@@ -25,7 +25,7 @@ namespace ModernKeePass.Views.UserControls
typeof(string), typeof(string),
typeof(HamburgerMenuUserControl), typeof(HamburgerMenuUserControl),
new PropertyMetadata("Header", (o, args) => { })); new PropertyMetadata("Header", (o, args) => { }));
public string ButtonLabel public string ButtonLabel
{ {
get { return (string)GetValue(ButtonLabelProperty); } get { return (string)GetValue(ButtonLabelProperty); }
@@ -62,18 +62,18 @@ namespace ModernKeePass.Views.UserControls
typeof(HamburgerMenuUserControl), typeof(HamburgerMenuUserControl),
new PropertyMetadata(Visibility.Collapsed, (o, args) => { })); new PropertyMetadata(Visibility.Collapsed, (o, args) => { }));
public IEnumerable<IEntityVm> ItemsSource public ObservableCollection<IEntityVm> ItemsSource
{ {
get { return (IEnumerable<IEntityVm>)GetValue(ItemsSourceProperty); } get { return (ObservableCollection<IEntityVm>)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); } set { SetValue(ItemsSourceProperty, value); }
} }
public static readonly DependencyProperty ItemsSourceProperty = public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register( DependencyProperty.Register(
nameof(ItemsSource), nameof(ItemsSource),
typeof(IEnumerable<IEntityVm>), typeof(ObservableCollection<IEntityVm>),
typeof(HamburgerMenuUserControl), typeof(HamburgerMenuUserControl),
new PropertyMetadata(new List<IEntityVm>(), (o, args) => { })); new PropertyMetadata(new ObservableCollection<IEntityVm>(), (o, args) => { }));
public object SelectedItem public object SelectedItem
{ {

View File

@@ -7,7 +7,7 @@
xmlns:interactivity="using:Microsoft.Xaml.Interactivity" xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core" xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:converters="using:ModernKeePass.Converters" xmlns:converters="using:ModernKeePass.Converters"
mc:Ignorable="d" > mc:Ignorable="d">
<UserControl.Resources> <UserControl.Resources>
<converters:EmptyStringToVisibilityConverter x:Key="EmptyStringToVisibilityConverter"/> <converters:EmptyStringToVisibilityConverter x:Key="EmptyStringToVisibilityConverter"/>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/> <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
@@ -85,6 +85,9 @@
<core:DataTriggerBehavior Binding="{Binding IsError}" Value="False"> <core:DataTriggerBehavior Binding="{Binding IsError}" Value="False">
<core:GoToStateAction StateName="Initial"/> <core:GoToStateAction StateName="Initial"/>
</core:DataTriggerBehavior> </core:DataTriggerBehavior>
<core:EventTriggerBehavior EventName="Unloaded">
<core:CallMethodAction TargetObject="{Binding}" MethodName="Cleanup"/>
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
</Grid> </Grid>
</UserControl> </UserControl>

View File

@@ -0,0 +1,384 @@
<UserControl x:Name="UserControl"
x:Class="ModernKeePass.Views.UserControls.PasswordGenerationBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:ModernKeePass.Controls"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:converters="using:ModernKeePass.Converters"
xmlns:actions="using:ModernKeePass.Actions"
mc:Ignorable="d"
BorderBrush="{ThemeResource ComboBoxBorderThemeBrush}">
<StackPanel x:Name="StackPanel" Orientation="Vertical" DataContext="{Binding Source={StaticResource Locator}, Path=PasswordGenerationBox}">
<StackPanel.Resources>
<converters:ProgressBarLegalValuesConverter x:Key="ProgressBarLegalValuesConverter" />
<converters:DoubleToSolidColorBrushConverter x:Key="DoubleToForegroundBrushComplexityConverter" />
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter" />
<Style TargetType="controls:PasswordBoxWithButton" x:Key="PasswordBoxWithButtonStyle">
<Setter Property="Background" Value="{ThemeResource SearchBoxBackgroundThemeBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource ComboBoxBorderThemeBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="FontWeight" Value="{ThemeResource SearchBoxContentThemeFontWeight}"/>
<Setter Property="Foreground" Value="{ThemeResource SearchBoxForegroundThemeBrush}" />
<Setter Property="Padding" Value="{ThemeResource SearchBoxThemePadding}"/>
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Typography.StylisticSet20" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:PasswordBoxWithButton">
<Grid x:Name="SearchBoxGrid">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Foreground}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxPointerOverBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxPointerOverBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxPointerOverTextThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledTextThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PasswordBox" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource MainColor}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="FocusedDropDown">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedTextThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.Resources>
<Style x:Key="ActionButtonStyle" TargetType="Button">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonPointerOverForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButtonBackground" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonPointerOverBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedTextThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButtonBackground" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled" />
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused" />
<VisualState x:Name="Unfocused" />
<VisualState x:Name="PointerFocused" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="ActionButtonBackground" Background="{TemplateBinding Background}">
<TextBlock x:Name="SearchGlyph"
AutomationProperties.AccessibilityView="Raw"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
Foreground="{TemplateBinding Foreground}"
HorizontalAlignment="Center"
FontStyle="Italic"
Padding="4,0,4,0"
Text="{TemplateBinding Content}"
VerticalAlignment="Center" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="PasswordBoxStyle" TargetType="PasswordBox">
<Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
<Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
<Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}" />
<Setter Property="Background" Value="{ThemeResource TextBoxBackgroundThemeBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource TextBoxBorderThemeBrush}" />
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextSelectionHighlightColorThemeBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="PasswordBox">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="{ThemeResource TextControlBackgroundThemeOpacity}" />
<DoubleAnimation Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="{ThemeResource TextControlBorderThemeOpacity}" />
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="{ThemeResource TextControlPointerOverBackgroundThemeOpacity}" />
<DoubleAnimation Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="{ThemeResource TextControlPointerOverBorderThemeOpacity}" />
</Storyboard>
</VisualState>
<VisualState x:Name="Focused" />
</VisualStateGroup>
<VisualStateGroup x:Name="ButtonStates" />
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border x:Name="BackgroundElement"
Grid.Row="1"
Background="{TemplateBinding Background}"
Margin="{TemplateBinding BorderThickness}" />
<Border x:Name="BorderElement"
Grid.Row="1"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" />
<ContentPresenter x:Name="HeaderContentPresenter"
Grid.Row="0"
Foreground="{ThemeResource TextBoxForegroundHeaderThemeBrush}"
Margin="0,4,0,4"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
FontWeight="Semilight" />
<ScrollViewer x:Name="ContentElement"
Grid.Row="1"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
IsTabStop="False"
AutomationProperties.AccessibilityView="Raw"
ZoomMode="Disabled" />
<ContentControl x:Name="PlaceholderTextContentPresenter"
Grid.Row="1"
Foreground="{ThemeResource TextBoxPlaceholderTextThemeBrush}"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
IsTabStop="False"
Grid.ColumnSpan="2"
Content="{TemplateBinding PlaceholderText}"
IsHitTestVisible="False" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Border x:Name="SearchBoxBorder"
Background="Transparent"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<PasswordBox x:Name="PasswordBox"
BorderThickness="0"
Background="Transparent"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
Foreground="{TemplateBinding Foreground}"
MaxLength="2048"
MinHeight="{ThemeResource SearchBoxTextBoxThemeMinHeight}"
Padding="{TemplateBinding Padding}"
PlaceholderText="{TemplateBinding PlaceholderText}"
Style="{StaticResource PasswordBoxStyle}"
VerticalAlignment="Stretch"
Margin="0"
Password="{Binding RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, Path=Password, UpdateSourceTrigger=PropertyChanged}"
IsPasswordRevealButtonEnabled="{TemplateBinding IsPasswordRevealEnabled}"/>
<Button x:Name="ActionButton"
AutomationProperties.AccessibilityView="Raw"
Background="Transparent"
FontWeight="{ThemeResource SearchBoxButtonThemeFontWeight}"
FontSize="12"
Grid.Column="1"
Style="{StaticResource ActionButtonStyle}"
Content="{TemplateBinding ButtonContent}"
IsEnabled="{TemplateBinding IsButtonEnabled}">
<Button.Flyout>
<Flyout>
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding Password}" ComparisonCondition="NotEqual" Value="" >
<core:CallMethodAction MethodName="Hide" />
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
<StackPanel>
<TextBlock>
<Run x:Uid="PasswordGeneratorLength" />
<Run Text="{Binding PasswordLength}" />
</TextBlock>
<Slider Value="{Binding PasswordLength, Mode=TwoWay}" Margin="0,-10,0,-20" />
<CheckBox IsChecked="{Binding UpperCasePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorUpper" />
<CheckBox IsChecked="{Binding LowerCasePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorLower" />
<CheckBox IsChecked="{Binding DigitsPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorDigits" />
<CheckBox IsChecked="{Binding MinusPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorMinus" />
<CheckBox IsChecked="{Binding UnderscorePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorUnderscore" />
<CheckBox IsChecked="{Binding SpacePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorSpace" />
<CheckBox IsChecked="{Binding SpecialPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorSpecial" />
<CheckBox IsChecked="{Binding BracketsPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorBrackets" />
<TextBlock x:Uid="PasswordGeneratorAlso" Margin="0,5,0,0"/>
<TextBox Text="{Binding CustomChars, Mode=TwoWay}" />
<Button x:Uid="PasswordGeneratorButton" Command="{Binding GeneratePasswordCommand}" />
</StackPanel>
</Flyout>
</Button.Flyout>
<ToolTipService.ToolTip>
<ToolTip x:Uid="PasswordGeneratorTooltip" />
</ToolTipService.ToolTip>
</Button>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources>
<controls:PasswordBoxWithButton x:Uid="PasswordGenerationButton"
Password="{Binding Password, Mode=TwoWay, ElementName=UserControl}"
IsPasswordRevealEnabled="True"
Style="{StaticResource PasswordBoxWithButtonStyle}"
IsEnabled="{Binding IsEnabled, ElementName=UserControl}"
PlaceholderText="{Binding PlaceholderText, ElementName=UserControl}"
Visibility="{Binding IsRevealPassword, Converter={StaticResource InverseBooleanToVisibilityConverter}}"
BorderBrush="{Binding BorderBrush, ElementName=UserControl}" />
<controls:TextBoxWithButton
x:Uid="PasswordTextBox"
Text="{Binding Password, Mode=TwoWay, ElementName=UserControl}"
Visibility="{Binding IsRevealPassword, Converter={StaticResource BooleanToVisibilityConverter}}"
Style="{StaticResource TextBoxWithButtonStyle}"
ButtonContent="&#xE16F;"
IsEnabled="{Binding IsEnabled, ElementName=UserControl}"
BorderBrush="{Binding BorderBrush, ElementName=UserControl}" >
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:ClipboardAction Text="{Binding Password}" />
<actions:ToastAction x:Uid="ToastCopyPassword" Title="Password" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</controls:TextBoxWithButton>
<ProgressBar
Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}"
Maximum="128"
Width="{Binding ActualWidth, ElementName=UserControl}"
Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroundBrushComplexityConverter}}" />
<ToggleSwitch x:Uid="EntryShowPassword" Margin="-3,-10,0,0" IsOn="{Binding IsRevealPassword, Mode=TwoWay}" />
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,44 @@
using Windows.UI.Xaml;
using ModernKeePass.ViewModels;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace ModernKeePass.Views.UserControls
{
public sealed partial class PasswordGenerationBox
{
public string Password
{
get { return (string)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.Register(
nameof(Password),
typeof(string),
typeof(PasswordGenerationBox),
new PropertyMetadata(string.Empty, (o, args) =>
{
var passwordGenerationBox = o as PasswordGenerationBox;
var vm = passwordGenerationBox?.StackPanel.DataContext as PasswordGenerationBoxControlVm;
if (vm != null) vm.Password = args.NewValue.ToString();
}));
public string PlaceholderText
{
get { return (string)GetValue(PlaceholderTextProperty); }
set { SetValue(PlaceholderTextProperty, value); }
}
public static readonly DependencyProperty PlaceholderTextProperty =
DependencyProperty.Register(
nameof(PlaceholderText),
typeof(string),
typeof(PasswordGenerationBox),
new PropertyMetadata(string.Empty, (o, args) => { }));
public PasswordGenerationBox()
{
InitializeComponent();
}
}
}

View File

@@ -7,10 +7,11 @@
xmlns:interactivity="using:Microsoft.Xaml.Interactivity" xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core" xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:converters="using:ModernKeePass.Converters" xmlns:converters="using:ModernKeePass.Converters"
xmlns:userControls="using:ModernKeePass.Views.UserControls"
mc:Ignorable="d"> mc:Ignorable="d">
<UserControl.Resources> <UserControl.Resources>
<converters:ProgressBarLegalValuesConverter x:Key="ProgressBarLegalValuesConverter"/> <!--<converters:ProgressBarLegalValuesConverter x:Key="ProgressBarLegalValuesConverter"/>
<converters:DoubleToSolidColorBrushConverter x:Key="DoubleToSolidColorBrushConverter"/> <converters:DoubleToSolidColorBrushConverter x:Key="DoubleToSolidColorBrushConverter"/>-->
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/> <converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
</UserControl.Resources> </UserControl.Resources>
<Grid DataContext="{Binding Source={StaticResource Locator}, Path=SetCredentials}"> <Grid DataContext="{Binding Source={StaticResource Locator}, Path=SetCredentials}">
@@ -23,30 +24,36 @@
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="45" /> <RowDefinition Height="Auto" />
<RowDefinition Height="45" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="40" /> <RowDefinition Height="40" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="40" /> <RowDefinition Height="40" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<CheckBox Grid.Row="0" Grid.Column="0" IsChecked="{Binding HasPassword, Mode=TwoWay}" /> <CheckBox Grid.Row="0" Grid.Column="0" IsChecked="{Binding HasPassword, Mode=TwoWay}" />
<PasswordBox Grid.Row="0" Grid.Column="1" Height="30" <!--<PasswordBox Grid.Row="0" Grid.Column="1" Height="30"
x:Uid="CompositeKeyPassword" x:Uid="CompositeKeyPassword"
x:Name="PasswordBox" x:Name="PasswordBox"
Password="{Binding Password, Mode=TwoWay}" Password="{Binding Password, Mode=TwoWay}"
IsEnabled="{Binding HasPassword}" IsEnabled="{Binding HasPassword}"
IsPasswordRevealButtonEnabled="True" /> IsPasswordRevealButtonEnabled="True" />-->
<PasswordBox Grid.Row="1" Grid.Column="1" Height="30" <userControls:PasswordGenerationBox Grid.Row="0" Grid.Column="1"
x:Uid="CompositeKeyPassword"
x:Name="PasswordBox"
Password="{Binding Password, Mode=TwoWay}"
IsEnabled="{Binding HasPassword}" />
<PasswordBox Grid.Row="1" Grid.Column="1"
x:Uid="CompositeKeyConfirmPassword" x:Uid="CompositeKeyConfirmPassword"
x:Name="ConfirmPasswordBox" x:Name="ConfirmPasswordBox"
Margin="0,5,0,0"
Password="{Binding ConfirmPassword, Mode=TwoWay}" Password="{Binding ConfirmPassword, Mode=TwoWay}"
IsEnabled="{Binding HasPassword}" IsEnabled="{Binding HasPassword}"
IsPasswordRevealButtonEnabled="True" /> IsPasswordRevealButtonEnabled="True" />
<ProgressBar Grid.Row="1" Grid.Column="1" <!--<ProgressBar Grid.Row="1" Grid.Column="1"
Maximum="128" VerticalAlignment="Bottom" Maximum="128" VerticalAlignment="Bottom"
Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}" Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}"
Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToSolidColorBrushConverter}}"/> Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToSolidColorBrushConverter}}"/>-->
<TextBlock Grid.Row="2" Grid.Column="1" <TextBlock Grid.Row="2" Grid.Column="1"
FontSize="14" FontWeight="Light" FontSize="14" FontWeight="Light"
x:Uid="SetCredentialsControlMatchingPasswords" x:Uid="SetCredentialsControlMatchingPasswords"
@@ -126,6 +133,9 @@
<core:DataTriggerBehavior Binding="{Binding IsKeyFileValid}" Value="True"> <core:DataTriggerBehavior Binding="{Binding IsKeyFileValid}" Value="True">
<core:GoToStateAction StateName="KeyFileValid"/> <core:GoToStateAction StateName="KeyFileValid"/>
</core:DataTriggerBehavior> </core:DataTriggerBehavior>
<core:EventTriggerBehavior EventName="Unloaded">
<core:CallMethodAction TargetObject="{Binding}" MethodName="Cleanup"/>
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
</Grid> </Grid>
</UserControl> </UserControl>

View File

@@ -98,7 +98,7 @@
</MenuFlyout> </MenuFlyout>
</Button.Flyout> </Button.Flyout>
</Button> </Button>
<ToggleButton Command="{Binding EditCommand, ElementName=UserControl}" IsChecked="{Binding IsEditButtonChecked, ElementName=UserControl, Mode=TwoWay}" Checked="EditButton_Click" Style="{StaticResource MenuToggleButtonStyle}"> <ToggleButton Visibility="{Binding EditButtonVisibility, ElementName=UserControl}" Command="{Binding EditCommand, ElementName=UserControl}" IsChecked="{Binding IsEditButtonChecked, ElementName=UserControl, Mode=TwoWay}" Checked="EditButton_Click" Style="{StaticResource MenuToggleButtonStyle}">
<SymbolIcon Symbol="Edit"> <SymbolIcon Symbol="Edit">
<ToolTipService.ToolTip> <ToolTipService.ToolTip>
<ToolTip x:Uid="TopMenuEditButton" /> <ToolTip x:Uid="TopMenuEditButton" />
@@ -151,7 +151,7 @@
<MenuFlyout Opening="OverflowFlyout_OnOpening"> <MenuFlyout Opening="OverflowFlyout_OnOpening">
<MenuFlyoutItem x:Uid="TopMenuSaveFlyout" x:Name="SaveFlyout" /> <MenuFlyoutItem x:Uid="TopMenuSaveFlyout" x:Name="SaveFlyout" />
<MenuFlyoutItem x:Uid="TopMenuRestoreFlyout" x:Name="RestoreFlyout" Visibility="{Binding RestoreButtonVisibility, ElementName=UserControl}" /> <MenuFlyoutItem x:Uid="TopMenuRestoreFlyout" x:Name="RestoreFlyout" Visibility="{Binding RestoreButtonVisibility, ElementName=UserControl}" />
<ToggleMenuFlyoutItem x:Uid="TopMenuEditFlyout" x:Name="EditFlyout" IsChecked="{Binding IsEditButtonChecked, ElementName=UserControl, Mode=TwoWay}" Click="EditButton_Click" /> <ToggleMenuFlyoutItem x:Uid="TopMenuEditFlyout" x:Name="EditFlyout" Visibility="{Binding EditButtonVisibility, ElementName=UserControl}" IsChecked="{Binding IsEditButtonChecked, ElementName=UserControl, Mode=TwoWay}" Click="EditButton_Click" />
<MenuFlyoutItem x:Uid="TopMenuDeleteFlyout" x:Name="DeleteFlyout" /> <MenuFlyoutItem x:Uid="TopMenuDeleteFlyout" x:Name="DeleteFlyout" />
<MenuFlyoutItem x:Uid="TopMenuSortEntriesFlyout" x:Name="SortEntriesFlyout" Visibility="{Binding SortButtonVisibility, ElementName=UserControl}" /> <MenuFlyoutItem x:Uid="TopMenuSortEntriesFlyout" x:Name="SortEntriesFlyout" Visibility="{Binding SortButtonVisibility, ElementName=UserControl}" />
<MenuFlyoutItem x:Uid="TopMenuSortGroupsFlyout" x:Name="SortGroupsFlyout" Visibility="{Binding SortButtonVisibility, ElementName=UserControl}" /> <MenuFlyoutItem x:Uid="TopMenuSortGroupsFlyout" x:Name="SortGroupsFlyout" Visibility="{Binding SortButtonVisibility, ElementName=UserControl}" />

View File

@@ -39,6 +39,18 @@ namespace ModernKeePass.Views.UserControls
typeof(TopMenuUserControl), typeof(TopMenuUserControl),
new PropertyMetadata(null, (o, args) => { })); new PropertyMetadata(null, (o, args) => { }));
public Visibility EditButtonVisibility
{
get { return (Visibility)GetValue(EditButtonVisibilityProperty); }
set { SetValue(EditButtonVisibilityProperty, value); }
}
public static readonly DependencyProperty EditButtonVisibilityProperty =
DependencyProperty.Register(
nameof(EditButtonVisibility),
typeof(Visibility),
typeof(TopMenuUserControl),
new PropertyMetadata(Visibility.Collapsed, (o, args) => { }));
public ICommand DeleteCommand public ICommand DeleteCommand
{ {
get { return (ICommand)GetValue(DeleteCommandProperty); } get { return (ICommand)GetValue(DeleteCommandProperty); }
@@ -213,8 +225,7 @@ namespace ModernKeePass.Views.UserControls
MoveButton.CommandParameter = args.Tag; MoveButton.CommandParameter = args.Tag;
MoveCommand.RaiseCanExecuteChanged(); MoveCommand.RaiseCanExecuteChanged();
} }
private async void EntrySearchBox_OnSuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args) private async void EntrySearchBox_OnSuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args)
{ {
var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appdata:/Assets/ModernKeePass-SmallLogo.scale-80.png")); var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appdata:/Assets/ModernKeePass-SmallLogo.scale-80.png"));

View File

@@ -15,7 +15,7 @@
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<PackageCertificateKeyFile>Win81App_StoreKey.pfx</PackageCertificateKeyFile> <PackageCertificateKeyFile>Win81App_StoreKey.pfx</PackageCertificateKeyFile>
<PackageCertificateThumbprint>2F2C96140E5F198DC331284960C96B3174A25070</PackageCertificateThumbprint> <PackageCertificateThumbprint>3C2433AEBC44667251EABCBFEBCE1A764FB3D544</PackageCertificateThumbprint>
<AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision> <AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
<AppxBundlePlatforms>x86|x64|arm</AppxBundlePlatforms> <AppxBundlePlatforms>x86|x64|arm</AppxBundlePlatforms>
<AppxBundle>Always</AppxBundle> <AppxBundle>Always</AppxBundle>
@@ -93,14 +93,15 @@
<DependentUpon>App.xaml</DependentUpon> <DependentUpon>App.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="DependencyInjection.cs" /> <Compile Include="DependencyInjection.cs" />
<Compile Include="Log\HockeyAppLog.cs" />
<Compile Include="Models\NavigationItem.cs" /> <Compile Include="Models\NavigationItem.cs" />
<Compile Include="ViewModels\ViewModelLocator.cs" /> <Compile Include="ViewModels\ViewModelLocator.cs" />
<Compile Include="Views\MainPageFrames\DonatePage.xaml.cs"> <Compile Include="Views\MainPageFrames\DonatePage.xaml.cs">
<DependentUpon>DonatePage.xaml</DependentUpon> <DependentUpon>DonatePage.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Views\BasePages\LayoutAwarePageBase.cs" /> <Compile Include="Views\BasePages\LayoutAwarePageBase.cs" />
<Compile Include="Views\MainPageFrames\ImportExportPage.xaml.cs"> <Compile Include="Views\MainPageFrames\ImportPage.xaml.cs">
<DependentUpon>ImportExportPage.xaml</DependentUpon> <DependentUpon>ImportPage.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Views\SettingsPageFrames\SettingsHistoryPage.xaml.cs"> <Compile Include="Views\SettingsPageFrames\SettingsHistoryPage.xaml.cs">
<DependentUpon>SettingsHistoryPage.xaml</DependentUpon> <DependentUpon>SettingsHistoryPage.xaml</DependentUpon>
@@ -123,6 +124,9 @@
<Compile Include="Views\SettingsPageFrames\SettingsWelcomePage.xaml.cs"> <Compile Include="Views\SettingsPageFrames\SettingsWelcomePage.xaml.cs">
<DependentUpon>SettingsWelcomePage.xaml</DependentUpon> <DependentUpon>SettingsWelcomePage.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Views\UserControls\BreadcrumbUserControl.xaml.cs">
<DependentUpon>BreadcrumbUserControl.xaml</DependentUpon>
</Compile>
<Compile Include="Views\UserControls\ColorPickerUserControl.xaml.cs"> <Compile Include="Views\UserControls\ColorPickerUserControl.xaml.cs">
<DependentUpon>ColorPickerUserControl.xaml</DependentUpon> <DependentUpon>ColorPickerUserControl.xaml</DependentUpon>
</Compile> </Compile>
@@ -167,6 +171,9 @@
<Compile Include="Views\UserControls\HamburgerMenuUserControl.xaml.cs"> <Compile Include="Views\UserControls\HamburgerMenuUserControl.xaml.cs">
<DependentUpon>HamburgerMenuUserControl.xaml</DependentUpon> <DependentUpon>HamburgerMenuUserControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Views\UserControls\PasswordGenerationBox.xaml.cs">
<DependentUpon>PasswordGenerationBox.xaml</DependentUpon>
</Compile>
<Compile Include="Views\UserControls\SymbolPickerUserControl.xaml.cs"> <Compile Include="Views\UserControls\SymbolPickerUserControl.xaml.cs">
<DependentUpon>SymbolPickerUserControl.xaml</DependentUpon> <DependentUpon>SymbolPickerUserControl.xaml</DependentUpon>
</Compile> </Compile>
@@ -185,10 +192,7 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
</None> </None>
<None Include="Win81App_StoreKey.pfx" /> <None Include="Win81App_StoreKey.pfx" />
<PRIResource Include="Strings\fr-FR\Resources.resw" /> <None Include="Win81App_TemporaryKey.pfx" />
<PRIResource Include="Strings\fr-FR\CodeBehind.resw" />
<PRIResource Include="Strings\en-US\CodeBehind.resw" />
<PRIResource Include="Strings\en-US\Resources.resw" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Package.StoreAssociation.xml" /> <None Include="Package.StoreAssociation.xml" />
@@ -203,7 +207,7 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page> </Page>
<Page Include="Views\MainPageFrames\ImportExportPage.xaml"> <Page Include="Views\MainPageFrames\ImportPage.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
@@ -219,6 +223,10 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Views\UserControls\BreadcrumbUserControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\UserControls\ColorPickerUserControl.xaml"> <Page Include="Views\UserControls\ColorPickerUserControl.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@@ -316,6 +324,10 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Views\UserControls\PasswordGenerationBox.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\UserControls\SymbolPickerUserControl.xaml"> <Page Include="Views\UserControls\SymbolPickerUserControl.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@@ -342,8 +354,8 @@
<HintPath>..\packages\Portable.BouncyCastle.1.8.5\lib\netstandard1.0\BouncyCastle.Crypto.dll</HintPath> <HintPath>..\packages\Portable.BouncyCastle.1.8.5\lib\netstandard1.0\BouncyCastle.Crypto.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="CommonServiceLocator, Version=2.0.5.0, Culture=neutral, PublicKeyToken=489b6accfaf20ef0, processorArchitecture=MSIL"> <Reference Include="CommonServiceLocator, Version=2.0.6.0, Culture=neutral, PublicKeyToken=489b6accfaf20ef0, processorArchitecture=MSIL">
<HintPath>..\packages\CommonServiceLocator.2.0.5\lib\netstandard1.0\CommonServiceLocator.dll</HintPath> <HintPath>..\packages\CommonServiceLocator.2.0.6\lib\netstandard1.0\CommonServiceLocator.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="FluentValidation, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7de548da2fbae0f0, processorArchitecture=MSIL"> <Reference Include="FluentValidation, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7de548da2fbae0f0, processorArchitecture=MSIL">

View File

@@ -1,8 +1 @@
Support for additional fields Fixed a duplication issue with additional fields
Support for attachments
Add an expiration timer for clipboard data
Ability to manually reorder groups
Ability to set max history count and size
Design changes
Update to KeePassLib version 2.45
Bug corrections

View File

@@ -1,8 +1 @@
Ajout des champs additionnels Correction d'un probleme de duplication des champs additionnels
Ajout des pi<70>ces-jointes
Ajout d'une expiration du presse papier
Possibilite de reorganiser les groupes manuellement
Possibilite de parametrer le nombre max et la taille de l'historique
Quelques changements de design
Mise a jour de la KeePassLib version 2.45
Correction de bugs

View File

@@ -2,7 +2,7 @@
<packages> <packages>
<package id="AutoMapper" version="5.2.0" targetFramework="win81" /> <package id="AutoMapper" version="5.2.0" targetFramework="win81" />
<package id="AutoMapper.Extensions.Microsoft.DependencyInjection" version="1.2.0" targetFramework="win81" /> <package id="AutoMapper.Extensions.Microsoft.DependencyInjection" version="1.2.0" targetFramework="win81" />
<package id="CommonServiceLocator" version="2.0.5" targetFramework="win81" /> <package id="CommonServiceLocator" version="2.0.6" targetFramework="win81" />
<package id="FluentValidation" version="8.6.2" targetFramework="win81" /> <package id="FluentValidation" version="8.6.2" targetFramework="win81" />
<package id="HockeySDK.Core" version="4.1.6" targetFramework="win81" /> <package id="HockeySDK.Core" version="4.1.6" targetFramework="win81" />
<package id="HockeySDK.WINRT" version="4.1.6" targetFramework="win81" /> <package id="HockeySDK.WINRT" version="4.1.6" targetFramework="win81" />
@@ -12,7 +12,7 @@
<package id="Microsoft.Extensions.DependencyInjection" version="1.1.1" targetFramework="win81" /> <package id="Microsoft.Extensions.DependencyInjection" version="1.1.1" targetFramework="win81" />
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="1.1.1" targetFramework="win81" /> <package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="1.1.1" targetFramework="win81" />
<package id="Microsoft.NETCore.Platforms" version="2.1.1" targetFramework="win81" /> <package id="Microsoft.NETCore.Platforms" version="2.1.1" targetFramework="win81" />
<package id="Microsoft.NETCore.Portable.Compatibility" version="1.0.1" targetFramework="win81" /> <package id="Microsoft.NETCore.Portable.Compatibility" version="1.0.2" targetFramework="win81" />
<package id="Microsoft.NETCore.UniversalWindowsPlatform" version="6.1.7" targetFramework="win81" /> <package id="Microsoft.NETCore.UniversalWindowsPlatform" version="6.1.7" targetFramework="win81" />
<package id="ModernKeePassLib" version="2.45.1" targetFramework="win81" /> <package id="ModernKeePassLib" version="2.45.1" targetFramework="win81" />
<package id="MvvmLight" version="5.4.1.1" targetFramework="win81" /> <package id="MvvmLight" version="5.4.1.1" targetFramework="win81" />

View File

@@ -159,8 +159,8 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="BouncyCastle.Crypto, Version=1.8.3.0, Culture=neutral, PublicKeyToken=0e99375e54769942, processorArchitecture=MSIL"> <Reference Include="BouncyCastle.Crypto, Version=1.8.5.0, Culture=neutral, PublicKeyToken=0e99375e54769942, processorArchitecture=MSIL">
<HintPath>..\packages\Portable.BouncyCastle.1.8.3\lib\netstandard1.0\BouncyCastle.Crypto.dll</HintPath> <HintPath>..\packages\Portable.BouncyCastle.1.8.5\lib\netstandard1.0\BouncyCastle.Crypto.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="ModernKeePassLib, Version=2.39.1.22027, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="ModernKeePassLib, Version=2.39.1.22027, Culture=neutral, processorArchitecture=MSIL">

View File

@@ -4,14 +4,14 @@
<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="ModernKeePassLib" version="2.39.1" targetFramework="win81" /> <package id="ModernKeePassLib" version="2.39.1" targetFramework="win81" />
<package id="NETStandard.Library" version="2.0.3" targetFramework="win81" /> <package id="NETStandard.Library" version="2.0.3" targetFramework="win81" />
<package id="Portable.BouncyCastle" version="1.8.3" targetFramework="win81" /> <package id="Portable.BouncyCastle" version="1.8.5" targetFramework="win81" />
<package id="Splat" version="3.0.0" targetFramework="win81" /> <package id="Splat" version="3.0.0" targetFramework="win81" />
<package id="System.Diagnostics.Contracts" version="4.3.0" targetFramework="win81" /> <package id="System.Diagnostics.Contracts" version="4.3.0" targetFramework="win81" />
<package id="System.Drawing.Primitives" version="4.3.0" targetFramework="win81" /> <package id="System.Drawing.Primitives" version="4.3.0" targetFramework="win81" />
<package id="System.Net.Requests" version="4.3.0" targetFramework="win81" /> <package id="System.Net.Requests" version="4.3.0" targetFramework="win81" />
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="win81" /> <package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="win81" />
<package id="System.Runtime.Serialization.Primitives" version="4.3.0" targetFramework="win81" /> <package id="System.Runtime.Serialization.Primitives" version="4.3.0" targetFramework="win81" />
<package id="System.Runtime.WindowsRuntime" version="4.3.0" targetFramework="win81" /> <package id="System.Runtime.WindowsRuntime" version="4.7.0" targetFramework="win81" />
<package id="System.Xml.XmlSerializer" version="4.3.0" targetFramework="win81" /> <package id="System.Xml.XmlSerializer" version="4.3.0" targetFramework="win81" />
<package id="Validation" version="2.4.18" targetFramework="win81" /> <package id="Validation" version="2.4.18" targetFramework="win81" />
</packages> </packages>

View File

@@ -1,5 +1,6 @@
using System; using System;
using Windows.ApplicationModel.DataTransfer; using Windows.ApplicationModel.DataTransfer;
using Windows.UI.Core;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Xaml.Interactivity; using Microsoft.Xaml.Interactivity;
@@ -10,7 +11,7 @@ namespace ModernKeePass.Actions
{ {
public class ClipboardAction : DependencyObject, IAction public class ClipboardAction : DependencyObject, IAction
{ {
private DispatcherTimer _dispatcher; private bool _isWindowActivated = true;
public string Text public string Text
{ {
@@ -19,29 +20,45 @@ namespace ModernKeePass.Actions
} }
public static readonly DependencyProperty TextProperty = public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(ClipboardAction), new PropertyMetadata(string.Empty)); DependencyProperty.Register(nameof(Text), typeof(string), typeof(ClipboardAction), new PropertyMetadata(string.Empty));
public bool IsProtected
{
get { return (bool)GetValue(IsProtectedProperty); }
set { SetValue(IsProtectedProperty, value); }
}
public static readonly DependencyProperty IsProtectedProperty =
DependencyProperty.Register(nameof(IsProtected), typeof(bool), typeof(ClipboardAction), new PropertyMetadata(false));
public object Execute(object sender, object parameter) public object Execute(object sender, object parameter)
{ {
if (string.IsNullOrEmpty(Text)) return null; if (string.IsNullOrEmpty(Text)) return null;
var settings = App.Services.GetRequiredService<ISettingsProxy>(); var settings = App.Services.GetRequiredService<ISettingsProxy>();
var cryptography = App.Services.GetRequiredService<ICryptographyClient>();
_dispatcher = new DispatcherTimer {Interval = TimeSpan.FromSeconds(settings.GetSetting(Constants.Settings.ClipboardTimeout, 10))}; CoreWindow.GetForCurrentThread().Activated += ClipboardAction_Activated;
_dispatcher.Tick += Dispatcher_Tick;
var dispatcher = new DispatcherTimer {Interval = TimeSpan.FromSeconds(settings.GetSetting(Constants.Settings.ClipboardTimeout, 10))};
dispatcher.Tick += Dispatcher_Tick;
var dataPackage = new DataPackage { RequestedOperation = DataPackageOperation.Copy }; var dataPackage = new DataPackage { RequestedOperation = DataPackageOperation.Copy };
dataPackage.SetText(Text); dataPackage.SetText(IsProtected ? cryptography.UnProtect(Text).GetAwaiter().GetResult() : Text);
Clipboard.SetContent(dataPackage); Clipboard.SetContent(dataPackage);
_dispatcher.Start(); Clipboard.Flush();
dispatcher.Start();
return null; return null;
} }
private void ClipboardAction_Activated(CoreWindow sender, WindowActivatedEventArgs args)
{
_isWindowActivated = args.WindowActivationState != CoreWindowActivationState.Deactivated;
}
private void Dispatcher_Tick(object sender, object e) private void Dispatcher_Tick(object sender, object e)
{ {
Clipboard.SetContent(null); if (_isWindowActivated) Clipboard.SetContent(null);
_dispatcher.Stop();
} }
} }
} }

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Windows.Foundation.Metadata;
using Windows.System; using Windows.System;
using Windows.UI.Core; using Windows.UI.Core;
using Windows.UI.Xaml; using Windows.UI.Xaml;
@@ -53,11 +54,11 @@ namespace ModernKeePass.Common
/// } /// }
/// </code> /// </code>
/// </example> /// </example>
[Windows.Foundation.Metadata.WebHostHidden] [WebHostHidden]
public class NavigationHelper : DependencyObject public class NavigationHelper : DependencyObject
{ {
private Page Page { get; set; } private Page Page { get; set; }
private Frame Frame { get { return this.Page.Frame; } } private Frame Frame => Page.Frame;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="NavigationHelper"/> class. /// Initializes a new instance of the <see cref="NavigationHelper"/> class.
@@ -67,31 +68,31 @@ namespace ModernKeePass.Common
/// navigation requests only occur when the page is occupying the entire window.</param> /// navigation requests only occur when the page is occupying the entire window.</param>
public NavigationHelper(Page page) public NavigationHelper(Page page)
{ {
this.Page = page; Page = page;
// When this page is part of the visual tree make two changes: // When this page is part of the visual tree make two changes:
// 1) Map application view state to visual state for the page // 1) Map application view state to visual state for the page
// 2) Handle hardware navigation requests // 2) Handle hardware navigation requests
this.Page.Loaded += (sender, e) => Page.Loaded += (sender, e) =>
{ {
#if WINDOWS_PHONE_APP #if WINDOWS_PHONE_APP
Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed; Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;
#else #else
// Keyboard and mouse navigation only apply when occupying the entire window // Keyboard and mouse navigation only apply when occupying the entire window
if (Page.ActualHeight == Window.Current.Bounds.Height && if (Page.ActualHeight.Equals(Window.Current.Bounds.Height) &&
Page.ActualWidth == Window.Current.Bounds.Width) Page.ActualWidth.Equals(Window.Current.Bounds.Width))
{ {
// Listen to the window directly so focus isn't required // Listen to the window directly so focus isn't required
Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated += Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated +=
CoreDispatcher_AcceleratorKeyActivated; CoreDispatcher_AcceleratorKeyActivated;
Window.Current.CoreWindow.PointerPressed += Window.Current.CoreWindow.PointerPressed +=
this.CoreWindow_PointerPressed; CoreWindow_PointerPressed;
} }
#endif #endif
}; };
// Undo the same changes when the page is no longer visible // Undo the same changes when the page is no longer visible
this.Page.Unloaded += (sender, e) => Page.Unloaded += (sender, e) =>
{ {
#if WINDOWS_PHONE_APP #if WINDOWS_PHONE_APP
Windows.Phone.UI.Input.HardwareButtons.BackPressed -= HardwareButtons_BackPressed; Windows.Phone.UI.Input.HardwareButtons.BackPressed -= HardwareButtons_BackPressed;
@@ -99,15 +100,15 @@ namespace ModernKeePass.Common
Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated -= Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated -=
CoreDispatcher_AcceleratorKeyActivated; CoreDispatcher_AcceleratorKeyActivated;
Window.Current.CoreWindow.PointerPressed -= Window.Current.CoreWindow.PointerPressed -=
this.CoreWindow_PointerPressed; CoreWindow_PointerPressed;
#endif #endif
}; };
} }
#region Navigation support #region Navigation support
RelayCommand _goBackCommand; private RelayCommand _goBackCommand;
RelayCommand _goForwardCommand; private RelayCommand _goForwardCommand;
/// <summary> /// <summary>
/// <see cref="RelayCommand"/> used to bind to the back Button's Command property /// <see cref="RelayCommand"/> used to bind to the back Button's Command property
@@ -119,21 +120,10 @@ namespace ModernKeePass.Common
/// </summary> /// </summary>
public RelayCommand GoBackCommand public RelayCommand GoBackCommand
{ {
get get { return _goBackCommand ?? (_goBackCommand = new RelayCommand(GoBack, CanGoBack)); }
{ set { _goBackCommand = value; }
if (_goBackCommand == null)
{
_goBackCommand = new RelayCommand(
() => this.GoBack(),
() => this.CanGoBack());
}
return _goBackCommand;
}
set
{
_goBackCommand = value;
}
} }
/// <summary> /// <summary>
/// <see cref="RelayCommand"/> used for navigating to the most recent item in /// <see cref="RelayCommand"/> used for navigating to the most recent item in
/// the forward navigation history, if a Frame manages its own navigation history. /// the forward navigation history, if a Frame manages its own navigation history.
@@ -141,19 +131,7 @@ namespace ModernKeePass.Common
/// The <see cref="RelayCommand"/> is set up to use the virtual method <see cref="GoForward"/> /// The <see cref="RelayCommand"/> is set up to use the virtual method <see cref="GoForward"/>
/// as the Execute Action and <see cref="CanGoForward"/> for CanExecute. /// as the Execute Action and <see cref="CanGoForward"/> for CanExecute.
/// </summary> /// </summary>
public RelayCommand GoForwardCommand public RelayCommand GoForwardCommand => _goForwardCommand ?? (_goForwardCommand = new RelayCommand(GoForward, CanGoForward));
{
get
{
if (_goForwardCommand == null)
{
_goForwardCommand = new RelayCommand(
() => this.GoForward(),
() => this.CanGoForward());
}
return _goForwardCommand;
}
}
/// <summary> /// <summary>
/// Virtual method used by the <see cref="GoBackCommand"/> property /// Virtual method used by the <see cref="GoBackCommand"/> property
@@ -165,8 +143,9 @@ namespace ModernKeePass.Common
/// </returns> /// </returns>
public virtual bool CanGoBack() public virtual bool CanGoBack()
{ {
return this.Frame != null && this.Frame.CanGoBack; return Frame != null && Frame.CanGoBack;
} }
/// <summary> /// <summary>
/// Virtual method used by the <see cref="GoForwardCommand"/> property /// Virtual method used by the <see cref="GoForwardCommand"/> property
/// to determine if the <see cref="Frame"/> can go forward. /// to determine if the <see cref="Frame"/> can go forward.
@@ -177,7 +156,7 @@ namespace ModernKeePass.Common
/// </returns> /// </returns>
public virtual bool CanGoForward() public virtual bool CanGoForward()
{ {
return this.Frame != null && this.Frame.CanGoForward; return Frame != null && Frame.CanGoForward;
} }
/// <summary> /// <summary>
@@ -186,15 +165,22 @@ namespace ModernKeePass.Common
/// </summary> /// </summary>
public virtual void GoBack() public virtual void GoBack()
{ {
if (this.Frame != null && this.Frame.CanGoBack) this.Frame.GoBack(); if (Frame != null && Frame.CanGoBack)
{
Frame.GoBack();
}
} }
/// <summary> /// <summary>
/// Virtual method used by the <see cref="GoForwardCommand"/> property /// Virtual method used by the <see cref="GoForwardCommand"/> property
/// to invoke the <see cref="Windows.UI.Xaml.Controls.Frame.GoForward"/> method. /// to invoke the <see cref="Windows.UI.Xaml.Controls.Frame.GoForward"/> method.
/// </summary> /// </summary>
public virtual void GoForward() public virtual void GoForward()
{ {
if (this.Frame != null && this.Frame.CanGoForward) this.Frame.GoForward(); if (Frame != null && Frame.CanGoForward)
{
Frame.GoForward();
}
} }
#if WINDOWS_PHONE_APP #if WINDOWS_PHONE_APP
@@ -220,38 +206,38 @@ namespace ModernKeePass.Common
/// <param name="sender">Instance that triggered the event.</param> /// <param name="sender">Instance that triggered the event.</param>
/// <param name="e">Event data describing the conditions that led to the event.</param> /// <param name="e">Event data describing the conditions that led to the event.</param>
private void CoreDispatcher_AcceleratorKeyActivated(CoreDispatcher sender, private void CoreDispatcher_AcceleratorKeyActivated(CoreDispatcher sender,
AcceleratorKeyEventArgs e) AcceleratorKeyEventArgs e)
{ {
var virtualKey = e.VirtualKey; var virtualKey = e.VirtualKey;
// Only investigate further when Left, Right, or the dedicated Previous or Next keys // Only investigate further when Left, Right, or the dedicated Previous or Next keys
// are pressed // are pressed
if ((e.EventType == CoreAcceleratorKeyEventType.SystemKeyDown || if ((e.EventType == CoreAcceleratorKeyEventType.SystemKeyDown ||
e.EventType == CoreAcceleratorKeyEventType.KeyDown) && e.EventType == CoreAcceleratorKeyEventType.KeyDown) &&
(virtualKey == VirtualKey.Left || virtualKey == VirtualKey.Right || (virtualKey == VirtualKey.Left || virtualKey == VirtualKey.Right ||
(int)virtualKey == 166 || (int)virtualKey == 167)) (int) virtualKey == 166 || (int) virtualKey == 167))
{ {
var coreWindow = Window.Current.CoreWindow; var coreWindow = Window.Current.CoreWindow;
var downState = CoreVirtualKeyStates.Down; const CoreVirtualKeyStates downState = CoreVirtualKeyStates.Down;
bool menuKey = (coreWindow.GetKeyState(VirtualKey.Menu) & downState) == downState; var menuKey = (coreWindow.GetKeyState(VirtualKey.Menu) & downState) == downState;
bool controlKey = (coreWindow.GetKeyState(VirtualKey.Control) & downState) == downState; var controlKey = (coreWindow.GetKeyState(VirtualKey.Control) & downState) == downState;
bool shiftKey = (coreWindow.GetKeyState(VirtualKey.Shift) & downState) == downState; var shiftKey = (coreWindow.GetKeyState(VirtualKey.Shift) & downState) == downState;
bool noModifiers = !menuKey && !controlKey && !shiftKey; var noModifiers = !menuKey && !controlKey && !shiftKey;
bool onlyAlt = menuKey && !controlKey && !shiftKey; var onlyAlt = menuKey && !controlKey && !shiftKey;
if (((int)virtualKey == 166 && noModifiers) || if ((int) virtualKey == 166 && noModifiers ||
(virtualKey == VirtualKey.Left && onlyAlt)) virtualKey == VirtualKey.Left && onlyAlt)
{ {
// When the previous key or Alt+Left are pressed navigate back // When the previous key or Alt+Left are pressed navigate back
e.Handled = true; e.Handled = true;
this.GoBackCommand.Execute(null); GoBackCommand.Execute(null);
} }
else if (((int)virtualKey == 167 && noModifiers) || else if ((int) virtualKey == 167 && noModifiers ||
(virtualKey == VirtualKey.Right && onlyAlt)) virtualKey == VirtualKey.Right && onlyAlt)
{ {
// When the next key or Alt+Right are pressed navigate forward // When the next key or Alt+Right are pressed navigate forward
e.Handled = true; e.Handled = true;
this.GoForwardCommand.Execute(null); GoForwardCommand.Execute(null);
} }
} }
} }
@@ -264,22 +250,32 @@ namespace ModernKeePass.Common
/// <param name="sender">Instance that triggered the event.</param> /// <param name="sender">Instance that triggered the event.</param>
/// <param name="e">Event data describing the conditions that led to the event.</param> /// <param name="e">Event data describing the conditions that led to the event.</param>
private void CoreWindow_PointerPressed(CoreWindow sender, private void CoreWindow_PointerPressed(CoreWindow sender,
PointerEventArgs e) PointerEventArgs e)
{ {
var properties = e.CurrentPoint.Properties; var properties = e.CurrentPoint.Properties;
// Ignore button chords with the left, right, and middle buttons // Ignore button chords with the left, right, and middle buttons
if (properties.IsLeftButtonPressed || properties.IsRightButtonPressed || if (properties.IsLeftButtonPressed || properties.IsRightButtonPressed ||
properties.IsMiddleButtonPressed) return; properties.IsMiddleButtonPressed)
{
return;
}
// If back or foward are pressed (but not both) navigate appropriately // If back or forward are pressed (but not both) navigate appropriately
bool backPressed = properties.IsXButton1Pressed; var backPressed = properties.IsXButton1Pressed;
bool forwardPressed = properties.IsXButton2Pressed; var forwardPressed = properties.IsXButton2Pressed;
if (backPressed ^ forwardPressed) if (backPressed ^ forwardPressed)
{ {
e.Handled = true; e.Handled = true;
if (backPressed) this.GoBackCommand.Execute(null); if (backPressed)
if (forwardPressed) this.GoForwardCommand.Execute(null); {
GoBackCommand.Execute(null);
}
if (forwardPressed)
{
GoForwardCommand.Execute(null);
}
} }
} }
#endif #endif
@@ -288,7 +284,7 @@ namespace ModernKeePass.Common
#region Process lifetime management #region Process lifetime management
private String _pageKey; private string _pageKey;
/// <summary> /// <summary>
/// Register this event on the current page to populate the page /// Register this event on the current page to populate the page
@@ -296,11 +292,12 @@ namespace ModernKeePass.Common
/// state provided when recreating a page from a prior session. /// state provided when recreating a page from a prior session.
/// </summary> /// </summary>
public event LoadStateEventHandler LoadState; public event LoadStateEventHandler LoadState;
/// <summary> /// <summary>
/// Register this event on the current page to preserve /// Register this event on the current page to preserve
/// state associated with the current page in case the /// state associated with the current page in case the
/// application is suspended or the page is discarded from /// application is suspended or the page is discarded from
/// the navigaqtion cache. /// the navigation cache.
/// </summary> /// </summary>
public event SaveStateEventHandler SaveState; public event SaveStateEventHandler SaveState;
@@ -313,15 +310,15 @@ namespace ModernKeePass.Common
/// property provides the group to be displayed.</param> /// property provides the group to be displayed.</param>
public void OnNavigatedTo(NavigationEventArgs e) public void OnNavigatedTo(NavigationEventArgs e)
{ {
var frameState = SuspensionManager.SessionStateForFrame(this.Frame); var frameState = SuspensionManager.SessionStateForFrame(Frame);
this._pageKey = "Page-" + this.Frame.BackStackDepth; _pageKey = "Page-" + Frame.BackStackDepth;
if (e.NavigationMode == NavigationMode.New) if (e.NavigationMode == NavigationMode.New)
{ {
// Clear existing state for forward navigation when adding a new page to the // Clear existing state for forward navigation when adding a new page to the
// navigation stack // navigation stack
var nextPageKey = this._pageKey; var nextPageKey = _pageKey;
int nextPageIndex = this.Frame.BackStackDepth; var nextPageIndex = Frame.BackStackDepth;
while (frameState.Remove(nextPageKey)) while (frameState.Remove(nextPageKey))
{ {
nextPageIndex++; nextPageIndex++;
@@ -329,20 +326,14 @@ namespace ModernKeePass.Common
} }
// Pass the navigation parameter to the new page // Pass the navigation parameter to the new page
if (this.LoadState != null) LoadState?.Invoke(this, new LoadStateEventArgs(e.Parameter, null));
{
this.LoadState(this, new LoadStateEventArgs(e.Parameter, null));
}
} }
else else
{ {
// Pass the navigation parameter and preserved page state to the page, using // Pass the navigation parameter and preserved page state to the page, using
// the same strategy for loading suspended state and recreating pages discarded // the same strategy for loading suspended state and recreating pages discarded
// from cache // from cache
if (this.LoadState != null) LoadState?.Invoke(this, new LoadStateEventArgs(e.Parameter, (Dictionary<string, object>) frameState[_pageKey]));
{
this.LoadState(this, new LoadStateEventArgs(e.Parameter, (Dictionary<String, Object>)frameState[this._pageKey]));
}
} }
} }
@@ -355,12 +346,9 @@ namespace ModernKeePass.Common
/// property provides the group to be displayed.</param> /// property provides the group to be displayed.</param>
public void OnNavigatedFrom(NavigationEventArgs e) public void OnNavigatedFrom(NavigationEventArgs e)
{ {
var frameState = SuspensionManager.SessionStateForFrame(this.Frame); var frameState = SuspensionManager.SessionStateForFrame(Frame);
var pageState = new Dictionary<String, Object>(); var pageState = new Dictionary<string, object>();
if (this.SaveState != null) SaveState?.Invoke(this, new SaveStateEventArgs(pageState));
{
this.SaveState(this, new SaveStateEventArgs(pageState));
}
frameState[_pageKey] = pageState; frameState[_pageKey] = pageState;
} }
@@ -371,6 +359,7 @@ namespace ModernKeePass.Common
/// Represents the method that will handle the <see cref="NavigationHelper.LoadState"/>event /// Represents the method that will handle the <see cref="NavigationHelper.LoadState"/>event
/// </summary> /// </summary>
public delegate void LoadStateEventHandler(object sender, LoadStateEventArgs e); public delegate void LoadStateEventHandler(object sender, LoadStateEventArgs e);
/// <summary> /// <summary>
/// Represents the method that will handle the <see cref="NavigationHelper.SaveState"/>event /// Represents the method that will handle the <see cref="NavigationHelper.SaveState"/>event
/// </summary> /// </summary>
@@ -382,34 +371,35 @@ namespace ModernKeePass.Common
public class LoadStateEventArgs : EventArgs public class LoadStateEventArgs : EventArgs
{ {
/// <summary> /// <summary>
/// The parameter value passed to <see cref="Frame.Navigate(Type, Object)"/> /// The parameter value passed to <see cref="Frame.Navigate(Type, object)"/>
/// when this page was initially requested. /// when this page was initially requested.
/// </summary> /// </summary>
public Object NavigationParameter { get; private set; } public object NavigationParameter { get; private set; }
/// <summary> /// <summary>
/// A dictionary of state preserved by this page during an earlier /// A dictionary of state preserved by this page during an earlier
/// session. This will be null the first time a page is visited. /// session. This will be null the first time a page is visited.
/// </summary> /// </summary>
public Dictionary<string, Object> PageState { get; private set; } public Dictionary<string, object> PageState { get; private set; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="LoadStateEventArgs"/> class. /// Initializes a new instance of the <see cref="LoadStateEventArgs"/> class.
/// </summary> /// </summary>
/// <param name="navigationParameter"> /// <param name="navigationParameter">
/// The parameter value passed to <see cref="Frame.Navigate(Type, Object)"/> /// The parameter value passed to <see cref="Frame.Navigate(Type, object)"/>
/// when this page was initially requested. /// when this page was initially requested.
/// </param> /// </param>
/// <param name="pageState"> /// <param name="pageState">
/// A dictionary of state preserved by this page during an earlier /// A dictionary of state preserved by this page during an earlier
/// session. This will be null the first time a page is visited. /// session. This will be null the first time a page is visited.
/// </param> /// </param>
public LoadStateEventArgs(Object navigationParameter, Dictionary<string, Object> pageState) public LoadStateEventArgs(object navigationParameter, Dictionary<string, object> pageState)
: base()
{ {
this.NavigationParameter = navigationParameter; NavigationParameter = navigationParameter;
this.PageState = pageState; PageState = pageState;
} }
} }
/// <summary> /// <summary>
/// Class used to hold the event data required when a page attempts to save state. /// Class used to hold the event data required when a page attempts to save state.
/// </summary> /// </summary>
@@ -418,16 +408,15 @@ namespace ModernKeePass.Common
/// <summary> /// <summary>
/// An empty dictionary to be populated with serializable state. /// An empty dictionary to be populated with serializable state.
/// </summary> /// </summary>
public Dictionary<string, Object> PageState { get; private set; } public Dictionary<string, object> PageState { get; private set; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SaveStateEventArgs"/> class. /// Initializes a new instance of the <see cref="SaveStateEventArgs"/> class.
/// </summary> /// </summary>
/// <param name="pageState">An empty dictionary to be populated with serializable state.</param> /// <param name="pageState">An empty dictionary to be populated with serializable state.</param>
public SaveStateEventArgs(Dictionary<string, Object> pageState) public SaveStateEventArgs(Dictionary<string, object> pageState)
: base()
{ {
this.PageState = pageState; PageState = pageState;
} }
} }
} }

View File

@@ -8,14 +8,14 @@ namespace ModernKeePass.Controls
{ {
public event EventHandler<RoutedEventArgs> ButtonClick; public event EventHandler<RoutedEventArgs> ButtonClick;
public string ButtonSymbol public string ButtonContent
{ {
get { return (string)GetValue(ButtonSymbolProperty); } get { return (string)GetValue(ButtonContentProperty); }
set { SetValue(ButtonSymbolProperty, value); } set { SetValue(ButtonContentProperty, value); }
} }
public static readonly DependencyProperty ButtonSymbolProperty = public static readonly DependencyProperty ButtonContentProperty =
DependencyProperty.Register( DependencyProperty.Register(
nameof(ButtonSymbol), nameof(ButtonContent),
typeof(string), typeof(string),
typeof(PasswordBoxWithButton), typeof(PasswordBoxWithButton),
new PropertyMetadata("&#xE107;", (o, args) => { })); new PropertyMetadata("&#xE107;", (o, args) => { }));

View File

@@ -0,0 +1,87 @@
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace ModernKeePass.Controls
{
public class PasswordGenerationBox : SearchBox
{
public event EventHandler<RoutedEventArgs> ButtonClick;
public string ButtonSymbol
{
get { return (string)GetValue(ButtonSymbolProperty); }
set { SetValue(ButtonSymbolProperty, value); }
}
public static readonly DependencyProperty ButtonSymbolProperty =
DependencyProperty.Register(
nameof(ButtonSymbol),
typeof(string),
typeof(PasswordGenerationBox),
new PropertyMetadata("&#xE107;", (o, args) => { }));
public string ButtonTooltip
{
get { return (string)GetValue(ButtonTooltipProperty); }
set { SetValue(ButtonTooltipProperty, value); }
}
public static readonly DependencyProperty ButtonTooltipProperty =
DependencyProperty.Register(
nameof(ButtonTooltip),
typeof(string),
typeof(PasswordGenerationBox),
new PropertyMetadata(string.Empty, (o, args) => { }));
public string Password
{
get { return (string)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.Register(
nameof(Password),
typeof(string),
typeof(PasswordGenerationBox),
new PropertyMetadata(string.Empty, (o, args) => { }));
public bool IsButtonEnabled
{
get { return (bool)GetValue(IsButtonEnabledProperty); }
set { SetValue(IsButtonEnabledProperty, value); }
}
public static readonly DependencyProperty IsButtonEnabledProperty =
DependencyProperty.Register(
nameof(IsButtonEnabled),
typeof(bool),
typeof(PasswordGenerationBox),
new PropertyMetadata(true, (o, args) => { }));
public bool IsPasswordRevealEnabled
{
get { return (bool)GetValue(IsPasswordRevealEnabledProperty); }
set { SetValue(IsPasswordRevealEnabledProperty, value); }
}
public static readonly DependencyProperty IsPasswordRevealEnabledProperty =
DependencyProperty.Register(
nameof(IsPasswordRevealEnabled),
typeof(bool),
typeof(PasswordGenerationBox),
new PropertyMetadata(true, (o, args) => { }));
public PasswordGenerationBox()
{
DefaultStyleKey = typeof(PasswordGenerationBox);
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
var actionButton = GetTemplateChild("ActionButton") as Button;
if (actionButton != null)
{
actionButton.Click += (sender, e) => ButtonClick?.Invoke(sender, e);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More