diff --git a/Bitvault.Avalonia/App.axaml.cs b/Bitvault.Avalonia/App.axaml.cs index a0eefac..74bc733 100644 --- a/Bitvault.Avalonia/App.axaml.cs +++ b/Bitvault.Avalonia/App.axaml.cs @@ -66,7 +66,9 @@ public partial class App : Application { args.UseSqlite($"{connection.Value}"); } - }); + }); + + services.AddHandler(ServiceLifetime.Singleton); services.AddHandler(); @@ -78,10 +80,12 @@ public partial class App : Application services.AddTemplate("OpenContainer"); - services.AddTemplate("Container"); - services.AddHandler(); + services.AddScoped(); - services.AddTemplate("SearchHeader"); + services.AddTemplate("Container"); + services.AddHandler(); + + services.AddTemplate(); services.AddTemplate("ContainerHeader"); services.AddTemplate(); diff --git a/Bitvault.Avalonia/AppHandler.cs b/Bitvault.Avalonia/AppHandler.cs index 23cb017..6b64479 100644 --- a/Bitvault.Avalonia/AppHandler.cs +++ b/Bitvault.Avalonia/AppHandler.cs @@ -1,6 +1,5 @@ using Avalonia; using Avalonia.Controls.ApplicationLifetimes; -using System.Threading; using System.Threading.Tasks; using Toolkit.Foundation; diff --git a/Bitvault.Avalonia/Bitvault.Avalonia.csproj b/Bitvault.Avalonia/Bitvault.Avalonia.csproj index 1519675..b85da66 100644 --- a/Bitvault.Avalonia/Bitvault.Avalonia.csproj +++ b/Bitvault.Avalonia/Bitvault.Avalonia.csproj @@ -79,9 +79,6 @@ ContainerNavigationView.axaml - - SearchHeaderView.axaml - ContainerView.axaml diff --git a/Bitvault.Avalonia/ContainerHeaderView.axaml b/Bitvault.Avalonia/ContainerHeaderView.axaml index cd17475..3e7ad15 100644 --- a/Bitvault.Avalonia/ContainerHeaderView.axaml +++ b/Bitvault.Avalonia/ContainerHeaderView.axaml @@ -4,32 +4,5 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="using:Bitvault" x:DataType="vm:ContainerHeaderViewModel"> - - 40 - 36 - - - - 0 - - - - - - - - - - - + diff --git a/Bitvault.Avalonia/ContainerView.axaml b/Bitvault.Avalonia/ContainerView.axaml index 422eaa3..703f224 100644 --- a/Bitvault.Avalonia/ContainerView.axaml +++ b/Bitvault.Avalonia/ContainerView.axaml @@ -5,17 +5,20 @@ xmlns:vm="using:Bitvault" x:DataType="vm:ContainerViewModel"> - - - - - - - + Grid.ColumnSpan="3" + Height="44" + ColumnDefinitions="*, Auto"> + + + + + + + + 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); + } + } } \ No newline at end of file diff --git a/Bitvault.Avalonia/MainView.axaml b/Bitvault.Avalonia/MainView.axaml index c1a5984..dfb579f 100644 --- a/Bitvault.Avalonia/MainView.axaml +++ b/Bitvault.Avalonia/MainView.axaml @@ -14,11 +14,11 @@ - + - + diff --git a/Bitvault.Avalonia/SearchContainerActionView.axaml b/Bitvault.Avalonia/SearchContainerActionView.axaml new file mode 100644 index 0000000..1768711 --- /dev/null +++ b/Bitvault.Avalonia/SearchContainerActionView.axaml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Bitvault.Avalonia/SearchContainerActionView.axaml.cs b/Bitvault.Avalonia/SearchContainerActionView.axaml.cs new file mode 100644 index 0000000..38fb854 --- /dev/null +++ b/Bitvault.Avalonia/SearchContainerActionView.axaml.cs @@ -0,0 +1,8 @@ +using Avalonia.Controls; + +namespace Bitvault.Avalonia; + +public partial class SearchContainerActionView : UserControl +{ + public SearchContainerActionView() => InitializeComponent(); +} diff --git a/Bitvault.Avalonia/SearchHeaderView.axaml b/Bitvault.Avalonia/SearchHeaderView.axaml deleted file mode 100644 index 582acf0..0000000 --- a/Bitvault.Avalonia/SearchHeaderView.axaml +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/Bitvault.Avalonia/SearchHeaderView.axaml.cs b/Bitvault.Avalonia/SearchHeaderView.axaml.cs deleted file mode 100644 index 5ae00f9..0000000 --- a/Bitvault.Avalonia/SearchHeaderView.axaml.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Avalonia.Controls; - -namespace Bitvault.Avalonia; - -public partial class SearchHeaderView : UserControl -{ - public SearchHeaderView() => InitializeComponent(); -} diff --git a/Bitvault/ArchiveItemActionViewModel.cs b/Bitvault/ArchiveItemActionViewModel.cs index 1442e59..e74a387 100644 --- a/Bitvault/ArchiveItemActionViewModel.cs +++ b/Bitvault/ArchiveItemActionViewModel.cs @@ -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()); diff --git a/Bitvault/ConfirmItemActionViewModel.cs b/Bitvault/ConfirmItemActionViewModel.cs index 6066cc6..73e4e9a 100644 --- a/Bitvault/ConfirmItemActionViewModel.cs +++ b/Bitvault/ConfirmItemActionViewModel.cs @@ -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] diff --git a/Bitvault/ConfirmItemHandler.cs b/Bitvault/ConfirmItemHandler.cs index d37a137..cc92bed 100644 --- a/Bitvault/ConfirmItemHandler.cs +++ b/Bitvault/ConfirmItemHandler.cs @@ -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 dbContextFactory, - IPublisher publisher) : - INotificationHandler> +public class EditItemHander(IDbContextFactory dbContextFactory) : + IHandler, bool> { - public async Task Handle(ConfirmEventArgs args, + public async Task Handle(EditEventArgs<(int, ItemConfiguration)> args, CancellationToken cancellationToken) { - await mediator.Handle, 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 args) +public class CreateItemHander(IDbContextFactory dbContextFactory) : + IHandler, (bool, int)> +{ + public async Task<(bool, int)> Handle(CreateEventArgs args, + CancellationToken cancellationToken) { - ItemHeaderConfiguration? headerConfiguration = await mediator.Handle, ItemHeaderConfiguration>(args); + if (args.Value is ItemConfiguration configuration) + { + try + { + using ContainerDbContext context = dbContextFactory.CreateDbContext(); + EntityEntry? 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 valueStore, + IPublisher publisher) : + INotificationHandler> +{ + public async Task Handle(ConfirmEventArgs args) + { + (bool result, int index) result = await mediator.Handle, + (bool, int)>(new CreateEventArgs(new ItemConfiguration())); + + ItemHeaderConfiguration? configuration = await mediator.Handle, + ItemHeaderConfiguration>(args); } } diff --git a/Bitvault/ContainerActivatedHandler.cs b/Bitvault/ContainerActivatedHandler.cs index 5f243d8..dd86e07 100644 --- a/Bitvault/ContainerActivatedHandler.cs +++ b/Bitvault/ContainerActivatedHandler.cs @@ -1,5 +1,4 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Toolkit.Foundation; namespace Bitvault; diff --git a/Bitvault/ContainerConfiguration.cs b/Bitvault/ContainerConfiguration.cs index d45c5ac..64b919b 100644 --- a/Bitvault/ContainerConfiguration.cs +++ b/Bitvault/ContainerConfiguration.cs @@ -2,7 +2,8 @@ namespace Bitvault; -public record ContainerConfiguration : ComponentConfiguration +public record ContainerConfiguration : + ComponentConfiguration { public string? Name { get; set; } diff --git a/Bitvault/ContainerHeaderViewModel.cs b/Bitvault/ContainerHeaderViewModel.cs index e301ee7..de79283 100644 --- a/Bitvault/ContainerHeaderViewModel.cs +++ b/Bitvault/ContainerHeaderViewModel.cs @@ -2,8 +2,8 @@ namespace Bitvault; -public partial class ContainerHeaderViewModel : ObservableCollectionViewModel, - INotificationHandler>> +public partial class ContainerHeaderViewModel : + ObservableCollection { public ContainerHeaderViewModel(IServiceProvider provider, IServiceFactory factory, @@ -15,18 +15,20 @@ public partial class ContainerHeaderViewModel : ObservableCollectionViewModel(scope: true); + Add(); + + //Add(scope: true); } public IContentTemplate Template { get; set; } - public Task Handle(RequestEventArgs> args) - { - if (args.Value is Filter filter) - { - Value = filter.Value; - } + //public Task Handle(RequestEventArgs> args) + //{ + // if (args.Value is Filter filter) + // { + // Value = filter.Value; + // } - return Task.CompletedTask; - } + // return Task.CompletedTask; + //} } diff --git a/Bitvault/ContainerInitializer.cs b/Bitvault/ContainerInitializer.cs index 74a5afe..46080f7 100644 --- a/Bitvault/ContainerInitializer.cs +++ b/Bitvault/ContainerInitializer.cs @@ -10,12 +10,13 @@ public class ContainerInitializer(IEnumerable configuration in configurations) { - if (componentFactory.Create(configuration.Section, configuration.Value) is IComponentHost host) + if (componentFactory.Create(configuration.Section, configuration.Value) + is IComponentHost host) { vaults.Add(host); await host.StartAsync(); } - } } } diff --git a/Bitvault/ContainerNavigationViewModel.cs b/Bitvault/ContainerNavigationViewModel.cs index eef0e80..da2eb75 100644 --- a/Bitvault/ContainerNavigationViewModel.cs +++ b/Bitvault/ContainerNavigationViewModel.cs @@ -4,12 +4,12 @@ using Toolkit.Foundation; namespace Bitvault; public partial class ContainerNavigationViewModel : - ObservableCollectionViewModel, + ObservableCollection, IMainNavigationViewModel, - INotificationHandler>, - INotificationHandler>, - INotificationHandler>, - INotificationHandler> + INotificationHandler>, + INotificationHandler>, + INotificationHandler>, + INotificationHandler> { [ObservableProperty] private bool activated; @@ -41,7 +41,7 @@ public partial class ContainerNavigationViewModel : public IContentTemplate Template { get; set; } - public Task Handle(OpenedEventArgs args) + public Task Handle(OpenedEventArgs args) { Add("All"); Add("Starred"); @@ -52,7 +52,7 @@ public partial class ContainerNavigationViewModel : return Task.CompletedTask; } - public Task Handle(ClosedEventArgs args) + public Task Handle(ClosedEventArgs args) { Opened = true; Clear(); @@ -60,9 +60,9 @@ public partial class ContainerNavigationViewModel : return Task.CompletedTask; } - public Task Handle(DeactivatedEventArgs args) => - Task.FromResult(Activated = false); + public Task Handle(DeactivatedEventArgs args) => + Task.FromResult(Activated = false); - public Task Handle(ActivatedEventArgs args) => - Task.FromResult(Activated = true); + public Task Handle(ActivatedEventArgs args) => + Task.FromResult(Activated = true); } \ No newline at end of file diff --git a/Bitvault/Container.cs b/Bitvault/ContainerToken.cs similarity index 65% rename from Bitvault/Container.cs rename to Bitvault/ContainerToken.cs index d906bb4..ed576a4 100644 --- a/Bitvault/Container.cs +++ b/Bitvault/ContainerToken.cs @@ -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() { } diff --git a/Bitvault/ContainerViewModel.cs b/Bitvault/ContainerViewModel.cs index a6ee071..933c498 100644 --- a/Bitvault/ContainerViewModel.cs +++ b/Bitvault/ContainerViewModel.cs @@ -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(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(provider, factory, mediator, publisher, subscriber, disposer), - INotificationHandler>> + ContainerViewModelConfiguration configuration) : Toolkit.Foundation.ObservableCollection(provider, factory, mediator, publisher, subscriber, disposer), + INotificationHandler>, + INotificationHandler> { - [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()); + Publisher.Publish(Activated.As()); await base.OnActivated(); } public override async Task OnDeactivated() { - Publisher.Publish(Deactivated.As()); + Publisher.Publish(Deactivated.As()); await base.OnDeactivated(); } - public Task Handle(RequestEventArgs> args) + public Task Handle(NotifyEventArgs args) { - if (args.Value is Filter filter) + if (args.Value is Filter filter) { - Filter = filter.Value; + configuration = configuration with { Filter = filter.Value }; + Enumerate(); + } + + return Task.CompletedTask; + } + public Task Handle(NotifyEventArgs 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.With(new ContainerViewModelConfiguration { Filter = Filter }) with { Key = key }; + EnumerateEventArgs.With(configuration) with { Key = key }; } \ No newline at end of file diff --git a/Bitvault/ContainerViewModelConfiguration.cs b/Bitvault/ContainerViewModelConfiguration.cs index bb9bfa6..198daf8 100644 --- a/Bitvault/ContainerViewModelConfiguration.cs +++ b/Bitvault/ContainerViewModelConfiguration.cs @@ -2,5 +2,7 @@ public record ContainerViewModelConfiguration { - public string? Filter { get; set; } + public string? Filter { get; set; } = "All"; + + public string? Query { get; set; } } diff --git a/Bitvault/ContainerViewModelHandler.cs b/Bitvault/ContainerViewModelHandler.cs deleted file mode 100644 index 55991d1..0000000 --- a/Bitvault/ContainerViewModelHandler.cs +++ /dev/null @@ -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 dbContextFactory, - IServiceProvider serviceProvider, - ICache cache, - IPublisher publisher) : - INotificationHandler> -{ - public async Task Handle(Enumerate args) - { - if (args.Options is ContainerViewModelConfiguration configuration) - { - cache.Clear(); - - ExpressionStarter predicate = PredicateBuilder.New(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().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(); - IValueStore valueStore = serviceScope.ServiceProvider.GetRequiredService>(); - - if (serviceFactory.Create(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; - } - } - } -} \ No newline at end of file diff --git a/Bitvault/CreateContainerHandler.cs b/Bitvault/CreateContainerHandler.cs index 9427750..980a765 100644 --- a/Bitvault/CreateContainerHandler.cs +++ b/Bitvault/CreateContainerHandler.cs @@ -7,12 +7,12 @@ namespace Bitvault; public class CreateContainerHandler(IContainerFactory componentFactory, IPublisher publisher) : - IHandler, bool> + IHandler, bool> { - public async Task Handle(CreateEventArgs args, + public async Task Handle(CreateEventArgs 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) diff --git a/Bitvault/CreateContainerNavigationViewModel.cs b/Bitvault/CreateContainerNavigationViewModel.cs index 345328f..e9c5dd4 100644 --- a/Bitvault/CreateContainerNavigationViewModel.cs +++ b/Bitvault/CreateContainerNavigationViewModel.cs @@ -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; \ No newline at end of file diff --git a/Bitvault/CreateContainerViewModel.cs b/Bitvault/CreateContainerViewModel.cs index 62c264d..b59f2cc 100644 --- a/Bitvault/CreateContainerViewModel.cs +++ b/Bitvault/CreateContainerViewModel.cs @@ -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 Confirm() => - await Mediator.Handle, bool>(Create.As(new Container(Name, Password))); + await Mediator.Handle, bool>(Create.As(new ContainerToken(Name, Password))); } \ No newline at end of file diff --git a/Bitvault/CreateItemActionViewModel.cs b/Bitvault/CreateItemActionViewModel.cs index f794e9d..c566ee6 100644 --- a/Bitvault/CreateItemActionViewModel.cs +++ b/Bitvault/CreateItemActionViewModel.cs @@ -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] diff --git a/Bitvault/DeleteItemActionViewModel.cs b/Bitvault/DeleteItemActionViewModel.cs index 3a03411..0154903 100644 --- a/Bitvault/DeleteItemActionViewModel.cs +++ b/Bitvault/DeleteItemActionViewModel.cs @@ -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()); diff --git a/Bitvault/DismissItemActionViewModel.cs b/Bitvault/DismissItemActionViewModel.cs index 044f3b8..79b4a07 100644 --- a/Bitvault/DismissItemActionViewModel.cs +++ b/Bitvault/DismissItemActionViewModel.cs @@ -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); \ No newline at end of file + IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer); \ No newline at end of file diff --git a/Bitvault/EditItemActionViewModel.cs b/Bitvault/EditItemActionViewModel.cs index 153bc36..cd45e1c 100644 --- a/Bitvault/EditItemActionViewModel.cs +++ b/Bitvault/EditItemActionViewModel.cs @@ -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()); -} - +} \ No newline at end of file diff --git a/Bitvault/EnumerateContainerViewModelHandler.cs b/Bitvault/EnumerateContainerViewModelHandler.cs new file mode 100644 index 0000000..ce33150 --- /dev/null +++ b/Bitvault/EnumerateContainerViewModelHandler.cs @@ -0,0 +1,45 @@ +using Microsoft.Extensions.DependencyInjection; +using Toolkit.Foundation; + +namespace Bitvault; + +public class EnumerateContainerViewModelHandler(IMediator mediator, + IServiceProvider serviceProvider, + ICache cache, + IPublisher publisher) : + INotificationHandler> +{ + public async Task Handle(Enumerate args) + { + if (args.Options is ContainerViewModelConfiguration configuration) + { + cache.Clear(); + bool selected = true; + + if (await mediator.Handle, + 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(); + IValueStore valueStore = serviceScope.ServiceProvider.GetRequiredService>(); + + if (serviceFactory.Create(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; + } + } + } + } +} diff --git a/Bitvault/Filter.cs b/Bitvault/Filter.cs index 23680f4..c8f5ede 100644 --- a/Bitvault/Filter.cs +++ b/Bitvault/Filter.cs @@ -1,3 +1,3 @@ namespace Bitvault; -public record Filter(TValue? Value); \ No newline at end of file +public record Filter(string? Value); diff --git a/Bitvault/FilterContainerNavigationViewModel.cs b/Bitvault/FilterContainerNavigationViewModel.cs index f857b9f..8e59220 100644 --- a/Bitvault/FilterContainerNavigationViewModel.cs +++ b/Bitvault/FilterContainerNavigationViewModel.cs @@ -4,10 +4,10 @@ using Toolkit.Foundation; namespace Bitvault; -public partial class FilterContainerNavigationViewModel : ObservableViewModel, +public partial class FilterContainerNavigationViewModel : Observable, IContainerNavigationViewModel, - INotificationHandler>, - INotificationHandler> + INotificationHandler>, + INotificationHandler> { [ObservableProperty] private bool activated; @@ -29,12 +29,13 @@ public partial class FilterContainerNavigationViewModel : ObservableViewModel, Filter = filter; } - public Task Handle(DeactivatedEventArgs args) => - Task.FromResult(Activated = false); + public Task Handle(DeactivatedEventArgs args) => + Task.FromResult(Activated = false); - public Task Handle(ActivatedEventArgs args) => - Task.FromResult(Activated = true); + public Task Handle(ActivatedEventArgs args) => + Task.FromResult(Activated = true); [RelayCommand] - public void Invoke() => Publisher.Publish(Request.As(new Filter(Filter)), nameof(ContainerViewModel)); + public void Invoke() => Publisher.Publish(Notify.As(new Filter(Filter)), + nameof(ContainerViewModel)); } \ No newline at end of file diff --git a/Bitvault/FooterViewModel.cs b/Bitvault/FooterViewModel.cs index a3c30ae..2a0e854 100644 --- a/Bitvault/FooterViewModel.cs +++ b/Bitvault/FooterViewModel.cs @@ -3,7 +3,7 @@ namespace Bitvault; public partial class FooterViewModel : - ObservableCollectionViewModel + ObservableCollection { public FooterViewModel(IServiceProvider provider, IServiceFactory factory, diff --git a/Bitvault/IItemViewModel.cs b/Bitvault/IItemViewModel.cs deleted file mode 100644 index 36f32ad..0000000 --- a/Bitvault/IItemViewModel.cs +++ /dev/null @@ -1,6 +0,0 @@ -using Toolkit.Foundation; - -namespace Bitvault; - -public interface IItemViewModel : - IValueInvoker; diff --git a/Bitvault/IconViewModel.cs b/Bitvault/IconViewModel.cs index c4b6a9c..2280bf3 100644 --- a/Bitvault/IconViewModel.cs +++ b/Bitvault/IconViewModel.cs @@ -2,7 +2,7 @@ namespace Bitvault; -public partial class IconViewModel : ObservableViewModel +public partial class IconViewModel : Observable { public IconViewModel(IServiceProvider provider, IServiceFactory factory, diff --git a/Bitvault/ItemCommandHeaderViewModel.cs b/Bitvault/ItemCommandHeaderViewModel.cs index 6668cb7..1705326 100644 --- a/Bitvault/ItemCommandHeaderViewModel.cs +++ b/Bitvault/ItemCommandHeaderViewModel.cs @@ -2,7 +2,7 @@ namespace Bitvault; -public partial class ItemCommandHeaderViewModel : ObservableCollectionViewModel +public partial class ItemCommandHeaderViewModel : ObservableCollection { public ItemCommandHeaderViewModel(IServiceProvider provider, IServiceFactory factory, diff --git a/Bitvault/ItemHeaderViewModel.cs b/Bitvault/ItemHeaderViewModel.cs index ade40ad..8c659de 100644 --- a/Bitvault/ItemHeaderViewModel.cs +++ b/Bitvault/ItemHeaderViewModel.cs @@ -10,7 +10,7 @@ public partial class ItemHeaderViewModel(IServiceProvider provider, ISubscription subscriber, IDisposer disposer, bool immutable, - string? value = null) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer, value), + string? value = null) : Observable(provider, factory, mediator, publisher, subscriber, disposer, value), IHandler, bool>, IHandler, ItemHeaderConfiguration> { diff --git a/Bitvault/ItemNavigationViewModel.cs b/Bitvault/ItemNavigationViewModel.cs index 075c6ac..fdb1f68 100644 --- a/Bitvault/ItemNavigationViewModel.cs +++ b/Bitvault/ItemNavigationViewModel.cs @@ -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>, ISelectable, IRemovable diff --git a/Bitvault/ItemViewModel.cs b/Bitvault/ItemViewModel.cs index ecbdee4..de963f1 100644 --- a/Bitvault/ItemViewModel.cs +++ b/Bitvault/ItemViewModel.cs @@ -4,7 +4,7 @@ using Toolkit.Foundation; namespace Bitvault; public partial class ItemViewModel : - ObservableCollectionViewModel + ObservableCollection { [ObservableProperty] private int? id; diff --git a/Bitvault/MainViewModel.cs b/Bitvault/MainViewModel.cs index d73c7d5..c229cbd 100644 --- a/Bitvault/MainViewModel.cs +++ b/Bitvault/MainViewModel.cs @@ -5,7 +5,7 @@ namespace Bitvault; [Enumerate(nameof(MainViewModel))] public partial class MainViewModel : - ObservableCollectionViewModel + ObservableCollection { [ObservableProperty] private FooterViewModel footer; diff --git a/Bitvault/MainWindowViewModel.cs b/Bitvault/MainWindowViewModel.cs index 6b31819..505bb41 100644 --- a/Bitvault/MainWindowViewModel.cs +++ b/Bitvault/MainWindowViewModel.cs @@ -8,4 +8,4 @@ public class MainWindowViewModel(IServiceProvider provider, IPublisher publisher, ISubscription subscriber, IDisposer disposer) : - ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer); \ No newline at end of file + Observable(provider, factory, mediator, publisher, subscriber, disposer); \ No newline at end of file diff --git a/Bitvault/ManageNavigationViewModel.cs b/Bitvault/ManageNavigationViewModel.cs index 37e1512..3d5cec6 100644 --- a/Bitvault/ManageNavigationViewModel.cs +++ b/Bitvault/ManageNavigationViewModel.cs @@ -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; \ No newline at end of file diff --git a/Bitvault/ManageViewModel.cs b/Bitvault/ManageViewModel.cs index 98bd643..6d917e9 100644 --- a/Bitvault/ManageViewModel.cs +++ b/Bitvault/ManageViewModel.cs @@ -3,7 +3,7 @@ namespace Bitvault; public partial class ManageViewModel : - ObservableCollectionViewModel, + ObservableCollection, IMainNavigationViewModel { public ManageViewModel(IServiceProvider provider, diff --git a/Bitvault/NoteViewModel.cs b/Bitvault/NoteViewModel.cs index f32621d..26e6a32 100644 --- a/Bitvault/NoteViewModel.cs +++ b/Bitvault/NoteViewModel.cs @@ -2,7 +2,7 @@ namespace Bitvault; -public partial class NoteViewModel : ObservableViewModel +public partial class NoteViewModel : Observable { public NoteViewModel(IServiceProvider provider, IServiceFactory factory, diff --git a/Bitvault/OpenContainerHandler.cs b/Bitvault/OpenContainerHandler.cs index 41eec01..9a97714 100644 --- a/Bitvault/OpenContainerHandler.cs +++ b/Bitvault/OpenContainerHandler.cs @@ -6,12 +6,12 @@ namespace Bitvault; public class OpenContainerHandler(ContainerConfiguration configuration, ISecurityKeyFactory keyVaultFactory, IContainerStorageFactory vaultStorage) : - IHandler, bool> + IHandler, bool> { - public async Task Handle(ActivateEventArgs args, + public async Task Handle(ActivateEventArgs 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) { diff --git a/Bitvault/OpenContainerViewModel.cs b/Bitvault/OpenContainerViewModel.cs index b8ced71..b7e6709 100644 --- a/Bitvault/OpenContainerViewModel.cs +++ b/Bitvault/OpenContainerViewModel.cs @@ -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, bool>(Activate.As(new Container(Password)))) + if (await Mediator.Handle, bool>(Activate.As(new ContainerToken(Password)))) { - Publisher.Publish(Opened.As()); + Publisher.Publish(Opened.As()); } } } diff --git a/Bitvault/PasswordViewModel.cs b/Bitvault/PasswordViewModel.cs index 4b1ee22..d9c48d7 100644 --- a/Bitvault/PasswordViewModel.cs +++ b/Bitvault/PasswordViewModel.cs @@ -2,7 +2,7 @@ namespace Bitvault; -public partial class PasswordViewModel : ObservableViewModel +public partial class PasswordViewModel : Observable { public PasswordViewModel(IServiceProvider provider, IServiceFactory factory, diff --git a/Bitvault/QueryContainerConfiguration.cs b/Bitvault/QueryContainerConfiguration.cs new file mode 100644 index 0000000..0ab7ec3 --- /dev/null +++ b/Bitvault/QueryContainerConfiguration.cs @@ -0,0 +1,8 @@ +namespace Bitvault; + +public record QueryContainerConfiguration +{ + public string? Filter { get; set; } + + public string? Query { get; set; } +} diff --git a/Bitvault/QueryContainerHandler.cs b/Bitvault/QueryContainerHandler.cs new file mode 100644 index 0000000..ff21068 --- /dev/null +++ b/Bitvault/QueryContainerHandler.cs @@ -0,0 +1,59 @@ +using Bitvault.Data; +using LinqKit; +using Microsoft.EntityFrameworkCore; +using Toolkit.Foundation; + +namespace Bitvault; + +public class QueryContainerHandler(IDbContextFactory dbContextFactory) : + IHandler, IReadOnlyCollection<(int Id, string? Name)>> +{ + public async Task> Handle(RequestEventArgs args, + CancellationToken cancellationToken) + { + List<(int Id, string? Name)> items = []; + + if (args.Value is QueryContainerConfiguration queryConfiguration) + { + ExpressionStarter predicate = + PredicateBuilder.New(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().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; + } +} diff --git a/Bitvault/Search.cs b/Bitvault/Search.cs new file mode 100644 index 0000000..41f4d94 --- /dev/null +++ b/Bitvault/Search.cs @@ -0,0 +1,3 @@ +namespace Bitvault; + +public record Search(string? Value); \ No newline at end of file diff --git a/Bitvault/SearchContainerActionViewModel.cs b/Bitvault/SearchContainerActionViewModel.cs new file mode 100644 index 0000000..e8e7b4b --- /dev/null +++ b/Bitvault/SearchContainerActionViewModel.cs @@ -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(provider, factory, mediator, publisher, subscriber, disposer) +{ + [RelayCommand] + public void Invoke() => Publisher.Publish(Notify.As(new Search(Value)), + nameof(ContainerViewModel)); +} + diff --git a/Bitvault/SearchHeaderViewModel.cs b/Bitvault/SearchHeaderViewModel.cs deleted file mode 100644 index 557328a..0000000 --- a/Bitvault/SearchHeaderViewModel.cs +++ /dev/null @@ -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(provider, factory, mediator, publisher, subscriber, disposer); diff --git a/Bitvault/TextViewModel.cs b/Bitvault/TextViewModel.cs index 213f7aa..3dffae8 100644 --- a/Bitvault/TextViewModel.cs +++ b/Bitvault/TextViewModel.cs @@ -2,7 +2,7 @@ namespace Bitvault; -public partial class TextViewModel : ObservableViewModel +public partial class TextViewModel : Observable { public TextViewModel(IServiceProvider provider, IServiceFactory factory,