46 Commits
V1.17 ... V1.21

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
Geoffroy BONNEVILLE
7a2ce30512 Design improvements 2020-05-14 16:09:06 +02:00
Geoffroy BONNEVILLE
d497f69a5e Updated deleted text information
Improved dirty status detection (restored removed variable...)
This corrected history creation on navigation when entry deleted
2020-05-14 13:32:44 +02:00
Geoffroy BONNEVILLE
72e5bf4ee1 Added a cryptography service to encrypt protected information (unused atm)
Corrected a bug when deleting recycle bin
2020-05-14 12:05:05 +02:00
Geoffroy BONNEVILLE
2e01fa2212 Changed tooltip styles
Removed useless isdirty field in entry
When an app can't be saved on suspend, don't reopen it to avoid possible de-sync
2020-05-13 18:59:26 +02:00
Geoffroy BONNEVILLE
0adb44bc81 Some design changes
Again fixed open url bug
2020-05-13 15:14:58 +02:00
Geoffroy BONNEVILLE
d38d6461bd Updated Settings page
Added new settings (history and clipboard)
Renamed and moved Settings Vms
2020-05-13 13:50:33 +02:00
Geoffroy BONNEVILLE
7ac1595aaa Clipboard action now sets an expiration timer
WIP Max History count (back-end done, front-end todo)
2020-05-12 18:43:37 +02:00
Geoffroy BONNEVILLE
f8f7c19f65 Display a big database size warning
Auto rename additional field when it matches standard
Treated all fields as new Field class
Added the Is Protected property
2020-05-12 17:14:30 +02:00
Geoffroy BONNEVILLE
d6dc6a74a3 Groups can now also be manually reordered
Design improvements
2020-05-11 19:22:41 +02:00
Geoffroy BONNEVILLE
bb2b99ed66 Additional fields Add, Update and Delete work (too well)
SelectableListView works when programmatically setting selection
2020-05-11 10:53:14 +02:00
Geoffroy BONNEVILLE
71b6009a29 Remove some useless code (again)
Improve some visuals
2020-05-07 19:10:25 +02:00
Geoffroy BONNEVILLE
fbcc354809 Additional fields rendering done
Removed lots of unused classes
2020-05-07 16:01:59 +02:00
Geoffroy BONNEVILLE
e901afaf29 Attachment Add and Delete commands implemented 2020-05-07 12:11:12 +02:00
Geoffroy BONNEVILLE
ca04a6c8ee Entry page is now a Hub
EntryDetailVM and GroupDetailVM are now singleton
Read-only Additional fields and Attachments
2020-05-06 18:54:39 +02:00
183 changed files with 3965 additions and 33933 deletions

2
.gitignore vendored
View File

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

View File

@@ -36,6 +36,16 @@
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
</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' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
@@ -77,31 +87,42 @@
<ItemGroup>
<Compile Include="Common\Behaviors\DirtyStatusBehavior.cs" />
<Compile Include="Common\Interfaces\ICryptographyClient.cs" />
<Compile Include="Common\Interfaces\IDatabaseSettingsProxy.cs" />
<Compile Include="Common\Interfaces\IDatabaseProxy.cs" />
<Compile Include="Common\Interfaces\IEntityVm.cs" />
<Compile Include="Common\Interfaces\IFileProxy.cs" />
<Compile Include="Common\Interfaces\IImportFormat.cs" />
<Compile Include="Common\Interfaces\ICredentialsProxy.cs" />
<Compile Include="Common\Interfaces\ILogger.cs" />
<Compile Include="Common\Interfaces\INotificationService.cs" />
<Compile Include="Common\Interfaces\IRecentProxy.cs" />
<Compile Include="Common\Interfaces\IResourceProxy.cs" />
<Compile Include="Common\Interfaces\ISettingsProxy.cs" />
<Compile Include="Common\Mappings\IMapFrom.cs" />
<Compile Include="Common\Mappings\MappingProfile.cs" />
<Compile Include="Common\Models\BreadcrumbItem.cs" />
<Compile Include="Entry\Commands\AddAttachment\AddAttachmentCommand.cs" />
<Compile Include="Entry\Commands\AddHistory\AddHistoryCommand.cs" />
<Compile Include="Entry\Commands\DeleteAttachment\DeleteAttachmentCommand.cs" />
<Compile Include="Entry\Commands\DeleteField\DeleteFieldCommand.cs" />
<Compile Include="Entry\Commands\DeleteHistory\DeleteHistoryCommand.cs" />
<Compile Include="Entry\Commands\RestoreHistory\RestoreHistoryCommand.cs" />
<Compile Include="Entry\Models\FieldVm.cs" />
<Compile Include="Entry\Queries\GetEntry\GetEntryQuery.cs" />
<Compile Include="Group\Commands\DeleteEntry\DeleteEntryCommand.cs" />
<Compile Include="Group\Commands\DeleteGroup\DeleteGroupCommand.cs" />
<Compile Include="Group\Commands\MoveGroup\MoveGroupCommand.cs" />
<Compile Include="Group\Commands\UpdateGroup\UpdateGroupCommand.cs" />
<Compile Include="Group\Queries\GetAllGroups\GetAllGroupsQuery.cs" />
<Compile Include="Group\Queries\GetGroup\GetGroupQuery.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\SetCompression\SetCompressionCommand.cs" />
<Compile Include="Parameters\Commands\SetHasRecycleBin\SetHasRecycleBinCommand.cs" />
<Compile Include="Parameters\Commands\SetMaxHistoryCount\SetHistoryCountCommand.cs" />
<Compile Include="Parameters\Commands\SetKeyDerivation\SetKeyDerivationCommand.cs" />
<Compile Include="Parameters\Commands\SetMaxHistorySize\SetMaxHistorySizeCommand.cs" />
<Compile Include="Parameters\Commands\SetRecycleBin\SetRecycleBinCommand.cs" />
<Compile Include="Parameters\Models\CipherVm.cs" />
<Compile Include="Parameters\Models\KeyDerivationVm.cs" />
@@ -110,7 +131,7 @@
<Compile Include="Parameters\Queries\GetKeyDerivations\GetKeyDerivationsQuery.cs" />
<Compile Include="Database\Commands\CloseDatabase\CloseDatabaseCommand.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\UpdateCredentials\UpdateCredentialsCommand.cs" />
<Compile Include="Database\Models\DatabaseVm.cs" />
@@ -119,8 +140,8 @@
<Compile Include="Database\Queries\OpenDatabase\OpenDatabaseQueryValidator.cs" />
<Compile Include="Database\Queries\ReOpenDatabase\ReOpenDatabaseQuery.cs" />
<Compile Include="DependencyInjection.cs" />
<Compile Include="Entry\Commands\SetFieldValue\SetFieldValueCommand.cs" />
<Compile Include="Entry\Commands\SetFieldValue\SetFieldValueCommandValidator.cs" />
<Compile Include="Entry\Commands\UpsertField\UpsertFieldCommand.cs" />
<Compile Include="Entry\Commands\UpsertField\UpsertFieldCommandValidator.cs" />
<Compile Include="Entry\Models\EntryVm.cs" />
<Compile Include="Group\Commands\AddEntry\AddEntryCommand.cs" />
<Compile Include="Group\Commands\AddGroup\AddGroupCommand.cs" />

View File

@@ -1,12 +1,11 @@
using System.Collections.Generic;
using ModernKeePass.Domain.Entities;
using System.Threading.Tasks;
namespace ModernKeePass.Application.Common.Interfaces
{
public interface ICryptographyClient
{
IEnumerable<BaseEntity> Ciphers { get; }
IEnumerable<BaseEntity> KeyDerivations { get; }
IEnumerable<string> CompressionAlgorithms { get; }
Task<string> Protect(string value);
Task<string> UnProtect(string value);
byte[] Random(uint length);
}
}

View File

@@ -22,6 +22,8 @@ namespace ModernKeePass.Application.Common.Interfaces
string FileAccessToken { get; set; }
int Size { get; set; }
bool IsDirty { get; set; }
int MaxHistoryCount { get; set; }
long MaxHistorySize { get; set; }
Task Open(byte[] file, Credentials credentials);
Task ReOpen(byte[] file);
@@ -31,19 +33,25 @@ namespace ModernKeePass.Application.Common.Interfaces
void CloseDatabase();
EntryEntity GetEntry(string id);
GroupEntity GetGroup(string id);
Task AddEntry(string parentGroupId, string entryId);
Task MoveEntry(string parentGroupId, string entryId, int index);
Task AddGroup(string parentGroupId, string groupId);
void UpdateEntry(string entryId, string fieldName, object fieldValue);
void UpdateGroup(GroupEntity group);
Task UpdateEntry(string entryId, string fieldName, object fieldValue, bool isProtected);
void DeleteField(string entryId, string fieldName);
Task RemoveEntry(string parentGroupId, string entryId);
EntryEntity CreateEntry(string parentGroupId);
void SortEntries(string groupId);
GroupEntity GetGroup(string id);
Task AddGroup(string parentGroupId, string groupId);
Task MoveGroup(string parentGroupId, string groupId, int index);
void UpdateGroup(GroupEntity group);
Task RemoveGroup(string parentGroupId, string groupId);
void DeleteEntity(string entityId);
EntryEntity CreateEntry(string parentGroupId);
GroupEntity CreateGroup(string parentGroupId, string name, bool isRecycleBin = false);
void SortEntries(string groupId);
void SortSubGroups(string groupId);
void AddAttachment(string entryId, string attachmentName, byte[] attachmentContent);
void DeleteAttachment(string entryId, string attachmentName);
EntryEntity AddHistory(string entryId);
EntryEntity RestoreFromHistory(string entryId, int historyIndex);

View File

@@ -0,0 +1,12 @@
using System.Collections.Generic;
using ModernKeePass.Domain.Entities;
namespace ModernKeePass.Application.Common.Interfaces
{
public interface IDatabaseSettingsProxy
{
IEnumerable<BaseEntity> Ciphers { get; }
IEnumerable<BaseEntity> KeyDerivations { get; }
IEnumerable<string> CompressionAlgorithms { get; }
}
}

View File

@@ -5,7 +5,6 @@ namespace ModernKeePass.Application.Common.Interfaces
public interface IEntityVm
{
string Id { get; set; }
string Title { get; set; }
Icon Icon { get; set; }
string ParentGroupId { get; set; }
string ParentGroupName { get; set; }

View File

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

@@ -17,6 +17,8 @@ namespace ModernKeePass.Application.Database.Commands.CloseDatabase
public void Handle(CloseDatabaseCommand message)
{
if (!_database.IsOpen) throw new DatabaseClosedException();
// Prevent reopening the database due to possible de-synchronization between app and data
if (_database.IsDirty) _database.FileAccessToken = null;
_database.CloseDatabase();
}
}

View File

@@ -64,17 +64,17 @@ namespace ModernKeePass.Application.Database.Commands.CreateDatabase
_database.UpdateGroup(internetGroup);
var sample1 = _database.CreateEntry(_database.RootGroupId);
_database.UpdateEntry(sample1.Id, EntryFieldName.Title, "Sample Entry" );
_database.UpdateEntry(sample1.Id, EntryFieldName.UserName, "Username" );
_database.UpdateEntry(sample1.Id, EntryFieldName.Password, "Password" );
_database.UpdateEntry(sample1.Id, EntryFieldName.Url, "https://keepass.info/" );
_database.UpdateEntry(sample1.Id, EntryFieldName.Notes, "You may safely delete this sample" );
await _database.UpdateEntry(sample1.Id, EntryFieldName.Title, "Sample Entry", false);
await _database.UpdateEntry(sample1.Id, EntryFieldName.UserName, "Username", false);
await _database.UpdateEntry(sample1.Id, EntryFieldName.Password, "Password", true);
await _database.UpdateEntry(sample1.Id, EntryFieldName.Url, "https://keepass.info/", false);
await _database.UpdateEntry(sample1.Id, EntryFieldName.Notes, "You may safely delete this sample", false);
var sample2 = _database.CreateEntry(_database.RootGroupId);
_database.UpdateEntry(sample2.Id, EntryFieldName.Title, "Sample Entry #2" );
_database.UpdateEntry(sample2.Id, EntryFieldName.UserName, "Michael321" );
_database.UpdateEntry(sample2.Id, EntryFieldName.Password, "12345" );
_database.UpdateEntry(sample2.Id, EntryFieldName.Url, "https://keepass.info/help/kb/testform.html" );
await _database.UpdateEntry(sample2.Id, EntryFieldName.Title, "Sample Entry #2", false);
await _database.UpdateEntry(sample2.Id, EntryFieldName.UserName, "Michael321", false);
await _database.UpdateEntry(sample2.Id, EntryFieldName.Password, "12345", true);
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
{
public class CreateDatabaseQueryValidator : AbstractValidator<CreateDatabaseCommand>
public class CreateDatabaseCommandValidator : AbstractValidator<CreateDatabaseCommand>
{
public CreateDatabaseQueryValidator()
public CreateDatabaseCommandValidator()
{
RuleFor(v => v.FilePath)
.NotNull()

View File

@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using MediatR;
using System.Threading.Tasks;
using ModernKeePass.Application.Common.Interfaces;
@@ -14,11 +16,13 @@ namespace ModernKeePass.Application.Database.Commands.SaveDatabase
{
private readonly IDatabaseProxy _database;
private readonly IFileProxy _file;
private readonly ILogger _logger;
public SaveDatabaseCommandHandler(IDatabaseProxy database, IFileProxy file)
public SaveDatabaseCommandHandler(IDatabaseProxy database, IFileProxy file, ILogger logger)
{
_database = database;
_file = file;
_logger = logger;
}
public async Task Handle(SaveDatabaseCommand message)
@@ -27,6 +31,7 @@ namespace ModernKeePass.Application.Database.Commands.SaveDatabase
try
{
var timeToSave = Stopwatch.StartNew();
if (!string.IsNullOrEmpty(message.FilePath))
{
_database.FileAccessToken = message.FilePath;
@@ -40,6 +45,13 @@ namespace ModernKeePass.Application.Database.Commands.SaveDatabase
// Transactional write to file
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)
{

View File

@@ -12,5 +12,7 @@
public string KeyDerivationId { get; set; }
public int Size { get; internal set; }
public bool IsDirty { get; internal set; }
public int MaxHistoryCount { get; set; }
public long MaxHistorySize { get; set; }
}
}

View File

@@ -33,6 +33,8 @@ namespace ModernKeePass.Application.Database.Queries.GetDatabase
database.KeyDerivationId = _databaseProxy.KeyDerivationId;
database.Size = _databaseProxy.Size;
database.IsDirty = _databaseProxy.IsDirty;
database.MaxHistoryCount = _databaseProxy.MaxHistoryCount;
database.MaxHistorySize = _databaseProxy.MaxHistorySize;
}
return database;
}

View File

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

View File

@@ -0,0 +1,34 @@
using System;
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Entry.Models;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Entry.Commands.AddAttachment
{
public class AddAttachmentCommand : IRequest
{
public EntryVm Entry { get; set; }
public string AttachmentName { get; set; }
public byte[] AttachmentContent { get; set; }
public class AddAttachmentCommandHandler : IRequestHandler<AddAttachmentCommand>
{
private readonly IDatabaseProxy _database;
public AddAttachmentCommandHandler(IDatabaseProxy database)
{
_database = database;
}
public void Handle(AddAttachmentCommand message)
{
if (!_database.IsOpen) throw new DatabaseClosedException();
if (message.Entry.Attachments.ContainsKey(message.AttachmentName)) throw new ArgumentException("AttachmentAlreadyExists", nameof(message.AttachmentName));
_database.AddAttachment(message.Entry.Id, message.AttachmentName, message.AttachmentContent);
message.Entry.Attachments.Add(message.AttachmentName, message.AttachmentContent);
}
}
}
}

View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Entry.Models;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Entry.Commands.DeleteAttachment
{
public class DeleteAttachmentCommand : IRequest
{
public EntryVm Entry { get; set; }
public string AttachmentName { get; set; }
public class DeleteAttachmentCommandHandler : IRequestHandler<DeleteAttachmentCommand>
{
private readonly IDatabaseProxy _database;
public DeleteAttachmentCommandHandler(IDatabaseProxy database)
{
_database = database;
}
public void Handle(DeleteAttachmentCommand message)
{
if (!_database.IsOpen) throw new DatabaseClosedException();
if (!message.Entry.Attachments.ContainsKey(message.AttachmentName)) throw new KeyNotFoundException("AttachmentDoesntExist");
_database.DeleteAttachment(message.Entry.Id, message.AttachmentName);
message.Entry.Attachments.Remove(message.AttachmentName);
}
}
}
}

View File

@@ -0,0 +1,29 @@
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Entry.Commands.DeleteField
{
public class DeleteFieldCommand: IRequest
{
public string EntryId { get; set; }
public string FieldName { get; set; }
public class DeleteFieldCommandHandler : IRequestHandler<DeleteFieldCommand>
{
private readonly IDatabaseProxy _database;
public DeleteFieldCommandHandler(IDatabaseProxy database)
{
_database = database;
}
public void Handle(DeleteFieldCommand message)
{
if (!_database.IsOpen) throw new DatabaseClosedException();
_database.DeleteField(message.EntryId, message.FieldName);
}
}
}
}

View File

@@ -1,30 +0,0 @@
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Entry.Commands.SetFieldValue
{
public class SetFieldValueCommand : IRequest
{
public string EntryId { get; set; }
public string FieldName { get; set; }
public object FieldValue { get; set; }
public class SetFieldValueCommandHandler : IRequestHandler<SetFieldValueCommand>
{
private readonly IDatabaseProxy _database;
public SetFieldValueCommandHandler(IDatabaseProxy database)
{
_database = database;
}
public void Handle(SetFieldValueCommand message)
{
if (!_database.IsOpen) throw new DatabaseClosedException();
_database.UpdateEntry(message.EntryId, message.FieldName, message.FieldValue);
}
}
}
}

View File

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

View File

@@ -1,10 +1,10 @@
using FluentValidation;
namespace ModernKeePass.Application.Entry.Commands.SetFieldValue
namespace ModernKeePass.Application.Entry.Commands.UpsertField
{
public class SetFieldValueCommandValidator: AbstractValidator<SetFieldValueCommand>
public class UpsertFieldCommandValidator: AbstractValidator<UpsertFieldCommand>
{
public SetFieldValueCommandValidator()
public UpsertFieldCommandValidator()
{
RuleFor(v => v.EntryId)
.NotNull()

View File

@@ -15,13 +15,13 @@ namespace ModernKeePass.Application.Entry.Models
public string ParentGroupId { get; set; }
public string ParentGroupName { get; set; }
public string Id { get; set; }
public string Title { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string Notes { get; set; }
public string Url { get; set; }
public bool HasUrl => !string.IsNullOrEmpty(Url);
public Dictionary<string, string> AdditionalFields { get; set; }
public FieldVm Title { get; set; }
public FieldVm Username { get; set; }
public FieldVm Password { get; set; }
public FieldVm Notes { get; set; }
public FieldVm Url { get; set; }
public bool IsValidUrl => Uri.IsWellFormedUriString(Url.Value, UriKind.Absolute);
public List<FieldVm> AdditionalFields { get; set; }
public List<EntryVm> History { get; set; }
public Icon Icon { get; set; }
public Color ForegroundColor { get; set; }
@@ -29,6 +29,7 @@ namespace ModernKeePass.Application.Entry.Models
public bool HasExpirationDate { get; set; }
public DateTimeOffset ExpirationDate { get; set; }
public DateTimeOffset ModificationDate { get; set; }
public Dictionary<string, byte[]> Attachments { get; set; }
public override string ToString()
{
@@ -38,22 +39,20 @@ namespace ModernKeePass.Application.Entry.Models
public void Mapping(Profile profile)
{
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.Name))
.ForMember(d => d.Username, opts => opts.MapFrom(s => s.UserName))
.ForMember(d => d.Password, opts => opts.MapFrom(s => s.Password))
.ForMember(d => d.Url, opts => opts.MapFrom(s => s.Url))
.ForMember(d => d.Notes, opts => opts.MapFrom(s => s.Notes))
.ForMember(d => d.AdditionalFields, opts => opts.MapFrom(s => s.AdditionalFields))
.ForMember(d => d.Title, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f =>
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 =>
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 =>
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 =>
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 =>
f.Name.Equals(EntryFieldName.Notes, StringComparison.Ordinal)) ?? new FieldEntity { Name = EntryFieldName.Notes, IsProtected = false } ))
.ForMember(d => d.AdditionalFields, opts => opts.MapFrom(s =>
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.HasExpirationDate, opts => opts.MapFrom(s => s.HasExpirationDate))
.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.Icon, opts => opts.MapFrom(s => s.HasExpirationDate && s.ExpirationDate < DateTimeOffset.Now ? Icon.ReportHacked : s.Icon));
}
}
}

View File

@@ -0,0 +1,20 @@
using AutoMapper;
using ModernKeePass.Application.Common.Mappings;
using ModernKeePass.Domain.Entities;
namespace ModernKeePass.Application.Entry.Models
{
public class FieldVm: IMapFrom<FieldEntity>
{
public string Name { get; set; }
public string Value { get; set; }
public bool IsProtected { get; set; }
public override string ToString() => Value;
public void Mapping(Profile profile)
{
profile.CreateMap<FieldEntity, FieldVm>();
}
}
}

View File

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

View File

@@ -25,12 +25,13 @@ namespace ModernKeePass.Application.Group.Commands.DeleteGroup
{
if (!_database.IsOpen) throw new DatabaseClosedException();
var isRecycleBin = message.GroupId.Equals(_database.RecycleBinId);
if (_database.IsRecycleBinEnabled && (string.IsNullOrEmpty(_database.RecycleBinId) || _database.RecycleBinId.Equals(Constants.EmptyId)))
{
_database.CreateGroup(_database.RootGroupId, message.RecycleBinName, true);
}
if (!_database.IsRecycleBinEnabled || message.ParentGroupId.Equals(_database.RecycleBinId))
if (!_database.IsRecycleBinEnabled || message.ParentGroupId.Equals(_database.RecycleBinId) || isRecycleBin)
{
_database.DeleteEntity(message.GroupId);
}
@@ -40,6 +41,7 @@ namespace ModernKeePass.Application.Group.Commands.DeleteGroup
}
await _database.RemoveGroup(message.ParentGroupId, message.GroupId);
if (isRecycleBin) _database.RecycleBinId = Constants.EmptyId;
}
}
}

View File

@@ -0,0 +1,33 @@
using System.Threading.Tasks;
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Group.Commands.MoveGroup
{
public class MoveGroupCommand : IRequest
{
public GroupVm ParentGroup { get; set; }
public GroupVm Group { get; set; }
public int Index { get; set; }
public class MoveGroupCommandHandler : IAsyncRequestHandler<MoveGroupCommand>
{
private readonly IDatabaseProxy _database;
public MoveGroupCommandHandler(IDatabaseProxy database)
{
_database = database;
}
public async Task Handle(MoveGroupCommand message)
{
if (!_database.IsOpen) throw new DatabaseClosedException();
await _database.MoveGroup(message.ParentGroup.Id, message.Group.Id, message.Index);
message.ParentGroup.Groups.Insert(message.Index, message.Group);
}
}
}
}

View File

@@ -24,7 +24,7 @@ namespace ModernKeePass.Application.Group.Commands.SortEntries
if (!_database.IsOpen) throw new DatabaseClosedException();
_database.SortEntries(message.Group.Id);
message.Group.Entries = message.Group.Entries.OrderBy(e => e.Title).ToList();
message.Group.Entries = message.Group.Entries.OrderBy(e => e.Title.Value).ToList();
}
}
}

View File

@@ -24,7 +24,7 @@ namespace ModernKeePass.Application.Group.Commands.SortGroups
if (!_database.IsOpen) throw new DatabaseClosedException();
_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 Title { 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 override string ToString()
@@ -26,13 +26,7 @@ namespace ModernKeePass.Application.Group.Models
public void Mapping(Profile profile)
{
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.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);
}
}

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

@@ -0,0 +1,27 @@
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Parameters.Commands.SetMaxHistoryCount
{
public class SetMaxHistoryCountCommand : IRequest
{
public int MaxHistoryCount { get; set; }
public class SetMaxHistoryCountCommandHandler : IRequestHandler<SetMaxHistoryCountCommand>
{
private readonly IDatabaseProxy _database;
public SetMaxHistoryCountCommandHandler(IDatabaseProxy database)
{
_database = database;
}
public void Handle(SetMaxHistoryCountCommand message)
{
if (_database.IsOpen) _database.MaxHistoryCount = message.MaxHistoryCount;
else throw new DatabaseClosedException();
}
}
}
}

View File

@@ -0,0 +1,28 @@
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Parameters.Commands.SetMaxHistorySize
{
public class SetMaxHistorySizeCommand : IRequest
{
public long MaxHistorySize { get; set; }
public class SetMaxHistorySizeCommandHandler : IRequestHandler<SetMaxHistorySizeCommand>
{
private readonly IDatabaseProxy _database;
public SetMaxHistorySizeCommandHandler(IDatabaseProxy database)
{
_database = database;
}
public void Handle(SetMaxHistorySizeCommand message)
{
if (_database.IsOpen) _database.MaxHistorySize = message.MaxHistorySize;
else throw new DatabaseClosedException();
}
}
}
}

View File

@@ -10,16 +10,16 @@ namespace ModernKeePass.Application.Parameters.Queries.GetCiphers
{
public class GetCiphersQueryHandler: IRequestHandler<GetCiphersQuery, IEnumerable<CipherVm>>
{
private readonly ICryptographyClient _cryptography;
private readonly IDatabaseSettingsProxy _databaseSettings;
public GetCiphersQueryHandler(ICryptographyClient cryptography)
public GetCiphersQueryHandler(IDatabaseSettingsProxy databaseSettings)
{
_cryptography = cryptography;
_databaseSettings = databaseSettings;
}
public IEnumerable<CipherVm> Handle(GetCiphersQuery message)
{
return _cryptography.Ciphers.Select(c => new CipherVm
return _databaseSettings.Ciphers.Select(c => new CipherVm
{
Id = c.Id,
Name = c.Name

View File

@@ -9,16 +9,16 @@ namespace ModernKeePass.Application.Parameters.Queries.GetCompressions
{
public class GetCompressionsQueryHandler : IRequestHandler<GetCompressionsQuery, IEnumerable<string>>
{
private readonly ICryptographyClient _cryptography;
private readonly IDatabaseSettingsProxy _databaseSettings;
public GetCompressionsQueryHandler(ICryptographyClient cryptography)
public GetCompressionsQueryHandler(IDatabaseSettingsProxy databaseSettings)
{
_cryptography = cryptography;
_databaseSettings = databaseSettings;
}
public IEnumerable<string> Handle(GetCompressionsQuery message)
{
return _cryptography.CompressionAlgorithms.OrderBy(c => c);
return _databaseSettings.CompressionAlgorithms.OrderBy(c => c);
}
}
}

View File

@@ -10,16 +10,16 @@ namespace ModernKeePass.Application.Parameters.Queries.GetKeyDerivations
{
public class GetKeyDerivationsQueryHandler : IRequestHandler<GetKeyDerivationsQuery, IEnumerable<KeyDerivationVm>>
{
private readonly ICryptographyClient _cryptography;
private readonly IDatabaseSettingsProxy _databaseSettings;
public GetKeyDerivationsQueryHandler(ICryptographyClient cryptography)
public GetKeyDerivationsQueryHandler(IDatabaseSettingsProxy databaseSettings)
{
_cryptography = cryptography;
_databaseSettings = databaseSettings;
}
public IEnumerable<KeyDerivationVm> Handle(GetKeyDerivationsQuery message)
{
return _cryptography.KeyDerivations.Select(c => new KeyDerivationVm
return _databaseSettings.KeyDerivations.Select(c => new KeyDerivationVm
{
Id = c.Id,
Name = c.Name

View File

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

View File

@@ -6,7 +6,7 @@
"MediatR": "3.0.1",
"MediatR.Extensions.Microsoft.DependencyInjection": "2.0.0",
"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",
"Splat": "3.0.0"
},

View File

@@ -36,6 +36,16 @@
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
</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' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
@@ -76,11 +86,13 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Common\Constants.cs" />
<Compile Include="Dtos\Attachment.cs" />
<Compile Include="Dtos\Credentials.cs" />
<Compile Include="Dtos\FileInfo.cs" />
<Compile Include="Dtos\PasswordGenerationOptions.cs" />
<Compile Include="Entities\BaseEntity.cs" />
<Compile Include="Entities\EntryEntity.cs" />
<Compile Include="Entities\FieldEntity.cs" />
<Compile Include="Entities\GroupEntity.cs" />
<Compile Include="Enums\CredentialStatusTypes.cs" />
<Compile Include="Enums\DatabaseVersion.cs" />

View File

@@ -0,0 +1,8 @@
namespace ModernKeePass.Domain.Dtos
{
public class Attachment
{
public string Name { get; set; }
public byte[] Content { get; set; }
}
}

View File

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

View File

@@ -7,13 +7,10 @@ namespace ModernKeePass.Domain.Entities
{
public class EntryEntity: BaseEntity
{
public string UserName { get; set; }
public string Password { get; set; }
public string Url { get; set; }
public string Notes { get; set; }
public DateTimeOffset ExpirationDate { get; set; }
public Dictionary<string, string> AdditionalFields { get; set; } = new Dictionary<string, string>();
public IEnumerable<FieldEntity> Fields { get; set; } = new List<FieldEntity>();
public IEnumerable<EntryEntity> History { get; set; } = new List<EntryEntity>();
public Dictionary<string, byte[]> Attachments { get; set; } = new Dictionary<string, byte[]>();
public DateTimeOffset ExpirationDate { get; set; }
public Icon Icon { get; set; }
public Color ForegroundColor { get; set; }
public Color BackgroundColor { get; set; }

View File

@@ -0,0 +1,9 @@
namespace ModernKeePass.Domain.Entities
{
public class FieldEntity
{
public string Name { get; set; }
public string Value { get; set; }
public bool IsProtected { get; set; }
}
}

View File

@@ -5,7 +5,7 @@ namespace ModernKeePass.Domain.Entities
{
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 Icon Icon { get; set; }
}

View File

@@ -1,16 +1,32 @@
namespace ModernKeePass.Domain.Enums
using System.Collections.Generic;
namespace ModernKeePass.Domain.Enums
{
public static class EntryFieldName
{
public const string Title = nameof(Title);
public const string UserName = nameof(UserName);
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 Icon = nameof(Icon);
public const string ExpirationDate = nameof(ExpirationDate);
public const string HasExpirationDate = nameof(HasExpirationDate);
public const string BackgroundColor = nameof(BackgroundColor);
public const string ForegroundColor = nameof(ForegroundColor);
public static IEnumerable<string> StandardFieldNames => new[]
{
Title,
UserName,
Password,
Url,
Notes,
Icon,
ExpirationDate,
HasExpirationDate,
BackgroundColor,
ForegroundColor
};
}
}

View File

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

View File

@@ -18,7 +18,7 @@ namespace ModernKeePass.Infrastructure
public static IServiceCollection AddInfrastructureKeePass(this IServiceCollection services)
{
services.AddSingleton(typeof(IDatabaseProxy), typeof(KeePassDatabaseClient));
services.AddTransient(typeof(ICryptographyClient), typeof(KeePassCryptographyClient));
services.AddTransient(typeof(IDatabaseSettingsProxy), typeof(KeePassDatabaseSettingsProxy));
services.AddTransient(typeof(ICredentialsProxy), typeof(KeePassCredentialsClient));
return services;
}
@@ -29,6 +29,7 @@ namespace ModernKeePass.Infrastructure
services.AddTransient(typeof(ISettingsProxy), typeof(UwpSettingsClient));
services.AddTransient(typeof(IRecentProxy), typeof(UwpRecentFilesClient));
services.AddTransient(typeof(IResourceProxy), typeof(UwpResourceClient));
services.AddTransient(typeof(ICryptographyClient), typeof(UwpCryptographyClient));
services.AddTransient(typeof(INotificationService), typeof(ToastNotificationService));
return services;
}

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>
<PlatformTarget>x64</PlatformTarget>
</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' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
@@ -78,17 +88,15 @@
<ItemGroup>
<Compile Include="Common\MachineDateTime.cs" />
<Compile Include="DependencyInjection.cs" />
<Compile Include="File\CsvImportFormat.cs" />
<Compile Include="KeePass\EntryFieldMapper.cs" />
<Compile Include="KeePass\EntryMappingProfile.cs" />
<Compile Include="KeePass\GroupMappingProfile.cs" />
<Compile Include="KeePass\MappingProfiles.cs" />
<Compile Include="KeePass\IconMapper.cs" />
<Compile Include="KeePass\KeePassCryptographyClient.cs" />
<Compile Include="KeePass\KeePassDatabaseSettingsProxy.cs" />
<Compile Include="KeePass\KeePassDatabaseClient.cs" />
<Compile Include="KeePass\KeePassCredentialsClient.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UWP\StorageFileClient.cs" />
<Compile Include="UWP\ToastNotificationService.cs" />
<Compile Include="UWP\UwpCryptographyClient.cs" />
<Compile Include="UWP\UwpRecentFilesClient.cs" />
<Compile Include="UWP\UwpResourceClient.cs" />
<Compile Include="UWP\UwpSettingsClient.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

@@ -1,35 +0,0 @@
using System;
using System.Linq;
using AutoMapper;
using ModernKeePass.Domain.Entities;
using ModernKeePassLib;
namespace ModernKeePass.Infrastructure.KeePass
{
public class EntryMappingProfile: Profile
{
public EntryMappingProfile()
{
CreateMap<PwEntry, EntryEntity>()
.ForMember(dest => dest.ParentId, 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.Name, opt => opt.MapFrom(src => GetEntryValue(src, PwDefs.TitleField)))
.ForMember(dest => dest.UserName, opt => opt.MapFrom(src => GetEntryValue(src, PwDefs.UserNameField)))
.ForMember(dest => dest.Password, opt => opt.MapFrom(src => GetEntryValue(src, PwDefs.PasswordField)))
.ForMember(dest => dest.Url, opt => opt.MapFrom(src => GetEntryValue(src, PwDefs.UrlField)))
.ForMember(dest => dest.Notes, opt => opt.MapFrom(src => GetEntryValue(src, PwDefs.NotesField)))
.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.HasExpirationDate, opt => opt.MapFrom(src => src.Expires))
.ForMember(dest => dest.Icon, opt => opt.MapFrom(src => IconMapper.MapPwIconToIcon(src.IconId)))
.ForMember(dest => dest.AdditionalFields, opt => opt.MapFrom(src =>
src.Strings.Where(s => !PwDefs.GetStandardFields().Contains(s.Key))
.ToDictionary(s => s.Key, s => GetEntryValue(src, s.Key))))
.ForMember(dest => dest.LastModificationDate, opt => opt.MapFrom(src => new DateTimeOffset(src.LastModificationTime)));
}
private string GetEntryValue(PwEntry entry, string key) => entry.Strings.GetSafe(key).ReadString();
}
}

View File

@@ -1,23 +0,0 @@
using AutoMapper;
using ModernKeePass.Domain.Entities;
using ModernKeePassLib;
namespace ModernKeePass.Infrastructure.KeePass
{
public class GroupMappingProfile : Profile
{
public GroupMappingProfile()
{
CreateMap<PwGroup, GroupEntity>()
.ForMember(d => d.ParentId, 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.Name, opts => opts.MapFrom(s => s.Name))
.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.Entries, opts => opts.MapFrom(s => s.Entries))
.ForMember(d => d.SubGroups, opts => opts.MapFrom(s => s.Groups))
.MaxDepth(2);
}
}
}

View File

@@ -25,6 +25,7 @@ namespace ModernKeePass.Infrastructure.KeePass
{
private readonly IMapper _mapper;
private readonly IDateTime _dateTime;
private readonly ICryptographyClient _cryptography;
private readonly PwDatabase _pwDatabase = new PwDatabase();
private Credentials _credentials;
// Flag: Has Dispose already been called?
@@ -40,6 +41,18 @@ namespace ModernKeePass.Infrastructure.KeePass
public int Size { get; set; }
public bool IsDirty { get; set; }
public int MaxHistoryCount
{
get { return _pwDatabase.HistoryMaxItems; }
set { _pwDatabase.HistoryMaxItems = value; }
}
public long MaxHistorySize
{
get { return _pwDatabase.HistoryMaxSize; }
set { _pwDatabase.HistoryMaxSize = value; }
}
// Settings
public bool IsRecycleBinEnabled
{
@@ -82,10 +95,11 @@ namespace ModernKeePass.Infrastructure.KeePass
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;
_dateTime = dateTime;
_cryptography = cryptography;
}
public async Task Open(byte[] file, Credentials credentials)
@@ -189,6 +203,20 @@ namespace ModernKeePass.Infrastructure.KeePass
parentPwGroup.AddGroup(pwGroup, true);
});
}
public async Task MoveGroup(string parentGroupId, string groupId, int index)
{
await Task.Run(() =>
{
var parentPwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(parentGroupId), true);
var pwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(groupId), true);
var currentIndex = (uint)parentPwGroup.Groups.IndexOf(pwGroup);
parentPwGroup.Groups.RemoveAt(currentIndex);
parentPwGroup.Groups.Insert((uint)index, pwGroup);
});
}
public async Task RemoveEntry(string parentGroupId, string entryId)
{
await Task.Run(() =>
@@ -214,19 +242,12 @@ namespace ModernKeePass.Infrastructure.KeePass
_pwDatabase.DeletedObjects.Add(new PwDeletedObject(BuildIdFromString(entityId), _dateTime.Now));
}
public void UpdateEntry(string entryId, string fieldName, object fieldValue)
public async Task UpdateEntry(string entryId, string fieldName, object fieldValue, bool isProtected)
{
var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
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(true, fieldValue.ToString()));
break;
case EntryFieldName.HasExpirationDate:
pwEntry.Expires = (bool)fieldValue;
break;
@@ -242,9 +263,20 @@ namespace ModernKeePass.Infrastructure.KeePass
case EntryFieldName.ForegroundColor:
pwEntry.ForegroundColor = (Color)fieldValue;
break;
default:
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;
}
}
public void DeleteField(string entryId, string fieldName)
{
var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
pwEntry.Strings.Remove(fieldName);
}
public EntryEntity AddHistory(string entryId)
{
var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
@@ -306,6 +338,18 @@ namespace ModernKeePass.Infrastructure.KeePass
var pwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(groupId), true);
pwGroup.SortSubGroups(false);
}
public void AddAttachment(string entryId, string attachmentName, byte[] attachmentContent)
{
var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
pwEntry.Binaries.Set(attachmentName, new ProtectedBinary(true, attachmentContent));
}
public void DeleteAttachment(string entryId, string attachmentName)
{
var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
pwEntry.Binaries.Remove(attachmentName);
}
public EntryEntity GetEntry(string id)
{
@@ -347,7 +391,7 @@ namespace ModernKeePass.Infrastructure.KeePass
{
Id = g.Uuid.ToHexString(),
Name = g.Name,
ParentName = g.ParentGroup?.Name
ParentGroupName = g.ParentGroup?.Name
});
return groups;
}

View File

@@ -9,7 +9,7 @@ using ModernKeePassLib.Cryptography.KeyDerivation;
namespace ModernKeePass.Infrastructure.KeePass
{
public class KeePassCryptographyClient: ICryptographyClient
public class KeePassDatabaseSettingsProxy: IDatabaseSettingsProxy
{
public IEnumerable<BaseEntity> Ciphers
{

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.Entities;
using ModernKeePassLib;
using ModernKeePassLib.Security;
namespace ModernKeePass.Infrastructure.KeePass
{
public class MappingProfiles: Profile
{
public MappingProfiles()
{
CreateMap<KeyValuePair<string, ProtectedString>, FieldEntity>()
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Key))
.ForMember(dest => dest.Value, opt => opt.ResolveUsing<ProtectedStringResolver>())
.ForMember(dest => dest.IsProtected, opt => opt.MapFrom(src => src.Value.IsProtected));
CreateMap<PwEntry, EntryEntity>()
.ForMember(dest => dest.ParentGroupId, opt => opt.MapFrom(src => src.ParentGroup.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.ExpirationDate, opt => opt.MapFrom(src => new DateTimeOffset(src.ExpiryTime)))
.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.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()) )));
CreateMap<PwGroup, GroupEntity>()
.ForMember(d => d.ParentGroupId, opts => opts.MapFrom(s => s.ParentGroup.Uuid.ToHexString()))
.ForMember(d => d.Id, opts => opts.MapFrom(s => s.Uuid.ToHexString()))
.ForMember(d => d.Icon, opts => opts.MapFrom(s => IconMapper.MapPwIconToIcon(s.IconId)))
.ForMember(d => d.ModificationDate, opts => opts.MapFrom(s => s.LastModificationTime))
.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;
}
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)
{
StorageApplicationPermissions.FutureAccessList.Remove(path);

View File

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

View File

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

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

@@ -32,17 +32,17 @@ namespace ModernKeePass
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App
{
{ public static IServiceProvider Services { get; private set; }
private readonly IResourceProxy _resource;
private readonly IMediator _mediator;
private readonly ISettingsProxy _settings;
private readonly INavigationService _navigation;
private readonly IHockeyClient _hockey;
private readonly INotificationService _notification;
private readonly IFileProxy _file;
private readonly IMessenger _messenger;
public static IServiceProvider Services { get; private set; }
private readonly ILogger _log;
private readonly IHockeyClient _hockey;
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
@@ -64,6 +64,7 @@ namespace ModernKeePass
_settings = Services.GetService<ISettingsProxy>();
_navigation = Services.GetService<INavigationService>();
_notification = Services.GetService<INotificationService>();
_log = Services.GetService<ILogger>();
_hockey = Services.GetService<IHockeyClient>();
_file = Services.GetService<IFileProxy>();
_messenger = Services.GetService<IMessenger>();
@@ -94,8 +95,7 @@ namespace ModernKeePass
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
_hockey.TrackException(e.Exception);
_hockey.Flush();
_log.LogError(e.Exception);
}
/// <summary>
@@ -166,14 +166,6 @@ namespace ModernKeePass
#if DEBUG
_notification.Show("App resumed", "Nothing to do, no previous database opened");
#endif
}
catch (Exception ex)
{
_hockey.TrackException(ex);
_hockey.Flush();
}
finally
{
_navigation.NavigateTo(Constants.Navigation.MainPage);
}
}
@@ -214,12 +206,11 @@ namespace ModernKeePass
}
catch (SaveException ex)
{
_notification.Show(_resource.GetResourceValue("MessageDialogSaveErrorTitle"), ex.Message);
_notification.Show(ex.Source, ex.Message);
}
catch (Exception ex)
{
_hockey.TrackException(ex);
_hockey.Flush();
await _log.LogError(ex);
}
finally
{

View File

@@ -4,8 +4,10 @@ using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Views;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.HockeyApp;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Common;
using ModernKeePass.Views;
using ModernKeePass.Log;
namespace ModernKeePass
{
@@ -37,6 +39,7 @@ namespace ModernKeePass
#endif
return HockeyClient.Current;
});
services.AddSingleton(typeof(ILogger), typeof(HockeyAppLog));
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>
<PackageInfo>
<OsMinVersion>6.3.0.0</OsMinVersion>
<PackageArchitecture>Neutral</PackageArchitecture>
<PackageMaxArchitectureVersion>1.15.2557.0</PackageMaxArchitectureVersion>
<PackageArchitecture>X64</PackageArchitecture>
<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>
<OsMinVersion>6.3.0.0</OsMinVersion>
<PackageArchitecture>Neutral</PackageArchitecture>
<PackageMaxArchitectureVersion>1.15.2557.0</PackageMaxArchitectureVersion>
<PackageMaxArchitectureVersion>1.20.640.0</PackageMaxArchitectureVersion>
</PackageInfo>
<PackageInfo>
<OsMinVersion>6.3.0.0</OsMinVersion>
<PackageArchitecture>Neutral</PackageArchitecture>
<PackageMaxArchitectureVersion>1.15.2557.0</PackageMaxArchitectureVersion>
<PackageMaxArchitectureVersion>1.20.640.0</PackageMaxArchitectureVersion>
</PackageInfo>
<PackageInfo>
<OsMinVersion>6.3.0.0</OsMinVersion>
<PackageArchitecture>Neutral</PackageArchitecture>
<PackageMaxArchitectureVersion>1.15.2557.0</PackageMaxArchitectureVersion>
<PackageMaxArchitectureVersion>1.20.640.0</PackageMaxArchitectureVersion>
</PackageInfo>
</BundleInfo>
</PackageInfoList>

View File

@@ -1,6 +1,6 @@
<?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">
<Identity Name="wismna.ModernKeePass" Publisher="CN=0719A91A-C322-4EE0-A257-E60733EECF06" Version="1.17.0.12" />
<Identity Name="wismna.ModernKeePass" Publisher="CN=0719A91A-C322-4EE0-A257-E60733EECF06" Version="1.21.0.22" />
<Properties>
<DisplayName>ModernKeePass</DisplayName>
<PublisherDisplayName>wismna</PublisherDisplayName>

View File

@@ -191,7 +191,7 @@
To="1" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="contentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource MainColor}" />
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListViewItemSelectedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
@@ -358,13 +358,13 @@
</Grid>
</Border>
<Border x:Name="SelectedLeftIndicator"
BorderBrush="{StaticResource MainColor}"
BorderBrush="{ThemeResource MainColorBrush}"
BorderThickness="5,0,0,0"
Opacity="0"/>
<Rectangle x:Name="SelectedBorder"
IsHitTestVisible="False"
Opacity="0"
Stroke="{StaticResource MainColor}"
Stroke="{ThemeResource MainColorBrush}"
StrokeThickness="{ThemeResource ListViewItemSelectedBorderThemeThickness}"
Margin="0" />
<Border x:Name="SelectedCheckMarkOuter"
@@ -373,7 +373,7 @@
VerticalAlignment="Top"
Margin="4">
<Grid x:Name="SelectedCheckMark" Opacity="0" Height="40" Width="40">
<Path x:Name="SelectedEarmark" Data="M0,0 L40,0 L40,40 z" Fill="{StaticResource MainColor}" Stretch="Fill"/>
<Path x:Name="SelectedEarmark" Data="M0,0 L40,0 L40,40 z" Fill="{ThemeResource MainColorBrush}" Stretch="Fill"/>
<Path Data="F1 M133.1,17.9 L137.2,13.2 L144.6,19.6 L156.4,5.8 L161.2,9.9 L145.6,28.4 z" Fill="{ThemeResource ListViewItemCheckThemeBrush}" Height="13" Stretch="Fill" Width="15" HorizontalAlignment="Right" Margin="0,5.5,5.5,0" VerticalAlignment="Top" FlowDirection="LeftToRight"/>
</Grid>
</Border>

View File

@@ -5,10 +5,10 @@
<!-- Common theme values -->
<x:Double x:Key="MenuWidth">60</x:Double>
<x:Double x:Key="MenuHeight">40</x:Double>
<x:Double x:Key="ExpandedMenuSize">300</x:Double>
<x:Double x:Key="ExpandedMenuSize">250</x:Double>
<GridLength x:Key="MenuHeightGridLength">40</GridLength>
<GridLength x:Key="MenuWidthGridLength">60</GridLength>
<GridLength x:Key="ExpandedMenuGridLength">300</GridLength>
<GridLength x:Key="ExpandedMenuGridLength">250</GridLength>
<Color x:Key="MainColor">SlateBlue</Color>
<Color x:Key="MainColorLight">MediumPurple</Color>
@@ -16,17 +16,22 @@
<Color x:Key="TextColorLight">WhiteSmoke</Color>
<Color x:Key="BorderColor">DarkGray</Color>
<Color x:Key="FlyoutColor">#FFF0F0F0</Color>
<Color x:Key="HubSectionColor">#FF777777</Color>
<SolidColorBrush x:Key="MainColorBrush" Color="{ThemeResource MainColor}" />
<SolidColorBrush x:Key="MainColorLightBrush" Color="{ThemeResource MainColorLight}" />
<SolidColorBrush x:Key="MainColorDarkBrush" Color="{ThemeResource MainColorDark}" />
<SolidColorBrush x:Key="TextColorLightBrush" Color="{ThemeResource TextColorLight}" />
<SolidColorBrush x:Key="HubSectionBrush" Color="{ThemeResource HubSectionColor}" />
<Style TargetType="TextBlock" x:Key="TextBlockSettingsHeaderStyle" >
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontSize" Value="16" />
<Setter Property="FontWeight" Value="SemiLight" />
</Style>
<Style TargetType="HyperlinkButton">
<Setter Property="FontWeight" Value="SemiLight" />
</Style>
<SolidColorBrush x:Key="TextBoxBorderThemeBrush" Color="{ThemeResource BorderColor}" />
<SolidColorBrush x:Key="TextSelectionHighlightColorThemeBrush" Color="{ThemeResource MainColor}" />
@@ -42,7 +47,6 @@
<SolidColorBrush x:Key="HyperlinkForegroundThemeBrush" Color="{ThemeResource MainColor}" />
<SolidColorBrush x:Key="HyperlinkPointerOverForegroundThemeBrush" Color="{ThemeResource MainColorLight}" />
<!--<SolidColorBrush x:Key="SearchBoxPointerOverBorderThemeBrush" Color="{ThemeResource MainColorLight}" />-->
<SolidColorBrush x:Key="SearchBoxPointerOverTextThemeBrush" Color="{ThemeResource MainColorLight}" />
<SolidColorBrush x:Key="SearchBoxBorderThemeBrush" Color="{ThemeResource BorderColor}" />
<SolidColorBrush x:Key="SearchBoxFocusedBorderThemeBrush" Color="{ThemeResource MainColor}" />
@@ -81,4 +85,8 @@
<Thickness x:Key="FlyoutBorderThemeThickness">0</Thickness>
<SolidColorBrush x:Key="FlyoutBorderThemeBrush" Color="{ThemeResource FlyoutColor}" />
<SolidColorBrush x:Key="FlyoutBackgroundThemeBrush" Color="{ThemeResource FlyoutColor}" />
<Thickness x:Key="ToolTipBorderThemeThickness">0</Thickness>
<SolidColorBrush x:Key="ToolTipBorderThemeBrush" Color="{ThemeResource FlyoutColor}" />
<SolidColorBrush x:Key="ToolTipBackgroundThemeBrush" Color="{ThemeResource FlyoutColor}" />
</ResourceDictionary>

View File

@@ -8,14 +8,11 @@
<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="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="Width" Value="350" />
<Setter Property="Height" Value="32" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Typography.StylisticSet20" Value="True"/>
<Setter Property="Template">
<Setter.Value>
@@ -299,8 +296,7 @@
FontSize="{TemplateBinding FontSize}"
Grid.Column="1"
Style="{StaticResource ActionButtonStyle}"
Content="{TemplateBinding ButtonSymbol}"
IsEnabled="{TemplateBinding IsButtonEnabled}"
Content="{TemplateBinding ButtonContent}"
Command="{TemplateBinding ButtonCommand}"
CommandParameter="{TemplateBinding ButtonCommandParameter}">
<ToolTipService.ToolTip>

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
@@ -14,72 +13,57 @@ using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Database.Commands.SaveDatabase;
using ModernKeePass.Application.Database.Models;
using ModernKeePass.Application.Database.Queries.GetDatabase;
using ModernKeePass.Application.Entry.Commands.AddAttachment;
using ModernKeePass.Application.Entry.Commands.AddHistory;
using ModernKeePass.Application.Entry.Commands.DeleteAttachment;
using ModernKeePass.Application.Entry.Commands.DeleteField;
using ModernKeePass.Application.Entry.Commands.DeleteHistory;
using ModernKeePass.Application.Entry.Commands.RestoreHistory;
using ModernKeePass.Application.Entry.Commands.SetFieldValue;
using ModernKeePass.Application.Entry.Commands.UpsertField;
using ModernKeePass.Application.Entry.Models;
using ModernKeePass.Application.Entry.Queries.GetEntry;
using ModernKeePass.Application.Group.Commands.AddEntry;
using ModernKeePass.Application.Group.Commands.DeleteEntry;
using ModernKeePass.Application.Group.Commands.RemoveEntry;
using ModernKeePass.Application.Group.Queries.GetGroup;
using ModernKeePass.Application.Security.Commands.GeneratePassword;
using ModernKeePass.Application.Security.Queries.EstimatePasswordComplexity;
using ModernKeePass.Domain.Enums;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Common;
using ModernKeePass.Domain.Dtos;
using ModernKeePass.Domain.Exceptions;
using ModernKeePass.Domain.Interfaces;
using ModernKeePass.Extensions;
using ModernKeePass.Models;
using ModernKeePass.ViewModels.ListItems;
namespace ModernKeePass.ViewModels
{
public class EntryDetailVm : ViewModelBase
{
public bool IsRevealPasswordEnabled => !string.IsNullOrEmpty(Password);
public bool HasExpired => HasExpirationDate && ExpiryDate < DateTime.Now;
public double PasswordComplexityIndicator => _mediator.Send(new EstimatePasswordComplexityQuery {Password = Password}).GetAwaiter().GetResult();
public bool UpperCasePatternSelected { get; set; } = true;
public bool LowerCasePatternSelected { get; set; } = true;
public bool DigitsPatternSelected { get; set; } = true;
public bool MinusPatternSelected { get; set; }
public bool UnderscorePatternSelected { get; set; }
public bool SpacePatternSelected { get; set; }
public bool SpecialPatternSelected { get; set; }
public bool BracketsPatternSelected { get; set; }
public string CustomChars { get; set; } = string.Empty;
public bool HasExpired => HasExpirationDate && ExpiryDate < _dateTime.Now;
public string Id => _current.Id;
public string Id => SelectedItem.Id;
public string ParentGroupName => _parent.Title;
public GroupVm Parent { get; private set; }
public bool IsRecycleOnDelete
{
get
{
var database = Database;
return database.IsRecycleBinEnabled && _parent.Id != database.RecycleBinId;
return database.IsRecycleBinEnabled && Parent.Id != database.RecycleBinId;
}
}
public IEnumerable<GroupVm> BreadCrumb => new List<GroupVm> { _parent };
public ObservableCollection<EntryVm> History { get; private set; }
public ObservableCollection<IEntityVm> History { get; private set; }
public ObservableCollection<EntryFieldVm> AdditionalFields { get; private set; }
public ObservableCollection<Attachment> Attachments { get; private set; }
/// <summary>
/// Determines if the Entry is current or from history
/// </summary>
public bool IsCurrentEntry => SelectedIndex == 0;
public EntryVm SelectedItem
{
get { return _selectedItem; }
set
{
Set(() => SelectedItem, ref _selectedItem, value);
if (value != null) RaisePropertyChanged();
}
}
public int SelectedIndex
{
get { return _selectedIndex; }
@@ -87,199 +71,255 @@ namespace ModernKeePass.ViewModels
{
Set(() => SelectedIndex, ref _selectedIndex, value);
RaisePropertyChanged(nameof(IsCurrentEntry));
AddAttachmentCommand.RaiseCanExecuteChanged();
}
}
public double PasswordLength
public int AdditionalFieldSelectedIndex
{
get { return _passwordLength; }
set { Set(() => PasswordLength, ref _passwordLength, value); }
}
public string Title
{
get { return SelectedItem.Title; }
get { return _additionalFieldSelectedIndex; }
set
{
SelectedItem.Title = value;
SetFieldValue(nameof(Title), value).Wait();
Set(() => AdditionalFieldSelectedIndex, ref _additionalFieldSelectedIndex, value);
DeleteAdditionalField.RaiseCanExecuteChanged();
}
}
public string Title
{
get { return _current.Title.Value; }
set
{
_current.Title.Value = value;
SetFieldValue(_current.Title.Name, value, false).ConfigureAwait(false).GetAwaiter();
}
}
public string UserName
{
get { return SelectedItem.Username; }
get { return _current.Username.Value; }
set
{
SelectedItem.Username = value;
SetFieldValue(nameof(UserName), value).Wait();
_current.Username.Value = value;
SetFieldValue(_current.Username.Name, value, false).ConfigureAwait(false).GetAwaiter();
RaisePropertyChanged(nameof(UserName));
}
}
public string Password
{
get { return SelectedItem.Password; }
get { return _cryptography.UnProtect(_current.Password.Value).GetAwaiter().GetResult(); }
set
{
SelectedItem.Password = value;
SetFieldValue(nameof(Password), value).Wait();
var protectedPassword = _cryptography.Protect(value).ConfigureAwait(false).GetAwaiter().GetResult();
_current.Password.Value = protectedPassword;
SetFieldValue(_current.Password.Name, protectedPassword, true).ConfigureAwait(false).GetAwaiter();
RaisePropertyChanged(nameof(Password));
RaisePropertyChanged(nameof(PasswordComplexityIndicator));
}
}
public string Url
{
get { return SelectedItem.Url; }
get { return _current.Url.Value; }
set
{
SelectedItem.Url = value;
SetFieldValue(nameof(Url), value).Wait();
_current.Url.Value = value;
SetFieldValue(_current.Url.Name, value, false).ConfigureAwait(false).GetAwaiter();
RaisePropertyChanged(nameof(Url));
}
}
public string Notes
{
get { return SelectedItem.Notes; }
get { return _current.Notes.Value; }
set
{
SelectedItem.Notes = value;
SetFieldValue(nameof(Notes), value).Wait();
_current.Notes.Value = value;
SetFieldValue(_current.Notes.Name, value, false).ConfigureAwait(false).GetAwaiter();
}
}
public Symbol Icon
{
get { return (Symbol)Enum.Parse(typeof(Symbol), SelectedItem.Icon.ToString()); }
get { return (Symbol)Enum.Parse(typeof(Symbol), _current.Icon.ToString()); }
set
{
SelectedItem.Icon = (Icon)Enum.Parse(typeof(Icon), value.ToString());
SetFieldValue(nameof(Icon), SelectedItem.Icon).Wait();
_current.Icon = (Icon)Enum.Parse(typeof(Icon), value.ToString());
SetFieldValue(EntryFieldName.Icon, _current.Icon, false).ConfigureAwait(false).GetAwaiter();
}
}
public DateTimeOffset ExpiryDate
{
get { return SelectedItem.ExpirationDate; }
get { return _current.ExpirationDate; }
set
{
if (!HasExpirationDate) return;
SelectedItem.ExpirationDate = value.Date;
SetFieldValue("ExpirationDate", SelectedItem.ExpirationDate).Wait();
_current.ExpirationDate = value.Date;
SetFieldValue(EntryFieldName.ExpirationDate, _current.ExpirationDate, false).ConfigureAwait(false).GetAwaiter();
}
}
public TimeSpan ExpiryTime
{
get { return SelectedItem.ExpirationDate.TimeOfDay; }
get { return _current.ExpirationDate.TimeOfDay; }
set
{
if (!HasExpirationDate) return;
SelectedItem.ExpirationDate = SelectedItem.ExpirationDate.Date.Add(value);
SetFieldValue("ExpirationDate", SelectedItem.ExpirationDate).Wait();
_current.ExpirationDate = _current.ExpirationDate.Date.Add(value);
SetFieldValue(EntryFieldName.ExpirationDate, _current.ExpirationDate, false).ConfigureAwait(false).GetAwaiter();
}
}
public bool HasExpirationDate
{
get { return SelectedItem.HasExpirationDate; }
get { return _current.HasExpirationDate; }
set
{
SelectedItem.HasExpirationDate = value;
SetFieldValue(nameof(HasExpirationDate), value).Wait();
_current.HasExpirationDate = value;
SetFieldValue(EntryFieldName.HasExpirationDate, value, false).ConfigureAwait(false).GetAwaiter();
RaisePropertyChanged(nameof(HasExpirationDate));
}
}
public SolidColorBrush BackgroundColor
{
get { return SelectedItem?.BackgroundColor.ToSolidColorBrush(); }
get { return _current?.BackgroundColor.ToSolidColorBrush(); }
set
{
SelectedItem.BackgroundColor = value.ToColor();
SetFieldValue(nameof(BackgroundColor), SelectedItem.BackgroundColor).Wait();
_current.BackgroundColor = value.ToColor();
SetFieldValue(EntryFieldName.BackgroundColor, _current.BackgroundColor, false).ConfigureAwait(false).GetAwaiter();
}
}
public SolidColorBrush ForegroundColor
{
get { return SelectedItem?.ForegroundColor.ToSolidColorBrush(); }
get { return _current?.ForegroundColor.ToSolidColorBrush(); }
set
{
SelectedItem.ForegroundColor = value.ToColor();
SetFieldValue(nameof(ForegroundColor), SelectedItem.ForegroundColor).Wait();
_current.ForegroundColor = value.ToColor();
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 GeneratePasswordCommand { get; }
public RelayCommand<string> MoveCommand { get; }
public RelayCommand RestoreCommand { get; }
public RelayCommand DeleteCommand { get; }
public RelayCommand GoBackCommand { get; }
public RelayCommand GoToParentCommand { get; set; }
public RelayCommand AddAdditionalField { get; }
public RelayCommand<EntryFieldVm> DeleteAdditionalField { get; }
public RelayCommand<Attachment> OpenAttachmentCommand { get; }
public RelayCommand AddAttachmentCommand { get; }
public RelayCommand<Attachment> DeleteAttachmentCommand { get; }
public RelayCommand<EntryVm> SetCurrentEntryCommand { get; }
private DatabaseVm Database => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
private readonly IMediator _mediator;
private readonly INavigationService _navigation;
private readonly IResourceProxy _resource;
private readonly IDialogService _dialog;
private readonly INotificationService _notification;
private GroupVm _parent;
private EntryVm _selectedItem;
private readonly IFileProxy _file;
private readonly ICryptographyClient _cryptography;
private readonly IDateTime _dateTime;
private EntryVm _current;
private int _selectedIndex;
private bool _isEditMode;
private bool _isRevealPassword;
private double _passwordLength = 25;
private int _additionalFieldSelectedIndex = -1;
private bool _isDirty;
public EntryDetailVm(IMediator mediator, INavigationService navigation, IResourceProxy resource, IDialogService dialog, INotificationService notification)
public EntryDetailVm(IMediator mediator, INavigationService navigation, IResourceProxy resource, IDialogService dialog, INotificationService notification, IFileProxy file, ICryptographyClient cryptography, IDateTime dateTime)
{
_mediator = mediator;
_navigation = navigation;
_resource = resource;
_dialog = dialog;
_notification = notification;
_file = file;
_cryptography = cryptography;
_dateTime = dateTime;
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());
DeleteCommand = new RelayCommand(async () => await AskForDelete());
GoBackCommand = new RelayCommand(() => _navigation.GoBack());
GoToParentCommand = new RelayCommand(() => GoToGroup(_parent.Id));
AddAdditionalField = new RelayCommand(AddField, () => IsCurrentEntry);
DeleteAdditionalField = new RelayCommand<EntryFieldVm>(async field => await DeleteField(field), field => field != null && IsCurrentEntry);
OpenAttachmentCommand = new RelayCommand<Attachment>(async attachment => await OpenAttachment(attachment));
AddAttachmentCommand = new RelayCommand(async () => await AddAttachment(), () => 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<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<PasswordGeneratedMessage>(this, message => Password = message.Password);
}
public async Task Initialize(string entryId)
{
SelectedItem = await _mediator.Send(new GetEntryQuery { Id = entryId });
_parent = await _mediator.Send(new GetGroupQuery { Id = SelectedItem.ParentGroupId });
History = new ObservableCollection<EntryVm> { SelectedItem };
foreach (var entry in SelectedItem.History.Skip(1))
SelectedIndex = 0;
_current = await _mediator.Send(new GetEntryQuery { Id = entryId });
SetCurrentEntry(_current);
Parent = await _mediator.Send(new GetGroupQuery { Id = _current.ParentGroupId });
History = new ObservableCollection<IEntityVm> { _current };
foreach (var entry in _current.History.Skip(1))
{
History.Add(entry);
}
SelectedIndex = 0;
History.CollectionChanged += (sender, args) =>
{
SelectedIndex = 0;
SaveCommand.RaiseCanExecuteChanged();
};
}
public async Task AddHistory()
{
if (_isDirty && Database.IsOpen) await _mediator.Send(new AddHistoryCommand { Entry = History[0] as EntryVm });
}
public void GoToGroup(string groupId)
{
_navigation.NavigateTo(Constants.Navigation.GroupPage, new NavigationItem { Id = groupId });
}
private async Task Move(string destination)
{
await _mediator.Send(new AddEntryCommand { ParentGroupId = destination, EntryId = Id });
await _mediator.Send(new RemoveEntryCommand { ParentGroupId = Parent.Id, EntryId = Id });
GoToGroup(destination);
}
private async Task SetFieldValue(string fieldName, object value, bool isProtected)
{
await _mediator.Send(new UpsertFieldCommand { EntryId = Id, FieldName = fieldName, FieldValue = value, IsProtected = isProtected});
UpdateDirtyStatus(true);
}
private async Task UpdateFieldName(string oldName, string newName, string value, bool isProtected)
{
if (!string.IsNullOrEmpty(oldName)) await _mediator.Send(new DeleteFieldCommand { EntryId = Id, FieldName = oldName });
await SetFieldValue(newName, value, isProtected);
}
private void AddField()
{
AdditionalFields.Add(new EntryFieldVm(_cryptography));
AdditionalFieldSelectedIndex = AdditionalFields.Count - 1;
}
private async Task DeleteField(EntryFieldVm field)
{
AdditionalFields.Remove(field);
if (!string.IsNullOrEmpty(field.Name))
{
await _mediator.Send(new DeleteFieldCommand {EntryId = Id, FieldName = field.Name});
UpdateDirtyStatus(true);
}
}
private async Task AskForDelete()
@@ -289,12 +329,13 @@ namespace ModernKeePass.ViewModels
if (IsRecycleOnDelete)
{
await Delete();
_notification.Show(_resource.GetResourceValue("EntryRecyclingConfirmation"), _resource.GetResourceValue("EntryRecycled"));
_notification.Show(_resource.GetResourceValue("EntityDeleting"), string.Format(_resource.GetResourceValue("EntryRecycled"), Title));
}
else
{
await _dialog.ShowMessage(_resource.GetResourceValue("EntryDeletingConfirmation"),
_resource.GetResourceValue("EntityDeleteTitle"),
await _dialog.ShowMessage(
string.Format(_resource.GetResourceValue("EntryDeletingConfirmation"), Title),
_resource.GetResourceValue("EntityDeleting"),
_resource.GetResourceValue("EntityDeleteActionButton"),
_resource.GetResourceValue("EntityDeleteCancelButton"),
async isOk =>
@@ -305,62 +346,22 @@ namespace ModernKeePass.ViewModels
}
else
{
await _dialog.ShowMessage(_resource.GetResourceValue("HistoryDeleteDescription"), _resource.GetResourceValue("HistoryDeleteTitle"),
await _dialog.ShowMessage(_resource.GetResourceValue("HistoryDeleteDescription"),
_resource.GetResourceValue("HistoryDeleteTitle"),
_resource.GetResourceValue("EntityDeleteActionButton"),
_resource.GetResourceValue("EntityDeleteCancelButton"), async isOk =>
{
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);
SelectedIndex = 0;
SaveCommand.RaiseCanExecuteChanged();
});
}
}
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
});
RaisePropertyChanged(nameof(IsRevealPasswordEnabled));
}
public async Task Move(string destination)
{
await _mediator.Send(new AddEntryCommand { ParentGroupId = destination, EntryId = Id });
await _mediator.Send(new RemoveEntryCommand { ParentGroupId = _parent.Id, EntryId = Id });
GoToGroup(destination);
}
public async Task SetFieldValue(string fieldName, object value)
{
await _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = fieldName, FieldValue = value });
SaveCommand.RaiseCanExecuteChanged();
_isDirty = true;
}
public async Task AddHistory()
{
if (_isDirty) await _mediator.Send(new AddHistoryCommand { Entry = History[0] });
}
private async Task RestoreHistory()
{
await _mediator.Send(new RestoreHistoryCommand { Entry = History[0], HistoryIndex = History.Count - SelectedIndex - 1 });
History.Insert(0, SelectedItem);
SelectedIndex = 0;
SaveCommand.RaiseCanExecuteChanged();
await _mediator.Send(new RestoreHistoryCommand { Entry = History[0] as EntryVm, HistoryIndex = History.Count - SelectedIndex - 1 });
History.Insert(0, _current);
}
private async Task SaveChanges()
@@ -374,8 +375,7 @@ namespace ModernKeePass.ViewModels
{
MessengerInstance.Send(new SaveErrorMessage { Message = e.Message });
}
SaveCommand.RaiseCanExecuteChanged();
_isDirty = false;
UpdateDirtyStatus(false);
}
private async Task Delete()
@@ -383,15 +383,73 @@ namespace ModernKeePass.ViewModels
await _mediator.Send(new DeleteEntryCommand
{
EntryId = Id,
ParentGroupId = SelectedItem.ParentGroupId,
ParentGroupId = _current.ParentGroupId,
RecycleBinName = _resource.GetResourceValue("RecycleBinTitle")
});
_isDirty = false;
_navigation.GoBack();
}
public void GoToGroup(string groupId)
private async Task OpenAttachment(Attachment attachment)
{
_navigation.NavigateTo(Constants.Navigation.GroupPage, new NavigationItem { Id = groupId });
var extensionIndex = attachment.Name.LastIndexOf('.');
var fileInfo = await _file.CreateFile(attachment.Name,
attachment.Name.Substring(extensionIndex, attachment.Name.Length - extensionIndex),
string.Empty,
false);
if (fileInfo == null) return;
await _file.WriteBinaryContentsToFile(fileInfo.Id, attachment.Content);
}
private async Task AddAttachment()
{
var fileInfo = await _file.OpenFile(string.Empty, Domain.Common.Constants.Extensions.Any, false);
if (fileInfo == null) return;
var contents = await _file.ReadBinaryFile(fileInfo.Id);
await _mediator.Send(new AddAttachmentCommand { Entry = _current, AttachmentName = fileInfo.Name, AttachmentContent = contents });
Attachments.Add(new Attachment { Name = fileInfo.Name, Content = contents });
}
private async Task DeleteAttachment(Attachment attachment)
{
await _mediator.Send(new DeleteAttachmentCommand { Entry = _current, AttachmentName = attachment.Name });
Attachments.Remove(attachment);
}
private void UpdateDirtyStatus(bool isDirty)
{
SaveCommand.RaiseCanExecuteChanged();
_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,8 +18,10 @@ using ModernKeePass.Application.Group.Commands.AddEntry;
using ModernKeePass.Application.Group.Commands.AddGroup;
using ModernKeePass.Application.Group.Commands.CreateEntry;
using ModernKeePass.Application.Group.Commands.CreateGroup;
using ModernKeePass.Application.Group.Commands.DeleteEntry;
using ModernKeePass.Application.Group.Commands.DeleteGroup;
using ModernKeePass.Application.Group.Commands.MoveEntry;
using ModernKeePass.Application.Group.Commands.MoveGroup;
using ModernKeePass.Application.Group.Commands.RemoveGroup;
using ModernKeePass.Application.Group.Commands.SortEntries;
using ModernKeePass.Application.Group.Commands.SortGroups;
@@ -37,12 +39,14 @@ namespace ModernKeePass.ViewModels
{
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 GroupVm Parent { get; private set; }
public IOrderedEnumerable<IGrouping<char, EntryVm>> EntriesZoomedOut => from e in Entries
group e by e.Title.ToUpper().FirstOrDefault() into grp
group e by (e.Title.Value ?? string.Empty).ToUpper().FirstOrDefault() into grp
orderby grp.Key
select grp;
@@ -79,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 IsInRecycleBin => _parent != null && _parent.Id == Database.RecycleBinId;
public bool IsInRecycleBin => Parent != null && Parent.Id == Database.RecycleBinId;
public RelayCommand SaveCommand { get; }
public RelayCommand SortEntriesCommand { get; }
@@ -91,9 +95,12 @@ namespace ModernKeePass.ViewModels
public RelayCommand<string> MoveCommand { get; }
public RelayCommand CreateEntryCommand { get; }
public RelayCommand<string> CreateGroupCommand { get; }
public RelayCommand DeleteCommand { get; set; }
public RelayCommand GoBackCommand { get; set; }
public RelayCommand GoToParentCommand { get; set; }
public RelayCommand DeleteCommand { get; }
public RelayCommand GoBackCommand { get; }
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();
@@ -103,10 +110,10 @@ namespace ModernKeePass.ViewModels
private readonly IDialogService _dialog;
private readonly INotificationService _notification;
private GroupVm _group;
private GroupVm _parent;
private bool _isEditMode;
private EntryVm _reorderedEntry;
private GroupVm _reorderedGroup;
public GroupDetailVm(IMediator mediator, IResourceProxy resource, INavigationService navigation, IDialogService dialog, INotificationService notification)
{
_mediator = mediator;
@@ -123,7 +130,10 @@ namespace ModernKeePass.ViewModels
CreateGroupCommand = new RelayCommand<string>(async newGroupName => await AddNewGroup(newGroupName), _ => !IsInRecycleBin && Database.RecycleBinId != Id);
DeleteCommand = new RelayCommand(async () => await AskForDelete(),() => IsNotRoot);
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());
}
@@ -133,12 +143,14 @@ namespace ModernKeePass.ViewModels
_group = await _mediator.Send(new GetGroupQuery { Id = groupId });
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.CollectionChanged += Entries_CollectionChanged;
Groups = new ObservableCollection<GroupVm>(_group.SubGroups);
Groups = new ObservableCollection<IEntityVm>(_group.Groups);
Groups.CollectionChanged += Groups_CollectionChanged;
}
public void GoToEntry(string entryId, bool isNew = false)
@@ -173,7 +185,7 @@ namespace ModernKeePass.ViewModels
public async Task Move(string destinationId)
{
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);
}
@@ -213,6 +225,29 @@ namespace ModernKeePass.ViewModels
SaveCommand.RaiseCanExecuteChanged();
}
private async void Groups_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Remove:
var oldIndex = e.OldStartingIndex;
_reorderedGroup = _group.Groups[oldIndex];
break;
case NotifyCollectionChangedAction.Add:
if (_reorderedGroup == null)
{
var group = (GroupVm)e.NewItems[0];
await _mediator.Send(new AddGroupCommand() { GroupId = group.Id, ParentGroupId = Id });
}
else
{
await _mediator.Send(new MoveGroupCommand { Group = _reorderedGroup, ParentGroup = _group, Index = e.NewStartingIndex });
}
break;
}
SaveCommand.RaiseCanExecuteChanged();
}
private async Task SortEntriesAsync()
{
await _mediator.Send(new SortEntriesCommand {Group = _group});
@@ -225,7 +260,7 @@ namespace ModernKeePass.ViewModels
private async Task SortGroupsAsync()
{
await _mediator.Send(new SortGroupsCommand {Group = _group});
Groups = new ObservableCollection<GroupVm>(_group.SubGroups);
Groups = new ObservableCollection<IEntityVm>(_group.Groups);
RaisePropertyChanged(nameof(Groups));
SaveCommand.RaiseCanExecuteChanged();
}
@@ -235,11 +270,13 @@ namespace ModernKeePass.ViewModels
if (IsRecycleOnDelete)
{
await Delete();
_notification.Show(_resource.GetResourceValue("GroupRecyclingConfirmation"), _resource.GetResourceValue("GroupRecycled"));
_notification.Show(_resource.GetResourceValue("EntityDeleting"), string.Format(_resource.GetResourceValue("GroupRecycled"), Title));
}
else
{
await _dialog.ShowMessage(_resource.GetResourceValue("GroupDeletingConfirmation"), _resource.GetResourceValue("EntityDeleteTitle"),
await _dialog.ShowMessage(
string.Format(_resource.GetResourceValue("GroupDeletingConfirmation"), Title),
_resource.GetResourceValue("EntityDeleting"),
_resource.GetResourceValue("EntityDeleteActionButton"),
_resource.GetResourceValue("EntityDeleteCancelButton"),
async isOk =>
@@ -257,7 +294,39 @@ namespace ModernKeePass.ViewModels
ParentGroupId = _group.ParentGroupId,
RecycleBinName = _resource.GetResourceValue("RecycleBinTitle")
});
_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 });
});
}
public override void Cleanup()
{
MessengerInstance.Unregister(this);
base.Cleanup();
}
}
}

View File

@@ -8,6 +8,7 @@ using ModernKeePass.Application.Database.Queries.GetDatabase;
using ModernKeePass.Domain.Interfaces;
using ModernKeePass.ViewModels.ListItems;
using ModernKeePass.Views;
using ModernKeePass.Views.SettingsPageFrames;
namespace ModernKeePass.ViewModels
{
@@ -57,19 +58,11 @@ namespace ModernKeePass.ViewModels
IsSelected = true
},
new ListMenuItemVm
{
Title = resource.GetResourceValue("SettingsMenuItemSave"),
Group = resource.GetResourceValue("SettingsMenuGroupApplication"),
SymbolIcon = Symbol.Save,
PageType = typeof(SettingsSavePage)
},
new ListMenuItemVm
{
Title = resource.GetResourceValue("SettingsMenuItemGeneral"),
Group = resource.GetResourceValue("SettingsMenuGroupDatabase"),
Group = resource.GetResourceValue("SettingsMenuGroupApplication"),
SymbolIcon = Symbol.Setting,
PageType = typeof(SettingsDatabasePage),
IsEnabled = database.IsOpen
PageType = typeof(SettingsGeneralPage)
},
new ListMenuItemVm
{
@@ -78,6 +71,30 @@ namespace ModernKeePass.ViewModels
SymbolIcon = Symbol.Permissions,
PageType = typeof(SettingsSecurityPage),
IsEnabled = database.IsOpen
},
new ListMenuItemVm
{
Title = resource.GetResourceValue("SettingsMenuItemHistory"),
Group = resource.GetResourceValue("SettingsMenuGroupDatabase"),
SymbolIcon = Symbol.Undo,
PageType = typeof(SettingsHistoryPage),
IsEnabled = database.IsOpen
},
new ListMenuItemVm
{
Title = resource.GetResourceValue("SettingsMenuItemRecycleBin"),
Group = resource.GetResourceValue("SettingsMenuGroupDatabase"),
SymbolIcon = Symbol.Delete,
PageType = typeof(SettingsRecycleBinPage),
IsEnabled = database.IsOpen
},
new ListMenuItemVm
{
Title = resource.GetResourceValue("SettingsMenuItemCredentials"),
Group = resource.GetResourceValue("SettingsMenuGroupDatabase"),
SymbolIcon = Symbol.Account,
PageType = typeof(SettingsCredentialsPage),
IsEnabled = database.IsOpen
}
};
SelectedItem = menuItems.FirstOrDefault(m => m.IsSelected);

View File

@@ -85,7 +85,7 @@ namespace ModernKeePass.Views.BasePages
/// <summary>
/// Preserves state associated with this page in case the application is suspended or the
/// page is discarded from the navigation cache. Values must conform to the serialization
/// requirements of <see cref="Common.SuspensionManager.SessionState"/>.
/// requirements of <see cref="SuspensionManager.SessionState"/>.
/// </summary>
/// <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

View File

@@ -1,4 +1,4 @@
<Page
<Page x:Name="Page"
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"
@@ -8,7 +8,7 @@
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:actions="using:ModernKeePass.Actions"
xmlns:userControls="using:ModernKeePass.Views.UserControls"
xmlns:controls="using:ModernKeePass.Views.UserControls"
x:Class="ModernKeePass.Views.EntryDetailPage"
mc:Ignorable="d"
SizeChanged="EntryDetailPage_OnSizeChanged"
@@ -16,347 +16,6 @@
<Page.Resources>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<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>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ChildrenTransitions>
@@ -373,146 +32,208 @@
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<userControls:HamburgerMenuUserControl
<Grid Grid.Column="1">
<Hub x:Name="Hub" Padding="0">
<Hub.Resources>
<Style TargetType="TextBlock" x:Key="EntryTextBlockStyle">
<Setter Property="Margin" Value="0,20,0,0"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
</Hub.Resources>
<HubSection x:Uid="EntryHubMain">
<DataTemplate>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Width="350" Margin="0,0,25,0">
<StackPanel.Resources>
<Style TargetType="CheckBox">
<Setter Property="Margin" Value="0,20,0,0"/>
<Setter Property="FontSize" Value="18"/>
</Style>
</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}" />
<local:TextBoxWithButton x:Uid="LoginTextBox" Text="{Binding UserName, Mode=TwoWay}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonContent="&#xE16F;" IsEnabled="{Binding IsCurrentEntry}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:ClipboardAction Text="{Binding UserName}" />
<actions:ToastAction x:Uid="ToastCopyLogin" Title="{Binding Title}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</local:TextBoxWithButton>
<TextBlock x:Uid="EntryPassword" Style="{StaticResource EntryTextBlockStyle}" />
<controls:PasswordGenerationBox Password="{Binding Password, Mode=TwoWay}" IsEnabled="{Binding IsCurrentEntry}" />
<TextBlock Text="URL" Style="{StaticResource EntryTextBlockStyle}"/>
<local:TextBoxWithButton x:Uid="UrlTextBox" Text="{Binding Url, Mode=TwoWay}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonContent="&#xE111;" IsEnabled="{Binding IsCurrentEntry}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:NavigateToUrlAction Url="{Binding Url}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</local:TextBoxWithButton>
<TextBlock x:Uid="EntryNotes" Style="{StaticResource EntryTextBlockStyle}" />
<TextBox TextWrapping="Wrap" Text="{Binding Notes, Mode=TwoWay}" Width="350" Height="200" AcceptsReturn="True" IsSpellCheckEnabled="True" IsEnabled="{Binding IsCurrentEntry}" />
<CheckBox x:Uid="EntryExpirationDate" Margin="-3,0,0,0" IsChecked="{Binding HasExpirationDate, Mode=TwoWay}" IsEnabled="{Binding IsCurrentEntry}" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<SymbolIcon Grid.Column="0" Symbol="Important" Foreground="DarkRed" Visibility="{Binding HasExpired, Converter={StaticResource BooleanToVisibilityConverter}}">
<ToolTipService.ToolTip>
<ToolTip x:Uid="EntryExpirationTooltip" />
</ToolTipService.ToolTip>
</SymbolIcon>
<StackPanel Grid.Column="1" x:Name="ExpirationDatePanel" Orientation="Vertical" Visibility="{Binding HasExpirationDate, Converter={StaticResource BooleanToVisibilityConverter}}">
<DatePicker Margin="10,5,20,0" Date="{Binding ExpiryDate, Mode=TwoWay}" />
<TimePicker Margin="10,10,0,0" Time="{Binding ExpiryTime, Mode=TwoWay}" />
</StackPanel>
</Grid>
</StackPanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Small">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpirationDatePanel" Storyboard.TargetProperty="Orientation">
<DiscreteObjectKeyFrame KeyTime="0" Value="Vertical"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Large">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpirationDatePanel" Storyboard.TargetProperty="Orientation">
<DiscreteObjectKeyFrame KeyTime="0" Value="Horizontal"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ScrollViewer>
</DataTemplate>
</HubSection>
<HubSection x:Uid="EntryHubPresentation">
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock x:Uid="EntryIcon" Style="{StaticResource EntryTextBlockStyle}" />
<controls:SymbolPickerUserControl SelectedSymbol="{Binding Icon, Mode=TwoWay}" HorizontalAlignment="Left" IsEnabled="{Binding IsCurrentEntry}" />
<TextBlock x:Uid="EntryBackgroundColor" Style="{StaticResource EntryTextBlockStyle}" />
<controls:ColorPickerUserControl SelectedColor="{Binding BackgroundColor, Mode=TwoWay}" IsEnabled="{Binding IsCurrentEntry}" Width="250" />
<TextBlock x:Uid="EntryForegroundColor" Style="{StaticResource EntryTextBlockStyle}" />
<controls:ColorPickerUserControl SelectedColor="{Binding ForegroundColor, Mode=TwoWay}" IsEnabled="{Binding IsCurrentEntry}" Width="250" />
</StackPanel>
</DataTemplate>
</HubSection>
<HubSection x:Uid="EntryHubAdditional">
<DataTemplate>
<local:SelectableTemplateListView
ItemsSource="{Binding AdditionalFields}"
SelectedIndex="{Binding AdditionalFieldSelectedIndex, Mode=TwoWay}"
ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}">
<local:SelectableTemplateListView.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<HyperlinkButton Command="{Binding Path=DataContext.AddAdditionalField, ElementName=Page}">
<StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="Add" />
<TextBlock x:Uid="EntryAddAdditionalField" VerticalAlignment="Center" Margin="10,0,0,0" />
</StackPanel>
</HyperlinkButton>
<Border BorderBrush="DarkGray" BorderThickness="0,0,0,1" />
</StackPanel>
</DataTemplate>
</local:SelectableTemplateListView.HeaderTemplate>
<local:SelectableTemplateListView.SelectedItemTemplate>
<DataTemplate>
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Text="{Binding Name, Mode=TwoWay}" Width="350"
IsEnabled="{Binding Path=DataContext.IsCurrentEntry, ElementName=Page}" />
<TextBox Grid.Row="1" AcceptsReturn="True" Height="100" TextWrapping="Wrap" Width="350" Margin="0,5,0,0"
Text="{Binding Value, Mode=TwoWay}"
IsEnabled="{Binding Path=DataContext.IsCurrentEntry, ElementName=Page}" />
<ToggleSwitch Grid.Row="2" x:Uid="EntryEnableFieldProtection" HorizontalAlignment="Left" IsOn="{Binding IsProtected, Mode=TwoWay}" />
<Button Grid.Row="2" x:Uid="EntryDeleteAdditionalField" HorizontalAlignment="Right" Margin="0,15,0,0" Command="{Binding Path=DataContext.DeleteAdditionalField, ElementName=Page}" CommandParameter="{Binding}" />
</Grid>
</DataTemplate>
</local:SelectableTemplateListView.SelectedItemTemplate>
<local:SelectableTemplateListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Margin="5">
<TextBlock Text="{Binding Name}" Style="{StaticResource EntryTextBlockStyle}" FontWeight="SemiBold" />
<TextBlock HorizontalAlignment="Left" MaxLines="3" FontSize="12" Margin="2,0,2,5" Text="{Binding DisplayValue}" Style="{StaticResource EntryTextBlockStyle}"/>
</StackPanel>
</DataTemplate>
</local:SelectableTemplateListView.ItemTemplate>
</local:SelectableTemplateListView>
</DataTemplate>
</HubSection>
<HubSection x:Uid="EntryHubAttachments" Foreground="{StaticResource HubSectionBrush}">
<DataTemplate>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Orientation="Vertical">
<HyperlinkButton Command="{Binding Path=DataContext.AddAttachmentCommand, ElementName=Page}">
<StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="Attach" />
<TextBlock x:Uid="EntryAddAttachment" VerticalAlignment="Center" Margin="10,0,0,0" />
</StackPanel>
</HyperlinkButton>
<Border BorderBrush="DarkGray" BorderThickness="0,0,0,1" />
<ItemsControl ItemsSource="{Binding Attachments}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<HyperlinkButton Content="{Binding Name}" Command="{Binding Path=DataContext.OpenAttachmentCommand, ElementName=Page}" CommandParameter="{Binding}" />
<HyperlinkButton Grid.Column="1" Margin="10,0,0,0" HorizontalAlignment="Right" Command="{Binding Path=DataContext.DeleteAttachmentCommand, ElementName=Page}" CommandParameter="{Binding}">
<SymbolIcon Symbol="Delete" />
</HyperlinkButton>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
</DataTemplate>
</HubSection>
</Hub>
</Grid>
<controls:HamburgerMenuUserControl
Grid.Column="0"
x:Name="HamburgerMenu"
x:Uid="HistoryLeftListView"
ItemsSource="{Binding History}"
SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
<Grid Grid.Column="1">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Margin="20,0,0,20">
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="0,20,0,0"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
<Style TargetType="CheckBox">
<Setter Property="Margin" Value="0,20,0,0"/>
<Setter Property="FontSize" Value="18"/>
</Style>
</StackPanel.Resources>
<TextBlock x:Uid="EntryLogin" />
<local:TextBoxWithButton x:Uid="LoginTextBox" Text="{Binding UserName, Mode=TwoWay}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonSymbol="&#xE16F;" IsEnabled="{Binding IsCurrentEntry}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:ClipboardAction Text="{Binding UserName}" />
<actions:ToastAction x:Uid="ToastCopyLogin" Title="{Binding Title}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</local:TextBoxWithButton>
<TextBlock x:Uid="EntryPassword" />
<local:PasswordBoxWithButton Password="{Binding Password, Mode=TwoWay}" IsPasswordRevealEnabled="True" Visibility="{Binding IsRevealPassword, Converter={StaticResource InverseBooleanToVisibilityConverter}}" Style="{StaticResource PasswordBoxWithButtonStyle}" IsEnabled="{Binding IsCurrentEntry}" ButtonSymbol="&#xE15E;" />
<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}" IsEnabled="{Binding IsRevealPasswordEnabled}" />
<TextBlock TextWrapping="Wrap" Text="URL" FontSize="18"/>
<local:TextBoxWithButton x:Uid="UrlTextBox" Text="{Binding Url, Mode=TwoWay}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonSymbol="&#xE111;" IsEnabled="{Binding IsCurrentEntry}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:NavigateToUrlAction Url="{Binding Url}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</local:TextBoxWithButton>
<TextBlock x:Uid="EntryNotes" />
<TextBox HorizontalAlignment="Left" 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}" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<SymbolIcon Grid.Column="0" Symbol="Important" Foreground="DarkRed" Visibility="{Binding HasExpired, Converter={StaticResource BooleanToVisibilityConverter}}">
<ToolTipService.ToolTip>
<ToolTip x:Uid="EntryExpirationTooltip" />
</ToolTipService.ToolTip>
</SymbolIcon>
<StackPanel Grid.Column="1" x:Name="ExpirationDatePanel" Orientation="Horizontal" Visibility="{Binding HasExpirationDate, Converter={StaticResource BooleanToVisibilityConverter}}">
<DatePicker Margin="0,0,20,0" Date="{Binding ExpiryDate, Mode=TwoWay}" />
<TimePicker Time="{Binding ExpiryTime, Mode=TwoWay}" />
</StackPanel>
</Grid>
<StackPanel x:Name="EditDesign" Visibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}" Orientation="Horizontal">
<StackPanel Width="250" HorizontalAlignment="Left">
<TextBlock x:Uid="EntryBackgroundColor" />
<userControls:ColorPickerUserControl SelectedColor="{Binding BackgroundColor, Mode=TwoWay}" IsEnabled="{Binding IsCurrentEntry}" />
</StackPanel>
<StackPanel Width="250" HorizontalAlignment="Left">
<TextBlock x:Uid="EntryForegroundColor" />
<userControls:ColorPickerUserControl SelectedColor="{Binding ForegroundColor, Mode=TwoWay}" IsEnabled="{Binding IsCurrentEntry}" />
</StackPanel>
</StackPanel>
</StackPanel>
</ScrollViewer>
</Grid>
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>
<!-- Bouton Précédent et titre de la page -->
<Grid Grid.Row="0" Background="{ThemeResource AppBarBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{StaticResource MenuWidthGridLength}"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0"
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>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<Button
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 MaxHeight="200" Visibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}">
<userControls:SymbolPickerUserControl Width="100" Height="70" SelectedSymbol="{Binding Icon, Mode=TwoWay}" />
</Viewbox>
<Viewbox MaxHeight="200" Visibility="{Binding IsEditMode, Converter={StaticResource InverseBooleanToVisibilityConverter}}">
<SymbolIcon Symbol="{Binding Icon}" Width="100" Height="70" />
</Viewbox>
<TextBox
x:Uid="EntryTitle"
x:Name="TitleTextBox"
Text="{Binding Title, Mode=TwoWay}"
Background="Transparent"
IsHitTestVisible="{Binding IsEditMode}"
FontSize="20"
FontWeight="Light"
TextWrapping="NoWrap"
MinWidth="360"
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>
</StackPanel>
<userControls:TopMenuUserControl
x:Name="TopMenu" Grid.Column="2"
IsEditButtonChecked="{Binding IsEditMode, Mode=TwoWay}"
<controls:BreadcrumbUserControl x:Name="Breadcrumb" Group="{Binding Parent}" />
<controls:TopMenuUserControl
x:Name="TopMenu" Grid.Column="1"
MoveButtonVisibility="{Binding IsCurrentEntry, Converter={StaticResource BooleanToVisibilityConverter}}"
RestoreButtonVisibility="{Binding IsCurrentEntry, Converter={StaticResource InverseBooleanToVisibilityConverter}}"
SaveCommand="{Binding SaveCommand}"
@@ -524,27 +245,28 @@
<actions:SetupFocusAction TargetObject="{Binding ElementName=TitleTextBox}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</userControls:TopMenuUserControl>
</controls:TopMenuUserControl>
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualStateGroup x:Name="PageLayout">
<VisualState x:Name="Small">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpirationDatePanel" Storyboard.TargetProperty="Orientation">
<DiscreteObjectKeyFrame KeyTime="0" Value="Vertical"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Hub" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="-30,0,0,0"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="EditDesign" Storyboard.TargetProperty="Orientation">
<DiscreteObjectKeyFrame KeyTime="0" Value="Vertical"/>
</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="ExpirationDatePanel" Storyboard.TargetProperty="Orientation">
<DiscreteObjectKeyFrame KeyTime="0" Value="Horizontal"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="EditDesign" Storyboard.TargetProperty="Orientation">
<DiscreteObjectKeyFrame KeyTime="0" Value="Horizontal"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Hub" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,0"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>

View File

@@ -14,7 +14,7 @@ namespace ModernKeePass.Views
public sealed partial class EntryDetailPage
{
public EntryDetailVm Model => (EntryDetailVm) DataContext;
public EntryDetailPage()
{
InitializeComponent();
@@ -28,14 +28,13 @@ namespace ModernKeePass.Views
if (args != null)
{
await Model.Initialize(args.Id);
Model.IsEditMode = args.IsNew;
if (args.IsNew) await Model.GeneratePassword();
}
}
protected override async void OnNavigatedFrom(NavigationEventArgs e)
{
await Model.AddHistory();
Model.Cleanup();
}
#endregion
@@ -47,18 +46,21 @@ namespace ModernKeePass.Views
VisualStateManager.GoToState(this, "Small", true);
VisualStateManager.GoToState(TopMenu, "Collapsed", true);
VisualStateManager.GoToState(HamburgerMenu, "Hidden", true);
VisualStateManager.GoToState(Breadcrumb, "Small", true);
}
else if (e.NewSize.Width > 640 && e.NewSize.Width <= 1008)
{
VisualStateManager.GoToState(this, "Medium", true);
VisualStateManager.GoToState(TopMenu, "Overflowed", true);
VisualStateManager.GoToState(HamburgerMenu, "Collapsed", true);
VisualStateManager.GoToState(Breadcrumb, "Medium", true);
}
else
{
VisualStateManager.GoToState(this, "Large", true);
VisualStateManager.GoToState(TopMenu, "Overflowed", 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:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
@@ -15,14 +15,10 @@
<Page.Resources>
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
<converters:IconToSymbolConverter x:Key="IconToSymbolConverter"/>
</Page.Resources>
<Grid>
<Grid.Resources>
<CollectionViewSource
x:Name="EntriesViewSource"
Source="{Binding Entries}" />
<CollectionViewSource
x:Name="EntriesZoomedOutViewSource"
Source="{Binding EntriesZoomedOut}" IsSourceGrouped="True" />
@@ -44,13 +40,6 @@
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<userControls:HamburgerMenuUserControl
x:Name="HamburgerMenu"
x:Uid="GroupsLeftListView"
ItemsSource="{Binding Groups}"
SelectionChanged="groups_SelectionChanged"
ActionButtonCommand="{Binding CreateGroupCommand}"
IsButtonVisible="Visible" />
<Grid Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
@@ -62,7 +51,6 @@
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" x:Uid="ReorderEntriesLabel" Margin="10,10,0,0" Visibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}" Style="{StaticResource BodyTextBlockStyle}" />
<!--<TextBlock Grid.Column="1" Grid.Row="0" x:Uid="EntrySymbol" Margin="40,20,0,0" Visibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}" Style="{StaticResource BodyTextBlockStyle}" />-->
<HyperlinkButton Grid.Column="2" Grid.Row="0" VerticalAlignment="Top" Command="{Binding CreateEntryCommand}" HorizontalAlignment="Right">
<StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="Add">
@@ -74,27 +62,27 @@
</StackPanel>
</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>
<!-- Horizontal scrolling grid -->
<GridView
x:Name="GridView"
ItemsSource="{Binding Source={StaticResource EntriesViewSource}}"
ItemsSource="{Binding Entries}"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Entries"
TabIndex="1"
Margin="10,0,0,0"
SelectionChanged="entries_SelectionChanged"
IsSynchronizedWithCurrentItem="False"
BorderBrush="{StaticResource ListViewItemSelectedBackgroundThemeBrush}"
AllowDrop="True"
CanReorderItems="True"
CanDragItems="True"
DragItemsStarting="GridView_DragItemsStarting">
CanReorderItems="{Binding IsEditMode}"
CanDragItems="{Binding IsEditMode}">
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="False">
<actions:SetupFocusAction TargetObject="{Binding ElementName=GridView}" />
</core:DataTriggerBehavior>
<core:EventTriggerBehavior EventName="SelectionChanged">
<core:InvokeCommandAction Command="{Binding GoToEntryCommand}" CommandParameter="{Binding SelectedItem, ElementName=GridView}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
<GridView.ItemTemplate>
<DataTemplate>
@@ -130,18 +118,19 @@
<MenuFlyoutItem x:Uid="EntryItemCopyPassword">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<actions:ClipboardAction Text="{Binding Password}" />
<actions:ClipboardAction Text="{Binding Password}" IsProtected="True" />
<actions:ToastAction x:Uid="ToastCopyPassword" Title="{Binding Title}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</MenuFlyoutItem>
<MenuFlyoutItem x:Uid="EntryItemCopyUrl" IsEnabled="{Binding HasUrl}">
<MenuFlyoutItem x:Uid="EntryItemCopyUrl" IsEnabled="{Binding IsValidUrl}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<actions:NavigateToUrlAction Url="{Binding Url}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</MenuFlyoutItem>
<MenuFlyoutItem x:Uid="EntryItemDelete" Command="{Binding DataContext.DeleteEntryCommand, ElementName=Page}" CommandParameter="{Binding}" />
</MenuFlyout>
</Button.Flyout>
</Button>
@@ -153,23 +142,26 @@
<SemanticZoom.ZoomedOutView>
<GridView
ItemsSource="{Binding Source={StaticResource EntriesZoomedOutViewSource}}"
SelectionChanged="groups_SelectionChanged"
SelectionMode="None"
IsSynchronizedWithCurrentItem="False">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical" ItemWidth="140" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Width="100" Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/>
</StackPanel>
<TextBlock Width="100" Margin="5,0,0,0" Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.GroupStyle>
<GroupStyle HidesIfEmpty="True">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Background="LightGray" HorizontalAlignment="Left">
<TextBlock Text="{Binding Key}" Width="50" Margin="30" Foreground="{StaticResource MainColorBrush}" Style="{StaticResource HeaderTextBlockStyle}" TextAlignment="Center" />
</Grid>
<StackPanel Orientation="Vertical" HorizontalAlignment="Left">
<TextBlock Text="{Binding Key}" Width="50" Margin="20" Foreground="{StaticResource MainColorBrush}" Style="{StaticResource SubheaderTextBlockStyle}" TextAlignment="Center" />
<Border BorderBrush="DarkGray" BorderThickness="0,0,0,1" />
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
@@ -178,65 +170,32 @@
</SemanticZoom.ZoomedOutView>
</SemanticZoom>
</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>
<!-- Back button and page title -->
<Grid Grid.Row="0" Background="{ThemeResource AppBarBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{StaticResource MenuWidthGridLength}"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0"
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>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<Button
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 MaxHeight="200" Visibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}">
<userControls:SymbolPickerUserControl Width="100" Height="70" SelectedSymbol="{Binding Icon, Mode=TwoWay}" />
</Viewbox>
<Viewbox MaxHeight="200" Visibility="{Binding IsEditMode, Converter={StaticResource InverseBooleanToVisibilityConverter}}">
<SymbolIcon Symbol="{Binding Icon}" Width="100" Height="70" />
</Viewbox>
<TextBox
x:Uid="GroupTitle"
x:Name="TitleTextBox"
Text="{Binding Title, Mode=TwoWay}"
Background="Transparent"
IsHitTestVisible="{Binding IsEditMode}"
FontSize="20"
FontWeight="Light"
TextWrapping="NoWrap"
MinWidth="360"
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>
</StackPanel>
<userControls:TopMenuUserControl x:Name="TopMenu" Grid.Column="2"
<userControls:BreadcrumbUserControl x:Name="Breadcrumb" Group="{Binding Parent}" />
<userControls:TopMenuUserControl x:Name="TopMenu" Grid.Column="1"
SortButtonVisibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}"
EditButtonVisibility="Visible"
IsEditButtonChecked="{Binding IsEditMode, Mode=TwoWay}"
SaveCommand="{Binding SaveCommand}"
MoveCommand="{Binding MoveCommand}"
@@ -249,25 +208,8 @@
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</userControls:TopMenuUserControl>
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="DragDropGroup">
<VisualState x:Name="Dragging">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GridView" Storyboard.TargetProperty="BorderThickness">
<DiscreteObjectKeyFrame KeyTime="0" Value="2"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Dropped">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GridView" Storyboard.TargetProperty="BorderThickness">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="PageLayout">
<VisualState x:Name="Small">
<Storyboard>
@@ -277,6 +219,9 @@
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HamburgerMenu" Storyboard.TargetProperty="IsOpen">
<DiscreteObjectKeyFrame KeyTime="0" Value="False"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SemanticZoom" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="-60,0,0,0"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Medium">
@@ -284,6 +229,9 @@
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HamburgerMenu" Storyboard.TargetProperty="IsOpen">
<DiscreteObjectKeyFrame KeyTime="0" Value="False"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SemanticZoom" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,0"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Large">
@@ -294,6 +242,9 @@
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HamburgerMenu" Storyboard.TargetProperty="IsOpen">
<DiscreteObjectKeyFrame KeyTime="0" Value="True"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SemanticZoom" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,0"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>

View File

@@ -1,8 +1,6 @@
using Windows.ApplicationModel.DataTransfer;
using Windows.UI.Xaml;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using ModernKeePass.Application.Entry.Models;
using ModernKeePass.Models;
using ModernKeePass.ViewModels;
@@ -38,33 +36,6 @@ namespace ModernKeePass.Views
#endregion
#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)
{
@@ -74,12 +45,6 @@ namespace ModernKeePass.Views
e.DestinationItem.Item = e.SourceItem.Item;
}
}
private void GridView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
e.Cancel = !Model.IsEditMode;
e.Data.RequestedOperation = DataPackageOperation.Move;
}
private void GroupDetailPage_OnSizeChanged(object sender, SizeChangedEventArgs e)
{
@@ -88,18 +53,21 @@ namespace ModernKeePass.Views
VisualStateManager.GoToState(this, "Small", true);
VisualStateManager.GoToState(TopMenu, "Collapsed", true);
VisualStateManager.GoToState(HamburgerMenu, "Hidden", true);
VisualStateManager.GoToState(Breadcrumb, "Small", true);
}
else if (e.NewSize.Width > 640 && e.NewSize.Width <= 1008)
{
VisualStateManager.GoToState(this, "Medium", true);
VisualStateManager.GoToState(TopMenu, "Overflowed", true);
VisualStateManager.GoToState(HamburgerMenu, "Collapsed", true);
VisualStateManager.GoToState(Breadcrumb, "Medium", true);
}
else
{
VisualStateManager.GoToState(this, "Large", true);
VisualStateManager.GoToState(TopMenu, "Overflowed", true);
VisualStateManager.GoToState(HamburgerMenu, "Expanded", true);
VisualStateManager.GoToState(Breadcrumb, "Large", true);
}
}

View File

@@ -53,24 +53,25 @@
</Button>
<TextBlock x:Name="TitleTextBox" Text="{Binding Name}" Grid.Column="1" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
<controls:ListViewWithDisable
<controls:DisableListView
Grid.Column="0"
Grid.Row="1"
x:Name="MenuListView"
ScrollViewer.VerticalScrollMode="Disabled"
SelectionChanged="ListView_SelectionChanged"
Background="{ThemeResource AppBarBackgroundThemeBrush}"
ItemsSource="{Binding Source={StaticResource MenuItemsSource}}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}">
<controls:ListViewWithDisable.ItemTemplate>
<controls:DisableListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="{Binding SymbolIcon}" />
<TextBlock Text="{Binding Title}" Margin="10,5,0,0" />
</StackPanel>
</DataTemplate>
</controls:ListViewWithDisable.ItemTemplate>
<controls:ListViewWithDisable.GroupStyle>
</controls:DisableListView.ItemTemplate>
<controls:DisableListView.GroupStyle>
<GroupStyle HidesIfEmpty="True">
<GroupStyle.HeaderTemplate>
<DataTemplate>
@@ -80,8 +81,8 @@
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</controls:ListViewWithDisable.GroupStyle>
</controls:ListViewWithDisable>
</controls:DisableListView.GroupStyle>
</controls:DisableListView>
<TextBlock x:Name="PageTitleTextBlock" Grid.Column="1" Grid.Row="0" FontSize="24" VerticalAlignment="Center" Margin="10,0,0,0" >
<Run Text="{Binding SelectedItem}" />
</TextBlock>

View File

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

View File

@@ -1,5 +1,5 @@
<Page
x:Class="ModernKeePass.Views.ImportExportPage"
x:Class="ModernKeePass.Views.ImportPage"
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"

View File

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

View File

@@ -1,5 +1,8 @@
// 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
{
/// <summary>
@@ -7,9 +10,16 @@ namespace ModernKeePass.Views
/// </summary>
public sealed partial class NewDatabasePage
{
public NewVm Model => (NewVm)DataContext;
public NewDatabasePage()
{
InitializeComponent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
Model.Cleanup();
}
}
}

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