diff --git a/Bitvault.Avalonia/App.axaml.cs b/Bitvault.Avalonia/App.axaml.cs index 7b0ded4..25c66b6 100644 --- a/Bitvault.Avalonia/App.axaml.cs +++ b/Bitvault.Avalonia/App.axaml.cs @@ -42,8 +42,7 @@ public partial class App : Application { args.AddServices(services => { - services.AddTransient>(provider => Comparer.Create((x, z) => - x.Name!.CompareTo(z.Name) == 0 ? 1 : x.Name!.CompareTo(z.Name))); + services.AddTransient>(provider => Comparer.Create((x, z) => x.Name.CompareTo(z.Name))); services.AddCache(); @@ -69,7 +68,8 @@ public partial class App : Application }); services.AddHandler(); - services.AddHandler(); + services.AddHandler(); + services.AddHandler(); services.AddHandler(); @@ -108,13 +108,14 @@ public partial class App : Application services.AddScoped, ValueStore>(); - services.AddHandler(ServiceLifetime.Scoped); - services.AddHandler(ServiceLifetime.Scoped); - services.AddHandler(ServiceLifetime.Scoped); - services.AddHandler(ServiceLifetime.Scoped); - services.AddHandler(ServiceLifetime.Scoped); + services.AddHandler(); + services.AddHandler(); + services.AddHandler(); + services.AddHandler(); + services.AddHandler(); - services.AddHandler(ServiceLifetime.Singleton); + services.AddHandler(ServiceLifetime.Singleton); + services.AddHandler(ServiceLifetime.Singleton); }); })!); diff --git a/Bitvault.Avalonia/CreateItemActionView.axaml b/Bitvault.Avalonia/CreateItemActionView.axaml index 104dbac..f55fd1a 100644 --- a/Bitvault.Avalonia/CreateItemActionView.axaml +++ b/Bitvault.Avalonia/CreateItemActionView.axaml @@ -28,14 +28,10 @@ - + Scope="new"> diff --git a/Bitvault.Avalonia/ItemHeaderView.axaml b/Bitvault.Avalonia/ItemHeaderView.axaml index b7d105b..f3e60ab 100644 --- a/Bitvault.Avalonia/ItemHeaderView.axaml +++ b/Bitvault.Avalonia/ItemHeaderView.axaml @@ -12,7 +12,7 @@ - + diff --git a/Bitvault.Avalonia/ItemView.axaml b/Bitvault.Avalonia/ItemView.axaml index a58c63b..02d0732 100644 --- a/Bitvault.Avalonia/ItemView.axaml +++ b/Bitvault.Avalonia/ItemView.axaml @@ -4,6 +4,14 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="using:Bitvault" x:DataType="vm:ItemViewModel"> + + + + + diff --git a/Bitvault.Data/ItemEntry.cs b/Bitvault.Data/ItemEntry.cs index 0c8ae06..22b3af8 100644 --- a/Bitvault.Data/ItemEntry.cs +++ b/Bitvault.Data/ItemEntry.cs @@ -9,7 +9,7 @@ public record ItemEntry [Key] public int Id { get; set; } - public string? Name { get; set; } + public required string Name { get; set; } public string? Description { get; set; } diff --git a/Bitvault/AggerateContainerViewModelHandler.cs b/Bitvault/AggerateContainerViewModelHandler.cs index 993c226..457f6b2 100644 --- a/Bitvault/AggerateContainerViewModelHandler.cs +++ b/Bitvault/AggerateContainerViewModelHandler.cs @@ -18,13 +18,13 @@ public class AggerateContainerViewModelHandler(IMediator mediator, bool selected = true; if (await mediator.Handle, - IReadOnlyCollection<(int Id, string? Name, bool Favourite, bool Archived)>>(Request.As(new QueryContainerConfiguration + IReadOnlyCollection<(int Id, string Name, bool Favourite, bool Archived)>>(Request.As(new QueryContainerConfiguration { Filter = configuration.Filter, Query = configuration.Query - })) is IReadOnlyCollection<(int Id, string? Name, bool Favourite, bool Archived)> results) + })) is IReadOnlyCollection<(int Id, string Name, bool Favourite, bool Archived)> results) { - foreach ((int Id, string? Name, bool Favourite, bool Archived) in results) + foreach ((int Id, string Name, bool Favourite, bool Archived) in results) { IServiceScope serviceScope = serviceProvider.CreateScope(); IServiceFactory serviceFactory = serviceScope.ServiceProvider.GetRequiredService(); @@ -35,6 +35,7 @@ public class AggerateContainerViewModelHandler(IMediator mediator, Item item = new() { Id = Id, Name = Name }; valueStore.Set(item); + cache.Add(item); publisher.Publish(Create.As(viewModel), nameof(ContainerViewModel)); } diff --git a/Bitvault/ConfirmItemHandler.cs b/Bitvault/ConfirmItemHandler.cs index 81fb2c9..eb68e8d 100644 --- a/Bitvault/ConfirmItemHandler.cs +++ b/Bitvault/ConfirmItemHandler.cs @@ -2,7 +2,8 @@ namespace Bitvault; -public class ConfirmItemHandler(IMediator mediator, +public class ConfirmItemHandler(IValueStore valueStore, + IMediator mediator, IPublisher publisher) : INotificationHandler> { @@ -11,12 +12,28 @@ public class ConfirmItemHandler(IMediator mediator, ItemHeaderConfiguration? configuration = await mediator.Handle, ItemHeaderConfiguration>(args); - (bool Success, int Id, string Name) result = await mediator.Handle, - (bool, int, string)>(new CreateEventArgs(new ItemConfiguration { Name = configuration?.Name })); - - if (result.Success) + if (valueStore?.Value is Item item) { - publisher.Publish(Activated.As(new Item { Id = result.Id, Name = result.Name })); + (bool Success, int Id, string Name) = await mediator.Handle, + (bool, int, string)>(new EditEventArgs<(int, ItemConfiguration)>((item.Id, new ItemConfiguration { Name = configuration?.Name }))); + + if (Success) + { + Item newItem = new Item { Id = Id, Name = Name }; + publisher.Publish(Modified.As(item, newItem)); + + valueStore.Set(newItem); + } + } + else + { + (bool Success, int Id, string Name) = await mediator.Handle, + (bool, int, string)>(new CreateEventArgs(new ItemConfiguration { Name = configuration?.Name })); + + if (Success) + { + publisher.Publish(Created.As(new Item { Id = Id, Name = Name })); + } } } } diff --git a/Bitvault/ContainerToken.cs b/Bitvault/ContainerToken.cs index ed576a4..d3c6253 100644 --- a/Bitvault/ContainerToken.cs +++ b/Bitvault/ContainerToken.cs @@ -1,6 +1,4 @@ -using System.Diagnostics.CodeAnalysis; - -namespace Bitvault; +namespace Bitvault; public record ContainerToken { @@ -21,9 +19,7 @@ public record ContainerToken } - [MaybeNull] - public string Name { get; } + public string Name { get; } = ""; - [MaybeNull] - public string? Password { get; } + public string? Password { get; } = ""; } diff --git a/Bitvault/CreateItemHander.cs b/Bitvault/CreateItemHandler.cs similarity index 92% rename from Bitvault/CreateItemHander.cs rename to Bitvault/CreateItemHandler.cs index 6773c01..551afe6 100644 --- a/Bitvault/CreateItemHander.cs +++ b/Bitvault/CreateItemHandler.cs @@ -5,7 +5,7 @@ using Toolkit.Foundation; namespace Bitvault; -public class CreateItemHander(IDbContextFactory dbContextFactory) : +public class CreateItemHandler(IDbContextFactory dbContextFactory) : IHandler, (bool, int, string?)> { public async Task<(bool, int, string?)> Handle(CreateEventArgs args, diff --git a/Bitvault/ItemActivatedHandler.cs b/Bitvault/CreatedItemHandler.cs similarity index 59% rename from Bitvault/ItemActivatedHandler.cs rename to Bitvault/CreatedItemHandler.cs index 9ea7d78..e02a352 100644 --- a/Bitvault/ItemActivatedHandler.cs +++ b/Bitvault/CreatedItemHandler.cs @@ -4,24 +4,27 @@ using Toolkit.Foundation; namespace Bitvault; -public class ItemActivatedHandler(IServiceProvider serviceProvider, - ICache cache, +public class CreatedItemHandler(IServiceProvider serviceProvider, + ICache< Item> cache, IPublisher publisher) : - INotificationHandler> + INotificationHandler> { - public Task Handle(ActivatedEventArgs args) + public Task Handle(CreatedEventArgs args) { if (args.Value is Item item) { IServiceScope serviceScope = serviceProvider.CreateScope(); IServiceFactory serviceFactory = serviceScope.ServiceProvider.GetRequiredService(); + IValueStore valueStore = serviceScope.ServiceProvider.GetRequiredService>(); - cache.Add(item); - int index = cache.IndexOf(item); - - if (serviceFactory.Create(item.Id, item.Name, "Description " + 1, true) + if (serviceFactory.Create(item.Id, item.Name, "Description", true) is ItemNavigationViewModel viewModel) { + cache.Add(item); + + int index = cache.IndexOf(item); + valueStore.Set(item); + publisher.Publish(Insert.As(index, viewModel), nameof(ContainerViewModel)); } } diff --git a/Bitvault/EditItemActionViewModel.cs b/Bitvault/EditItemActionViewModel.cs index cd45e1c..3ad9feb 100644 --- a/Bitvault/EditItemActionViewModel.cs +++ b/Bitvault/EditItemActionViewModel.cs @@ -11,5 +11,5 @@ public partial class EditItemActionViewModel(IServiceProvider provider, IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer) { [RelayCommand] - public void Invoke() => Publisher.Publish(Edit.As()); + public void Invoke() => Publisher.Publish(Edit.As(), nameof(ItemViewModel)); } \ No newline at end of file diff --git a/Bitvault/EditItemHander.cs b/Bitvault/EditItemHander.cs index 0a2e07f..6a72930 100644 --- a/Bitvault/EditItemHander.cs +++ b/Bitvault/EditItemHander.cs @@ -5,36 +5,41 @@ using Toolkit.Foundation; namespace Bitvault; public class EditItemHander(IDbContextFactory dbContextFactory) : - IHandler, bool> + IHandler, (bool, int, string?)> { - public async Task Handle(EditEventArgs<(int, ItemConfiguration)> args, + public async Task<(bool, int, string?)> Handle(EditEventArgs<(int, ItemConfiguration)> args, CancellationToken cancellationToken) { - //if (args.Value is ItemConfiguration configuration) - //{ - // try - // { - // using ContainerDbContext context = dbContextFactory.CreateDbContext(); - // EntityEntry? result = null; + if (args.Value is (int id, ItemConfiguration configuration)) + { + try + { + using ContainerDbContext context = dbContextFactory.CreateDbContext(); + ItemEntry? result = null; - // await Task.Run(async () => - // { - // result = await context.AddAsync(new ItemEntry { Name = configuration.Name }, cancellationToken); - // await context.SaveChangesAsync(cancellationToken); + await Task.Run(async () => + { + result = await context.Set().FindAsync(id); - // }, cancellationToken); + if (result is not null) + { + result.Name = configuration.Name; + await context.SaveChangesAsync(cancellationToken); + } - // if (result is not null) - // { - // return true; - // } - // } - // catch - // { + }, cancellationToken); - // } - //} + if (result is not null) + { + return (true, result.Id, result.Name); + } + } + catch + { - return false; + } + } + + return (false, -1, ""); } } diff --git a/Bitvault/IContainerNavigationViewModel.cs b/Bitvault/IContainerNavigationViewModel.cs index 641cec5..2523ab2 100644 --- a/Bitvault/IContainerNavigationViewModel.cs +++ b/Bitvault/IContainerNavigationViewModel.cs @@ -2,4 +2,6 @@ namespace Bitvault; -public interface IContainerNavigationViewModel : ISelectable; \ No newline at end of file +public interface IContainerNavigationViewModel : + ISelectable, + IDisposable; \ No newline at end of file diff --git a/Bitvault/IMainNavigationViewModel.cs b/Bitvault/IMainNavigationViewModel.cs index 4f58127..895ac5f 100644 --- a/Bitvault/IMainNavigationViewModel.cs +++ b/Bitvault/IMainNavigationViewModel.cs @@ -1,3 +1,3 @@ namespace Bitvault; -public interface IMainNavigationViewModel; +public interface IMainNavigationViewModel : IDisposable; diff --git a/Bitvault/Item.cs b/Bitvault/Item.cs index 3f585dc..af5f6e6 100644 --- a/Bitvault/Item.cs +++ b/Bitvault/Item.cs @@ -1,9 +1,11 @@ -namespace Bitvault; +using System.Diagnostics.CodeAnalysis; + +namespace Bitvault; public record Item { public int Id { get; init; } - public string? Name { get; init; } + public string Name { get; init; } = ""; } diff --git a/Bitvault/ItemConfiguration.cs b/Bitvault/ItemConfiguration.cs index 41840ea..eaa811a 100644 --- a/Bitvault/ItemConfiguration.cs +++ b/Bitvault/ItemConfiguration.cs @@ -2,5 +2,5 @@ public record ItemConfiguration { - public string? Name { get; set; } + public string Name { get; set; } = ""; } diff --git a/Bitvault/ItemHeaderViewModel.cs b/Bitvault/ItemHeaderViewModel.cs index ad9f8f8..21a98b0 100644 --- a/Bitvault/ItemHeaderViewModel.cs +++ b/Bitvault/ItemHeaderViewModel.cs @@ -13,7 +13,7 @@ public partial class ItemHeaderViewModel(IServiceProvider provider, string? value = null) : Observable(provider, factory, mediator, publisher, subscriber, disposer, value), IHandler, bool>, IHandler, ItemHeaderConfiguration>, - IItemEntryViewModel + IItemEntryViewModel, IRemovable { [ObservableProperty] private bool immutable = immutable; @@ -24,6 +24,11 @@ public partial class ItemHeaderViewModel(IServiceProvider provider, return Task.FromResult(true); } + public override void Dispose() + { + base.Dispose(); + } + public Task Handle(ConfirmEventArgs args, CancellationToken cancellationToken) => Task.FromResult(new ItemHeaderConfiguration { Name = Value }); } diff --git a/Bitvault/ItemNavigationViewModel.cs b/Bitvault/ItemNavigationViewModel.cs index 77a054b..bc33d40 100644 --- a/Bitvault/ItemNavigationViewModel.cs +++ b/Bitvault/ItemNavigationViewModel.cs @@ -12,9 +12,9 @@ public partial class ItemNavigationViewModel(IServiceProvider provider, IContentTemplate template, NamedComponent named, int id, - string name, - string description, - bool selected, + string? name = "", + string? description = "", + bool selected = false, bool favourite = false, bool archived = false) : Observable(provider, factory, mediator, publisher, subscriber, disposer), diff --git a/Bitvault/ItemViewModel.cs b/Bitvault/ItemViewModel.cs index f0cec0c..8954254 100644 --- a/Bitvault/ItemViewModel.cs +++ b/Bitvault/ItemViewModel.cs @@ -18,21 +18,31 @@ public partial class ItemViewModel : [ObservableProperty] private bool immutable; - public ItemViewModel(IServiceProvider provider, + [ObservableProperty] + private string named; + + [ObservableProperty] + private string name; + + public ItemViewModel(IServiceProvider provider, IServiceFactory factory, IMediator mediator, IPublisher publisher, ISubscription subscriber, IDisposer disposer, IContentTemplate template, + NamedComponent named, + string name = "", bool immutable = true, bool favourite = false, bool archived = false) : base(provider, factory, mediator, publisher, subscriber, disposer) { + Named = $"{named}"; Template = template; Immutable = immutable; Favourite = favourite; Archived = archived; + Name = name; } public IContentTemplate Template { get; set; } diff --git a/Bitvault/ModifiedItemHandler.cs b/Bitvault/ModifiedItemHandler.cs new file mode 100644 index 0000000..6f8e86c --- /dev/null +++ b/Bitvault/ModifiedItemHandler.cs @@ -0,0 +1,42 @@ +using Microsoft.Extensions.DependencyInjection; +using Toolkit.Foundation; + +namespace Bitvault; + +public class ModifiedItemHandler(IServiceProvider serviceProvider, + ICache cache, + IPublisher publisher) : + INotificationHandler> +{ + public Task Handle(ModifiedEventArgs args) + { + Item oldItem = args.OldView; + Item newItem = args.NewValue; + + if (cache.TryGetValue(oldItem, out Item? cachedItem)) + { + if (cachedItem is not null) + { + IServiceScope serviceScope = serviceProvider.CreateScope(); + IServiceFactory serviceFactory = serviceScope.ServiceProvider.GetRequiredService(); + IValueStore valueStore = serviceScope.ServiceProvider.GetRequiredService>(); + + if (serviceFactory.Create(newItem.Id, newItem.Name, "Description", true) + is ItemNavigationViewModel viewModel) + { + int oldIndex = cache.IndexOf(cachedItem); + cache.Remove(cachedItem); + + cache.Add(newItem); + + int newIndex = cache.IndexOf(newItem); + valueStore.Set(newItem); + + publisher.Publish(RemoveAndInsertAt.As(oldIndex, newIndex, viewModel), nameof(ContainerViewModel)); + } + } + } + + return Task.CompletedTask; + } +} diff --git a/Bitvault/QueryContainerHandler.cs b/Bitvault/QueryContainerHandler.cs index 4c60fcf..b43bdd5 100644 --- a/Bitvault/QueryContainerHandler.cs +++ b/Bitvault/QueryContainerHandler.cs @@ -15,18 +15,13 @@ public class QueryItemHandler(IDbContextFactory dbContextFac } } -public record QueryItemConfiguration -{ - public int Id { get; set; } -} - public class QueryContainerHandler(IDbContextFactory dbContextFactory) : IHandler, IReadOnlyCollection<(int Id, string? Name, bool Favourite, bool Archived)>> { - public async Task> Handle(RequestEventArgs args, + public async Task> Handle(RequestEventArgs args, CancellationToken cancellationToken) { - List<(int Id, string? Name, bool Favourite, bool Archived)> items = []; + List<(int Id, string Name, bool Favourite, bool Archived)> items = []; if (args.Value is QueryContainerConfiguration queryConfiguration) { diff --git a/Bitvault/QueryItemConfiguration.cs b/Bitvault/QueryItemConfiguration.cs new file mode 100644 index 0000000..a27eb73 --- /dev/null +++ b/Bitvault/QueryItemConfiguration.cs @@ -0,0 +1,6 @@ +namespace Bitvault; + +public record QueryItemConfiguration +{ + public int Id { get; set; } +} diff --git a/Toolkit b/Toolkit index 72a37c7..1190303 160000 --- a/Toolkit +++ b/Toolkit @@ -1 +1 @@ -Subproject commit 72a37c72758c59e16a1e126dd9f17e0e11a5b1b0 +Subproject commit 11903030442162f86cfd8a3d7f43146edd916f9b