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),
+10
View File
@@ -18,6 +18,12 @@ public partial class ItemViewModel :
[ObservableProperty] [ObservableProperty]
private bool immutable; private bool immutable;
[ObservableProperty]
private string named;
[ObservableProperty]
private string name;
public ItemViewModel(IServiceProvider provider, public ItemViewModel(IServiceProvider provider,
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
@@ -25,14 +31,18 @@ public partial class ItemViewModel :
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