diff --git a/Wallet.Avalonia/ItemNavigationView.axaml b/Wallet.Avalonia/ItemNavigationView.axaml index ec7fd26..3feb952 100644 --- a/Wallet.Avalonia/ItemNavigationView.axaml +++ b/Wallet.Avalonia/ItemNavigationView.axaml @@ -15,6 +15,7 @@ Route="Item" Scope="self"> + diff --git a/Wallet.Data/LockerContext.cs b/Wallet.Data/LockerContext.cs index 3c53193..34f594b 100644 --- a/Wallet.Data/LockerContext.cs +++ b/Wallet.Data/LockerContext.cs @@ -16,11 +16,6 @@ public class WalletContext(DbContextOptions options) : modelBuilder.Entity() .HasKey(x => x.Id); - modelBuilder.Entity() - .Property(x => x.Id) - .ValueGeneratedOnAdd() - .HasDefaultValueSql("NEWID()"); - modelBuilder.Entity() .HasMany(x => x.Tags) .WithOne() @@ -40,10 +35,5 @@ public class WalletContext(DbContextOptions options) : modelBuilder.Entity() .HasKey(x => x.Id); - - modelBuilder.Entity() - .Property(x => x.Id) - .ValueGeneratedOnAdd() - .HasDefaultValueSql("NEWID()"); } } \ No newline at end of file diff --git a/Wallet/ConfirmCreateItemHandler.cs b/Wallet/ConfirmCreateItemHandler.cs index 9332555..f17d0d2 100644 --- a/Wallet/ConfirmCreateItemHandler.cs +++ b/Wallet/ConfirmCreateItemHandler.cs @@ -24,8 +24,8 @@ public class ConfirmCreateItemHandler(IMediator mediator, ItemConfiguration)>((id, name, category, imageDescriptor ?? default, itemConfiguration))); Item<(Guid, string, string)> item = new((id, name, category)); - publisher.Publish(Created.As(item)); + publisher.Publish(Created.As(item)); publisher.Publish(Changed.As()); } } diff --git a/Wallet/ConfirmUpdateItemHandler.cs b/Wallet/ConfirmUpdateItemHandler.cs index e834f3a..0d005d2 100644 --- a/Wallet/ConfirmUpdateItemHandler.cs +++ b/Wallet/ConfirmUpdateItemHandler.cs @@ -15,22 +15,26 @@ public class ConfirmUpdateItemHandler(IDecoratorService> it itemHeaderConfiguration.Service is ItemHeaderConfiguration headerConfiguration && itemConfigurationDecorator.Service is ItemConfiguration itemConfiguration) { - string? name = headerConfiguration?.Name; - if (name is not null) + if (headerConfiguration?.Name is { Length: > 0 } name && + headerConfiguration.Category is { Length: > 0 } category) { - publisher.Publish(Notify.As(new ItemHeader(name))); + IImageDescriptor? imageDescriptor = headerConfiguration.ImageDescriptor; - (Guid id, string _) = item.Value; + publisher.Publish(Notify.As(new Item(name))); + publisher.Publish(Notify.As(new Item(imageDescriptor))); + + (Guid id, _) = item.Value; + + await mediator.Handle>, bool>(new UpdateEventArgs>(new Item<(Guid, string, string, IImageDescriptor?, ItemConfiguration)>((id, + name, category, imageDescriptor, itemConfiguration)))); Item<(Guid, string)> newItem = new((id, name)); publisher.Publish(Modified.As(item, newItem)); itemDecorator.Set(newItem); - - await mediator.Handle>, bool>(new UpdateEventArgs>(new Item<(Guid, string, ItemConfiguration)>((id, name, itemConfiguration)))); - - publisher.Publish(Changed.As(item)); + publisher.Publish(Changed.As(newItem)); } } } diff --git a/Wallet/CreateItemHandler.cs b/Wallet/CreateItemHandler.cs index b8a77eb..d3c46c0 100644 --- a/Wallet/CreateItemHandler.cs +++ b/Wallet/CreateItemHandler.cs @@ -15,6 +15,7 @@ public class CreateItemHandler(IImageWriter imageWriter, CancellationToken cancellationToken) { (Guid id, string name, string category, IImageDescriptor? imageDescriptor, ItemConfiguration configuration) = args.Sender; + try { string content = JsonSerializer.Serialize(configuration); diff --git a/Wallet/ItemHeaderViewModel.cs b/Wallet/ItemHeaderViewModel.cs index 5a06fb4..3858db7 100644 --- a/Wallet/ItemHeaderViewModel.cs +++ b/Wallet/ItemHeaderViewModel.cs @@ -41,7 +41,8 @@ public partial class ItemHeaderViewModel : Value = value; ImageDescriptor = imageDescriptor; - Track(nameof(Value), () => Value, newValue => Value = newValue); + Track(nameof(Value), () => Value, x => Value = x); + Track(nameof(ImageDescriptor), () => ImageDescriptor, x => ImageDescriptor = x); } public Task Handle(UpdateEventArgs args) => @@ -74,29 +75,6 @@ public partial class ItemHeaderViewModel : return Task.CompletedTask; } - [RelayCommand] - private async Task Import() => ImageDescriptor = await Mediator.Handle, - IImageDescriptor>(Create.As()); - - [RelayCommand] - private void Remove() => ImageDescriptor = null; - - protected override void OnValueChanged() - { - if (configuration is not null) - { - configuration.Name = Value; - } - } - - partial void OnImageDescriptorChanging(IImageDescriptor? value) - { - if (configuration is not null) - { - configuration.ImageDescriptor = value; - } - } - public Task Handle(NotifyEventArgs> args) { if (args.Sender is Item item) @@ -106,4 +84,46 @@ public partial class ItemHeaderViewModel : return Task.CompletedTask; } + + protected override void OnValueChanged() + { + if (configuration is not null) + { + configuration.Name = Value; + } + } + + [RelayCommand] + private async Task Import() => ImageDescriptor = await Mediator.Handle, + IImageDescriptor>(Create.As()); + + partial void OnImageDescriptorChanged(IImageDescriptor? value) + { + if (configuration is not null) + { + configuration.ImageDescriptor = value; + } + } + + partial void OnImageDescriptorChanged(IImageDescriptor? oldValue, + IImageDescriptor? newValue) + { + if (configuration is not null) + { + if (State is ItemState.Write) + { + if (newValue != oldValue) + { + configuration.ImageDescriptor = newValue; + } + } + else + { + configuration.ImageDescriptor = newValue; + } + } + } + + [RelayCommand] + private void Remove() => ImageDescriptor = null; } \ No newline at end of file diff --git a/Wallet/ItemNavigationViewModel.cs b/Wallet/ItemNavigationViewModel.cs index c2dc9fa..ad39c97 100644 --- a/Wallet/ItemNavigationViewModel.cs +++ b/Wallet/ItemNavigationViewModel.cs @@ -25,7 +25,7 @@ public partial class ItemNavigationViewModel(IServiceProvider provider, INotificationHandler>, INotificationHandler>, INotificationHandler>, - INotificationHandler>>, + INotificationHandler>>, INotificationHandler>>, IKeyed, ISelectable, @@ -45,11 +45,13 @@ public partial class ItemNavigationViewModel(IServiceProvider provider, [ObservableProperty] private bool isArchived = isArchived; + [ObservableProperty] private bool isAttached; [ObservableProperty] private bool isFavourite = isFavourite; + [ObservableProperty] private bool isSelected = isSelected; @@ -84,9 +86,9 @@ public partial class ItemNavigationViewModel(IServiceProvider provider, return Task.CompletedTask; } - public Task Handle(NotifyEventArgs> args) + public Task Handle(NotifyEventArgs> args) { - if (args.Sender is ItemHeader header) + if (args.Sender is Item header) { Name = header.Value; } diff --git a/Wallet/ItemViewModel.cs b/Wallet/ItemViewModel.cs index 4248e7c..63e8fc1 100644 --- a/Wallet/ItemViewModel.cs +++ b/Wallet/ItemViewModel.cs @@ -37,6 +37,7 @@ public partial class ItemViewModel : NamedComponent named, IDecoratorService itemHeaderConfigurationDecorator, string name = "", + string category = "", ImageDescriptor? imageDescriptor = null, bool fromCategory = false, bool favourite = false, @@ -53,7 +54,8 @@ public partial class ItemViewModel : ItemHeaderConfiguration configuration = new() { - Name = name + Name = name, + Category = category, }; itemHeaderConfigurationDecorator.Set(configuration); diff --git a/Wallet/UpdateItemHander.cs b/Wallet/UpdateItemHander.cs index 8b680c3..9019269 100644 --- a/Wallet/UpdateItemHander.cs +++ b/Wallet/UpdateItemHander.cs @@ -6,20 +6,22 @@ using Toolkit.Foundation; namespace Wallet; -public class UpdateItemHander(IDbContextFactory dbContextFactory) : - IHandler>, bool> +public class UpdateItemHander(IDbContextFactory dbContextFactory, + IImageWriter imageWriter) : + IHandler>, bool> { - public async Task Handle(UpdateEventArgs> args, + public async Task Handle(UpdateEventArgs> args, CancellationToken cancellationToken) { - if (args.Sender is Item<(Guid, string, ItemConfiguration)> item) + if (args.Sender is Item<(Guid, string, string, IImageDescriptor?, ItemConfiguration)> item) { - (Guid id, string name, ItemConfiguration configuration) = item.Value; + (Guid id, string name, string category, IImageDescriptor? imageDescriptor, ItemConfiguration configuration) = item.Value; try { using WalletContext context = await dbContextFactory.CreateDbContextAsync(cancellationToken); - ItemEntry? result = result = await context.Set().FindAsync([id], cancellationToken); + ItemEntry? result = result = await context.Set() + .Include(x => x.Image).FirstOrDefaultAsync(x => x.Id == id, cancellationToken); if (result is not null) { @@ -31,7 +33,45 @@ public class UpdateItemHander(IDbContextFactory dbContextFactory) Type = 0, }); + if (imageDescriptor is not null) + { + byte[]? thumbData = null; + using MemoryStream memoryStream = new(); + imageWriter.Write(imageDescriptor, memoryStream); + thumbData = memoryStream.ToArray(); + + if (result.Image is BlobEntry existingImageBlob) + { + existingImageBlob.Data = thumbData; + existingImageBlob.DateTime = DateTime.UtcNow; + + context.Entry(result.Image).State = EntityState.Modified; + } + else + { + result.Image = new BlobEntry + { + Id = Guid.NewGuid(), + Data = thumbData, + DateTime = DateTime.UtcNow, + Type = 1 + }; + + context.Entry(result.Image).State = EntityState.Added; + } + } + else + { + if (result.Image is not null) + { + context.Remove(result.Image); + result.Image = null; + } + } + result.Name = name; + result.Category = category; + await context.SaveChangesAsync(cancellationToken); } diff --git a/Wallet/WalletHeaderViewModel.cs b/Wallet/WalletHeaderViewModel.cs index 8f06e00..169b524 100644 --- a/Wallet/WalletHeaderViewModel.cs +++ b/Wallet/WalletHeaderViewModel.cs @@ -17,7 +17,6 @@ public partial class WalletHeaderViewModel(IServiceProvider provider, public Task Handle(NotifyEventArgs args) { Clear(); - if (args.Sender is WalletCommandHeaderCollection commandCollection) { foreach (IDisposable command in commandCollection)