Fixed more edge cases

This commit is contained in:
TheXamlGuy
2024-05-21 20:32:41 +01:00
parent 15de406460
commit 5c1a579984
24 changed files with 173 additions and 87 deletions
+10 -9
View File
@@ -42,8 +42,7 @@ public partial class App : Application
{ {
args.AddServices(services => args.AddServices(services =>
{ {
services.AddTransient<IComparer<Item>>(provider => Comparer<Item>.Create((x, z) => services.AddTransient<IComparer<Item>>(provider => Comparer<Item>.Create((x, z) => x.Name.CompareTo(z.Name)));
x.Name!.CompareTo(z.Name) == 0 ? 1 : x.Name!.CompareTo(z.Name)));
services.AddCache<Item>(); services.AddCache<Item>();
@@ -69,7 +68,8 @@ public partial class App : Application
}); });
services.AddHandler<QueryContainerHandler>(); services.AddHandler<QueryContainerHandler>();
services.AddHandler<CreateItemHander>(); services.AddHandler<CreateItemHandler>();
services.AddHandler<EditItemHander>();
services.AddHandler<OpenContainerHandler>(); services.AddHandler<OpenContainerHandler>();
@@ -108,13 +108,14 @@ public partial class App : Application
services.AddScoped<IValueStore<Item>, ValueStore<Item>>(); services.AddScoped<IValueStore<Item>, ValueStore<Item>>();
services.AddHandler<ConfirmItemHandler>(ServiceLifetime.Scoped); services.AddHandler<ConfirmItemHandler>();
services.AddHandler<ArchiveItemHandler>(ServiceLifetime.Scoped); services.AddHandler<ArchiveItemHandler>();
services.AddHandler<UnarchiveItemHandler>(ServiceLifetime.Scoped); services.AddHandler<UnarchiveItemHandler>();
services.AddHandler<FavouriteItemHandler>(ServiceLifetime.Scoped); services.AddHandler<FavouriteItemHandler>();
services.AddHandler<UnfavouriteItemHandler>(ServiceLifetime.Scoped); services.AddHandler<UnfavouriteItemHandler>();
services.AddHandler<ItemActivatedHandler>(ServiceLifetime.Singleton); services.AddHandler<CreatedItemHandler>(ServiceLifetime.Singleton);
services.AddHandler<ModifiedItemHandler>(ServiceLifetime.Singleton);
}); });
})!); })!);
+1 -5
View File
@@ -28,14 +28,10 @@
</Grid> </Grid>
<Interaction.Behaviors> <Interaction.Behaviors>
<EventTriggerBehavior EventName="Click"> <EventTriggerBehavior EventName="Click">
<NavigateAction
Region="{Binding Named, StringFormat='{}{0}:ContentHeader'}"
Route="ItemCommandHeader"
Scope="self" />
<NavigateAction <NavigateAction
Region="{Binding Named, StringFormat='{}{0}:Content'}" Region="{Binding Named, StringFormat='{}{0}:Content'}"
Route="Item" Route="Item"
Scope="self"> Scope="new">
<NavigateAction.ParameterBindings> <NavigateAction.ParameterBindings>
<ParameterBinding Key="Immutable" Value="{x:False}" /> <ParameterBinding Key="Immutable" Value="{x:False}" />
</NavigateAction.ParameterBindings> </NavigateAction.ParameterBindings>
+1 -1
View File
@@ -12,7 +12,7 @@
<TextBox <TextBox
MaxWidth="360" MaxWidth="360"
IsVisible="{Binding !Immutable}" IsVisible="{Binding !Immutable}"
Text="{Binding Value}" Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}"
TextAlignment="Center" TextAlignment="Center"
Watermark="Enter name" /> Watermark="Enter name" />
<SelectableTextBlock <SelectableTextBlock
+1 -4
View File
@@ -10,15 +10,12 @@
</ListBoxItem.Resources> </ListBoxItem.Resources>
<Interaction.Behaviors> <Interaction.Behaviors>
<DataTriggerBehavior Binding="{Binding Selected}" Value="True"> <DataTriggerBehavior Binding="{Binding Selected}" Value="True">
<NavigateAction
Region="{Binding Named, StringFormat='{}{0}:ContentHeader'}"
Route="ItemCommandHeader"
Scope="self" />
<NavigateAction <NavigateAction
Region="{Binding Named, StringFormat='{}{0}:Content'}" Region="{Binding Named, StringFormat='{}{0}:Content'}"
Route="Item" Route="Item"
Scope="self"> Scope="self">
<NavigateAction.ParameterBindings> <NavigateAction.ParameterBindings>
<ParameterBinding Key="Name" Value="{Binding Name}" />
<ParameterBinding Key="Immutable" Value="{x:True}" /> <ParameterBinding Key="Immutable" Value="{x:True}" />
<ParameterBinding Key="Archived" Value="{Binding Archived}" /> <ParameterBinding Key="Archived" Value="{Binding Archived}" />
<ParameterBinding Key="Favourite" Value="{Binding Favourite}" /> <ParameterBinding Key="Favourite" Value="{Binding Favourite}" />
+8
View File
@@ -4,6 +4,14 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Bitvault" xmlns:vm="using:Bitvault"
x:DataType="vm:ItemViewModel"> x:DataType="vm:ItemViewModel">
<Interaction.Behaviors>
<AttachedBehaviour>
<NavigateAction
Region="{Binding Named, StringFormat='{}{0}:ContentHeader'}"
Route="ItemCommandHeader"
Scope="self" />
</AttachedBehaviour>
</Interaction.Behaviors>
<ScrollViewer Padding="12,12,12,0"> <ScrollViewer Padding="12,12,12,0">
<ItemsControl ItemTemplate="{ReflectionBinding Template}" ItemsSource="{Binding}" /> <ItemsControl ItemTemplate="{ReflectionBinding Template}" ItemsSource="{Binding}" />
</ScrollViewer> </ScrollViewer>
+1 -1
View File
@@ -9,7 +9,7 @@ public record ItemEntry
[Key] [Key]
public int Id { get; set; } public int Id { get; set; }
public string? Name { get; set; } public required string Name { get; set; }
public string? Description { get; set; } public string? Description { get; set; }
@@ -18,13 +18,13 @@ public class AggerateContainerViewModelHandler(IMediator mediator,
bool selected = true; bool selected = true;
if (await mediator.Handle<RequestEventArgs<QueryContainerConfiguration>, if (await mediator.Handle<RequestEventArgs<QueryContainerConfiguration>,
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, Filter = configuration.Filter,
Query = configuration.Query 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(); IServiceScope serviceScope = serviceProvider.CreateScope();
IServiceFactory serviceFactory = serviceScope.ServiceProvider.GetRequiredService<IServiceFactory>(); IServiceFactory serviceFactory = serviceScope.ServiceProvider.GetRequiredService<IServiceFactory>();
@@ -35,6 +35,7 @@ public class AggerateContainerViewModelHandler(IMediator mediator,
Item item = new() { Id = Id, Name = Name }; Item item = new() { Id = Id, Name = Name };
valueStore.Set(item); valueStore.Set(item);
cache.Add(item);
publisher.Publish(Create.As(viewModel), nameof(ContainerViewModel)); publisher.Publish(Create.As(viewModel), nameof(ContainerViewModel));
} }
+23 -6
View File
@@ -2,7 +2,8 @@
namespace Bitvault; namespace Bitvault;
public class ConfirmItemHandler(IMediator mediator, public class ConfirmItemHandler(IValueStore<Item> valueStore,
IMediator mediator,
IPublisher publisher) : IPublisher publisher) :
INotificationHandler<ConfirmEventArgs<Item>> INotificationHandler<ConfirmEventArgs<Item>>
{ {
@@ -11,12 +12,28 @@ public class ConfirmItemHandler(IMediator mediator,
ItemHeaderConfiguration? configuration = await mediator.Handle<ConfirmEventArgs<Item>, ItemHeaderConfiguration? configuration = await mediator.Handle<ConfirmEventArgs<Item>,
ItemHeaderConfiguration>(args); ItemHeaderConfiguration>(args);
(bool Success, int Id, string Name) result = await mediator.Handle<CreateEventArgs<ItemConfiguration>, if (valueStore?.Value is Item item)
(bool, int, string)>(new CreateEventArgs<ItemConfiguration>(new ItemConfiguration { Name = configuration?.Name }));
if (result.Success)
{ {
publisher.Publish(Activated.As(new Item { Id = result.Id, Name = result.Name })); (bool Success, int Id, string Name) = await mediator.Handle<EditEventArgs<(int, ItemConfiguration)>,
(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<CreateEventArgs<ItemConfiguration>,
(bool, int, string)>(new CreateEventArgs<ItemConfiguration>(new ItemConfiguration { Name = configuration?.Name }));
if (Success)
{
publisher.Publish(Created.As(new Item { Id = Id, Name = Name }));
}
} }
} }
} }
+3 -7
View File
@@ -1,6 +1,4 @@
using System.Diagnostics.CodeAnalysis; namespace Bitvault;
namespace Bitvault;
public record ContainerToken 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; }
} }
@@ -5,7 +5,7 @@ using Toolkit.Foundation;
namespace Bitvault; namespace Bitvault;
public class CreateItemHander(IDbContextFactory<ContainerDbContext> dbContextFactory) : public class CreateItemHandler(IDbContextFactory<ContainerDbContext> dbContextFactory) :
IHandler<CreateEventArgs<ItemConfiguration>, (bool, int, string?)> IHandler<CreateEventArgs<ItemConfiguration>, (bool, int, string?)>
{ {
public async Task<(bool, int, string?)> Handle(CreateEventArgs<ItemConfiguration> args, public async Task<(bool, int, string?)> Handle(CreateEventArgs<ItemConfiguration> args,
@@ -4,24 +4,27 @@ using Toolkit.Foundation;
namespace Bitvault; namespace Bitvault;
public class ItemActivatedHandler(IServiceProvider serviceProvider, public class CreatedItemHandler(IServiceProvider serviceProvider,
ICache<Item> cache, ICache< Item> cache,
IPublisher publisher) : IPublisher publisher) :
INotificationHandler<ActivatedEventArgs<Item>> INotificationHandler<CreatedEventArgs<Item>>
{ {
public Task Handle(ActivatedEventArgs<Item> args) public Task Handle(CreatedEventArgs<Item> args)
{ {
if (args.Value is Item item) if (args.Value is Item item)
{ {
IServiceScope serviceScope = serviceProvider.CreateScope(); IServiceScope serviceScope = serviceProvider.CreateScope();
IServiceFactory serviceFactory = serviceScope.ServiceProvider.GetRequiredService<IServiceFactory>(); IServiceFactory serviceFactory = serviceScope.ServiceProvider.GetRequiredService<IServiceFactory>();
IValueStore<Item> valueStore = serviceScope.ServiceProvider.GetRequiredService<IValueStore<Item>>();
cache.Add(item); if (serviceFactory.Create<ItemNavigationViewModel>(item.Id, item.Name, "Description", true)
int index = cache.IndexOf(item);
if (serviceFactory.Create<ItemNavigationViewModel>(item.Id, item.Name, "Description " + 1, true)
is ItemNavigationViewModel viewModel) is ItemNavigationViewModel viewModel)
{ {
cache.Add(item);
int index = cache.IndexOf(item);
valueStore.Set(item);
publisher.Publish(Insert.As(index, viewModel), nameof(ContainerViewModel)); publisher.Publish(Insert.As(index, viewModel), nameof(ContainerViewModel));
} }
} }
+1 -1
View File
@@ -11,5 +11,5 @@ public partial class EditItemActionViewModel(IServiceProvider provider,
IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer) IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer)
{ {
[RelayCommand] [RelayCommand]
public void Invoke() => Publisher.Publish(Edit.As<Item>()); public void Invoke() => Publisher.Publish(Edit.As<Item>(), nameof(ItemViewModel));
} }
+28 -23
View File
@@ -5,36 +5,41 @@ using Toolkit.Foundation;
namespace Bitvault; namespace Bitvault;
public class EditItemHander(IDbContextFactory<ContainerDbContext> dbContextFactory) : public class EditItemHander(IDbContextFactory<ContainerDbContext> dbContextFactory) :
IHandler<EditEventArgs<(int, ItemConfiguration)>, bool> IHandler<EditEventArgs<(int, ItemConfiguration)>, (bool, int, string?)>
{ {
public async Task<bool> Handle(EditEventArgs<(int, ItemConfiguration)> args, public async Task<(bool, int, string?)> Handle(EditEventArgs<(int, ItemConfiguration)> args,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
//if (args.Value is ItemConfiguration configuration) if (args.Value is (int id, ItemConfiguration configuration))
//{ {
// try try
// { {
// using ContainerDbContext context = dbContextFactory.CreateDbContext(); using ContainerDbContext context = dbContextFactory.CreateDbContext();
// EntityEntry<ItemEntry>? result = null; ItemEntry? result = null;
// await Task.Run(async () => await Task.Run(async () =>
// { {
// result = await context.AddAsync(new ItemEntry { Name = configuration.Name }, cancellationToken); result = await context.Set<ItemEntry>().FindAsync(id);
// await context.SaveChangesAsync(cancellationToken);
// }, cancellationToken); if (result is not null)
{
result.Name = configuration.Name;
await context.SaveChangesAsync(cancellationToken);
}
// if (result is not null) }, cancellationToken);
// {
// return true;
// }
// }
// catch
// {
// } if (result is not null)
//} {
return (true, result.Id, result.Name);
}
}
catch
{
return false; }
}
return (false, -1, "");
} }
} }
+3 -1
View File
@@ -2,4 +2,6 @@
namespace Bitvault; namespace Bitvault;
public interface IContainerNavigationViewModel : ISelectable; public interface IContainerNavigationViewModel :
ISelectable,
IDisposable;
+1 -1
View File
@@ -1,3 +1,3 @@
namespace Bitvault; namespace Bitvault;
public interface IMainNavigationViewModel; public interface IMainNavigationViewModel : IDisposable;
+4 -2
View File
@@ -1,9 +1,11 @@
namespace Bitvault; using System.Diagnostics.CodeAnalysis;
namespace Bitvault;
public record Item public record Item
{ {
public int Id { get; init; } public int Id { get; init; }
public string? Name { get; init; } public string Name { get; init; } = "";
} }
+1 -1
View File
@@ -2,5 +2,5 @@
public record ItemConfiguration public record ItemConfiguration
{ {
public string? Name { get; set; } public string Name { get; set; } = "";
} }
+6 -1
View File
@@ -13,7 +13,7 @@ public partial class ItemHeaderViewModel(IServiceProvider provider,
string? value = null) : Observable<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<ValidationEventArgs<Item>, bool>,
IHandler<ConfirmEventArgs<Item>, ItemHeaderConfiguration>, IHandler<ConfirmEventArgs<Item>, ItemHeaderConfiguration>,
IItemEntryViewModel IItemEntryViewModel, IRemovable
{ {
[ObservableProperty] [ObservableProperty]
private bool immutable = immutable; private bool immutable = immutable;
@@ -24,6 +24,11 @@ public partial class ItemHeaderViewModel(IServiceProvider provider,
return Task.FromResult(true); return Task.FromResult(true);
} }
public override void Dispose()
{
base.Dispose();
}
public Task<ItemHeaderConfiguration> Handle(ConfirmEventArgs<Item> args, public Task<ItemHeaderConfiguration> Handle(ConfirmEventArgs<Item> args,
CancellationToken cancellationToken) => Task.FromResult(new ItemHeaderConfiguration { Name = Value }); CancellationToken cancellationToken) => Task.FromResult(new ItemHeaderConfiguration { Name = Value });
} }
+3 -3
View File
@@ -12,9 +12,9 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
IContentTemplate template, IContentTemplate template,
NamedComponent named, NamedComponent named,
int id, int id,
string name, string? name = "",
string description, string? description = "",
bool selected, bool selected = false,
bool favourite = false, bool favourite = false,
bool archived = false) : bool archived = false) :
Observable(provider, factory, mediator, publisher, subscriber, disposer), Observable(provider, factory, mediator, publisher, subscriber, disposer),
+11 -1
View File
@@ -18,21 +18,31 @@ public partial class ItemViewModel :
[ObservableProperty] [ObservableProperty]
private bool immutable; private bool immutable;
public ItemViewModel(IServiceProvider provider, [ObservableProperty]
private string named;
[ObservableProperty]
private string name;
public ItemViewModel(IServiceProvider provider,
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
IPublisher publisher, IPublisher publisher,
ISubscription subscriber, ISubscription subscriber,
IDisposer disposer, IDisposer disposer,
IContentTemplate template, IContentTemplate template,
NamedComponent named,
string name = "",
bool immutable = true, bool immutable = true,
bool favourite = false, bool favourite = false,
bool archived = false) : base(provider, factory, mediator, publisher, subscriber, disposer) bool archived = false) : base(provider, factory, mediator, publisher, subscriber, disposer)
{ {
Named = $"{named}";
Template = template; Template = template;
Immutable = immutable; Immutable = immutable;
Favourite = favourite; Favourite = favourite;
Archived = archived; Archived = archived;
Name = name;
} }
public IContentTemplate Template { get; set; } public IContentTemplate Template { get; set; }
+42
View File
@@ -0,0 +1,42 @@
using Microsoft.Extensions.DependencyInjection;
using Toolkit.Foundation;
namespace Bitvault;
public class ModifiedItemHandler(IServiceProvider serviceProvider,
ICache<Item> cache,
IPublisher publisher) :
INotificationHandler<ModifiedEventArgs<Item>>
{
public Task Handle(ModifiedEventArgs<Item> 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<IServiceFactory>();
IValueStore<Item> valueStore = serviceScope.ServiceProvider.GetRequiredService<IValueStore<Item>>();
if (serviceFactory.Create<ItemNavigationViewModel>(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;
}
}
+2 -7
View File
@@ -15,18 +15,13 @@ public class QueryItemHandler(IDbContextFactory<ContainerDbContext> dbContextFac
} }
} }
public record QueryItemConfiguration
{
public int Id { get; set; }
}
public class QueryContainerHandler(IDbContextFactory<ContainerDbContext> dbContextFactory) : public class QueryContainerHandler(IDbContextFactory<ContainerDbContext> dbContextFactory) :
IHandler<RequestEventArgs<QueryContainerConfiguration>, IReadOnlyCollection<(int Id, string? Name, bool Favourite, bool Archived)>> IHandler<RequestEventArgs<QueryContainerConfiguration>, IReadOnlyCollection<(int Id, string? Name, bool Favourite, bool Archived)>>
{ {
public async Task<IReadOnlyCollection<(int Id, string? Name, bool Favourite, bool Archived)>> Handle(RequestEventArgs<QueryContainerConfiguration> args, public async Task<IReadOnlyCollection<(int Id, string Name, bool Favourite, bool Archived)>> Handle(RequestEventArgs<QueryContainerConfiguration> args,
CancellationToken cancellationToken) 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) if (args.Value is QueryContainerConfiguration queryConfiguration)
{ {
+6
View File
@@ -0,0 +1,6 @@
namespace Bitvault;
public record QueryItemConfiguration
{
public int Id { get; set; }
}
+1 -1
Submodule Toolkit updated: 72a37c7275...1190303044