Ensure containers show up in the menu when they are created

This commit is contained in:
TheXamlGuy
2024-05-12 17:09:59 +01:00
parent 0ae3f60334
commit 975d5e6894
32 changed files with 211 additions and 174 deletions
+5 -1
View File
@@ -15,9 +15,13 @@
ToolTip.Tip="Add item">
<Interaction.Behaviors>
<EventTriggerBehavior EventName="Click">
<NavigateAction
Context="{Binding Named, StringFormat='{}{0}:ContentHeader'}"
Route="ItemCommandHeader"
Scope="self" />
<NavigateAction
Context="{Binding Named, StringFormat='{}{0}:Content'}"
Route="AddItem"
Route="Item"
Scope="self" />
</EventTriggerBehavior>
</Interaction.Behaviors>
@@ -1,8 +0,0 @@
using Avalonia.Controls;
namespace Bitvault.Avalonia;
public partial class AddItemCommandHeaderView : UserControl
{
public AddItemCommandHeaderView() => InitializeComponent();
}
-18
View File
@@ -1,18 +0,0 @@
<UserControl
x:Class="Bitvault.Avalonia.AddItemView"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Bitvault"
x:DataType="vm:AddItemViewModel">
<Interaction.Behaviors>
<EventTriggerBehavior EventName="Loaded">
<NavigateAction
Context="{Binding Named, StringFormat='{}{0}:ContentHeader'}"
Route="AddVaultContentCommandHeader"
Scope="self" />
</EventTriggerBehavior>
</Interaction.Behaviors>
<ScrollViewer Padding="12,12,12,0">
<ItemsControl ItemTemplate="{ReflectionBinding Template}" ItemsSource="{Binding}" />
</ScrollViewer>
</UserControl>
-8
View File
@@ -1,8 +0,0 @@
using Avalonia.Controls;
namespace Bitvault.Avalonia;
public partial class AddItemView : UserControl
{
public AddItemView() => InitializeComponent();
}
+8 -7
View File
@@ -35,6 +35,8 @@ public partial class App : Application
services.AddTemplate<MainWindowViewModel, MainWindow>("MainWindow");
}
services.AddHandler<ContainerActivatedHandler>();
services.AddTransient<IContainerComponent> (provider => Component.Create<ContainerComponent>(provider, args =>
{
args.AddServices(services =>
@@ -47,14 +49,14 @@ public partial class App : Application
services.AddTransient<IKeyDeriver, KeyDeriver>();
services.AddTransient<ISecurityKeyFactory, SecurityKeyFactory>();
services.AddTransient<IContainer, ContainerFactory>();
services.TryAddSingleton<IContainer<SecurityKey>, Container<SecurityKey>>();
services.TryAddSingleton<IContainer<ContainerConnection>, Container<ContainerConnection>>();
services.AddTransient<IContainerFactory, ContainerFactory>();
services.TryAddSingleton<IValueStore<SecurityKey>, ValueStore<SecurityKey>>();
services.TryAddSingleton<IValueStore<ContainerConnection>, ValueStore<ContainerConnection>>();
services.AddDbContextFactory<ContainerDbContext>((provider, args) =>
{
if (provider.GetRequiredService<IContainer<ContainerConnection>>()
is IContainer<ContainerConnection> connection)
if (provider.GetRequiredService<IValueStore<ContainerConnection>>()
is IValueStore<ContainerConnection> connection)
{
args.UseSqlite($"{connection.Value}");
}
@@ -80,8 +82,7 @@ public partial class App : Application
services.AddTemplate<ItemNavigationViewModel, ItemNavigationView>();
services.AddTemplate<ItemViewModel, ItemView>("Item");
services.AddTemplate<AddItemViewModel, AddItemView>("AddItem");
services.AddTemplate<AddItemCommandHeaderViewModel, AddItemCommandHeaderView>("AddVaultContentCommandHeader");
services.AddTemplate<ItemCommandHeaderViewModel, ItemCommandHeaderView>("ItemCommandHeader");
services.AddTemplate<ConfirmItemActionViewModel, ConfirmItemActionView>();
services.AddTemplate<DismissItemActionViewModel, DismissItemActionView>();
+2 -5
View File
@@ -43,11 +43,8 @@
<Compile Update="AddItemActionView.axaml.cs">
<DependentUpon>AddItemActionView.axaml</DependentUpon>
</Compile>
<Compile Update="AddItemCommandHeaderView.axaml.cs">
<DependentUpon>AddItemCommandHeaderView.axaml</DependentUpon>
</Compile>
<Compile Update="AddItemView.axaml.cs">
<DependentUpon>AddItemView.axaml</DependentUpon>
<Compile Update="ItemCommandHeaderView.axaml.cs">
<DependentUpon>ItemCommandHeaderView.axaml</DependentUpon>
</Compile>
<Compile Update="ConfirmItemActionView.axaml.cs">
<DependentUpon>ConfirmItemActionView.axaml</DependentUpon>
@@ -1,9 +1,9 @@
<UserControl
x:Class="Bitvault.Avalonia.AddItemCommandHeaderView"
x:Class="Bitvault.Avalonia.ItemCommandHeaderView"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Bitvault"
x:DataType="vm:AddItemCommandHeaderViewModel">
x:DataType="vm:ItemCommandHeaderViewModel">
<UserControl.Resources>
<ResourceDictionary>
<x:Double x:Key="ButtonWidth">40</x:Double>
@@ -0,0 +1,8 @@
using Avalonia.Controls;
namespace Bitvault.Avalonia;
public partial class ItemCommandHeaderView : UserControl
{
public ItemCommandHeaderView() => InitializeComponent();
}
+11 -4
View File
@@ -3,15 +3,22 @@
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Bitvault"
x:Name="Name"
x:CompileBindings="False"
x:DataType="vm:ItemNavigationViewModel">
<Interaction.Behaviors>
<DataTriggerBehavior Binding="{Binding Selected}" Value="True">
<NavigateAction Context="{Binding Named, StringFormat='{}{0}:Content'}" Route="Item" />
<NavigateAction
Context="{Binding Named, StringFormat='{}{0}:ContentHeader'}"
Route="ItemCommandHeader"
Scope="self" />
<NavigateAction Context="{Binding Named, StringFormat='{}{0}:Content'}" Route="Item">
<NavigateAction.ParameterBindings>
<ParameterBinding Key="Id" Value="{Binding Id}" />
<ParameterBinding Key="Name" Value="{Binding Name}" />
</NavigateAction.ParameterBindings>
</NavigateAction>
</DataTriggerBehavior>
</Interaction.Behaviors>
<Grid ColumnDefinitions="Auto,*">
<Grid Background="Transparent" ColumnDefinitions="Auto,*">
<PersonPicture
Grid.Column="0"
Height="34"
+6 -2
View File
@@ -1,6 +1,10 @@
<UserControl
x:Class="Bitvault.Avalonia.ItemView"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
Vault content placeholder
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Bitvault"
x:DataType="vm:ItemViewModel">
<ScrollViewer Padding="12,12,12,0">
<ItemsControl ItemTemplate="{ReflectionBinding Template}" ItemsSource="{Binding}" />
</ScrollViewer>
</UserControl>
-40
View File
@@ -1,40 +0,0 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Toolkit.Foundation;
namespace Bitvault;
public partial class AddItemViewModel :
ObservableCollectionViewModel<IItemViewModel>,
INotificationHandler<Confirm<Item>>
{
[ObservableProperty]
private string named;
public AddItemViewModel(IServiceProvider provider,
IServiceFactory factory,
IMediator mediator,
IPublisher publisher,
ISubscriber subscriber,
IDisposer disposer,
IContentTemplate template,
NamedComponent named) : base(provider, factory, mediator, publisher, subscriber, disposer)
{
Template = template;
Named = $"{named}";
Add<ItemHeaderViewModel>();
}
public IContentTemplate Template { get; set; }
public async Task Handle(Confirm<Item> args, CancellationToken cancellationToken = default)
{
ItemConfiguration configuration = new();
foreach (IItemViewModel item in this)
{
item.Invoke(configuration);
}
await Mediator.Handle<Create<ItemConfiguration>, bool>(Create.As(configuration), cancellationToken);
}
}
+1
View File
@@ -6,6 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="LinqKit.Microsoft.EntityFrameworkCore" Version="8.1.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0-preview.3.24172.4" />
</ItemGroup>
<ItemGroup>
+6 -6
View File
@@ -2,25 +2,25 @@
namespace Bitvault;
public record SecureStorage<TValue>(TValue? Value = default);
public record Container<TValue>(TValue? Value = default);
public record Vault
public record Container
{
public Vault(string name, string password)
public Container(string name, string password)
{
Name = name;
Password = password;
}
public Vault(string password)
public Container(string password)
{
Password = password;
}
public static SecureStorage<TValue> As<TValue>(TValue value) => new(value);
public static Container<TValue> As<TValue>(TValue value) => new(value);
public static SecureStorage<TValue> As<TValue>() where TValue : new() => new(new TValue());
public static Container<TValue> As<TValue>() where TValue : new() => new(new TValue());
[MaybeNull]
+26
View File
@@ -0,0 +1,26 @@
using Microsoft.Extensions.DependencyInjection;
using Toolkit.Foundation;
namespace Bitvault;
public record ContainerActivatedHandler(IPublisher publisher) :
INotificationHandler<Activated<IComponentHost>>
{
public async Task Handle(Activated<IComponentHost> args, CancellationToken cancellationToken = default)
{
if (args.Value is IComponentHost container)
{
if (container.Services.GetRequiredService<ContainerConfiguration>() is ContainerConfiguration configuration)
{
if (container.Services.GetRequiredService<IServiceFactory>() is IServiceFactory factory)
{
if (factory.Create<ContainerNavigationViewModel>(configuration.Name) is ContainerNavigationViewModel viewModel)
{
await publisher.Publish(new Create<IMainNavigationViewModel>(viewModel),
nameof(MainViewModel), cancellationToken);
}
}
}
}
}
}
+1 -1
View File
@@ -7,4 +7,4 @@ public record ContainerConfiguration : ComponentConfiguration
public string? Name { get; set; }
public string? Key { get; set; }
}
}
+2 -2
View File
@@ -6,10 +6,10 @@ using Toolkit.Foundation;
namespace Bitvault;
public class ContainerFactory(IContainer<ContainerConnection> connection,
public class ContainerFactory(IValueStore<ContainerConnection> connection,
IHostEnvironment environment,
IServiceProvider provider) :
IContainer
IContainerFactory
{
public async Task<bool> Create(string name,
SecurityKey key)
+2 -2
View File
@@ -3,7 +3,7 @@
namespace Bitvault;
public partial class ContainerHeaderViewModel : ObservableCollectionViewModel<string, IDisposable>,
INotificationHandler<SecureStorage<Filter<string>>>
INotificationHandler<Container<Filter<string>>>
{
public ContainerHeaderViewModel(IServiceProvider provider,
IServiceFactory factory,
@@ -20,7 +20,7 @@ public partial class ContainerHeaderViewModel : ObservableCollectionViewModel<st
public IContentTemplate Template { get; set; }
public Task Handle(SecureStorage<Filter<string>> args,
public Task Handle(Container<Filter<string>> args,
CancellationToken cancellationToken = default)
{
if (args.Value is Filter<string> filter)
+8 -8
View File
@@ -6,10 +6,10 @@ namespace Bitvault;
public partial class ContainerNavigationViewModel :
ObservableCollectionViewModel<IContainerNavigationViewModel>,
IMainNavigationViewModel,
INotificationHandler<SecureStorage<Opened>>,
INotificationHandler<SecureStorage<Closed>>,
INotificationHandler<SecureStorage<Activated>>,
INotificationHandler<SecureStorage<Deactivated>>
INotificationHandler<Container<Opened>>,
INotificationHandler<Container<Closed>>,
INotificationHandler<Container<Activated>>,
INotificationHandler<Container<Deactivated>>
{
[ObservableProperty]
private bool activated;
@@ -41,7 +41,7 @@ public partial class ContainerNavigationViewModel :
public IContentTemplate Template { get; set; }
public Task Handle(SecureStorage<Opened> args,
public Task Handle(Container<Opened> args,
CancellationToken cancellationToken = default)
{
Add<AllNavigationViewModel>("All");
@@ -53,7 +53,7 @@ public partial class ContainerNavigationViewModel :
return Task.CompletedTask;
}
public Task Handle(SecureStorage<Closed> args,
public Task Handle(Container<Closed> args,
CancellationToken cancellationToken = default)
{
Opened = true;
@@ -62,11 +62,11 @@ public partial class ContainerNavigationViewModel :
return Task.CompletedTask;
}
public Task Handle(SecureStorage<Deactivated> args,
public Task Handle(Container<Deactivated> args,
CancellationToken cancellationToken = default) =>
Task.FromResult(Activated = false);
public Task Handle(SecureStorage<Activated> args,
public Task Handle(Container<Activated> args,
CancellationToken cancellationToken = default) =>
Task.FromResult(Activated = true);
}
+4 -4
View File
@@ -14,7 +14,7 @@ public partial class ContainerViewModel(IServiceProvider provider,
IContentTemplate template,
NamedComponent named,
string? filter = null) : ObservableCollectionViewModel<ItemNavigationViewModel>(provider, factory, mediator, publisher, subscriber, disposer),
INotificationHandler<SecureStorage<Filter<string>>>
INotificationHandler<Container<Filter<string>>>
{
[ObservableProperty]
private string? filter = filter;
@@ -26,17 +26,17 @@ public partial class ContainerViewModel(IServiceProvider provider,
public override async Task Activated()
{
await Publisher.Publish(Vault.As<Activated>());
await Publisher.Publish(Container.As<Activated>());
await base.Activated();
}
public override async Task Deactivated()
{
await Publisher.Publish(Vault.As<Deactivated>());
await Publisher.Publish(Container.As<Deactivated>());
await base.Deactivated();
}
public async Task Handle(SecureStorage<Filter<string>> args,
public async Task Handle(Container<Filter<string>> args,
CancellationToken cancellationToken = default)
{
if (args.Value is Filter<string> filter)
+40 -15
View File
@@ -1,34 +1,59 @@
using Bitvault.Data;
using LinqKit;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Toolkit.Foundation;
namespace Bitvault;
public class ContainerViewModelHandler(IDbContextFactory<ContainerDbContext> dbContextFactory,
IServiceFactory factory,
IServiceProvider serviceProvider,
IPublisher publisher) :
INotificationHandler<Enumerate<ItemNavigationViewModel, ContainerViewModelConfiguration>>
{
public async Task Handle(Enumerate<ItemNavigationViewModel, ContainerViewModelConfiguration> args,
CancellationToken cancellationToken = default)
{
var items = await Task.Run(async () =>
if (args.Options is ContainerViewModelConfiguration configuration)
{
using ContainerDbContext context = dbContextFactory.CreateDbContext();
return await context.Set<Data.Item>().Select(x => new
{
x.Name,
x.State
}).Where(x => x.State != 3).ToListAsync();
ExpressionStarter<Data.Item> predicate = PredicateBuilder.New<Data.Item>(true);
}, cancellationToken);
foreach (var item in items)
{
if (factory.Create<ItemNavigationViewModel>(item.Name, "Description " + 1) is ItemNavigationViewModel viewModel)
if (configuration.Filter == "All")
{
await publisher.Publish(new Create<ItemNavigationViewModel>(viewModel),
nameof(ContainerViewModel), cancellationToken);
predicate = predicate.And(x => x.State != 3);
}
if (configuration.Filter == "Starred")
{
predicate = predicate.And(x => x.State != 3 && x.State == 2);
}
if (configuration.Filter == "Archive")
{
predicate = predicate.And(x => x.State == 3);
}
var items = await Task.Run(async () =>
{
using ContainerDbContext context = dbContextFactory.CreateDbContext();
return await context.Set<Data.Item>().Where(predicate).Select(x => new
{
x.Id,
x.Name
}).ToListAsync();
}, cancellationToken);
foreach (var item in items)
{
IServiceScope serviceScope = serviceProvider.CreateScope();
IServiceFactory serviceFactory = serviceScope.ServiceProvider.GetRequiredService<IServiceFactory>();
if (serviceFactory.Create<ItemNavigationViewModel>(item.Id, item.Name, "Description " + 1) is ItemNavigationViewModel viewModel)
{
await publisher.Publish(new Create<ItemNavigationViewModel>(viewModel),
nameof(ContainerViewModel), cancellationToken);
}
}
}
}
+11 -9
View File
@@ -5,26 +5,27 @@ using Toolkit.Foundation;
namespace Bitvault;
public class CreateContainerHandler(IContainerComponentFactory componentFactory) :
IHandler<Create<Vault>, bool>
public class CreateContainerHandler(IContainerComponentFactory componentFactory,
IPublisher publisher) :
IHandler<Create<Container>, bool>
{
public async Task<bool> Handle(Create<Vault> args,
public async Task<bool> Handle(Create<Container> args,
CancellationToken cancellationToken)
{
if (args.Value is Vault vault && vault.Name is { Length: > 0 } name &&
vault.Password is { Length: > 0 } password)
if (args.Value is Container container && container.Name is { Length: > 0 } name &&
container.Password is { Length: > 0 } password)
{
if (componentFactory.Create(name) is IComponentHost host)
{
ISecurityKeyFactory keyVaultFactory = host.Services.GetRequiredService<ISecurityKeyFactory>();
IContainer<SecurityKey> vaultKeyContainer = host.Services.GetRequiredService<IContainer<SecurityKey>>();
IContainer vaultStorage = host.Services.GetRequiredService<IContainer>();
IValueStore<SecurityKey> secureKeyStore = host.Services.GetRequiredService<IValueStore<SecurityKey>>();
IContainerFactory containerFactory = host.Services.GetRequiredService<IContainerFactory>();
if (keyVaultFactory.Create(Encoding.UTF8.GetBytes(password)) is SecurityKey key)
{
vaultKeyContainer.Set(key);
secureKeyStore.Set(key);
if (await vaultStorage.Create(name, key))
if (await containerFactory.Create(name, key))
{
IWritableConfiguration<ContainerConfiguration> configuration =
host.Services.GetRequiredService<IWritableConfiguration<ContainerConfiguration>>();
@@ -32,6 +33,7 @@ public class CreateContainerHandler(IContainerComponentFactory componentFactory)
configuration.Write(args => args.Key = $"{Convert.ToBase64String(key.Salt)}:{Convert.ToBase64String(key.EncryptedKey)}:{Convert.ToBase64String(key.DecryptedKey)}");
host.Start();
await publisher.Publish(Activated.As(host), cancellationToken);
return true;
}
}
+1 -1
View File
@@ -22,5 +22,5 @@ public partial class CreateContainerViewModel(IServiceProvider provider,
private string password;
public async Task<bool> Confirm() =>
await Mediator.Handle<Create<Vault>, bool>(Create.As(new Vault(Name, Password)));
await Mediator.Handle<Create<Container>, bool>(Create.As(new Container(Name, Password)));
}
@@ -6,8 +6,8 @@ namespace Bitvault;
public partial class FilterContainerNavigationViewModel : ObservableViewModel,
IContainerNavigationViewModel,
INotificationHandler<SecureStorage<Activated>>,
INotificationHandler<SecureStorage<Deactivated>>
INotificationHandler<Container<Activated>>,
INotificationHandler<Container<Deactivated>>
{
[ObservableProperty]
private bool activated;
@@ -29,14 +29,14 @@ public partial class FilterContainerNavigationViewModel : ObservableViewModel,
Filter = filter;
}
public Task Handle(SecureStorage<Deactivated> args,
public Task Handle(Container<Deactivated> args,
CancellationToken cancellationToken = default) =>
Task.FromResult(Activated = false);
public Task Handle(SecureStorage<Activated> args,
public Task Handle(Container<Activated> args,
CancellationToken cancellationToken = default) =>
Task.FromResult(Activated = true);
[RelayCommand]
public async Task Invoke() => await Publisher.Publish(Vault.As(new Filter<string>(Filter)));
public async Task Invoke() => await Publisher.Publish(Container.As(new Filter<string>(Filter)));
}
@@ -1,6 +1,6 @@
namespace Bitvault;
public interface IContainer
public interface IContainerFactory
{
Task<bool> Create(string name, SecurityKey key);
}
@@ -2,9 +2,9 @@
namespace Bitvault;
public partial class AddItemCommandHeaderViewModel : ObservableCollectionViewModel
public partial class ItemCommandHeaderViewModel : ObservableCollectionViewModel
{
public AddItemCommandHeaderViewModel(IServiceProvider provider,
public ItemCommandHeaderViewModel(IServiceProvider provider,
IServiceFactory factory,
IMediator mediator,
IPublisher publisher,
-1
View File
@@ -17,7 +17,6 @@ public class ItemConfigurationHandler(IDbContextFactory<ContainerDbContext> dbCo
await Task.Run(async () =>
{
using ContainerDbContext context = dbContextFactory.CreateDbContext();
await context.AddAsync(new Data.Item { Name = configuration.Name }, cancellationToken);
await context.SaveChangesAsync(cancellationToken);
}, cancellationToken);
+3 -1
View File
@@ -7,9 +7,11 @@ public partial class ItemHeaderViewModel(IServiceProvider provider,
IMediator mediator,
IPublisher publisher,
ISubscriber subscriber,
IDisposer disposer) : ObservableViewModel<string, string>(provider, factory, mediator, publisher, subscriber, disposer),
IDisposer disposer,
string? value = null) : ObservableViewModel<string, string>(provider, factory, mediator, publisher, subscriber, disposer, value),
IItemViewModel
{
public void Invoke(ItemConfiguration args) =>
args.Name = Value;
}
+4
View File
@@ -11,6 +11,7 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
IDisposer disposer,
IContentTemplate template,
NamedComponent named,
int id,
string name,
string description) :
ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer)
@@ -18,6 +19,9 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
[ObservableProperty]
private string? description = description;
[ObservableProperty]
private int id = id;
[ObservableProperty]
private string? name = name;
+42 -11
View File
@@ -1,15 +1,46 @@
using Toolkit.Foundation;
using CommunityToolkit.Mvvm.ComponentModel;
using Toolkit.Foundation;
namespace Bitvault;
public class ItemViewModel(IServiceProvider provider,
IServiceFactory factory,
IMediator mediator,
IPublisher publisher,
ISubscriber subscriber,
IDisposer disposer,
IContentTemplate template) :
ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer)
public partial class ItemViewModel :
ObservableCollectionViewModel<IItemViewModel>,
INotificationHandler<Confirm<Item>>
{
public IContentTemplate Template { get; set; } = template;
}
[ObservableProperty]
private int? id;
[ObservableProperty]
private string named;
public ItemViewModel(IServiceProvider provider,
IServiceFactory factory,
IMediator mediator,
IPublisher publisher,
ISubscriber subscriber,
IDisposer disposer,
IContentTemplate template,
NamedComponent named,
int? id = null,
string? name = null) : base(provider, factory, mediator, publisher, subscriber, disposer)
{
Template = template;
Named = $"{named}";
Id = id;
Add<ItemHeaderViewModel>(name ?? "");
}
public IContentTemplate Template { get; set; }
public async Task Handle(Confirm<Item> args, CancellationToken cancellationToken = default)
{
ItemConfiguration configuration = new();
foreach (IItemViewModel item in this)
{
item.Invoke(configuration);
}
await Mediator.Handle<Create<ItemConfiguration>, bool>(Create.As(configuration), cancellationToken);
}
}
+4 -4
View File
@@ -4,17 +4,17 @@ using Toolkit.Foundation;
namespace Bitvault;
public class MainViewModelHandler(IPublisher publisher,
IContainerHostCollection vaults) :
IContainerHostCollection containers) :
INotificationHandler<Enumerate<IMainNavigationViewModel>>
{
public async Task Handle(Enumerate<IMainNavigationViewModel> args,
CancellationToken cancellationToken = default)
{
foreach (IComponentHost vault in vaults)
foreach (IComponentHost container in containers)
{
if (vault.Services.GetRequiredService<ContainerConfiguration>() is ContainerConfiguration configuration)
if (container.Services.GetRequiredService<ContainerConfiguration>() is ContainerConfiguration configuration)
{
if (vault.Services.GetRequiredService<IServiceFactory>() is IServiceFactory factory)
if (container.Services.GetRequiredService<IServiceFactory>() is IServiceFactory factory)
{
if (factory.Create<ContainerNavigationViewModel>(configuration.Name) is ContainerNavigationViewModel viewModel)
{
+4 -4
View File
@@ -5,13 +5,13 @@ namespace Bitvault;
public class OpenContainerHandler(ContainerConfiguration configuration,
ISecurityKeyFactory keyVaultFactory,
IContainer vaultStorage) :
IHandler<Open<Vault>, bool>
IContainerFactory vaultStorage) :
IHandler<Open<Container>, bool>
{
public async Task<bool> Handle(Open<Vault> args,
public async Task<bool> Handle(Open<Container> args,
CancellationToken cancellationToken)
{
if (args.Value is Vault vault && configuration.Name is { Length: > 0 } name && vault.Password is { Length: > 0 } password)
if (args.Value is Container container && configuration.Name is { Length: > 0 } name && container.Password is { Length: > 0 } password)
{
if (configuration.Key?.Split(':') is { Length: >= 2 } keyPart)
{
+2 -2
View File
@@ -20,9 +20,9 @@ public partial class OpenContainerViewModel(IServiceProvider provider,
{
if (Password is { Length: > 0 })
{
if (await Mediator.Handle<Open<Vault>, bool>(Open.As(new Vault(Password))))
if (await Mediator.Handle<Open<Container>, bool>(Open.As(new Container(Password))))
{
await Publisher.Publish(Vault.As<Opened>());
await Publisher.Publish(Container.As<Opened>());
}
}
}