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