Ensure containers show up in the menu when they are created
This commit is contained in:
@@ -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();
|
||||
}
|
||||
@@ -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>
|
||||
@@ -1,8 +0,0 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace Bitvault.Avalonia;
|
||||
|
||||
public partial class AddItemView : UserControl
|
||||
{
|
||||
public AddItemView() => InitializeComponent();
|
||||
}
|
||||
@@ -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>();
|
||||
|
||||
@@ -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>
|
||||
|
||||
+2
-2
@@ -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();
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,4 +7,4 @@ public record ContainerConfiguration : ComponentConfiguration
|
||||
public string? Name { get; set; }
|
||||
|
||||
public string? Key { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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
@@ -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,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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user