mirror of
https://github.com/wismna/ModernKeePass.git
synced 2025-10-03 23:50:18 -04:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
80a255aa6f | ||
![]() |
1f06bf3ba7 | ||
![]() |
7dcd5a4a57 | ||
![]() |
c62ed584dc | ||
d6b17fe696 | |||
f477828628 | |||
![]() |
4a0bc1cb86 | ||
![]() |
4e7aca5517 | ||
![]() |
1f04f941c2 | ||
![]() |
5c1dfa1b0e |
@@ -36,6 +36,16 @@
|
|||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\ARM\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<PlatformTarget>ARM</PlatformTarget>
|
||||||
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
@@ -81,7 +91,6 @@
|
|||||||
<Compile Include="Common\Interfaces\IDatabaseProxy.cs" />
|
<Compile Include="Common\Interfaces\IDatabaseProxy.cs" />
|
||||||
<Compile Include="Common\Interfaces\IEntityVm.cs" />
|
<Compile Include="Common\Interfaces\IEntityVm.cs" />
|
||||||
<Compile Include="Common\Interfaces\IFileProxy.cs" />
|
<Compile Include="Common\Interfaces\IFileProxy.cs" />
|
||||||
<Compile Include="Common\Interfaces\IImportFormat.cs" />
|
|
||||||
<Compile Include="Common\Interfaces\ICredentialsProxy.cs" />
|
<Compile Include="Common\Interfaces\ICredentialsProxy.cs" />
|
||||||
<Compile Include="Common\Interfaces\ILogger.cs" />
|
<Compile Include="Common\Interfaces\ILogger.cs" />
|
||||||
<Compile Include="Common\Interfaces\INotificationService.cs" />
|
<Compile Include="Common\Interfaces\INotificationService.cs" />
|
||||||
@@ -90,6 +99,7 @@
|
|||||||
<Compile Include="Common\Interfaces\ISettingsProxy.cs" />
|
<Compile Include="Common\Interfaces\ISettingsProxy.cs" />
|
||||||
<Compile Include="Common\Mappings\IMapFrom.cs" />
|
<Compile Include="Common\Mappings\IMapFrom.cs" />
|
||||||
<Compile Include="Common\Mappings\MappingProfile.cs" />
|
<Compile Include="Common\Mappings\MappingProfile.cs" />
|
||||||
|
<Compile Include="Common\Models\BreadcrumbItem.cs" />
|
||||||
<Compile Include="Entry\Commands\AddAttachment\AddAttachmentCommand.cs" />
|
<Compile Include="Entry\Commands\AddAttachment\AddAttachmentCommand.cs" />
|
||||||
<Compile Include="Entry\Commands\AddHistory\AddHistoryCommand.cs" />
|
<Compile Include="Entry\Commands\AddHistory\AddHistoryCommand.cs" />
|
||||||
<Compile Include="Entry\Commands\DeleteAttachment\DeleteAttachmentCommand.cs" />
|
<Compile Include="Entry\Commands\DeleteAttachment\DeleteAttachmentCommand.cs" />
|
||||||
@@ -105,6 +115,8 @@
|
|||||||
<Compile Include="Group\Queries\GetAllGroups\GetAllGroupsQuery.cs" />
|
<Compile Include="Group\Queries\GetAllGroups\GetAllGroupsQuery.cs" />
|
||||||
<Compile Include="Group\Queries\GetGroup\GetGroupQuery.cs" />
|
<Compile Include="Group\Queries\GetGroup\GetGroupQuery.cs" />
|
||||||
<Compile Include="Group\Queries\SearchEntries\SearchEntriesQuery.cs" />
|
<Compile Include="Group\Queries\SearchEntries\SearchEntriesQuery.cs" />
|
||||||
|
<Compile Include="Import\Commands\ImportFromCsv\ImportFromCsvCommand.cs" />
|
||||||
|
<Compile Include="Import\Commands\ImportFromCsv\ImportFromCsvCommandValidator.cs" />
|
||||||
<Compile Include="Parameters\Commands\SetCipher\SetCipherCommand.cs" />
|
<Compile Include="Parameters\Commands\SetCipher\SetCipherCommand.cs" />
|
||||||
<Compile Include="Parameters\Commands\SetCompression\SetCompressionCommand.cs" />
|
<Compile Include="Parameters\Commands\SetCompression\SetCompressionCommand.cs" />
|
||||||
<Compile Include="Parameters\Commands\SetHasRecycleBin\SetHasRecycleBinCommand.cs" />
|
<Compile Include="Parameters\Commands\SetHasRecycleBin\SetHasRecycleBinCommand.cs" />
|
||||||
@@ -119,7 +131,7 @@
|
|||||||
<Compile Include="Parameters\Queries\GetKeyDerivations\GetKeyDerivationsQuery.cs" />
|
<Compile Include="Parameters\Queries\GetKeyDerivations\GetKeyDerivationsQuery.cs" />
|
||||||
<Compile Include="Database\Commands\CloseDatabase\CloseDatabaseCommand.cs" />
|
<Compile Include="Database\Commands\CloseDatabase\CloseDatabaseCommand.cs" />
|
||||||
<Compile Include="Database\Commands\CreateDatabase\CreateDatabaseCommand.cs" />
|
<Compile Include="Database\Commands\CreateDatabase\CreateDatabaseCommand.cs" />
|
||||||
<Compile Include="Database\Commands\CreateDatabase\CreateDatabaseQueryValidator.cs" />
|
<Compile Include="Database\Commands\CreateDatabase\CreateDatabaseCommandValidator.cs" />
|
||||||
<Compile Include="Database\Commands\SaveDatabase\SaveDatabaseCommand.cs" />
|
<Compile Include="Database\Commands\SaveDatabase\SaveDatabaseCommand.cs" />
|
||||||
<Compile Include="Database\Commands\UpdateCredentials\UpdateCredentialsCommand.cs" />
|
<Compile Include="Database\Commands\UpdateCredentials\UpdateCredentialsCommand.cs" />
|
||||||
<Compile Include="Database\Models\DatabaseVm.cs" />
|
<Compile Include="Database\Models\DatabaseVm.cs" />
|
||||||
|
@@ -1,9 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace ModernKeePass.Application.Common.Interfaces
|
|
||||||
{
|
|
||||||
public interface IImportFormat
|
|
||||||
{
|
|
||||||
List<Dictionary<string, string>> Import(IList<string> fileContents);
|
|
||||||
}
|
|
||||||
}
|
|
12
ModernKeePass.Application/Common/Models/BreadcrumbItem.cs
Normal file
12
ModernKeePass.Application/Common/Models/BreadcrumbItem.cs
Normal 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; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace ModernKeePass.Application.Database.Commands.CreateDatabase
|
namespace ModernKeePass.Application.Database.Commands.CreateDatabase
|
||||||
{
|
{
|
||||||
public class CreateDatabaseQueryValidator : AbstractValidator<CreateDatabaseCommand>
|
public class CreateDatabaseCommandValidator : AbstractValidator<CreateDatabaseCommand>
|
||||||
{
|
{
|
||||||
public CreateDatabaseQueryValidator()
|
public CreateDatabaseCommandValidator()
|
||||||
{
|
{
|
||||||
RuleFor(v => v.FilePath)
|
RuleFor(v => v.FilePath)
|
||||||
.NotNull()
|
.NotNull()
|
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -36,6 +36,16 @@
|
|||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\ARM\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<PlatformTarget>ARM</PlatformTarget>
|
||||||
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
|
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -44,6 +44,16 @@
|
|||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\ARM\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<PlatformTarget>ARM</PlatformTarget>
|
||||||
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
@@ -78,7 +88,6 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Common\MachineDateTime.cs" />
|
<Compile Include="Common\MachineDateTime.cs" />
|
||||||
<Compile Include="DependencyInjection.cs" />
|
<Compile Include="DependencyInjection.cs" />
|
||||||
<Compile Include="File\CsvImportFormat.cs" />
|
|
||||||
<Compile Include="KeePass\MappingProfiles.cs" />
|
<Compile Include="KeePass\MappingProfiles.cs" />
|
||||||
<Compile Include="KeePass\IconMapper.cs" />
|
<Compile Include="KeePass\IconMapper.cs" />
|
||||||
<Compile Include="KeePass\KeePassDatabaseSettingsProxy.cs" />
|
<Compile Include="KeePass\KeePassDatabaseSettingsProxy.cs" />
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest">
|
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest">
|
||||||
<Identity Name="wismna.ModernKeePass" Publisher="CN=0719A91A-C322-4EE0-A257-E60733EECF06" Version="1.19.0.12" />
|
<Identity Name="wismna.ModernKeePass" Publisher="CN=0719A91A-C322-4EE0-A257-E60733EECF06" Version="1.20.0.12" />
|
||||||
<Properties>
|
<Properties>
|
||||||
<DisplayName>ModernKeePass</DisplayName>
|
<DisplayName>ModernKeePass</DisplayName>
|
||||||
<PublisherDisplayName>wismna</PublisherDisplayName>
|
<PublisherDisplayName>wismna</PublisherDisplayName>
|
||||||
|
@@ -31,6 +31,7 @@ using ModernKeePass.Application.Group.Models;
|
|||||||
using ModernKeePass.Common;
|
using ModernKeePass.Common;
|
||||||
using ModernKeePass.Domain.Dtos;
|
using ModernKeePass.Domain.Dtos;
|
||||||
using ModernKeePass.Domain.Exceptions;
|
using ModernKeePass.Domain.Exceptions;
|
||||||
|
using ModernKeePass.Domain.Interfaces;
|
||||||
using ModernKeePass.Extensions;
|
using ModernKeePass.Extensions;
|
||||||
using ModernKeePass.Models;
|
using ModernKeePass.Models;
|
||||||
using ModernKeePass.ViewModels.ListItems;
|
using ModernKeePass.ViewModels.ListItems;
|
||||||
@@ -39,22 +40,22 @@ namespace ModernKeePass.ViewModels
|
|||||||
{
|
{
|
||||||
public class EntryDetailVm : ViewModelBase
|
public class EntryDetailVm : ViewModelBase
|
||||||
{
|
{
|
||||||
public bool HasExpired => HasExpirationDate && ExpiryDate < DateTime.Now;
|
public bool HasExpired => HasExpirationDate && ExpiryDate < _dateTime.Now;
|
||||||
|
|
||||||
public string Id => SelectedItem.Id;
|
public string Id => _current.Id;
|
||||||
|
|
||||||
public string ParentGroupName => _parent.Title;
|
public GroupVm Parent { get; private set; }
|
||||||
|
|
||||||
public bool IsRecycleOnDelete
|
public bool IsRecycleOnDelete
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var database = Database;
|
var database = Database;
|
||||||
return database.IsRecycleBinEnabled && _parent.Id != database.RecycleBinId;
|
return database.IsRecycleBinEnabled && Parent.Id != database.RecycleBinId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObservableCollection<EntryVm> History { get; private set; }
|
public ObservableCollection<IEntityVm> History { get; private set; }
|
||||||
public ObservableCollection<EntryFieldVm> AdditionalFields { get; private set; }
|
public ObservableCollection<EntryFieldVm> AdditionalFields { get; private set; }
|
||||||
public ObservableCollection<Attachment> Attachments { get; private set; }
|
public ObservableCollection<Attachment> Attachments { get; private set; }
|
||||||
|
|
||||||
@@ -63,37 +64,6 @@ namespace ModernKeePass.ViewModels
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsCurrentEntry => SelectedIndex == 0;
|
public bool IsCurrentEntry => SelectedIndex == 0;
|
||||||
|
|
||||||
public EntryVm SelectedItem
|
|
||||||
{
|
|
||||||
get { return _selectedItem; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Set(() => SelectedItem, ref _selectedItem, value, true);
|
|
||||||
if (value != null)
|
|
||||||
{
|
|
||||||
AdditionalFields =
|
|
||||||
new ObservableCollection<EntryFieldVm>(
|
|
||||||
SelectedItem.AdditionalFields.Select(f =>
|
|
||||||
{
|
|
||||||
var field = new EntryFieldVm(_cryptography);
|
|
||||||
field.Initialize(f.Name, f.Value, f.IsProtected);
|
|
||||||
return field;
|
|
||||||
}));
|
|
||||||
|
|
||||||
Attachments = new ObservableCollection<Attachment>(SelectedItem.Attachments.Select(f => new Attachment
|
|
||||||
{
|
|
||||||
Name = f.Key,
|
|
||||||
Content = f.Value
|
|
||||||
}));
|
|
||||||
Attachments.CollectionChanged += (sender, args) =>
|
|
||||||
{
|
|
||||||
UpdateDirtyStatus(true);
|
|
||||||
};
|
|
||||||
RaisePropertyChanged(string.Empty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int SelectedIndex
|
public int SelectedIndex
|
||||||
{
|
{
|
||||||
get { return _selectedIndex; }
|
get { return _selectedIndex; }
|
||||||
@@ -117,33 +87,33 @@ namespace ModernKeePass.ViewModels
|
|||||||
|
|
||||||
public string Title
|
public string Title
|
||||||
{
|
{
|
||||||
get { return SelectedItem.Title.Value; }
|
get { return _current.Title.Value; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SelectedItem.Title.Value = value;
|
_current.Title.Value = value;
|
||||||
SetFieldValue(SelectedItem.Title.Name, value, false).ConfigureAwait(false).GetAwaiter();
|
SetFieldValue(_current.Title.Name, value, false).ConfigureAwait(false).GetAwaiter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string UserName
|
public string UserName
|
||||||
{
|
{
|
||||||
get { return SelectedItem.Username.Value; }
|
get { return _current.Username.Value; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SelectedItem.Username.Value = value;
|
_current.Username.Value = value;
|
||||||
SetFieldValue(SelectedItem.Username.Name, value, false).ConfigureAwait(false).GetAwaiter();
|
SetFieldValue(_current.Username.Name, value, false).ConfigureAwait(false).GetAwaiter();
|
||||||
RaisePropertyChanged(nameof(UserName));
|
RaisePropertyChanged(nameof(UserName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Password
|
public string Password
|
||||||
{
|
{
|
||||||
get { return _cryptography.UnProtect(SelectedItem.Password.Value).GetAwaiter().GetResult(); }
|
get { return _cryptography.UnProtect(_current.Password.Value).GetAwaiter().GetResult(); }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
var protectedPassword = _cryptography.Protect(value).ConfigureAwait(false).GetAwaiter().GetResult();
|
var protectedPassword = _cryptography.Protect(value).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
SelectedItem.Password.Value = protectedPassword;
|
_current.Password.Value = protectedPassword;
|
||||||
SetFieldValue(SelectedItem.Password.Name, protectedPassword, true).ConfigureAwait(false).GetAwaiter();
|
SetFieldValue(_current.Password.Name, protectedPassword, true).ConfigureAwait(false).GetAwaiter();
|
||||||
|
|
||||||
RaisePropertyChanged(nameof(Password));
|
RaisePropertyChanged(nameof(Password));
|
||||||
}
|
}
|
||||||
@@ -151,65 +121,65 @@ namespace ModernKeePass.ViewModels
|
|||||||
|
|
||||||
public string Url
|
public string Url
|
||||||
{
|
{
|
||||||
get { return SelectedItem.Url.Value; }
|
get { return _current.Url.Value; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SelectedItem.Url.Value = value;
|
_current.Url.Value = value;
|
||||||
SetFieldValue(SelectedItem.Url.Name, value, false).ConfigureAwait(false).GetAwaiter();
|
SetFieldValue(_current.Url.Name, value, false).ConfigureAwait(false).GetAwaiter();
|
||||||
RaisePropertyChanged(nameof(Url));
|
RaisePropertyChanged(nameof(Url));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Notes
|
public string Notes
|
||||||
{
|
{
|
||||||
get { return SelectedItem.Notes.Value; }
|
get { return _current.Notes.Value; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SelectedItem.Notes.Value = value;
|
_current.Notes.Value = value;
|
||||||
SetFieldValue(SelectedItem.Notes.Name, value, false).ConfigureAwait(false).GetAwaiter();
|
SetFieldValue(_current.Notes.Name, value, false).ConfigureAwait(false).GetAwaiter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Symbol Icon
|
public Symbol Icon
|
||||||
{
|
{
|
||||||
get { return (Symbol)Enum.Parse(typeof(Symbol), SelectedItem.Icon.ToString()); }
|
get { return (Symbol)Enum.Parse(typeof(Symbol), _current.Icon.ToString()); }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SelectedItem.Icon = (Icon)Enum.Parse(typeof(Icon), value.ToString());
|
_current.Icon = (Icon)Enum.Parse(typeof(Icon), value.ToString());
|
||||||
SetFieldValue(EntryFieldName.Icon, SelectedItem.Icon, false).ConfigureAwait(false).GetAwaiter();
|
SetFieldValue(EntryFieldName.Icon, _current.Icon, false).ConfigureAwait(false).GetAwaiter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DateTimeOffset ExpiryDate
|
public DateTimeOffset ExpiryDate
|
||||||
{
|
{
|
||||||
get { return SelectedItem.ExpirationDate; }
|
get { return _current.ExpirationDate; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (!HasExpirationDate) return;
|
if (!HasExpirationDate) return;
|
||||||
|
|
||||||
SelectedItem.ExpirationDate = value.Date;
|
_current.ExpirationDate = value.Date;
|
||||||
SetFieldValue(EntryFieldName.ExpirationDate, SelectedItem.ExpirationDate, false).ConfigureAwait(false).GetAwaiter();
|
SetFieldValue(EntryFieldName.ExpirationDate, _current.ExpirationDate, false).ConfigureAwait(false).GetAwaiter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeSpan ExpiryTime
|
public TimeSpan ExpiryTime
|
||||||
{
|
{
|
||||||
get { return SelectedItem.ExpirationDate.TimeOfDay; }
|
get { return _current.ExpirationDate.TimeOfDay; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (!HasExpirationDate) return;
|
if (!HasExpirationDate) return;
|
||||||
|
|
||||||
SelectedItem.ExpirationDate = SelectedItem.ExpirationDate.Date.Add(value);
|
_current.ExpirationDate = _current.ExpirationDate.Date.Add(value);
|
||||||
SetFieldValue(EntryFieldName.ExpirationDate, SelectedItem.ExpirationDate, false).ConfigureAwait(false).GetAwaiter();
|
SetFieldValue(EntryFieldName.ExpirationDate, _current.ExpirationDate, false).ConfigureAwait(false).GetAwaiter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasExpirationDate
|
public bool HasExpirationDate
|
||||||
{
|
{
|
||||||
get { return SelectedItem.HasExpirationDate; }
|
get { return _current.HasExpirationDate; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SelectedItem.HasExpirationDate = value;
|
_current.HasExpirationDate = value;
|
||||||
SetFieldValue(EntryFieldName.HasExpirationDate, value, false).ConfigureAwait(false).GetAwaiter();
|
SetFieldValue(EntryFieldName.HasExpirationDate, value, false).ConfigureAwait(false).GetAwaiter();
|
||||||
RaisePropertyChanged(nameof(HasExpirationDate));
|
RaisePropertyChanged(nameof(HasExpirationDate));
|
||||||
}
|
}
|
||||||
@@ -217,41 +187,34 @@ namespace ModernKeePass.ViewModels
|
|||||||
|
|
||||||
public SolidColorBrush BackgroundColor
|
public SolidColorBrush BackgroundColor
|
||||||
{
|
{
|
||||||
get { return SelectedItem?.BackgroundColor.ToSolidColorBrush(); }
|
get { return _current?.BackgroundColor.ToSolidColorBrush(); }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SelectedItem.BackgroundColor = value.ToColor();
|
_current.BackgroundColor = value.ToColor();
|
||||||
SetFieldValue(EntryFieldName.BackgroundColor, SelectedItem.BackgroundColor, false).ConfigureAwait(false).GetAwaiter();
|
SetFieldValue(EntryFieldName.BackgroundColor, _current.BackgroundColor, false).ConfigureAwait(false).GetAwaiter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SolidColorBrush ForegroundColor
|
public SolidColorBrush ForegroundColor
|
||||||
{
|
{
|
||||||
get { return SelectedItem?.ForegroundColor.ToSolidColorBrush(); }
|
get { return _current?.ForegroundColor.ToSolidColorBrush(); }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SelectedItem.ForegroundColor = value.ToColor();
|
_current.ForegroundColor = value.ToColor();
|
||||||
SetFieldValue(EntryFieldName.ForegroundColor, SelectedItem.ForegroundColor, false).ConfigureAwait(false).GetAwaiter();
|
SetFieldValue(EntryFieldName.ForegroundColor, _current.ForegroundColor, false).ConfigureAwait(false).GetAwaiter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsEditMode
|
|
||||||
{
|
|
||||||
get { return IsCurrentEntry && _isEditMode; }
|
|
||||||
set { Set(() => IsEditMode, ref _isEditMode, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public RelayCommand SaveCommand { get; }
|
public RelayCommand SaveCommand { get; }
|
||||||
public RelayCommand<string> MoveCommand { get; }
|
public RelayCommand<string> MoveCommand { get; }
|
||||||
public RelayCommand RestoreCommand { get; }
|
public RelayCommand RestoreCommand { get; }
|
||||||
public RelayCommand DeleteCommand { get; }
|
public RelayCommand DeleteCommand { get; }
|
||||||
public RelayCommand GoBackCommand { get; }
|
public RelayCommand AddAdditionalField { get; }
|
||||||
public RelayCommand GoToParentCommand { get; set; }
|
public RelayCommand<EntryFieldVm> DeleteAdditionalField { get; }
|
||||||
public RelayCommand AddAdditionalField { get; set; }
|
public RelayCommand<Attachment> OpenAttachmentCommand { get; }
|
||||||
public RelayCommand<EntryFieldVm> DeleteAdditionalField { get; set; }
|
public RelayCommand AddAttachmentCommand { get; }
|
||||||
public RelayCommand<Attachment> OpenAttachmentCommand { get; set; }
|
public RelayCommand<Attachment> DeleteAttachmentCommand { get; }
|
||||||
public RelayCommand AddAttachmentCommand { get; set; }
|
public RelayCommand<EntryVm> SetCurrentEntryCommand { get; }
|
||||||
public RelayCommand<Attachment> DeleteAttachmentCommand { get; set; }
|
|
||||||
|
|
||||||
private DatabaseVm Database => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
|
private DatabaseVm Database => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
|
||||||
|
|
||||||
@@ -262,14 +225,13 @@ namespace ModernKeePass.ViewModels
|
|||||||
private readonly INotificationService _notification;
|
private readonly INotificationService _notification;
|
||||||
private readonly IFileProxy _file;
|
private readonly IFileProxy _file;
|
||||||
private readonly ICryptographyClient _cryptography;
|
private readonly ICryptographyClient _cryptography;
|
||||||
private GroupVm _parent;
|
private readonly IDateTime _dateTime;
|
||||||
private EntryVm _selectedItem;
|
private EntryVm _current;
|
||||||
private int _selectedIndex;
|
private int _selectedIndex;
|
||||||
private int _additionalFieldSelectedIndex = -1;
|
private int _additionalFieldSelectedIndex = -1;
|
||||||
private bool _isEditMode;
|
|
||||||
private bool _isDirty;
|
private bool _isDirty;
|
||||||
|
|
||||||
public EntryDetailVm(IMediator mediator, INavigationService navigation, IResourceProxy resource, IDialogService dialog, INotificationService notification, IFileProxy file, ICryptographyClient cryptography)
|
public EntryDetailVm(IMediator mediator, INavigationService navigation, IResourceProxy resource, IDialogService dialog, INotificationService notification, IFileProxy file, ICryptographyClient cryptography, IDateTime dateTime)
|
||||||
{
|
{
|
||||||
_mediator = mediator;
|
_mediator = mediator;
|
||||||
_navigation = navigation;
|
_navigation = navigation;
|
||||||
@@ -278,18 +240,18 @@ namespace ModernKeePass.ViewModels
|
|||||||
_notification = notification;
|
_notification = notification;
|
||||||
_file = file;
|
_file = file;
|
||||||
_cryptography = cryptography;
|
_cryptography = cryptography;
|
||||||
|
_dateTime = dateTime;
|
||||||
|
|
||||||
SaveCommand = new RelayCommand(async () => await SaveChanges(), () => Database.IsDirty);
|
SaveCommand = new RelayCommand(async () => await SaveChanges(), () => Database.IsDirty);
|
||||||
MoveCommand = new RelayCommand<string>(async destination => await Move(destination), destination => _parent != null && !string.IsNullOrEmpty(destination) && destination != _parent.Id);
|
MoveCommand = new RelayCommand<string>(async destination => await Move(destination), destination => Parent != null && !string.IsNullOrEmpty(destination) && destination != Parent.Id);
|
||||||
RestoreCommand = new RelayCommand(async () => await RestoreHistory());
|
RestoreCommand = new RelayCommand(async () => await RestoreHistory());
|
||||||
DeleteCommand = new RelayCommand(async () => await AskForDelete());
|
DeleteCommand = new RelayCommand(async () => await AskForDelete());
|
||||||
GoBackCommand = new RelayCommand(() => _navigation.GoBack());
|
|
||||||
GoToParentCommand = new RelayCommand(() => GoToGroup(_parent.Id));
|
|
||||||
AddAdditionalField = new RelayCommand(AddField, () => IsCurrentEntry);
|
AddAdditionalField = new RelayCommand(AddField, () => IsCurrentEntry);
|
||||||
DeleteAdditionalField = new RelayCommand<EntryFieldVm>(async field => await DeleteField(field), field => field != null && IsCurrentEntry);
|
DeleteAdditionalField = new RelayCommand<EntryFieldVm>(async field => await DeleteField(field), field => field != null && IsCurrentEntry);
|
||||||
OpenAttachmentCommand = new RelayCommand<Attachment>(async attachment => await OpenAttachment(attachment));
|
OpenAttachmentCommand = new RelayCommand<Attachment>(async attachment => await OpenAttachment(attachment));
|
||||||
AddAttachmentCommand = new RelayCommand(async () => await AddAttachment(), () => IsCurrentEntry);
|
AddAttachmentCommand = new RelayCommand(async () => await AddAttachment(), () => IsCurrentEntry);
|
||||||
DeleteAttachmentCommand = new RelayCommand<Attachment>(async attachment => await DeleteAttachment(attachment), _ => IsCurrentEntry);
|
DeleteAttachmentCommand = new RelayCommand<Attachment>(async attachment => await DeleteAttachment(attachment), _ => IsCurrentEntry);
|
||||||
|
SetCurrentEntryCommand = new RelayCommand<EntryVm>(SetCurrentEntry, entry => entry != null);
|
||||||
|
|
||||||
MessengerInstance.Register<DatabaseSavedMessage>(this, _ => SaveCommand.RaiseCanExecuteChanged());
|
MessengerInstance.Register<DatabaseSavedMessage>(this, _ => SaveCommand.RaiseCanExecuteChanged());
|
||||||
MessengerInstance.Register<EntryFieldValueChangedMessage>(this, async message => await SetFieldValue(message.FieldName, message.FieldValue, message.IsProtected));
|
MessengerInstance.Register<EntryFieldValueChangedMessage>(this, async message => await SetFieldValue(message.FieldName, message.FieldValue, message.IsProtected));
|
||||||
@@ -300,10 +262,11 @@ namespace ModernKeePass.ViewModels
|
|||||||
public async Task Initialize(string entryId)
|
public async Task Initialize(string entryId)
|
||||||
{
|
{
|
||||||
SelectedIndex = 0;
|
SelectedIndex = 0;
|
||||||
SelectedItem = await _mediator.Send(new GetEntryQuery { Id = entryId });
|
_current = await _mediator.Send(new GetEntryQuery { Id = entryId });
|
||||||
_parent = await _mediator.Send(new GetGroupQuery { Id = SelectedItem.ParentGroupId });
|
SetCurrentEntry(_current);
|
||||||
History = new ObservableCollection<EntryVm> { SelectedItem };
|
Parent = await _mediator.Send(new GetGroupQuery { Id = _current.ParentGroupId });
|
||||||
foreach (var entry in SelectedItem.History.Skip(1))
|
History = new ObservableCollection<IEntityVm> { _current };
|
||||||
|
foreach (var entry in _current.History.Skip(1))
|
||||||
{
|
{
|
||||||
History.Add(entry);
|
History.Add(entry);
|
||||||
}
|
}
|
||||||
@@ -316,7 +279,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
|
|
||||||
public async Task AddHistory()
|
public async Task AddHistory()
|
||||||
{
|
{
|
||||||
if (_isDirty && Database.IsOpen) await _mediator.Send(new AddHistoryCommand { Entry = History[0] });
|
if (_isDirty && Database.IsOpen) await _mediator.Send(new AddHistoryCommand { Entry = History[0] as EntryVm });
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GoToGroup(string groupId)
|
public void GoToGroup(string groupId)
|
||||||
@@ -327,7 +290,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
private async Task Move(string destination)
|
private async Task Move(string destination)
|
||||||
{
|
{
|
||||||
await _mediator.Send(new AddEntryCommand { ParentGroupId = destination, EntryId = Id });
|
await _mediator.Send(new AddEntryCommand { ParentGroupId = destination, EntryId = Id });
|
||||||
await _mediator.Send(new RemoveEntryCommand { ParentGroupId = _parent.Id, EntryId = Id });
|
await _mediator.Send(new RemoveEntryCommand { ParentGroupId = Parent.Id, EntryId = Id });
|
||||||
GoToGroup(destination);
|
GoToGroup(destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,7 +352,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
_resource.GetResourceValue("EntityDeleteCancelButton"), async isOk =>
|
_resource.GetResourceValue("EntityDeleteCancelButton"), async isOk =>
|
||||||
{
|
{
|
||||||
if (!isOk) return;
|
if (!isOk) return;
|
||||||
await _mediator.Send(new DeleteHistoryCommand { Entry = History[0], HistoryIndex = History.Count - SelectedIndex - 1 });
|
await _mediator.Send(new DeleteHistoryCommand { Entry = History[0] as EntryVm, HistoryIndex = History.Count - SelectedIndex - 1 });
|
||||||
History.RemoveAt(SelectedIndex);
|
History.RemoveAt(SelectedIndex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -397,8 +360,8 @@ namespace ModernKeePass.ViewModels
|
|||||||
|
|
||||||
private async Task RestoreHistory()
|
private async Task RestoreHistory()
|
||||||
{
|
{
|
||||||
await _mediator.Send(new RestoreHistoryCommand { Entry = History[0], HistoryIndex = History.Count - SelectedIndex - 1 });
|
await _mediator.Send(new RestoreHistoryCommand { Entry = History[0] as EntryVm, HistoryIndex = History.Count - SelectedIndex - 1 });
|
||||||
History.Insert(0, SelectedItem);
|
History.Insert(0, _current);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SaveChanges()
|
private async Task SaveChanges()
|
||||||
@@ -420,7 +383,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
await _mediator.Send(new DeleteEntryCommand
|
await _mediator.Send(new DeleteEntryCommand
|
||||||
{
|
{
|
||||||
EntryId = Id,
|
EntryId = Id,
|
||||||
ParentGroupId = SelectedItem.ParentGroupId,
|
ParentGroupId = _current.ParentGroupId,
|
||||||
RecycleBinName = _resource.GetResourceValue("RecycleBinTitle")
|
RecycleBinName = _resource.GetResourceValue("RecycleBinTitle")
|
||||||
});
|
});
|
||||||
_isDirty = false;
|
_isDirty = false;
|
||||||
@@ -443,13 +406,13 @@ namespace ModernKeePass.ViewModels
|
|||||||
var fileInfo = await _file.OpenFile(string.Empty, Domain.Common.Constants.Extensions.Any, false);
|
var fileInfo = await _file.OpenFile(string.Empty, Domain.Common.Constants.Extensions.Any, false);
|
||||||
if (fileInfo == null) return;
|
if (fileInfo == null) return;
|
||||||
var contents = await _file.ReadBinaryFile(fileInfo.Id);
|
var contents = await _file.ReadBinaryFile(fileInfo.Id);
|
||||||
await _mediator.Send(new AddAttachmentCommand { Entry = SelectedItem, AttachmentName = fileInfo.Name, AttachmentContent = contents });
|
await _mediator.Send(new AddAttachmentCommand { Entry = _current, AttachmentName = fileInfo.Name, AttachmentContent = contents });
|
||||||
Attachments.Add(new Attachment { Name = fileInfo.Name, Content = contents });
|
Attachments.Add(new Attachment { Name = fileInfo.Name, Content = contents });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DeleteAttachment(Attachment attachment)
|
private async Task DeleteAttachment(Attachment attachment)
|
||||||
{
|
{
|
||||||
await _mediator.Send(new DeleteAttachmentCommand { Entry = SelectedItem, AttachmentName = attachment.Name });
|
await _mediator.Send(new DeleteAttachmentCommand { Entry = _current, AttachmentName = attachment.Name });
|
||||||
Attachments.Remove(attachment);
|
Attachments.Remove(attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,5 +421,29 @@ namespace ModernKeePass.ViewModels
|
|||||||
SaveCommand.RaiseCanExecuteChanged();
|
SaveCommand.RaiseCanExecuteChanged();
|
||||||
_isDirty = isDirty;
|
_isDirty = isDirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetCurrentEntry(EntryVm entry)
|
||||||
|
{
|
||||||
|
_current = entry;
|
||||||
|
AdditionalFields =
|
||||||
|
new ObservableCollection<EntryFieldVm>(
|
||||||
|
entry.AdditionalFields.Select(f =>
|
||||||
|
{
|
||||||
|
var field = new EntryFieldVm(_cryptography);
|
||||||
|
field.Initialize(f.Name, f.Value, f.IsProtected);
|
||||||
|
return field;
|
||||||
|
}));
|
||||||
|
|
||||||
|
Attachments = new ObservableCollection<Attachment>(entry.Attachments.Select(f => new Attachment
|
||||||
|
{
|
||||||
|
Name = f.Key,
|
||||||
|
Content = f.Value
|
||||||
|
}));
|
||||||
|
Attachments.CollectionChanged += (sender, args) =>
|
||||||
|
{
|
||||||
|
UpdateDirtyStatus(true);
|
||||||
|
};
|
||||||
|
RaisePropertyChanged(string.Empty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,7 @@ using ModernKeePass.Application.Group.Commands.AddEntry;
|
|||||||
using ModernKeePass.Application.Group.Commands.AddGroup;
|
using ModernKeePass.Application.Group.Commands.AddGroup;
|
||||||
using ModernKeePass.Application.Group.Commands.CreateEntry;
|
using ModernKeePass.Application.Group.Commands.CreateEntry;
|
||||||
using ModernKeePass.Application.Group.Commands.CreateGroup;
|
using ModernKeePass.Application.Group.Commands.CreateGroup;
|
||||||
|
using ModernKeePass.Application.Group.Commands.DeleteEntry;
|
||||||
using ModernKeePass.Application.Group.Commands.DeleteGroup;
|
using ModernKeePass.Application.Group.Commands.DeleteGroup;
|
||||||
using ModernKeePass.Application.Group.Commands.MoveEntry;
|
using ModernKeePass.Application.Group.Commands.MoveEntry;
|
||||||
using ModernKeePass.Application.Group.Commands.MoveGroup;
|
using ModernKeePass.Application.Group.Commands.MoveGroup;
|
||||||
@@ -38,10 +39,12 @@ namespace ModernKeePass.ViewModels
|
|||||||
{
|
{
|
||||||
public ObservableCollection<EntryVm> Entries { get; private set; }
|
public ObservableCollection<EntryVm> Entries { get; private set; }
|
||||||
|
|
||||||
public ObservableCollection<GroupVm> Groups { get; private set; }
|
public ObservableCollection<IEntityVm> Groups { get; private set; }
|
||||||
|
|
||||||
public bool IsNotRoot => Database.RootGroupId != _group.Id;
|
public bool IsNotRoot => Database.RootGroupId != _group.Id;
|
||||||
|
|
||||||
|
public GroupVm Parent { get; private set; }
|
||||||
|
|
||||||
public IOrderedEnumerable<IGrouping<char, EntryVm>> EntriesZoomedOut => from e in Entries
|
public IOrderedEnumerable<IGrouping<char, EntryVm>> EntriesZoomedOut => from e in Entries
|
||||||
group e by (e.Title.Value ?? string.Empty).ToUpper().FirstOrDefault() into grp
|
group e by (e.Title.Value ?? string.Empty).ToUpper().FirstOrDefault() into grp
|
||||||
orderby grp.Key
|
orderby grp.Key
|
||||||
@@ -80,11 +83,11 @@ namespace ModernKeePass.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ParentGroupName => _parent?.Title;
|
public string ParentGroupName => Parent == null ? Database.Name : Parent.Title;
|
||||||
|
|
||||||
public bool IsRecycleOnDelete => Database.IsRecycleBinEnabled && !IsInRecycleBin;
|
public bool IsRecycleOnDelete => Database.IsRecycleBinEnabled && !IsInRecycleBin;
|
||||||
|
|
||||||
public bool IsInRecycleBin => _parent != null && _parent.Id == Database.RecycleBinId;
|
public bool IsInRecycleBin => Parent != null && Parent.Id == Database.RecycleBinId;
|
||||||
|
|
||||||
public RelayCommand SaveCommand { get; }
|
public RelayCommand SaveCommand { get; }
|
||||||
public RelayCommand SortEntriesCommand { get; }
|
public RelayCommand SortEntriesCommand { get; }
|
||||||
@@ -92,9 +95,12 @@ namespace ModernKeePass.ViewModels
|
|||||||
public RelayCommand<string> MoveCommand { get; }
|
public RelayCommand<string> MoveCommand { get; }
|
||||||
public RelayCommand CreateEntryCommand { get; }
|
public RelayCommand CreateEntryCommand { get; }
|
||||||
public RelayCommand<string> CreateGroupCommand { get; }
|
public RelayCommand<string> CreateGroupCommand { get; }
|
||||||
public RelayCommand DeleteCommand { get; set; }
|
public RelayCommand DeleteCommand { get; }
|
||||||
public RelayCommand GoBackCommand { get; set; }
|
public RelayCommand GoBackCommand { get; }
|
||||||
public RelayCommand GoToParentCommand { get; set; }
|
public RelayCommand GoToParentCommand { get; }
|
||||||
|
public RelayCommand<GroupVm> GoToGroupCommand { get; }
|
||||||
|
public RelayCommand<EntryVm> GoToEntryCommand { get; }
|
||||||
|
public RelayCommand<EntryVm> DeleteEntryCommand { get; }
|
||||||
|
|
||||||
private DatabaseVm Database => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
|
private DatabaseVm Database => _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
|
||||||
|
|
||||||
@@ -104,7 +110,6 @@ namespace ModernKeePass.ViewModels
|
|||||||
private readonly IDialogService _dialog;
|
private readonly IDialogService _dialog;
|
||||||
private readonly INotificationService _notification;
|
private readonly INotificationService _notification;
|
||||||
private GroupVm _group;
|
private GroupVm _group;
|
||||||
private GroupVm _parent;
|
|
||||||
private bool _isEditMode;
|
private bool _isEditMode;
|
||||||
private EntryVm _reorderedEntry;
|
private EntryVm _reorderedEntry;
|
||||||
private GroupVm _reorderedGroup;
|
private GroupVm _reorderedGroup;
|
||||||
@@ -125,7 +130,10 @@ namespace ModernKeePass.ViewModels
|
|||||||
CreateGroupCommand = new RelayCommand<string>(async newGroupName => await AddNewGroup(newGroupName), _ => !IsInRecycleBin && Database.RecycleBinId != Id);
|
CreateGroupCommand = new RelayCommand<string>(async newGroupName => await AddNewGroup(newGroupName), _ => !IsInRecycleBin && Database.RecycleBinId != Id);
|
||||||
DeleteCommand = new RelayCommand(async () => await AskForDelete(),() => IsNotRoot);
|
DeleteCommand = new RelayCommand(async () => await AskForDelete(),() => IsNotRoot);
|
||||||
GoBackCommand = new RelayCommand(() => _navigation.GoBack());
|
GoBackCommand = new RelayCommand(() => _navigation.GoBack());
|
||||||
GoToParentCommand= new RelayCommand(() => GoToGroup(_parent.Id), () => _parent != null);
|
GoToParentCommand = new RelayCommand(() => GoToGroup(Parent.Id), () => Parent != null);
|
||||||
|
GoToGroupCommand = new RelayCommand<GroupVm>(group => GoToGroup(group.Id), group => group != null);
|
||||||
|
GoToEntryCommand = new RelayCommand<EntryVm>(entry => GoToEntry(entry.Id), entry => entry != null);
|
||||||
|
DeleteEntryCommand = new RelayCommand<EntryVm>(async entry => await AskForDeleteEntry(entry), entry => entry != null);
|
||||||
|
|
||||||
MessengerInstance.Register<DatabaseSavedMessage>(this, _ => SaveCommand.RaiseCanExecuteChanged());
|
MessengerInstance.Register<DatabaseSavedMessage>(this, _ => SaveCommand.RaiseCanExecuteChanged());
|
||||||
}
|
}
|
||||||
@@ -135,12 +143,13 @@ namespace ModernKeePass.ViewModels
|
|||||||
_group = await _mediator.Send(new GetGroupQuery { Id = groupId });
|
_group = await _mediator.Send(new GetGroupQuery { Id = groupId });
|
||||||
if (!string.IsNullOrEmpty(_group.ParentGroupId))
|
if (!string.IsNullOrEmpty(_group.ParentGroupId))
|
||||||
{
|
{
|
||||||
_parent = await _mediator.Send(new GetGroupQuery { Id = _group.ParentGroupId });
|
Parent = await _mediator.Send(new GetGroupQuery {Id = _group.ParentGroupId});
|
||||||
}
|
}
|
||||||
|
else Parent = null;
|
||||||
|
|
||||||
Entries = new ObservableCollection<EntryVm>(_group.Entries);
|
Entries = new ObservableCollection<EntryVm>(_group.Entries);
|
||||||
Entries.CollectionChanged += Entries_CollectionChanged;
|
Entries.CollectionChanged += Entries_CollectionChanged;
|
||||||
Groups = new ObservableCollection<GroupVm>(_group.Groups);
|
Groups = new ObservableCollection<IEntityVm>(_group.Groups);
|
||||||
Groups.CollectionChanged += Groups_CollectionChanged;
|
Groups.CollectionChanged += Groups_CollectionChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +185,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
public async Task Move(string destinationId)
|
public async Task Move(string destinationId)
|
||||||
{
|
{
|
||||||
await _mediator.Send(new AddGroupCommand {ParentGroupId = destinationId, GroupId = Id });
|
await _mediator.Send(new AddGroupCommand {ParentGroupId = destinationId, GroupId = Id });
|
||||||
await _mediator.Send(new RemoveGroupCommand {ParentGroupId = _parent.Id, GroupId = Id });
|
await _mediator.Send(new RemoveGroupCommand {ParentGroupId = Parent.Id, GroupId = Id });
|
||||||
GoToGroup(destinationId);
|
GoToGroup(destinationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +260,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
private async Task SortGroupsAsync()
|
private async Task SortGroupsAsync()
|
||||||
{
|
{
|
||||||
await _mediator.Send(new SortGroupsCommand {Group = _group});
|
await _mediator.Send(new SortGroupsCommand {Group = _group});
|
||||||
Groups = new ObservableCollection<GroupVm>(_group.Groups);
|
Groups = new ObservableCollection<IEntityVm>(_group.Groups);
|
||||||
RaisePropertyChanged(nameof(Groups));
|
RaisePropertyChanged(nameof(Groups));
|
||||||
SaveCommand.RaiseCanExecuteChanged();
|
SaveCommand.RaiseCanExecuteChanged();
|
||||||
}
|
}
|
||||||
@@ -285,7 +294,39 @@ namespace ModernKeePass.ViewModels
|
|||||||
ParentGroupId = _group.ParentGroupId,
|
ParentGroupId = _group.ParentGroupId,
|
||||||
RecycleBinName = _resource.GetResourceValue("RecycleBinTitle")
|
RecycleBinName = _resource.GetResourceValue("RecycleBinTitle")
|
||||||
});
|
});
|
||||||
|
|
||||||
_navigation.GoBack();
|
_navigation.GoBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task AskForDeleteEntry(EntryVm entry)
|
||||||
|
{
|
||||||
|
if (IsRecycleOnDelete)
|
||||||
|
{
|
||||||
|
await DeleteEntry(entry);
|
||||||
|
_notification.Show(_resource.GetResourceValue("EntityDeleting"), string.Format(_resource.GetResourceValue("EntryRecycled"), entry.Title));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _dialog.ShowMessage(
|
||||||
|
string.Format(_resource.GetResourceValue("EntryDeletingConfirmation"), entry.Title),
|
||||||
|
_resource.GetResourceValue("EntityDeleting"),
|
||||||
|
_resource.GetResourceValue("EntityDeleteActionButton"),
|
||||||
|
_resource.GetResourceValue("EntityDeleteCancelButton"),
|
||||||
|
async isOk =>
|
||||||
|
{
|
||||||
|
if (isOk) await DeleteEntry(entry);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private async Task DeleteEntry(EntryVm entry)
|
||||||
|
{
|
||||||
|
await _mediator.Send(new DeleteEntryCommand
|
||||||
|
{
|
||||||
|
EntryId = entry.Id,
|
||||||
|
ParentGroupId = Id,
|
||||||
|
RecycleBinName = _resource.GetResourceValue("RecycleBinTitle")
|
||||||
|
});
|
||||||
|
Entries.Remove(entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -32,14 +32,8 @@
|
|||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<controls:HamburgerMenuUserControl
|
|
||||||
x:Name="HamburgerMenu"
|
|
||||||
x:Uid="HistoryLeftListView"
|
|
||||||
ItemsSource="{Binding History}"
|
|
||||||
SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}"
|
|
||||||
SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
|
|
||||||
<Grid Grid.Column="1">
|
<Grid Grid.Column="1">
|
||||||
<Hub Padding="0">
|
<Hub x:Name="Hub" Padding="0">
|
||||||
<Hub.Resources>
|
<Hub.Resources>
|
||||||
<Style TargetType="TextBlock" x:Key="EntryTextBlockStyle">
|
<Style TargetType="TextBlock" x:Key="EntryTextBlockStyle">
|
||||||
<Setter Property="Margin" Value="0,20,0,0"/>
|
<Setter Property="Margin" Value="0,20,0,0"/>
|
||||||
@@ -57,6 +51,15 @@
|
|||||||
<Setter Property="FontSize" Value="18"/>
|
<Setter Property="FontSize" Value="18"/>
|
||||||
</Style>
|
</Style>
|
||||||
</StackPanel.Resources>
|
</StackPanel.Resources>
|
||||||
|
<TextBlock x:Uid="EntryTitle" Style="{StaticResource EntryTextBlockStyle}" />
|
||||||
|
<local:TextBoxWithButton x:Uid="TitleTextBox" Text="{Binding Title, Mode=TwoWay}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonContent="" IsEnabled="{Binding IsCurrentEntry}">
|
||||||
|
<interactivity:Interaction.Behaviors>
|
||||||
|
<core:EventTriggerBehavior EventName="ButtonClick">
|
||||||
|
<actions:ClipboardAction Text="{Binding Title}" />
|
||||||
|
<actions:ToastAction x:Uid="ToastCopyTitle" Title="{Binding Title}" />
|
||||||
|
</core:EventTriggerBehavior>
|
||||||
|
</interactivity:Interaction.Behaviors>
|
||||||
|
</local:TextBoxWithButton>
|
||||||
<TextBlock x:Uid="EntryLogin" Style="{StaticResource EntryTextBlockStyle}" />
|
<TextBlock x:Uid="EntryLogin" Style="{StaticResource EntryTextBlockStyle}" />
|
||||||
<local:TextBoxWithButton x:Uid="LoginTextBox" Text="{Binding UserName, Mode=TwoWay}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonContent="" IsEnabled="{Binding IsCurrentEntry}">
|
<local:TextBoxWithButton x:Uid="LoginTextBox" Text="{Binding UserName, Mode=TwoWay}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonContent="" IsEnabled="{Binding IsCurrentEntry}">
|
||||||
<interactivity:Interaction.Behaviors>
|
<interactivity:Interaction.Behaviors>
|
||||||
@@ -209,62 +212,28 @@
|
|||||||
</HubSection>
|
</HubSection>
|
||||||
</Hub>
|
</Hub>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<controls:HamburgerMenuUserControl
|
||||||
|
Grid.Column="0"
|
||||||
|
x:Name="HamburgerMenu"
|
||||||
|
x:Uid="HistoryLeftListView"
|
||||||
|
ItemsSource="{Binding History}"
|
||||||
|
SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}">
|
||||||
|
<interactivity:Interaction.Behaviors>
|
||||||
|
<core:EventTriggerBehavior EventName="SelectionChanged">
|
||||||
|
<core:InvokeCommandAction Command="{Binding SetCurrentEntryCommand}" CommandParameter="{Binding SelectedItem, ElementName=HamburgerMenu}" />
|
||||||
|
</core:EventTriggerBehavior>
|
||||||
|
</interactivity:Interaction.Behaviors>
|
||||||
|
</controls:HamburgerMenuUserControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
<!-- Bouton Précédent et titre de la page -->
|
<!-- Bouton Précédent et titre de la page -->
|
||||||
<Grid Grid.Row="0" Background="{ThemeResource AppBarBackgroundThemeBrush}">
|
<Grid Grid.Row="0" Background="{ThemeResource AppBarBackgroundThemeBrush}">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="{StaticResource MenuWidthGridLength}"/>
|
|
||||||
<ColumnDefinition Width="{StaticResource MenuWidthGridLength}"/>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Button Grid.Column="0"
|
<controls:BreadcrumbUserControl x:Name="Breadcrumb" Group="{Binding Parent}" />
|
||||||
Command="{Binding GoBackCommand}"
|
|
||||||
Height="{StaticResource MenuHeight}"
|
|
||||||
Width="{StaticResource MenuWidth}"
|
|
||||||
AutomationProperties.Name="Back"
|
|
||||||
AutomationProperties.AutomationId="BackButton"
|
|
||||||
AutomationProperties.ItemType="Navigation Button"
|
|
||||||
Style="{StaticResource NoBorderButtonStyle}">
|
|
||||||
<SymbolIcon Symbol="Back" />
|
|
||||||
</Button>
|
|
||||||
<Button Grid.Column="1"
|
|
||||||
Height="{StaticResource MenuHeight}"
|
|
||||||
Width="{StaticResource MenuWidth}"
|
|
||||||
Command="{Binding GoToParentCommand}"
|
|
||||||
Style="{StaticResource NoBorderButtonStyle}">
|
|
||||||
<SymbolIcon Symbol="Up" />
|
|
||||||
<ToolTipService.ToolTip>
|
|
||||||
<ToolTip Content="{Binding ParentGroupName}" />
|
|
||||||
</ToolTipService.ToolTip>
|
|
||||||
</Button>
|
|
||||||
<Viewbox Grid.Column="2" MaxHeight="200">
|
|
||||||
<SymbolIcon Symbol="{Binding Icon}" Width="100" Height="70" />
|
|
||||||
</Viewbox>
|
|
||||||
<TextBox Grid.Column="3"
|
|
||||||
x:Uid="EntryTitle"
|
|
||||||
x:Name="TitleTextBox"
|
|
||||||
Text="{Binding Title, Mode=TwoWay}"
|
|
||||||
Background="Transparent"
|
|
||||||
IsHitTestVisible="{Binding IsEditMode}"
|
|
||||||
FontSize="20"
|
|
||||||
FontWeight="Light"
|
|
||||||
TextWrapping="NoWrap"
|
|
||||||
VerticalAlignment="Center">
|
|
||||||
<interactivity:Interaction.Behaviors>
|
|
||||||
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="True">
|
|
||||||
<actions:SetupFocusAction TargetObject="{Binding ElementName=TitleTextBox}" />
|
|
||||||
<core:ChangePropertyAction TargetObject="{Binding ElementName=TitleTextBox}" PropertyName="BorderThickness" Value="2" />
|
|
||||||
</core:DataTriggerBehavior>
|
|
||||||
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="False">
|
|
||||||
<core:ChangePropertyAction TargetObject="{Binding ElementName=TitleTextBox}" PropertyName="BorderThickness" Value="0" />
|
|
||||||
</core:DataTriggerBehavior>
|
|
||||||
</interactivity:Interaction.Behaviors>
|
|
||||||
</TextBox>
|
|
||||||
<controls:TopMenuUserControl
|
<controls:TopMenuUserControl
|
||||||
x:Name="TopMenu" Grid.Column="4"
|
x:Name="TopMenu" Grid.Column="1"
|
||||||
IsEditButtonChecked="{Binding IsEditMode, Mode=TwoWay}"
|
|
||||||
MoveButtonVisibility="{Binding IsCurrentEntry, Converter={StaticResource BooleanToVisibilityConverter}}"
|
MoveButtonVisibility="{Binding IsCurrentEntry, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||||
RestoreButtonVisibility="{Binding IsCurrentEntry, Converter={StaticResource InverseBooleanToVisibilityConverter}}"
|
RestoreButtonVisibility="{Binding IsCurrentEntry, Converter={StaticResource InverseBooleanToVisibilityConverter}}"
|
||||||
SaveCommand="{Binding SaveCommand}"
|
SaveCommand="{Binding SaveCommand}"
|
||||||
@@ -278,5 +247,30 @@
|
|||||||
</interactivity:Interaction.Behaviors>
|
</interactivity:Interaction.Behaviors>
|
||||||
</controls:TopMenuUserControl>
|
</controls:TopMenuUserControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="PageLayout">
|
||||||
|
<VisualState x:Name="Small">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Hub" Storyboard.TargetProperty="Margin">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="-30,0,0,0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Medium">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Hub" Storyboard.TargetProperty="Margin">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Large">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Hub" Storyboard.TargetProperty="Margin">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
@@ -28,7 +28,6 @@ namespace ModernKeePass.Views
|
|||||||
if (args != null)
|
if (args != null)
|
||||||
{
|
{
|
||||||
await Model.Initialize(args.Id);
|
await Model.Initialize(args.Id);
|
||||||
Model.IsEditMode = args.IsNew;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,18 +45,21 @@ namespace ModernKeePass.Views
|
|||||||
VisualStateManager.GoToState(this, "Small", true);
|
VisualStateManager.GoToState(this, "Small", true);
|
||||||
VisualStateManager.GoToState(TopMenu, "Collapsed", true);
|
VisualStateManager.GoToState(TopMenu, "Collapsed", true);
|
||||||
VisualStateManager.GoToState(HamburgerMenu, "Hidden", true);
|
VisualStateManager.GoToState(HamburgerMenu, "Hidden", true);
|
||||||
|
VisualStateManager.GoToState(Breadcrumb, "Small", true);
|
||||||
}
|
}
|
||||||
else if (e.NewSize.Width > 640 && e.NewSize.Width <= 1008)
|
else if (e.NewSize.Width > 640 && e.NewSize.Width <= 1008)
|
||||||
{
|
{
|
||||||
VisualStateManager.GoToState(this, "Medium", true);
|
VisualStateManager.GoToState(this, "Medium", true);
|
||||||
VisualStateManager.GoToState(TopMenu, "Overflowed", true);
|
VisualStateManager.GoToState(TopMenu, "Overflowed", true);
|
||||||
VisualStateManager.GoToState(HamburgerMenu, "Collapsed", true);
|
VisualStateManager.GoToState(HamburgerMenu, "Collapsed", true);
|
||||||
|
VisualStateManager.GoToState(Breadcrumb, "Medium", true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VisualStateManager.GoToState(this, "Large", true);
|
VisualStateManager.GoToState(this, "Large", true);
|
||||||
VisualStateManager.GoToState(TopMenu, "Overflowed", true);
|
VisualStateManager.GoToState(TopMenu, "Overflowed", true);
|
||||||
VisualStateManager.GoToState(HamburgerMenu, "Collapsed", true);
|
VisualStateManager.GoToState(HamburgerMenu, "Collapsed", true);
|
||||||
|
VisualStateManager.GoToState(Breadcrumb, "Large", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<Page
|
<Page x:Name="Page"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
@@ -15,7 +15,6 @@
|
|||||||
<Page.Resources>
|
<Page.Resources>
|
||||||
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
|
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
|
||||||
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||||
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
|
|
||||||
<converters:IconToSymbolConverter x:Key="IconToSymbolConverter"/>
|
<converters:IconToSymbolConverter x:Key="IconToSymbolConverter"/>
|
||||||
</Page.Resources>
|
</Page.Resources>
|
||||||
<Grid>
|
<Grid>
|
||||||
@@ -41,14 +40,6 @@
|
|||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<userControls:HamburgerMenuUserControl
|
|
||||||
x:Name="HamburgerMenu"
|
|
||||||
x:Uid="GroupsLeftListView"
|
|
||||||
ItemsSource="{Binding Groups}"
|
|
||||||
CanDragItems="{Binding IsEditMode}"
|
|
||||||
SelectionChanged="groups_SelectionChanged"
|
|
||||||
ActionButtonCommand="{Binding CreateGroupCommand}"
|
|
||||||
IsButtonVisible="Visible" />
|
|
||||||
<Grid Grid.Column="1">
|
<Grid Grid.Column="1">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
@@ -71,7 +62,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</HyperlinkButton>
|
</HyperlinkButton>
|
||||||
|
|
||||||
<SemanticZoom Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="1" ViewChangeStarted="SemanticZoom_ViewChangeStarted" ScrollViewer.HorizontalScrollBarVisibility="Visible">
|
<SemanticZoom x:Name="SemanticZoom" Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="1" ViewChangeStarted="SemanticZoom_ViewChangeStarted" ScrollViewer.HorizontalScrollBarVisibility="Visible">
|
||||||
<SemanticZoom.ZoomedInView>
|
<SemanticZoom.ZoomedInView>
|
||||||
<!-- Horizontal scrolling grid -->
|
<!-- Horizontal scrolling grid -->
|
||||||
<GridView
|
<GridView
|
||||||
@@ -80,7 +71,6 @@
|
|||||||
AutomationProperties.AutomationId="ItemGridView"
|
AutomationProperties.AutomationId="ItemGridView"
|
||||||
AutomationProperties.Name="Entries"
|
AutomationProperties.Name="Entries"
|
||||||
TabIndex="1"
|
TabIndex="1"
|
||||||
SelectionChanged="entries_SelectionChanged"
|
|
||||||
IsSynchronizedWithCurrentItem="False"
|
IsSynchronizedWithCurrentItem="False"
|
||||||
BorderBrush="{StaticResource ListViewItemSelectedBackgroundThemeBrush}"
|
BorderBrush="{StaticResource ListViewItemSelectedBackgroundThemeBrush}"
|
||||||
AllowDrop="True"
|
AllowDrop="True"
|
||||||
@@ -88,8 +78,11 @@
|
|||||||
CanDragItems="{Binding IsEditMode}">
|
CanDragItems="{Binding IsEditMode}">
|
||||||
<interactivity:Interaction.Behaviors>
|
<interactivity:Interaction.Behaviors>
|
||||||
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="False">
|
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="False">
|
||||||
<actions:SetupFocusAction TargetObject="{Binding}" />
|
<actions:SetupFocusAction TargetObject="{Binding ElementName=GridView}" />
|
||||||
</core:DataTriggerBehavior>
|
</core:DataTriggerBehavior>
|
||||||
|
<core:EventTriggerBehavior EventName="SelectionChanged">
|
||||||
|
<core:InvokeCommandAction Command="{Binding GoToEntryCommand}" CommandParameter="{Binding SelectedItem, ElementName=GridView}" />
|
||||||
|
</core:EventTriggerBehavior>
|
||||||
</interactivity:Interaction.Behaviors>
|
</interactivity:Interaction.Behaviors>
|
||||||
<GridView.ItemTemplate>
|
<GridView.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
@@ -137,6 +130,7 @@
|
|||||||
</core:EventTriggerBehavior>
|
</core:EventTriggerBehavior>
|
||||||
</interactivity:Interaction.Behaviors>
|
</interactivity:Interaction.Behaviors>
|
||||||
</MenuFlyoutItem>
|
</MenuFlyoutItem>
|
||||||
|
<MenuFlyoutItem x:Uid="EntryItemDelete" Command="{Binding DataContext.DeleteEntryCommand, ElementName=Page}" CommandParameter="{Binding}" />
|
||||||
</MenuFlyout>
|
</MenuFlyout>
|
||||||
</Button.Flyout>
|
</Button.Flyout>
|
||||||
</Button>
|
</Button>
|
||||||
@@ -176,64 +170,32 @@
|
|||||||
</SemanticZoom.ZoomedOutView>
|
</SemanticZoom.ZoomedOutView>
|
||||||
</SemanticZoom>
|
</SemanticZoom>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<userControls:HamburgerMenuUserControl
|
||||||
|
Grid.Column="0"
|
||||||
|
x:Name="HamburgerMenu"
|
||||||
|
x:Uid="GroupsLeftListView"
|
||||||
|
HeaderLabel="{Binding Title}"
|
||||||
|
ItemsSource="{Binding Groups}"
|
||||||
|
CanDragItems="{Binding IsEditMode}"
|
||||||
|
ActionButtonCommand="{Binding CreateGroupCommand}"
|
||||||
|
IsButtonVisible="Visible">
|
||||||
|
<interactivity:Interaction.Behaviors>
|
||||||
|
<core:EventTriggerBehavior EventName="SelectionChanged">
|
||||||
|
<core:InvokeCommandAction Command="{Binding GoToGroupCommand}" CommandParameter="{Binding SelectedItem, ElementName=HamburgerMenu}" />
|
||||||
|
</core:EventTriggerBehavior>
|
||||||
|
</interactivity:Interaction.Behaviors>
|
||||||
|
</userControls:HamburgerMenuUserControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
<!-- Back button and page title -->
|
<!-- Back button and page title -->
|
||||||
<Grid Grid.Row="0" Background="{ThemeResource AppBarBackgroundThemeBrush}">
|
<Grid Grid.Row="0" Background="{ThemeResource AppBarBackgroundThemeBrush}">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="{StaticResource MenuWidthGridLength}"/>
|
|
||||||
<ColumnDefinition Width="{StaticResource MenuWidthGridLength}"/>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Button Grid.Column="0"
|
<userControls:BreadcrumbUserControl x:Name="Breadcrumb" Group="{Binding Parent}" />
|
||||||
Command="{Binding GoBackCommand}"
|
<userControls:TopMenuUserControl x:Name="TopMenu" Grid.Column="1"
|
||||||
Height="{StaticResource MenuHeight}"
|
|
||||||
Width="{StaticResource MenuWidth}"
|
|
||||||
AutomationProperties.Name="Back"
|
|
||||||
AutomationProperties.AutomationId="BackButton"
|
|
||||||
AutomationProperties.ItemType="Navigation Button"
|
|
||||||
Style="{StaticResource NoBorderButtonStyle}">
|
|
||||||
<SymbolIcon Symbol="Back" />
|
|
||||||
</Button>
|
|
||||||
<Button Grid.Column="1"
|
|
||||||
Height="{StaticResource MenuHeight}"
|
|
||||||
Width="{StaticResource MenuWidth}"
|
|
||||||
Command="{Binding GoToParentCommand}"
|
|
||||||
Style="{StaticResource NoBorderButtonStyle}">
|
|
||||||
<SymbolIcon Symbol="Up" />
|
|
||||||
<ToolTipService.ToolTip>
|
|
||||||
<ToolTip Content="{Binding ParentGroupName}" />
|
|
||||||
</ToolTipService.ToolTip>
|
|
||||||
</Button>
|
|
||||||
<Viewbox Grid.Column="2" MaxHeight="200" Visibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}">
|
|
||||||
<userControls:SymbolPickerUserControl Width="100" Height="70" SelectedSymbol="{Binding Icon, Mode=TwoWay}" />
|
|
||||||
</Viewbox>
|
|
||||||
<Viewbox Grid.Column="2" MaxHeight="200" Visibility="{Binding IsEditMode, Converter={StaticResource InverseBooleanToVisibilityConverter}}">
|
|
||||||
<SymbolIcon Symbol="{Binding Icon}" Width="100" Height="70" />
|
|
||||||
</Viewbox>
|
|
||||||
<TextBox Grid.Column="3"
|
|
||||||
x:Uid="GroupTitle"
|
|
||||||
x:Name="TitleTextBox"
|
|
||||||
Text="{Binding Title, Mode=TwoWay}"
|
|
||||||
Background="Transparent"
|
|
||||||
IsHitTestVisible="{Binding IsEditMode}"
|
|
||||||
FontSize="20"
|
|
||||||
FontWeight="Light"
|
|
||||||
TextWrapping="NoWrap"
|
|
||||||
VerticalAlignment="Center">
|
|
||||||
<interactivity:Interaction.Behaviors>
|
|
||||||
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="True">
|
|
||||||
<actions:SetupFocusAction TargetObject="{Binding ElementName=TitleTextBox}" />
|
|
||||||
<core:ChangePropertyAction TargetObject="{Binding ElementName=TitleTextBox}" PropertyName="BorderThickness" Value="2" />
|
|
||||||
</core:DataTriggerBehavior>
|
|
||||||
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="False">
|
|
||||||
<core:ChangePropertyAction TargetObject="{Binding ElementName=TitleTextBox}" PropertyName="BorderThickness" Value="0" />
|
|
||||||
</core:DataTriggerBehavior>
|
|
||||||
</interactivity:Interaction.Behaviors>
|
|
||||||
</TextBox>
|
|
||||||
<userControls:TopMenuUserControl x:Name="TopMenu" Grid.Column="4"
|
|
||||||
SortButtonVisibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}"
|
SortButtonVisibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||||
|
EditButtonVisibility="Visible"
|
||||||
IsEditButtonChecked="{Binding IsEditMode, Mode=TwoWay}"
|
IsEditButtonChecked="{Binding IsEditMode, Mode=TwoWay}"
|
||||||
SaveCommand="{Binding SaveCommand}"
|
SaveCommand="{Binding SaveCommand}"
|
||||||
MoveCommand="{Binding MoveCommand}"
|
MoveCommand="{Binding MoveCommand}"
|
||||||
@@ -246,7 +208,6 @@
|
|||||||
</core:EventTriggerBehavior>
|
</core:EventTriggerBehavior>
|
||||||
</interactivity:Interaction.Behaviors>
|
</interactivity:Interaction.Behaviors>
|
||||||
</userControls:TopMenuUserControl>
|
</userControls:TopMenuUserControl>
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
<VisualStateManager.VisualStateGroups>
|
<VisualStateManager.VisualStateGroups>
|
||||||
<VisualStateGroup x:Name="PageLayout">
|
<VisualStateGroup x:Name="PageLayout">
|
||||||
@@ -258,6 +219,9 @@
|
|||||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HamburgerMenu" Storyboard.TargetProperty="IsOpen">
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HamburgerMenu" Storyboard.TargetProperty="IsOpen">
|
||||||
<DiscreteObjectKeyFrame KeyTime="0" Value="False"/>
|
<DiscreteObjectKeyFrame KeyTime="0" Value="False"/>
|
||||||
</ObjectAnimationUsingKeyFrames>
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SemanticZoom" Storyboard.TargetProperty="Margin">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="-60,0,0,0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
</Storyboard>
|
</Storyboard>
|
||||||
</VisualState>
|
</VisualState>
|
||||||
<VisualState x:Name="Medium">
|
<VisualState x:Name="Medium">
|
||||||
@@ -265,6 +229,9 @@
|
|||||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HamburgerMenu" Storyboard.TargetProperty="IsOpen">
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HamburgerMenu" Storyboard.TargetProperty="IsOpen">
|
||||||
<DiscreteObjectKeyFrame KeyTime="0" Value="False"/>
|
<DiscreteObjectKeyFrame KeyTime="0" Value="False"/>
|
||||||
</ObjectAnimationUsingKeyFrames>
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SemanticZoom" Storyboard.TargetProperty="Margin">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
</Storyboard>
|
</Storyboard>
|
||||||
</VisualState>
|
</VisualState>
|
||||||
<VisualState x:Name="Large">
|
<VisualState x:Name="Large">
|
||||||
@@ -275,6 +242,9 @@
|
|||||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HamburgerMenu" Storyboard.TargetProperty="IsOpen">
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HamburgerMenu" Storyboard.TargetProperty="IsOpen">
|
||||||
<DiscreteObjectKeyFrame KeyTime="0" Value="True"/>
|
<DiscreteObjectKeyFrame KeyTime="0" Value="True"/>
|
||||||
</ObjectAnimationUsingKeyFrames>
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SemanticZoom" Storyboard.TargetProperty="Margin">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
</Storyboard>
|
</Storyboard>
|
||||||
</VisualState>
|
</VisualState>
|
||||||
</VisualStateGroup>
|
</VisualStateGroup>
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using Windows.UI.Xaml.Navigation;
|
using Windows.UI.Xaml.Navigation;
|
||||||
using ModernKeePass.Application.Entry.Models;
|
|
||||||
using ModernKeePass.Models;
|
using ModernKeePass.Models;
|
||||||
using ModernKeePass.ViewModels;
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
@@ -38,33 +37,6 @@ namespace ModernKeePass.Views
|
|||||||
|
|
||||||
#region Event Handlers
|
#region Event Handlers
|
||||||
|
|
||||||
private void groups_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
var listView = sender as ListView;
|
|
||||||
switch (listView?.SelectedIndex)
|
|
||||||
{
|
|
||||||
case -1:
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
var group = listView?.SelectedItem as Application.Group.Models.GroupVm;
|
|
||||||
Model.GoToGroup(group?.Id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void entries_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
switch (GridView.SelectedIndex)
|
|
||||||
{
|
|
||||||
case -1:
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
var entry = GridView.SelectedItem as EntryVm;
|
|
||||||
Model.GoToEntry(entry?.Id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SemanticZoom_ViewChangeStarted(object sender, SemanticZoomViewChangedEventArgs e)
|
private void SemanticZoom_ViewChangeStarted(object sender, SemanticZoomViewChangedEventArgs e)
|
||||||
{
|
{
|
||||||
// We need to synchronize the two lists (zoomed-in and zoomed-out) because the source is different
|
// We need to synchronize the two lists (zoomed-in and zoomed-out) because the source is different
|
||||||
@@ -81,18 +53,21 @@ namespace ModernKeePass.Views
|
|||||||
VisualStateManager.GoToState(this, "Small", true);
|
VisualStateManager.GoToState(this, "Small", true);
|
||||||
VisualStateManager.GoToState(TopMenu, "Collapsed", true);
|
VisualStateManager.GoToState(TopMenu, "Collapsed", true);
|
||||||
VisualStateManager.GoToState(HamburgerMenu, "Hidden", true);
|
VisualStateManager.GoToState(HamburgerMenu, "Hidden", true);
|
||||||
|
VisualStateManager.GoToState(Breadcrumb, "Small", true);
|
||||||
}
|
}
|
||||||
else if (e.NewSize.Width > 640 && e.NewSize.Width <= 1008)
|
else if (e.NewSize.Width > 640 && e.NewSize.Width <= 1008)
|
||||||
{
|
{
|
||||||
VisualStateManager.GoToState(this, "Medium", true);
|
VisualStateManager.GoToState(this, "Medium", true);
|
||||||
VisualStateManager.GoToState(TopMenu, "Overflowed", true);
|
VisualStateManager.GoToState(TopMenu, "Overflowed", true);
|
||||||
VisualStateManager.GoToState(HamburgerMenu, "Collapsed", true);
|
VisualStateManager.GoToState(HamburgerMenu, "Collapsed", true);
|
||||||
|
VisualStateManager.GoToState(Breadcrumb, "Medium", true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VisualStateManager.GoToState(this, "Large", true);
|
VisualStateManager.GoToState(this, "Large", true);
|
||||||
VisualStateManager.GoToState(TopMenu, "Overflowed", true);
|
VisualStateManager.GoToState(TopMenu, "Overflowed", true);
|
||||||
VisualStateManager.GoToState(HamburgerMenu, "Expanded", true);
|
VisualStateManager.GoToState(HamburgerMenu, "Expanded", true);
|
||||||
|
VisualStateManager.GoToState(Breadcrumb, "Large", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -57,6 +57,7 @@
|
|||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
x:Name="MenuListView"
|
x:Name="MenuListView"
|
||||||
|
ScrollViewer.VerticalScrollMode="Disabled"
|
||||||
SelectionChanged="ListView_SelectionChanged"
|
SelectionChanged="ListView_SelectionChanged"
|
||||||
Background="{ThemeResource AppBarBackgroundThemeBrush}"
|
Background="{ThemeResource AppBarBackgroundThemeBrush}"
|
||||||
ItemsSource="{Binding Source={StaticResource MenuItemsSource}}"
|
ItemsSource="{Binding Source={StaticResource MenuItemsSource}}"
|
||||||
|
@@ -40,7 +40,11 @@ namespace ModernKeePass.Views
|
|||||||
protected override async void OnNavigatedTo(NavigationEventArgs e)
|
protected override async void OnNavigatedTo(NavigationEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnNavigatedTo(e);
|
base.OnNavigatedTo(e);
|
||||||
var file = e.Parameter as FileInfo;
|
FileInfo file;
|
||||||
|
if (e.NavigationMode == NavigationMode.Back)
|
||||||
|
file = null;
|
||||||
|
else
|
||||||
|
file = e.Parameter as FileInfo;
|
||||||
await Model.Initialize(Frame, MenuFrame, file);
|
await Model.Initialize(Frame, MenuFrame, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<Page
|
<Page
|
||||||
x:Class="ModernKeePass.Views.ImportExportPage"
|
x:Class="ModernKeePass.Views.ImportPage"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
@@ -5,9 +5,9 @@ namespace ModernKeePass.Views
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The import/export page.
|
/// The import/export page.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class ImportExportPage
|
public sealed partial class ImportPage
|
||||||
{
|
{
|
||||||
public ImportExportPage()
|
public ImportPage()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
@@ -9,6 +9,11 @@
|
|||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
DataContext="{Binding Source={StaticResource Locator}, Path=Recent}">
|
DataContext="{Binding Source={StaticResource Locator}, Path=Recent}">
|
||||||
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
|
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
<Grid.Resources>
|
||||||
|
<CollectionViewSource
|
||||||
|
x:Name="RecentItemsSource"
|
||||||
|
Source="{Binding RecentItems}" />
|
||||||
|
</Grid.Resources>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="40" />
|
<RowDefinition Height="40" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
@@ -21,7 +26,7 @@
|
|||||||
</HyperlinkButton>
|
</HyperlinkButton>
|
||||||
<controls:SelectableTemplateListView Grid.Row="1"
|
<controls:SelectableTemplateListView Grid.Row="1"
|
||||||
SelectedIndex="{Binding SelectedIndex}"
|
SelectedIndex="{Binding SelectedIndex}"
|
||||||
ItemsSource="{Binding RecentItems}"
|
ItemsSource="{Binding Source={StaticResource RecentItemsSource}}"
|
||||||
ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}">
|
ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}">
|
||||||
<controls:SelectableTemplateListView.SelectedItemTemplate>
|
<controls:SelectableTemplateListView.SelectedItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
|
117
ModernKeePass/Views/UserControls/BreadcrumbUserControl.xaml
Normal file
117
ModernKeePass/Views/UserControls/BreadcrumbUserControl.xaml
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<UserControl
|
||||||
|
x:Class="ModernKeePass.Views.UserControls.BreadcrumbUserControl"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:converters="using:ModernKeePass.Converters"
|
||||||
|
xmlns:templateSelectors="using:ModernKeePass.TemplateSelectors"
|
||||||
|
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||||
|
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
<StackPanel x:Name="StackPanel" DataContext="{Binding Source={StaticResource Locator}, Path=Breadcrumb}" Orientation="Horizontal">
|
||||||
|
<StackPanel.Resources>
|
||||||
|
<converters:IconToSymbolConverter x:Key="IconToSymbolConverter"/>
|
||||||
|
<DataTemplate x:Key="FirstItemTemplate">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Margin="10,5,10,0" Text="{Binding Name}" FontStyle="Italic" HorizontalAlignment="Center" />
|
||||||
|
<SymbolIcon Symbol="{Binding Icon, Converter={StaticResource IconToSymbolConverter}, ConverterParameter=33}" Margin="0,3,0,0" />
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
<DataTemplate x:Key="OtherItemTemplate">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Margin="10,5,10,0" Text="<" HorizontalAlignment="Center" />
|
||||||
|
<TextBlock Margin="10,5,10,0" Text="{Binding Name}" FontStyle="Italic" HorizontalAlignment="Center" />
|
||||||
|
<SymbolIcon Symbol="{Binding Icon, Converter={StaticResource IconToSymbolConverter}, ConverterParameter=33}" Margin="0,3,0,0" />
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</StackPanel.Resources>
|
||||||
|
<Button
|
||||||
|
Command="{Binding GoBackCommand}"
|
||||||
|
Height="{StaticResource MenuHeight}"
|
||||||
|
Width="{StaticResource MenuWidth}"
|
||||||
|
AutomationProperties.Name="Back"
|
||||||
|
AutomationProperties.AutomationId="BackButton"
|
||||||
|
AutomationProperties.ItemType="Navigation Button"
|
||||||
|
Style="{StaticResource NoBorderButtonStyle}">
|
||||||
|
<SymbolIcon Symbol="Back" />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
Height="{StaticResource MenuHeight}"
|
||||||
|
Command="{Binding GoUpCommand}"
|
||||||
|
Style="{StaticResource NoBorderButtonStyle}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<SymbolIcon Symbol="Up" />
|
||||||
|
<SymbolIcon x:Name="UpButtonIcon" Symbol="{Binding ParentGroupIcon, Converter={StaticResource IconToSymbolConverter}, ConverterParameter=33}" Margin="16,0,0,0" />
|
||||||
|
<TextBlock x:Name="UpButtonText" Margin="10,2,0,0" Text="{Binding ParentGroupName}" FontStyle="Italic" FontWeight="Normal" HorizontalAlignment="Center" />
|
||||||
|
</StackPanel>
|
||||||
|
<ToolTipService.ToolTip>
|
||||||
|
<ToolTip Content="{Binding ParentGroupName}" />
|
||||||
|
</ToolTipService.ToolTip>
|
||||||
|
</Button>
|
||||||
|
<ListView x:Name="ListView" ItemsSource="{Binding BreadcrumbItems}" ScrollViewer.HorizontalScrollMode="Auto">
|
||||||
|
<ListView.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<ItemsStackPanel FlowDirection="RightToLeft" Orientation="Horizontal" />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ListView.ItemsPanel>
|
||||||
|
<ListView.ItemTemplateSelector>
|
||||||
|
<templateSelectors:FirstItemDataTemplateSelector FirstItem="{StaticResource FirstItemTemplate}" OtherItem="{StaticResource OtherItemTemplate}" />
|
||||||
|
</ListView.ItemTemplateSelector>
|
||||||
|
<ListView.ItemContainerStyle>
|
||||||
|
<Style TargetType="ListViewItem">
|
||||||
|
<Setter Property="Margin" Value="0"/>
|
||||||
|
<Setter Property="Height" Value="{StaticResource MenuHeight}" />
|
||||||
|
</Style>
|
||||||
|
</ListView.ItemContainerStyle>
|
||||||
|
<interactivity:Interaction.Behaviors>
|
||||||
|
<core:EventTriggerBehavior EventName="SelectionChanged">
|
||||||
|
<core:InvokeCommandAction Command="{Binding GoToCommand}" CommandParameter="{Binding SelectedIndex, ElementName=ListView}" />
|
||||||
|
</core:EventTriggerBehavior>
|
||||||
|
</interactivity:Interaction.Behaviors>
|
||||||
|
</ListView>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="PageLayout">
|
||||||
|
<VisualState x:Name="Small">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="UpButtonIcon" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="UpButtonText" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ListView" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Medium">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="UpButtonIcon" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="UpButtonText" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ListView" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Large">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="UpButtonIcon" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="UpButtonText" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ListView" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
</StackPanel>
|
||||||
|
</UserControl>
|
@@ -0,0 +1,36 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using ModernKeePass.Application.Group.Models;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
|
||||||
|
|
||||||
|
namespace ModernKeePass.Views.UserControls
|
||||||
|
{
|
||||||
|
public sealed partial class BreadcrumbUserControl
|
||||||
|
{
|
||||||
|
public GroupVm Group
|
||||||
|
{
|
||||||
|
get { return (GroupVm)GetValue(GroupProperty); }
|
||||||
|
set { SetValue(GroupProperty, value); }
|
||||||
|
}
|
||||||
|
public static readonly DependencyProperty GroupProperty =
|
||||||
|
DependencyProperty.Register(
|
||||||
|
nameof(Group),
|
||||||
|
typeof(GroupVm),
|
||||||
|
typeof(BreadcrumbUserControl),
|
||||||
|
new PropertyMetadata(null, async (o, args) =>
|
||||||
|
{
|
||||||
|
var userControl = o as BreadcrumbUserControl;
|
||||||
|
var vm = userControl?.StackPanel.DataContext as BreadcrumbControlVm;
|
||||||
|
if (vm == null) return;
|
||||||
|
await vm.Initialize(args.NewValue as GroupVm).ConfigureAwait(false);
|
||||||
|
userControl?.ListView.ScrollIntoView(vm.BreadcrumbItems.Last());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public BreadcrumbUserControl()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,4 +1,5 @@
|
|||||||
using Windows.UI.Xaml;
|
using System.Linq;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using Windows.UI.Xaml.Media;
|
using Windows.UI.Xaml.Media;
|
||||||
using ModernKeePass.ViewModels;
|
using ModernKeePass.ViewModels;
|
||||||
@@ -33,6 +34,7 @@ namespace ModernKeePass.Views.UserControls
|
|||||||
|
|
||||||
private void ComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
|
private void ComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
|
if (e.AddedItems.Any())
|
||||||
SelectedColor = (e.AddedItems[0] as ColorPickerControlVm.Color)?.ColorBrush;
|
SelectedColor = (e.AddedItems[0] as ColorPickerControlVm.Color)?.ColorBrush;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -60,7 +60,10 @@
|
|||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<ToggleButton Style="{StaticResource HamburgerToggleButton}" IsChecked="{Binding IsOpen, ElementName=UserControl}" Unchecked="ToggleButton_OnUnchecked">
|
<ToggleButton Style="{StaticResource HamburgerToggleButton}" IsChecked="{Binding IsOpen, ElementName=UserControl, Mode=TwoWay}" Unchecked="ToggleButton_OnUnchecked">
|
||||||
|
<ToolTipService.ToolTip>
|
||||||
|
<ToolTip Content="{Binding HeaderLabel, ElementName=UserControl}" />
|
||||||
|
</ToolTipService.ToolTip>
|
||||||
<interactivity:Interaction.Behaviors>
|
<interactivity:Interaction.Behaviors>
|
||||||
<core:EventTriggerBehavior EventName="Checked">
|
<core:EventTriggerBehavior EventName="Checked">
|
||||||
<core:GoToStateAction StateName="Expanded" />
|
<core:GoToStateAction StateName="Expanded" />
|
||||||
@@ -94,7 +97,7 @@
|
|||||||
<ListView.ItemTemplate>
|
<ListView.ItemTemplate>
|
||||||
<DataTemplate x:Name="IsNormal">
|
<DataTemplate x:Name="IsNormal">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<SymbolIcon Symbol="{Binding Icon, Converter={StaticResource IconToSymbolConverter}, ConverterParameter=48}" Margin="7,10,0,15">
|
<SymbolIcon Symbol="{Binding Icon, Converter={StaticResource IconToSymbolConverter}, ConverterParameter=33}" Margin="7,10,0,15">
|
||||||
<ToolTipService.ToolTip>
|
<ToolTipService.ToolTip>
|
||||||
<ToolTip Content="{Binding Path={Binding DisplayMemberPath, ElementName=UserControl}}" />
|
<ToolTip Content="{Binding Path={Binding DisplayMemberPath, ElementName=UserControl}}" />
|
||||||
</ToolTipService.ToolTip>
|
</ToolTipService.ToolTip>
|
||||||
@@ -125,6 +128,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
<interactivity:Interaction.Behaviors>
|
<interactivity:Interaction.Behaviors>
|
||||||
<core:EventTriggerBehavior EventName="Click">
|
<core:EventTriggerBehavior EventName="Click">
|
||||||
|
<core:ChangePropertyAction TargetObject="{Binding ElementName=UserControl}" PropertyName="IsOpen" Value="True" />
|
||||||
<core:ChangePropertyAction TargetObject="{Binding ElementName=NewGroupTextBox}" PropertyName="Visibility" Value="Visible" />
|
<core:ChangePropertyAction TargetObject="{Binding ElementName=NewGroupTextBox}" PropertyName="Visibility" Value="Visible" />
|
||||||
<core:ChangePropertyAction TargetObject="{Binding ElementName=NewGroupButton}" PropertyName="Visibility" Value="Collapsed" />
|
<core:ChangePropertyAction TargetObject="{Binding ElementName=NewGroupButton}" PropertyName="Visibility" Value="Collapsed" />
|
||||||
<actions:SetupFocusAction TargetObject="{Binding ElementName=NewGroupTextBox}" />
|
<actions:SetupFocusAction TargetObject="{Binding ElementName=NewGroupTextBox}" />
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Windows.System;
|
using Windows.System;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
@@ -7,6 +6,7 @@ using Windows.UI.Xaml.Controls;
|
|||||||
using Windows.UI.Xaml.Input;
|
using Windows.UI.Xaml.Input;
|
||||||
using ModernKeePass.Application.Common.Interfaces;
|
using ModernKeePass.Application.Common.Interfaces;
|
||||||
using ModernKeePass.Controls;
|
using ModernKeePass.Controls;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
|
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
|
||||||
|
|
||||||
@@ -62,18 +62,18 @@ namespace ModernKeePass.Views.UserControls
|
|||||||
typeof(HamburgerMenuUserControl),
|
typeof(HamburgerMenuUserControl),
|
||||||
new PropertyMetadata(Visibility.Collapsed, (o, args) => { }));
|
new PropertyMetadata(Visibility.Collapsed, (o, args) => { }));
|
||||||
|
|
||||||
public IEnumerable<IEntityVm> ItemsSource
|
public ObservableCollection<IEntityVm> ItemsSource
|
||||||
{
|
{
|
||||||
get { return (IEnumerable<IEntityVm>)GetValue(ItemsSourceProperty); }
|
get { return (ObservableCollection<IEntityVm>)GetValue(ItemsSourceProperty); }
|
||||||
set { SetValue(ItemsSourceProperty, value); }
|
set { SetValue(ItemsSourceProperty, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly DependencyProperty ItemsSourceProperty =
|
public static readonly DependencyProperty ItemsSourceProperty =
|
||||||
DependencyProperty.Register(
|
DependencyProperty.Register(
|
||||||
nameof(ItemsSource),
|
nameof(ItemsSource),
|
||||||
typeof(IEnumerable<IEntityVm>),
|
typeof(ObservableCollection<IEntityVm>),
|
||||||
typeof(HamburgerMenuUserControl),
|
typeof(HamburgerMenuUserControl),
|
||||||
new PropertyMetadata(new List<IEntityVm>(), (o, args) => { }));
|
new PropertyMetadata(new ObservableCollection<IEntityVm>(), (o, args) => { }));
|
||||||
|
|
||||||
public object SelectedItem
|
public object SelectedItem
|
||||||
{
|
{
|
||||||
|
@@ -98,7 +98,7 @@
|
|||||||
</MenuFlyout>
|
</MenuFlyout>
|
||||||
</Button.Flyout>
|
</Button.Flyout>
|
||||||
</Button>
|
</Button>
|
||||||
<ToggleButton Command="{Binding EditCommand, ElementName=UserControl}" IsChecked="{Binding IsEditButtonChecked, ElementName=UserControl, Mode=TwoWay}" Checked="EditButton_Click" Style="{StaticResource MenuToggleButtonStyle}">
|
<ToggleButton Visibility="{Binding EditButtonVisibility, ElementName=UserControl}" Command="{Binding EditCommand, ElementName=UserControl}" IsChecked="{Binding IsEditButtonChecked, ElementName=UserControl, Mode=TwoWay}" Checked="EditButton_Click" Style="{StaticResource MenuToggleButtonStyle}">
|
||||||
<SymbolIcon Symbol="Edit">
|
<SymbolIcon Symbol="Edit">
|
||||||
<ToolTipService.ToolTip>
|
<ToolTipService.ToolTip>
|
||||||
<ToolTip x:Uid="TopMenuEditButton" />
|
<ToolTip x:Uid="TopMenuEditButton" />
|
||||||
@@ -151,7 +151,7 @@
|
|||||||
<MenuFlyout Opening="OverflowFlyout_OnOpening">
|
<MenuFlyout Opening="OverflowFlyout_OnOpening">
|
||||||
<MenuFlyoutItem x:Uid="TopMenuSaveFlyout" x:Name="SaveFlyout" />
|
<MenuFlyoutItem x:Uid="TopMenuSaveFlyout" x:Name="SaveFlyout" />
|
||||||
<MenuFlyoutItem x:Uid="TopMenuRestoreFlyout" x:Name="RestoreFlyout" Visibility="{Binding RestoreButtonVisibility, ElementName=UserControl}" />
|
<MenuFlyoutItem x:Uid="TopMenuRestoreFlyout" x:Name="RestoreFlyout" Visibility="{Binding RestoreButtonVisibility, ElementName=UserControl}" />
|
||||||
<ToggleMenuFlyoutItem x:Uid="TopMenuEditFlyout" x:Name="EditFlyout" IsChecked="{Binding IsEditButtonChecked, ElementName=UserControl, Mode=TwoWay}" Click="EditButton_Click" />
|
<ToggleMenuFlyoutItem x:Uid="TopMenuEditFlyout" x:Name="EditFlyout" Visibility="{Binding EditButtonVisibility, ElementName=UserControl}" IsChecked="{Binding IsEditButtonChecked, ElementName=UserControl, Mode=TwoWay}" Click="EditButton_Click" />
|
||||||
<MenuFlyoutItem x:Uid="TopMenuDeleteFlyout" x:Name="DeleteFlyout" />
|
<MenuFlyoutItem x:Uid="TopMenuDeleteFlyout" x:Name="DeleteFlyout" />
|
||||||
<MenuFlyoutItem x:Uid="TopMenuSortEntriesFlyout" x:Name="SortEntriesFlyout" Visibility="{Binding SortButtonVisibility, ElementName=UserControl}" />
|
<MenuFlyoutItem x:Uid="TopMenuSortEntriesFlyout" x:Name="SortEntriesFlyout" Visibility="{Binding SortButtonVisibility, ElementName=UserControl}" />
|
||||||
<MenuFlyoutItem x:Uid="TopMenuSortGroupsFlyout" x:Name="SortGroupsFlyout" Visibility="{Binding SortButtonVisibility, ElementName=UserControl}" />
|
<MenuFlyoutItem x:Uid="TopMenuSortGroupsFlyout" x:Name="SortGroupsFlyout" Visibility="{Binding SortButtonVisibility, ElementName=UserControl}" />
|
||||||
|
@@ -39,6 +39,18 @@ namespace ModernKeePass.Views.UserControls
|
|||||||
typeof(TopMenuUserControl),
|
typeof(TopMenuUserControl),
|
||||||
new PropertyMetadata(null, (o, args) => { }));
|
new PropertyMetadata(null, (o, args) => { }));
|
||||||
|
|
||||||
|
public Visibility EditButtonVisibility
|
||||||
|
{
|
||||||
|
get { return (Visibility)GetValue(EditButtonVisibilityProperty); }
|
||||||
|
set { SetValue(EditButtonVisibilityProperty, value); }
|
||||||
|
}
|
||||||
|
public static readonly DependencyProperty EditButtonVisibilityProperty =
|
||||||
|
DependencyProperty.Register(
|
||||||
|
nameof(EditButtonVisibility),
|
||||||
|
typeof(Visibility),
|
||||||
|
typeof(TopMenuUserControl),
|
||||||
|
new PropertyMetadata(Visibility.Collapsed, (o, args) => { }));
|
||||||
|
|
||||||
public ICommand DeleteCommand
|
public ICommand DeleteCommand
|
||||||
{
|
{
|
||||||
get { return (ICommand)GetValue(DeleteCommandProperty); }
|
get { return (ICommand)GetValue(DeleteCommandProperty); }
|
||||||
@@ -214,7 +226,6 @@ namespace ModernKeePass.Views.UserControls
|
|||||||
MoveCommand.RaiseCanExecuteChanged();
|
MoveCommand.RaiseCanExecuteChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async void EntrySearchBox_OnSuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args)
|
private async void EntrySearchBox_OnSuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args)
|
||||||
{
|
{
|
||||||
var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appdata:/Assets/ModernKeePass-SmallLogo.scale-80.png"));
|
var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appdata:/Assets/ModernKeePass-SmallLogo.scale-80.png"));
|
||||||
|
@@ -100,8 +100,8 @@
|
|||||||
<DependentUpon>DonatePage.xaml</DependentUpon>
|
<DependentUpon>DonatePage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Views\BasePages\LayoutAwarePageBase.cs" />
|
<Compile Include="Views\BasePages\LayoutAwarePageBase.cs" />
|
||||||
<Compile Include="Views\MainPageFrames\ImportExportPage.xaml.cs">
|
<Compile Include="Views\MainPageFrames\ImportPage.xaml.cs">
|
||||||
<DependentUpon>ImportExportPage.xaml</DependentUpon>
|
<DependentUpon>ImportPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Views\SettingsPageFrames\SettingsHistoryPage.xaml.cs">
|
<Compile Include="Views\SettingsPageFrames\SettingsHistoryPage.xaml.cs">
|
||||||
<DependentUpon>SettingsHistoryPage.xaml</DependentUpon>
|
<DependentUpon>SettingsHistoryPage.xaml</DependentUpon>
|
||||||
@@ -124,6 +124,9 @@
|
|||||||
<Compile Include="Views\SettingsPageFrames\SettingsWelcomePage.xaml.cs">
|
<Compile Include="Views\SettingsPageFrames\SettingsWelcomePage.xaml.cs">
|
||||||
<DependentUpon>SettingsWelcomePage.xaml</DependentUpon>
|
<DependentUpon>SettingsWelcomePage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Views\UserControls\BreadcrumbUserControl.xaml.cs">
|
||||||
|
<DependentUpon>BreadcrumbUserControl.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Views\UserControls\ColorPickerUserControl.xaml.cs">
|
<Compile Include="Views\UserControls\ColorPickerUserControl.xaml.cs">
|
||||||
<DependentUpon>ColorPickerUserControl.xaml</DependentUpon>
|
<DependentUpon>ColorPickerUserControl.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -189,10 +192,6 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</None>
|
</None>
|
||||||
<None Include="Win81App_StoreKey.pfx" />
|
<None Include="Win81App_StoreKey.pfx" />
|
||||||
<PRIResource Include="Strings\fr-FR\Resources.resw" />
|
|
||||||
<PRIResource Include="Strings\fr-FR\CodeBehind.resw" />
|
|
||||||
<PRIResource Include="Strings\en-US\CodeBehind.resw" />
|
|
||||||
<PRIResource Include="Strings\en-US\Resources.resw" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Package.StoreAssociation.xml" />
|
<None Include="Package.StoreAssociation.xml" />
|
||||||
@@ -207,7 +206,7 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Views\MainPageFrames\ImportExportPage.xaml">
|
<Page Include="Views\MainPageFrames\ImportPage.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
@@ -223,6 +222,10 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="Views\UserControls\BreadcrumbUserControl.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
<Page Include="Views\UserControls\ColorPickerUserControl.xaml">
|
<Page Include="Views\UserControls\ColorPickerUserControl.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
@@ -1,5 +1,2 @@
|
|||||||
Data is now protected in memory as well as at rest
|
(Re-)Added a breadcrumb to help with navigation
|
||||||
Improved zoomed-out Semantic view
|
Design improvements
|
||||||
Having a custom entry color doesn't automatically trigger a change
|
|
||||||
Fix clipboard copy expiration issue
|
|
||||||
Fix a resume bug
|
|
@@ -1,5 +1,2 @@
|
|||||||
Protection des donnees en memoire en plus du chiffrement de la base de donnees
|
(R)Ajout du fil d'Ariane pour aider a la navigation
|
||||||
Amelioration du rendu de la vue Semantique dezoomee
|
Ameliorations de design
|
||||||
Avoir une couleur personnalisee ne declenche plus automatiquement un changement
|
|
||||||
Correction d'un bug dans l'expiration des donnees copiees
|
|
||||||
Correction d'un bug de resume de l'app
|
|
@@ -372,9 +372,6 @@
|
|||||||
<data name="GroupsLeftListView.ButtonLabel" xml:space="preserve">
|
<data name="GroupsLeftListView.ButtonLabel" xml:space="preserve">
|
||||||
<value>New group</value>
|
<value>New group</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="GroupsLeftListView.HeaderLabel" xml:space="preserve">
|
|
||||||
<value>Groups</value>
|
|
||||||
</data>
|
|
||||||
<data name="HistoryLeftListView.HeaderLabel" xml:space="preserve">
|
<data name="HistoryLeftListView.HeaderLabel" xml:space="preserve">
|
||||||
<value>History</value>
|
<value>History</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -453,9 +450,6 @@
|
|||||||
<data name="ToastUpdateDatabase.Title" xml:space="preserve">
|
<data name="ToastUpdateDatabase.Title" xml:space="preserve">
|
||||||
<value>Composite Key</value>
|
<value>Composite Key</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EntryTitle.PlaceholderText" xml:space="preserve">
|
|
||||||
<value>New entry name...</value>
|
|
||||||
</data>
|
|
||||||
<data name="SearchButtonLabel.Text" xml:space="preserve">
|
<data name="SearchButtonLabel.Text" xml:space="preserve">
|
||||||
<value>Search</value>
|
<value>Search</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -570,4 +564,16 @@
|
|||||||
<data name="PasswordGenerationButton.ButtonContent" xml:space="preserve">
|
<data name="PasswordGenerationButton.ButtonContent" xml:space="preserve">
|
||||||
<value>Random</value>
|
<value>Random</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="EntryTitle.Text" xml:space="preserve">
|
||||||
|
<value>Title</value>
|
||||||
|
</data>
|
||||||
|
<data name="TitleTextBox.ButtonTooltip" xml:space="preserve">
|
||||||
|
<value>Copy title</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToastCopyTitle.Message" xml:space="preserve">
|
||||||
|
<value>Title copied to clipboard</value>
|
||||||
|
</data>
|
||||||
|
<data name="EntryItemDelete.Text" xml:space="preserve">
|
||||||
|
<value>Delete</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@@ -372,9 +372,6 @@
|
|||||||
<data name="GroupsLeftListView.ButtonLabel" xml:space="preserve">
|
<data name="GroupsLeftListView.ButtonLabel" xml:space="preserve">
|
||||||
<value>Nouveau groupe</value>
|
<value>Nouveau groupe</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="GroupsLeftListView.HeaderLabel" xml:space="preserve">
|
|
||||||
<value>Groupes</value>
|
|
||||||
</data>
|
|
||||||
<data name="HistoryLeftListView.HeaderLabel" xml:space="preserve">
|
<data name="HistoryLeftListView.HeaderLabel" xml:space="preserve">
|
||||||
<value>Historique</value>
|
<value>Historique</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -453,9 +450,6 @@
|
|||||||
<data name="ToastUpdateDatabase.Title" xml:space="preserve">
|
<data name="ToastUpdateDatabase.Title" xml:space="preserve">
|
||||||
<value>Clé maître</value>
|
<value>Clé maître</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EntryTitle.PlaceholderText" xml:space="preserve">
|
|
||||||
<value>Nom de la nouvelle entrée...</value>
|
|
||||||
</data>
|
|
||||||
<data name="SearchButtonLabel.Text" xml:space="preserve">
|
<data name="SearchButtonLabel.Text" xml:space="preserve">
|
||||||
<value>Recherche</value>
|
<value>Recherche</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -570,4 +564,16 @@
|
|||||||
<data name="PasswordGenerationButton.ButtonContent" xml:space="preserve">
|
<data name="PasswordGenerationButton.ButtonContent" xml:space="preserve">
|
||||||
<value>Aléatoire</value>
|
<value>Aléatoire</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="EntryTitle.Text" xml:space="preserve">
|
||||||
|
<value>Titre</value>
|
||||||
|
</data>
|
||||||
|
<data name="TitleTextBox.ButtonTooltip" xml:space="preserve">
|
||||||
|
<value>Copier le titre</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToastCopyTitle.Message" xml:space="preserve">
|
||||||
|
<value>Titre copié dans le presse-papiers</value>
|
||||||
|
</data>
|
||||||
|
<data name="EntryItemDelete.Text" xml:space="preserve">
|
||||||
|
<value>Supprimer</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@@ -0,0 +1,18 @@
|
|||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
|
||||||
|
namespace ModernKeePass.TemplateSelectors
|
||||||
|
{
|
||||||
|
public class FirstItemDataTemplateSelector : DataTemplateSelector
|
||||||
|
{
|
||||||
|
public DataTemplate FirstItem { get; set; }
|
||||||
|
public DataTemplate OtherItem { get; set; }
|
||||||
|
|
||||||
|
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
|
||||||
|
{
|
||||||
|
var itemsControl = ItemsControl.ItemsControlFromItemContainer(container);
|
||||||
|
var returnTemplate = itemsControl?.IndexFromContainer(container) == 0 ? FirstItem : OtherItem;
|
||||||
|
return returnTemplate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
WinAppCommon/ViewModels/UserControls/BreadcrumbControlVm.cs
Normal file
62
WinAppCommon/ViewModels/UserControls/BreadcrumbControlVm.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using GalaSoft.MvvmLight.Command;
|
||||||
|
using GalaSoft.MvvmLight.Views;
|
||||||
|
using MediatR;
|
||||||
|
using ModernKeePass.Application.Common.Models;
|
||||||
|
using ModernKeePass.Application.Group.Models;
|
||||||
|
using ModernKeePass.Application.Group.Queries.GetGroup;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
using ModernKeePass.Domain.Enums;
|
||||||
|
using ModernKeePass.Models;
|
||||||
|
|
||||||
|
namespace ModernKeePass.ViewModels
|
||||||
|
{
|
||||||
|
public class BreadcrumbControlVm
|
||||||
|
{
|
||||||
|
public ObservableCollection<BreadcrumbItem> BreadcrumbItems { get; }
|
||||||
|
public string ParentGroupName { get; private set; }
|
||||||
|
public Icon ParentGroupIcon { get; private set; } = Icon.Folder;
|
||||||
|
|
||||||
|
public RelayCommand GoBackCommand { get; }
|
||||||
|
public RelayCommand GoUpCommand { get; private set; }
|
||||||
|
public RelayCommand<int> GoToCommand { get; }
|
||||||
|
|
||||||
|
private readonly IMediator _mediator;
|
||||||
|
private readonly INavigationService _navigation;
|
||||||
|
|
||||||
|
public BreadcrumbControlVm(IMediator mediator, INavigationService navigation)
|
||||||
|
{
|
||||||
|
_mediator = mediator;
|
||||||
|
_navigation = navigation;
|
||||||
|
|
||||||
|
BreadcrumbItems = new ObservableCollection<BreadcrumbItem>();
|
||||||
|
GoBackCommand = new RelayCommand(() => _navigation.GoBack());
|
||||||
|
GoToCommand = new RelayCommand<int>(GoTo);
|
||||||
|
GoUpCommand = new RelayCommand(() => GoTo(BreadcrumbItems.Count - 1), () => !string.IsNullOrEmpty(ParentGroupName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Initialize(GroupVm group)
|
||||||
|
{
|
||||||
|
if (group == null) return;
|
||||||
|
GoBackCommand.RaiseCanExecuteChanged();
|
||||||
|
ParentGroupName = group.Title;
|
||||||
|
ParentGroupIcon = group.Icon;
|
||||||
|
|
||||||
|
BreadcrumbItems.Add(new BreadcrumbItem { Path = group.Id, Name = group.Title, Icon = group.Icon });
|
||||||
|
var parentGroup = group;
|
||||||
|
while (!string.IsNullOrEmpty(parentGroup.ParentGroupId))
|
||||||
|
{
|
||||||
|
parentGroup = await _mediator.Send(new GetGroupQuery {Id = parentGroup.ParentGroupId});
|
||||||
|
BreadcrumbItems.Add(new BreadcrumbItem {Path = parentGroup.Id, Name = parentGroup.Title, Icon = parentGroup.Icon});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GoTo(int index)
|
||||||
|
{
|
||||||
|
if (BreadcrumbItems.Count == 0) return;
|
||||||
|
var breadcrumb = BreadcrumbItems[index];
|
||||||
|
_navigation.NavigateTo(Constants.Navigation.GroupPage, new NavigationItem { Id = breadcrumb.Path });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -21,6 +21,7 @@ using MediatR;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using ModernKeePass.Application.Common.Interfaces;
|
using ModernKeePass.Application.Common.Interfaces;
|
||||||
using ModernKeePass.ViewModels.Settings;
|
using ModernKeePass.ViewModels.Settings;
|
||||||
|
using ModernKeePass.Domain.Interfaces;
|
||||||
|
|
||||||
namespace ModernKeePass.ViewModels
|
namespace ModernKeePass.ViewModels
|
||||||
{
|
{
|
||||||
@@ -45,7 +46,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Create run time view services and models
|
// Create run time view services and models
|
||||||
//SimpleIoc.Default.Register<IDataService, DataService>();IDataService
|
SimpleIoc.Default.Register(() => App.Services.GetRequiredService<IDateTime>());
|
||||||
SimpleIoc.Default.Register(() => App.Services.GetRequiredService<IMediator>());
|
SimpleIoc.Default.Register(() => App.Services.GetRequiredService<IMediator>());
|
||||||
SimpleIoc.Default.Register(() => App.Services.GetRequiredService<IRecentProxy>());
|
SimpleIoc.Default.Register(() => App.Services.GetRequiredService<IRecentProxy>());
|
||||||
SimpleIoc.Default.Register(() => App.Services.GetRequiredService<IResourceProxy>());
|
SimpleIoc.Default.Register(() => App.Services.GetRequiredService<IResourceProxy>());
|
||||||
@@ -69,6 +70,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
SimpleIoc.Default.Register<TopMenuVm>();
|
SimpleIoc.Default.Register<TopMenuVm>();
|
||||||
SimpleIoc.Default.Register<ColorPickerControlVm>();
|
SimpleIoc.Default.Register<ColorPickerControlVm>();
|
||||||
SimpleIoc.Default.Register<PasswordGenerationBoxControlVm>();
|
SimpleIoc.Default.Register<PasswordGenerationBoxControlVm>();
|
||||||
|
SimpleIoc.Default.Register<BreadcrumbControlVm>();
|
||||||
SimpleIoc.Default.Register<NewVm>();
|
SimpleIoc.Default.Register<NewVm>();
|
||||||
SimpleIoc.Default.Register<OpenVm>();
|
SimpleIoc.Default.Register<OpenVm>();
|
||||||
SimpleIoc.Default.Register<RecentVm>();
|
SimpleIoc.Default.Register<RecentVm>();
|
||||||
@@ -86,6 +88,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
public TopMenuVm TopMenu => ServiceLocator.Current.GetInstance<TopMenuVm>(Guid.NewGuid().ToString());
|
public TopMenuVm TopMenu => ServiceLocator.Current.GetInstance<TopMenuVm>(Guid.NewGuid().ToString());
|
||||||
public ColorPickerControlVm ColorPicker => ServiceLocator.Current.GetInstance<ColorPickerControlVm>(Guid.NewGuid().ToString());
|
public ColorPickerControlVm ColorPicker => ServiceLocator.Current.GetInstance<ColorPickerControlVm>(Guid.NewGuid().ToString());
|
||||||
public PasswordGenerationBoxControlVm PasswordGenerationBox => ServiceLocator.Current.GetInstance<PasswordGenerationBoxControlVm>(Guid.NewGuid().ToString());
|
public PasswordGenerationBoxControlVm PasswordGenerationBox => ServiceLocator.Current.GetInstance<PasswordGenerationBoxControlVm>(Guid.NewGuid().ToString());
|
||||||
|
public BreadcrumbControlVm Breadcrumb => ServiceLocator.Current.GetInstance<BreadcrumbControlVm>(Guid.NewGuid().ToString());
|
||||||
public NewVm New => ServiceLocator.Current.GetInstance<NewVm>(Guid.NewGuid().ToString());
|
public NewVm New => ServiceLocator.Current.GetInstance<NewVm>(Guid.NewGuid().ToString());
|
||||||
public OpenVm Open => ServiceLocator.Current.GetInstance<OpenVm>(Guid.NewGuid().ToString());
|
public OpenVm Open => ServiceLocator.Current.GetInstance<OpenVm>(Guid.NewGuid().ToString());
|
||||||
public RecentVm Recent => ServiceLocator.Current.GetInstance<RecentVm>(Guid.NewGuid().ToString());
|
public RecentVm Recent => ServiceLocator.Current.GetInstance<RecentVm>(Guid.NewGuid().ToString());
|
||||||
|
@@ -42,6 +42,7 @@
|
|||||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\NavigateToPageMessage.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Messages\NavigateToPageMessage.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\PasswordGeneratedMessage.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Messages\PasswordGeneratedMessage.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\SaveErrorMessage.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Messages\SaveErrorMessage.cs" />
|
||||||
|
<Compile Include="$(MSBuildThisFileDirectory)TemplateSelectors\FirstItemDataTemplateSelector.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\AboutVm.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\AboutVm.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Items\EntryFieldVm.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Items\EntryFieldVm.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Settings\CredentialsVm.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Settings\CredentialsVm.cs" />
|
||||||
@@ -50,6 +51,7 @@
|
|||||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Settings\RecycleBinVm.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Settings\RecycleBinVm.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Settings\GeneralVm.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Settings\GeneralVm.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Settings\SecurityVm.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Settings\SecurityVm.cs" />
|
||||||
|
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\BreadcrumbControlVm.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\ColorPickerControlVm.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\ColorPickerControlVm.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\PasswordGenerationBoxControlVm.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\PasswordGenerationBoxControlVm.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\ViewModelLocatorCommon.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\ViewModelLocatorCommon.cs" />
|
||||||
@@ -64,4 +66,10 @@
|
|||||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\SetCredentialsVm.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\SetCredentialsVm.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\TopMenuVm.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\TopMenuVm.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PRIResource Include="$(MSBuildThisFileDirectory)Strings\en-US\CodeBehind.resw" />
|
||||||
|
<PRIResource Include="$(MSBuildThisFileDirectory)Strings\en-US\Resources.resw" />
|
||||||
|
<PRIResource Include="$(MSBuildThisFileDirectory)Strings\fr-FR\CodeBehind.resw" />
|
||||||
|
<PRIResource Include="$(MSBuildThisFileDirectory)Strings\fr-FR\Resources.resw" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Reference in New Issue
Block a user