WIP
This commit is contained in:
@@ -66,7 +66,9 @@ public partial class App : Application
|
||||
{
|
||||
args.UseSqlite($"{connection.Value}");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
services.AddHandler<QueryContainerHandler>(ServiceLifetime.Singleton);
|
||||
|
||||
services.AddHandler<OpenContainerHandler>();
|
||||
|
||||
@@ -78,10 +80,12 @@ public partial class App : Application
|
||||
|
||||
services.AddTemplate<OpenContainerViewModel, OpenView>("OpenContainer");
|
||||
|
||||
services.AddTemplate<ContainerViewModel, ContainerView>("Container");
|
||||
services.AddHandler<ContainerViewModelHandler>();
|
||||
services.AddScoped<ContainerViewModelConfiguration>();
|
||||
|
||||
services.AddTemplate<SearchHeaderViewModel, SearchHeaderView>("SearchHeader");
|
||||
services.AddTemplate<ContainerViewModel, ContainerView>("Container");
|
||||
services.AddHandler<EnumerateContainerViewModelHandler>();
|
||||
|
||||
services.AddTemplate<SearchContainerActionViewModel, SearchContainerActionView>();
|
||||
services.AddTemplate<ContainerHeaderViewModel, ContainerHeaderView>("ContainerHeader");
|
||||
services.AddTemplate<CreateItemActionViewModel, CreateItemActionView>();
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
|
||||
@@ -79,9 +79,6 @@
|
||||
<Compile Update="ContainerNavigationView.axaml.cs">
|
||||
<DependentUpon>ContainerNavigationView.axaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="SearchHeaderView.axaml.cs">
|
||||
<DependentUpon>SearchHeaderView.axaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="ContainerView.axaml.cs">
|
||||
<DependentUpon>ContainerView.axaml</DependentUpon>
|
||||
</Compile>
|
||||
|
||||
@@ -4,32 +4,5 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:Bitvault"
|
||||
x:DataType="vm:ContainerHeaderViewModel">
|
||||
<UserControl.Resources>
|
||||
<x:Double x:Key="ButtonWidth">40</x:Double>
|
||||
<x:Double x:Key="ButtonHeight">36</x:Double>
|
||||
<SolidColorBrush x:Key="ButtonBackground" Color="{DynamicResource SubtleFillColorTransparent}" />
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="{DynamicResource SubtleFillColorSecondary}" />
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="{DynamicResource SubtleFillColorTertiary}" />
|
||||
<Thickness x:Key="ButtonBorderThemeThickness">0</Thickness>
|
||||
</UserControl.Resources>
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
Margin="16,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Value}"
|
||||
Theme="{DynamicResource BodyStrongTextBlockStyle}" />
|
||||
<ItemsControl
|
||||
Grid.Column="1"
|
||||
Margin="0,0,4,0"
|
||||
VerticalAlignment="Center"
|
||||
ItemTemplate="{ReflectionBinding Template}"
|
||||
ItemsSource="{Binding}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
<ItemsControl ItemTemplate="{ReflectionBinding Template}" ItemsSource="{Binding}" />
|
||||
</UserControl>
|
||||
|
||||
@@ -5,17 +5,20 @@
|
||||
xmlns:vm="using:Bitvault"
|
||||
x:DataType="vm:ContainerViewModel">
|
||||
<Grid ColumnDefinitions="320,Auto,*" RowDefinitions="Auto,*">
|
||||
<ContentControl
|
||||
<Grid
|
||||
x:Name="Title"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Height="40"
|
||||
Margin="4,4,0,0">
|
||||
<Interaction.Behaviors>
|
||||
<AttachedBehaviour>
|
||||
<NavigateAction Region="{Binding $self}" Route="ContainerHeader" />
|
||||
</AttachedBehaviour>
|
||||
</Interaction.Behaviors>
|
||||
</ContentControl>
|
||||
Grid.ColumnSpan="3"
|
||||
Height="44"
|
||||
ColumnDefinitions="*, Auto">
|
||||
<ContentControl Grid.Column="0" VerticalAlignment="Center">
|
||||
<Interaction.Behaviors>
|
||||
<AttachedBehaviour>
|
||||
<NavigateAction Region="{Binding $self}" Route="ContainerHeader" />
|
||||
</AttachedBehaviour>
|
||||
</Interaction.Behaviors>
|
||||
</ContentControl>
|
||||
</Grid>
|
||||
<ListBox
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
|
||||
@@ -1,8 +1,20 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using FluentAvalonia.UI.Windowing;
|
||||
|
||||
namespace Bitvault.Avalonia;
|
||||
|
||||
public partial class ContainerView : UserControl
|
||||
{
|
||||
public ContainerView() => InitializeComponent();
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs args)
|
||||
{
|
||||
base.OnLoaded(args);
|
||||
|
||||
if (VisualRoot is AppWindow appWindow)
|
||||
{
|
||||
Title.ColumnDefinitions[1].Width = new GridLength(appWindow.TitleBar.RightInset, GridUnitType.Pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,11 +14,11 @@
|
||||
</NavigationView.Resources>
|
||||
<Frame>
|
||||
<Interaction.Behaviors>
|
||||
<EventTriggerBehavior EventName="Loaded">
|
||||
<AttachedBehaviour>
|
||||
<NavigateRegionAction Name="Main">
|
||||
<NavigateAction Region="Main" Route="Container" />
|
||||
</NavigateRegionAction>
|
||||
</EventTriggerBehavior>
|
||||
</AttachedBehaviour>
|
||||
</Interaction.Behaviors>
|
||||
</Frame>
|
||||
</NavigationView>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<UserControl
|
||||
x:Class="Bitvault.Avalonia.SearchContainerActionView"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:Bitvault"
|
||||
x:DataType="vm:SearchContainerActionViewModel">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<StaticResource x:Key="TextControlBorderBrush" ResourceKey="ControlStrokeColorDefaultBrush" />
|
||||
<StaticResource x:Key="TextControlBorderBrushPointerOver" ResourceKey="ControlStrokeColorDefaultBrush" />
|
||||
<StaticResource x:Key="TextControlBorderBrushFocused" ResourceKey="ControlStrokeColorDefaultBrush" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<StaticResource x:Key="TextControlBorderBrush" ResourceKey="ControlStrokeColorDefaultBrush" />
|
||||
<StaticResource x:Key="TextControlBorderBrushPointerOver" ResourceKey="ControlStrokeColorDefaultBrush" />
|
||||
<StaticResource x:Key="TextControlBorderBrushFocused" ResourceKey="ControlStrokeColorDefaultBrush" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<AutoCompleteBox
|
||||
MaxWidth="500"
|
||||
CornerRadius="16"
|
||||
Text="{Binding Value}"
|
||||
Watermark="Search">
|
||||
<Interaction.Behaviors>
|
||||
<KeyBindingTriggerBehaviour Gesture="Enter">
|
||||
<InvokeCommandAction Command="{Binding InvokeCommand}" />
|
||||
</KeyBindingTriggerBehaviour>
|
||||
</Interaction.Behaviors>
|
||||
</AutoCompleteBox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,8 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace Bitvault.Avalonia;
|
||||
|
||||
public partial class SearchContainerActionView : UserControl
|
||||
{
|
||||
public SearchContainerActionView() => InitializeComponent();
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
<UserControl
|
||||
x:Class="Bitvault.Avalonia.SearchHeaderView"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<AutoCompleteBox VerticalAlignment="Center" />
|
||||
</UserControl>
|
||||
@@ -1,8 +0,0 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace Bitvault.Avalonia;
|
||||
|
||||
public partial class SearchHeaderView : UserControl
|
||||
{
|
||||
public SearchHeaderView() => InitializeComponent();
|
||||
}
|
||||
@@ -8,7 +8,7 @@ public partial class ArchiveItemActionViewModel(IServiceProvider provider,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
[RelayCommand]
|
||||
public void Invoke() => Publisher.Publish(Archive.As<Item>());
|
||||
|
||||
@@ -8,7 +8,7 @@ public partial class ConfirmItemActionViewModel(IServiceProvider provider,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
|
||||
[RelayCommand]
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
using Bitvault.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class ConfirmItemHandler(IMediator mediator,
|
||||
IDbContextFactory<ContainerDbContext> dbContextFactory,
|
||||
IPublisher publisher) :
|
||||
INotificationHandler<ConfirmEventArgs<Item>>
|
||||
public class EditItemHander(IDbContextFactory<ContainerDbContext> dbContextFactory) :
|
||||
IHandler<EditEventArgs<(int, ItemConfiguration)>, bool>
|
||||
{
|
||||
public async Task<bool> Handle(ConfirmEventArgs<Item> args,
|
||||
public async Task<bool> Handle(EditEventArgs<(int, ItemConfiguration)> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
await mediator.Handle<ConfirmEventArgs<Item>, bool>(args);
|
||||
//if (args.Value is ItemConfiguration configuration)
|
||||
//{
|
||||
// try
|
||||
@@ -29,9 +27,6 @@ public class ConfirmItemHandler(IMediator mediator,
|
||||
|
||||
// if (result is not null)
|
||||
// {
|
||||
// Item item = new() { Id = result.Entity.Id, Name = configuration.Name };
|
||||
// publisher.Publish(Activated.As(item), cancellationToken);
|
||||
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
@@ -43,9 +38,54 @@ public class ConfirmItemHandler(IMediator mediator,
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Handle(ConfirmEventArgs<Item> args)
|
||||
public class CreateItemHander(IDbContextFactory<ContainerDbContext> dbContextFactory) :
|
||||
IHandler<CreateEventArgs<ItemConfiguration>, (bool, int)>
|
||||
{
|
||||
public async Task<(bool, int)> Handle(CreateEventArgs<ItemConfiguration> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
ItemHeaderConfiguration? headerConfiguration = await mediator.Handle<ConfirmEventArgs<Item>, ItemHeaderConfiguration>(args);
|
||||
if (args.Value is ItemConfiguration configuration)
|
||||
{
|
||||
try
|
||||
{
|
||||
using ContainerDbContext context = dbContextFactory.CreateDbContext();
|
||||
EntityEntry<ItemEntry>? result = null;
|
||||
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
result = await context.AddAsync(new ItemEntry { Name = configuration.Name }, cancellationToken);
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
}, cancellationToken);
|
||||
|
||||
if (result is not null)
|
||||
{
|
||||
return (false, -1);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return (false, -1);
|
||||
}
|
||||
}
|
||||
|
||||
public class ConfirmItemHandler(IMediator mediator,
|
||||
IValueStore<Item> valueStore,
|
||||
IPublisher publisher) :
|
||||
INotificationHandler<ConfirmEventArgs<Item>>
|
||||
{
|
||||
public async Task Handle(ConfirmEventArgs<Item> args)
|
||||
{
|
||||
(bool result, int index) result = await mediator.Handle<CreateEventArgs<ItemConfiguration>,
|
||||
(bool, int)>(new CreateEventArgs<ItemConfiguration>(new ItemConfiguration()));
|
||||
|
||||
ItemHeaderConfiguration? configuration = await mediator.Handle<ConfirmEventArgs<Item>,
|
||||
ItemHeaderConfiguration>(args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public record ContainerConfiguration : ComponentConfiguration
|
||||
public record ContainerConfiguration :
|
||||
ComponentConfiguration
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public partial class ContainerHeaderViewModel : ObservableCollectionViewModel<string, IDisposable>,
|
||||
INotificationHandler<RequestEventArgs<Filter<string>>>
|
||||
public partial class ContainerHeaderViewModel :
|
||||
ObservableCollection
|
||||
{
|
||||
public ContainerHeaderViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
@@ -15,18 +15,20 @@ public partial class ContainerHeaderViewModel : ObservableCollectionViewModel<st
|
||||
{
|
||||
Template = template;
|
||||
|
||||
Add<CreateItemActionViewModel>(scope: true);
|
||||
Add<SearchContainerActionViewModel>();
|
||||
|
||||
//Add<CreateItemActionViewModel>(scope: true);
|
||||
}
|
||||
|
||||
public IContentTemplate Template { get; set; }
|
||||
|
||||
public Task Handle(RequestEventArgs<Filter<string>> args)
|
||||
{
|
||||
if (args.Value is Filter<string> filter)
|
||||
{
|
||||
Value = filter.Value;
|
||||
}
|
||||
//public Task Handle(RequestEventArgs<Filter<string>> args)
|
||||
//{
|
||||
// if (args.Value is Filter<string> filter)
|
||||
// {
|
||||
// Value = filter.Value;
|
||||
// }
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
// return Task.CompletedTask;
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,13 @@ public class ContainerInitializer(IEnumerable<IConfigurationDescriptor<Container
|
||||
{
|
||||
foreach (IConfigurationDescriptor<ContainerConfiguration> configuration in configurations)
|
||||
{
|
||||
if (componentFactory.Create<IContainerComponent, ContainerConfiguration>(configuration.Section, configuration.Value) is IComponentHost host)
|
||||
if (componentFactory.Create<IContainerComponent,
|
||||
ContainerConfiguration>(configuration.Section, configuration.Value)
|
||||
is IComponentHost host)
|
||||
{
|
||||
vaults.Add(host);
|
||||
await host.StartAsync();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@ using Toolkit.Foundation;
|
||||
namespace Bitvault;
|
||||
|
||||
public partial class ContainerNavigationViewModel :
|
||||
ObservableCollectionViewModel<IContainerNavigationViewModel>,
|
||||
ObservableCollection<IContainerNavigationViewModel>,
|
||||
IMainNavigationViewModel,
|
||||
INotificationHandler<OpenedEventArgs<Container>>,
|
||||
INotificationHandler<ClosedEventArgs<Container>>,
|
||||
INotificationHandler<ActivatedEventArgs<Container>>,
|
||||
INotificationHandler<DeactivatedEventArgs<Container>>
|
||||
INotificationHandler<OpenedEventArgs<ContainerToken>>,
|
||||
INotificationHandler<ClosedEventArgs<ContainerToken>>,
|
||||
INotificationHandler<ActivatedEventArgs<ContainerToken>>,
|
||||
INotificationHandler<DeactivatedEventArgs<ContainerToken>>
|
||||
{
|
||||
[ObservableProperty]
|
||||
private bool activated;
|
||||
@@ -41,7 +41,7 @@ public partial class ContainerNavigationViewModel :
|
||||
|
||||
public IContentTemplate Template { get; set; }
|
||||
|
||||
public Task Handle(OpenedEventArgs<Container> args)
|
||||
public Task Handle(OpenedEventArgs<ContainerToken> args)
|
||||
{
|
||||
Add<AllNavigationViewModel>("All");
|
||||
Add<StarredNavigationViewModel>("Starred");
|
||||
@@ -52,7 +52,7 @@ public partial class ContainerNavigationViewModel :
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Handle(ClosedEventArgs<Container> args)
|
||||
public Task Handle(ClosedEventArgs<ContainerToken> args)
|
||||
{
|
||||
Opened = true;
|
||||
Clear();
|
||||
@@ -60,9 +60,9 @@ public partial class ContainerNavigationViewModel :
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Handle(DeactivatedEventArgs<Container> args) =>
|
||||
Task.FromResult(Activated = false);
|
||||
public Task Handle(DeactivatedEventArgs<ContainerToken> args) =>
|
||||
Task.FromResult(Activated = false);
|
||||
|
||||
public Task Handle(ActivatedEventArgs<Container> args) =>
|
||||
Task.FromResult(Activated = true);
|
||||
public Task Handle(ActivatedEventArgs<ContainerToken> args) =>
|
||||
Task.FromResult(Activated = true);
|
||||
}
|
||||
@@ -2,20 +2,20 @@
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public record Container
|
||||
public record ContainerToken
|
||||
{
|
||||
public Container(string name, string password)
|
||||
public ContainerToken(string name, string password)
|
||||
{
|
||||
Name = name;
|
||||
Password = password;
|
||||
}
|
||||
|
||||
public Container(string password)
|
||||
public ContainerToken(string password)
|
||||
{
|
||||
Password = password;
|
||||
}
|
||||
|
||||
public Container()
|
||||
public ContainerToken()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +1,17 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.ObjectModel;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class ItemCommandCollection : ObservableCollection
|
||||
{
|
||||
public void Add<TItem>(IDisposable diposer)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[Enumerate(nameof(ContainerViewModel))]
|
||||
public partial class ContainerViewModel(IServiceProvider provider,
|
||||
@@ -13,12 +22,10 @@ public partial class ContainerViewModel(IServiceProvider provider,
|
||||
IDisposer disposer,
|
||||
IContentTemplate template,
|
||||
NamedComponent named,
|
||||
string? filter = null) : ObservableCollectionViewModel<ItemNavigationViewModel>(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
INotificationHandler<RequestEventArgs<Filter<string>>>
|
||||
ContainerViewModelConfiguration configuration) : Toolkit.Foundation.ObservableCollection<ItemNavigationViewModel>(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
INotificationHandler<NotifyEventArgs<Filter>>,
|
||||
INotificationHandler<NotifyEventArgs<Search>>
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string? filter = filter;
|
||||
|
||||
[ObservableProperty]
|
||||
private string named = $"{named}";
|
||||
|
||||
@@ -26,21 +33,31 @@ public partial class ContainerViewModel(IServiceProvider provider,
|
||||
|
||||
public override async Task OnActivated()
|
||||
{
|
||||
Publisher.Publish(Activated.As<Container>());
|
||||
Publisher.Publish(Activated.As<ContainerToken>());
|
||||
await base.OnActivated();
|
||||
}
|
||||
|
||||
public override async Task OnDeactivated()
|
||||
{
|
||||
Publisher.Publish(Deactivated.As<Container>());
|
||||
Publisher.Publish(Deactivated.As<ContainerToken>());
|
||||
await base.OnDeactivated();
|
||||
}
|
||||
|
||||
public Task Handle(RequestEventArgs<Filter<string>> args)
|
||||
public Task Handle(NotifyEventArgs<Filter> args)
|
||||
{
|
||||
if (args.Value is Filter<string> filter)
|
||||
if (args.Value is Filter filter)
|
||||
{
|
||||
Filter = filter.Value;
|
||||
configuration = configuration with { Filter = filter.Value };
|
||||
Enumerate();
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
public Task Handle(NotifyEventArgs<Search> args)
|
||||
{
|
||||
if (args.Value is Search search)
|
||||
{
|
||||
configuration = configuration with { Query = search.Value };
|
||||
Enumerate();
|
||||
}
|
||||
|
||||
@@ -48,5 +65,5 @@ public partial class ContainerViewModel(IServiceProvider provider,
|
||||
}
|
||||
|
||||
protected override IEnumerate PrepareEnumeration(object? key) =>
|
||||
EnumerateEventArgs<ItemNavigationViewModel>.With(new ContainerViewModelConfiguration { Filter = Filter }) with { Key = key };
|
||||
EnumerateEventArgs<ItemNavigationViewModel>.With(configuration) with { Key = key };
|
||||
}
|
||||
@@ -2,5 +2,7 @@
|
||||
|
||||
public record ContainerViewModelConfiguration
|
||||
{
|
||||
public string? Filter { get; set; }
|
||||
public string? Filter { get; set; } = "All";
|
||||
|
||||
public string? Query { get; set; }
|
||||
}
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
using Bitvault.Data;
|
||||
using LinqKit;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class ContainerViewModelHandler(IDbContextFactory<ContainerDbContext> dbContextFactory,
|
||||
IServiceProvider serviceProvider,
|
||||
ICache<Item> cache,
|
||||
IPublisher publisher) :
|
||||
INotificationHandler<Enumerate<ItemNavigationViewModel, ContainerViewModelConfiguration>>
|
||||
{
|
||||
public async Task Handle(Enumerate<ItemNavigationViewModel, ContainerViewModelConfiguration> args)
|
||||
{
|
||||
if (args.Options is ContainerViewModelConfiguration configuration)
|
||||
{
|
||||
cache.Clear();
|
||||
|
||||
ExpressionStarter<ItemEntry> predicate = PredicateBuilder.New<ItemEntry>(true);
|
||||
|
||||
if (configuration.Filter == "All")
|
||||
{
|
||||
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 results = await Task.Run(async () =>
|
||||
{
|
||||
using ContainerDbContext context = dbContextFactory.CreateDbContext();
|
||||
return await context.Set<ItemEntry>().Where(predicate).Select(x => new
|
||||
{
|
||||
x.Id,
|
||||
x.Name
|
||||
}).OrderBy(x => x.Name).ToListAsync();
|
||||
});
|
||||
|
||||
bool selected = true;
|
||||
foreach (var result in results)
|
||||
{
|
||||
IServiceScope serviceScope = serviceProvider.CreateScope();
|
||||
IServiceFactory serviceFactory = serviceScope.ServiceProvider.GetRequiredService<IServiceFactory>();
|
||||
IValueStore<Item> valueStore = serviceScope.ServiceProvider.GetRequiredService<IValueStore<Item>>();
|
||||
|
||||
if (serviceFactory.Create<ItemNavigationViewModel>(result.Id, result.Name, "Description " + 1, selected) is ItemNavigationViewModel viewModel)
|
||||
{
|
||||
Item item = new() { Id = result.Id, Name = result.Name };
|
||||
valueStore.Set(item);
|
||||
|
||||
publisher.Publish(Create.As(viewModel), nameof(ContainerViewModel));
|
||||
}
|
||||
|
||||
selected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,12 @@ namespace Bitvault;
|
||||
|
||||
public class CreateContainerHandler(IContainerFactory componentFactory,
|
||||
IPublisher publisher) :
|
||||
IHandler<CreateEventArgs<Container>, bool>
|
||||
IHandler<CreateEventArgs<ContainerToken>, bool>
|
||||
{
|
||||
public async Task<bool> Handle(CreateEventArgs<Container> args,
|
||||
public async Task<bool> Handle(CreateEventArgs<ContainerToken> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is Container container && container.Name is { Length: > 0 } name &&
|
||||
if (args.Value is ContainerToken container && container.Name is { Length: > 0 } name &&
|
||||
container.Password is { Length: > 0 } password)
|
||||
{
|
||||
if (componentFactory.Create(name) is IComponentHost host)
|
||||
|
||||
@@ -8,5 +8,5 @@ public partial class CreateContainerNavigationViewModel(IServiceProvider provide
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) :
|
||||
ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
IMainNavigationViewModel;
|
||||
@@ -10,7 +10,7 @@ public partial class CreateContainerViewModel(IServiceProvider provider,
|
||||
IMediator mediator,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) :
|
||||
ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
IPrimaryConfirmation
|
||||
{
|
||||
[MaybeNull]
|
||||
@@ -22,5 +22,5 @@ public partial class CreateContainerViewModel(IServiceProvider provider,
|
||||
private string password;
|
||||
|
||||
public async Task<bool> Confirm() =>
|
||||
await Mediator.Handle<CreateEventArgs<Container>, bool>(Create.As(new Container(Name, Password)));
|
||||
await Mediator.Handle<CreateEventArgs<ContainerToken>, bool>(Create.As(new ContainerToken(Name, Password)));
|
||||
}
|
||||
@@ -9,7 +9,7 @@ public partial class CreateItemActionViewModel(IServiceProvider provider,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
NamedComponent named) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
NamedComponent named) : Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
|
||||
[ObservableProperty]
|
||||
|
||||
@@ -8,7 +8,7 @@ public partial class DeleteItemActionViewModel(IServiceProvider provider,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
[RelayCommand]
|
||||
public void Invoke() => Publisher.Publish(Delete.As<Item>());
|
||||
|
||||
@@ -7,4 +7,4 @@ public partial class DismissItemActionViewModel(IServiceProvider provider,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer);
|
||||
IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer);
|
||||
@@ -8,9 +8,8 @@ public partial class EditItemActionViewModel(IServiceProvider provider,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
[RelayCommand]
|
||||
public void Invoke() => Publisher.Publish(Edit.As<Item>());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class EnumerateContainerViewModelHandler(IMediator mediator,
|
||||
IServiceProvider serviceProvider,
|
||||
ICache<Item> cache,
|
||||
IPublisher publisher) :
|
||||
INotificationHandler<Enumerate<ItemNavigationViewModel, ContainerViewModelConfiguration>>
|
||||
{
|
||||
public async Task Handle(Enumerate<ItemNavigationViewModel, ContainerViewModelConfiguration> args)
|
||||
{
|
||||
if (args.Options is ContainerViewModelConfiguration configuration)
|
||||
{
|
||||
cache.Clear();
|
||||
bool selected = true;
|
||||
|
||||
if (await mediator.Handle<RequestEventArgs<QueryContainerConfiguration>,
|
||||
IReadOnlyCollection<(int Id, string? Name)>>(Request.As(new QueryContainerConfiguration
|
||||
{
|
||||
Filter = configuration.Filter,
|
||||
Query = configuration.Query
|
||||
})) is IReadOnlyCollection<(int Id, string? Name)> results)
|
||||
{
|
||||
foreach ((int Id, string? Name) in results)
|
||||
{
|
||||
IServiceScope serviceScope = serviceProvider.CreateScope();
|
||||
IServiceFactory serviceFactory = serviceScope.ServiceProvider.GetRequiredService<IServiceFactory>();
|
||||
IValueStore<Item> valueStore = serviceScope.ServiceProvider.GetRequiredService<IValueStore<Item>>();
|
||||
|
||||
if (serviceFactory.Create<ItemNavigationViewModel>(Id, Name, "Description " + 1, selected) is ItemNavigationViewModel viewModel)
|
||||
{
|
||||
Item item = new() { Id = Id, Name = Name };
|
||||
valueStore.Set(item);
|
||||
|
||||
publisher.Publish(Create.As(viewModel), nameof(ContainerViewModel));
|
||||
}
|
||||
|
||||
selected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
namespace Bitvault;
|
||||
|
||||
public record Filter<TValue>(TValue? Value);
|
||||
public record Filter(string? Value);
|
||||
|
||||
@@ -4,10 +4,10 @@ using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public partial class FilterContainerNavigationViewModel : ObservableViewModel,
|
||||
public partial class FilterContainerNavigationViewModel : Observable,
|
||||
IContainerNavigationViewModel,
|
||||
INotificationHandler<ActivatedEventArgs<Container>>,
|
||||
INotificationHandler<DeactivatedEventArgs<Container>>
|
||||
INotificationHandler<ActivatedEventArgs<ContainerToken>>,
|
||||
INotificationHandler<DeactivatedEventArgs<ContainerToken>>
|
||||
{
|
||||
[ObservableProperty]
|
||||
private bool activated;
|
||||
@@ -29,12 +29,13 @@ public partial class FilterContainerNavigationViewModel : ObservableViewModel,
|
||||
Filter = filter;
|
||||
}
|
||||
|
||||
public Task Handle(DeactivatedEventArgs<Container> args) =>
|
||||
Task.FromResult(Activated = false);
|
||||
public Task Handle(DeactivatedEventArgs<ContainerToken> args) =>
|
||||
Task.FromResult(Activated = false);
|
||||
|
||||
public Task Handle(ActivatedEventArgs<Container> args) =>
|
||||
Task.FromResult(Activated = true);
|
||||
public Task Handle(ActivatedEventArgs<ContainerToken> args) =>
|
||||
Task.FromResult(Activated = true);
|
||||
|
||||
[RelayCommand]
|
||||
public void Invoke() => Publisher.Publish(Request.As(new Filter<string>(Filter)), nameof(ContainerViewModel));
|
||||
public void Invoke() => Publisher.Publish(Notify.As(new Filter(Filter)),
|
||||
nameof(ContainerViewModel));
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Bitvault;
|
||||
|
||||
public partial class FooterViewModel :
|
||||
ObservableCollectionViewModel<IMainNavigationViewModel>
|
||||
ObservableCollection<IMainNavigationViewModel>
|
||||
{
|
||||
public FooterViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public interface IItemViewModel :
|
||||
IValueInvoker<ItemConfiguration>;
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public partial class IconViewModel : ObservableViewModel
|
||||
public partial class IconViewModel : Observable
|
||||
{
|
||||
public IconViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public partial class ItemCommandHeaderViewModel : ObservableCollectionViewModel
|
||||
public partial class ItemCommandHeaderViewModel : ObservableCollection
|
||||
{
|
||||
public ItemCommandHeaderViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
|
||||
@@ -10,7 +10,7 @@ public partial class ItemHeaderViewModel(IServiceProvider provider,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
bool immutable,
|
||||
string? value = null) : ObservableViewModel<string, string>(provider, factory, mediator, publisher, subscriber, disposer, value),
|
||||
string? value = null) : Observable<string, string>(provider, factory, mediator, publisher, subscriber, disposer, value),
|
||||
IHandler<ValidationEventArgs<Item>, bool>,
|
||||
IHandler<ConfirmEventArgs<Item>, ItemHeaderConfiguration>
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
|
||||
string name,
|
||||
string description,
|
||||
bool selected) :
|
||||
ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
INotificationHandler<ArchiveEventArgs<Item>>,
|
||||
ISelectable,
|
||||
IRemovable
|
||||
|
||||
@@ -4,7 +4,7 @@ using Toolkit.Foundation;
|
||||
namespace Bitvault;
|
||||
|
||||
public partial class ItemViewModel :
|
||||
ObservableCollectionViewModel<IDisposable>
|
||||
ObservableCollection<IDisposable>
|
||||
{
|
||||
[ObservableProperty]
|
||||
private int? id;
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Bitvault;
|
||||
|
||||
[Enumerate(nameof(MainViewModel))]
|
||||
public partial class MainViewModel :
|
||||
ObservableCollectionViewModel<IMainNavigationViewModel>
|
||||
ObservableCollection<IMainNavigationViewModel>
|
||||
{
|
||||
[ObservableProperty]
|
||||
private FooterViewModel footer;
|
||||
|
||||
@@ -8,4 +8,4 @@ public class MainWindowViewModel(IServiceProvider provider,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) :
|
||||
ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer);
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer);
|
||||
@@ -8,5 +8,5 @@ public partial class ManageNavigationViewModel(IServiceProvider provider,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) :
|
||||
ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
IMainNavigationViewModel;
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Bitvault;
|
||||
|
||||
public partial class ManageViewModel :
|
||||
ObservableCollectionViewModel,
|
||||
ObservableCollection,
|
||||
IMainNavigationViewModel
|
||||
{
|
||||
public ManageViewModel(IServiceProvider provider,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public partial class NoteViewModel : ObservableViewModel
|
||||
public partial class NoteViewModel : Observable
|
||||
{
|
||||
public NoteViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
|
||||
@@ -6,12 +6,12 @@ namespace Bitvault;
|
||||
public class OpenContainerHandler(ContainerConfiguration configuration,
|
||||
ISecurityKeyFactory keyVaultFactory,
|
||||
IContainerStorageFactory vaultStorage) :
|
||||
IHandler<ActivateEventArgs<Container>, bool>
|
||||
IHandler<ActivateEventArgs<ContainerToken>, bool>
|
||||
{
|
||||
public async Task<bool> Handle(ActivateEventArgs<Container> args,
|
||||
public async Task<bool> Handle(ActivateEventArgs<ContainerToken> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is Container container && configuration.Name is { Length: > 0 } name && container.Password is { Length: > 0 } password)
|
||||
if (args.Value is ContainerToken container && configuration.Name is { Length: > 0 } name && container.Password is { Length: > 0 } password)
|
||||
{
|
||||
if (configuration.Key?.Split(':') is { Length: >= 2 } keyPart)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ public partial class OpenContainerViewModel(IServiceProvider provider,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) :
|
||||
ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string? password;
|
||||
@@ -20,9 +20,9 @@ public partial class OpenContainerViewModel(IServiceProvider provider,
|
||||
{
|
||||
if (Password is { Length: > 0 })
|
||||
{
|
||||
if (await Mediator.Handle<ActivateEventArgs<Container>, bool>(Activate.As(new Container(Password))))
|
||||
if (await Mediator.Handle<ActivateEventArgs<ContainerToken>, bool>(Activate.As(new ContainerToken(Password))))
|
||||
{
|
||||
Publisher.Publish(Opened.As<Container>());
|
||||
Publisher.Publish(Opened.As<ContainerToken>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public partial class PasswordViewModel : ObservableViewModel
|
||||
public partial class PasswordViewModel : Observable
|
||||
{
|
||||
public PasswordViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Bitvault;
|
||||
|
||||
public record QueryContainerConfiguration
|
||||
{
|
||||
public string? Filter { get; set; }
|
||||
|
||||
public string? Query { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using Bitvault.Data;
|
||||
using LinqKit;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class QueryContainerHandler(IDbContextFactory<ContainerDbContext> dbContextFactory) :
|
||||
IHandler<RequestEventArgs<QueryContainerConfiguration>, IReadOnlyCollection<(int Id, string? Name)>>
|
||||
{
|
||||
public async Task<IReadOnlyCollection<(int Id, string? Name)>> Handle(RequestEventArgs<QueryContainerConfiguration> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
List<(int Id, string? Name)> items = [];
|
||||
|
||||
if (args.Value is QueryContainerConfiguration queryConfiguration)
|
||||
{
|
||||
ExpressionStarter<ItemEntry> predicate =
|
||||
PredicateBuilder.New<ItemEntry>(true);
|
||||
|
||||
if (queryConfiguration.Filter == "All")
|
||||
{
|
||||
predicate = predicate.And(x => x.State != 3);
|
||||
}
|
||||
|
||||
if (queryConfiguration.Filter == "Starred")
|
||||
{
|
||||
predicate = predicate.And(x => x.State != 3 && x.State == 2);
|
||||
}
|
||||
|
||||
if (queryConfiguration.Filter == "Archive")
|
||||
{
|
||||
predicate = predicate.And(x => x.State == 3);
|
||||
}
|
||||
|
||||
if (queryConfiguration.Query is { Length: > 0} query)
|
||||
{
|
||||
predicate = predicate.And(x => EF.Functions.Like(x.Name, $"%{query}%"));
|
||||
}
|
||||
|
||||
var results = await Task.Run(async () =>
|
||||
{
|
||||
using ContainerDbContext context = dbContextFactory.CreateDbContext();
|
||||
return await context.Set<ItemEntry>().Where(predicate).Select(x => new
|
||||
{
|
||||
x.Id,
|
||||
x.Name
|
||||
}).OrderBy(x => x.Name).ToListAsync();
|
||||
});
|
||||
|
||||
foreach (var result in results)
|
||||
{
|
||||
items.Add(new(result.Id, result.Name));
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Bitvault;
|
||||
|
||||
public record Search(string? Value);
|
||||
@@ -0,0 +1,17 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public partial class SearchContainerActionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : Observable<string>(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
[RelayCommand]
|
||||
public void Invoke() => Publisher.Publish(Notify.As(new Search(Value)),
|
||||
nameof(ContainerViewModel));
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public partial class SearchHeaderViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : ObservableViewModel<string>(provider, factory, mediator, publisher, subscriber, disposer);
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public partial class TextViewModel : ObservableViewModel
|
||||
public partial class TextViewModel : Observable
|
||||
{
|
||||
public TextViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
|
||||
Reference in New Issue
Block a user