Added ability to modify image of existing items

This commit is contained in:
TheXamlGuy
2024-07-03 19:23:15 +01:00
parent d36a66b2fe
commit a7785edb02
10 changed files with 114 additions and 55 deletions
+1
View File
@@ -15,6 +15,7 @@
Route="Item" Route="Item"
Scope="self"> Scope="self">
<Parameter Key="Name" Value="{Binding Name}" /> <Parameter Key="Name" Value="{Binding Name}" />
<Parameter Key="Category" Value="{Binding Category}" />
<Parameter Key="ImageDescriptor" Value="{Binding ImageDescriptor}" /> <Parameter Key="ImageDescriptor" Value="{Binding ImageDescriptor}" />
<Parameter Key="FromCategory" Value="{x:False}" /> <Parameter Key="FromCategory" Value="{x:False}" />
<Parameter Key="Favourite" Value="{Binding IsFavourite}" /> <Parameter Key="Favourite" Value="{Binding IsFavourite}" />
-10
View File
@@ -16,11 +16,6 @@ public class WalletContext(DbContextOptions<WalletContext> options) :
modelBuilder.Entity<ItemEntry>() modelBuilder.Entity<ItemEntry>()
.HasKey(x => x.Id); .HasKey(x => x.Id);
modelBuilder.Entity<ItemEntry>()
.Property(x => x.Id)
.ValueGeneratedOnAdd()
.HasDefaultValueSql("NEWID()");
modelBuilder.Entity<ItemEntry>() modelBuilder.Entity<ItemEntry>()
.HasMany(x => x.Tags) .HasMany(x => x.Tags)
.WithOne() .WithOne()
@@ -40,10 +35,5 @@ public class WalletContext(DbContextOptions<WalletContext> options) :
modelBuilder.Entity<BlobEntry>() modelBuilder.Entity<BlobEntry>()
.HasKey(x => x.Id); .HasKey(x => x.Id);
modelBuilder.Entity<BlobEntry>()
.Property(x => x.Id)
.ValueGeneratedOnAdd()
.HasDefaultValueSql("NEWID()");
} }
} }
+1 -1
View File
@@ -24,8 +24,8 @@ public class ConfirmCreateItemHandler(IMediator mediator,
ItemConfiguration)>((id, name, category, imageDescriptor ?? default, itemConfiguration))); ItemConfiguration)>((id, name, category, imageDescriptor ?? default, itemConfiguration)));
Item<(Guid, string, string)> item = new((id, name, category)); Item<(Guid, string, string)> item = new((id, name, category));
publisher.Publish(Created.As(item));
publisher.Publish(Created.As(item));
publisher.Publish(Changed.As<Item>()); publisher.Publish(Changed.As<Item>());
} }
} }
+13 -9
View File
@@ -15,22 +15,26 @@ public class ConfirmUpdateItemHandler(IDecoratorService<Item<(Guid, string)>> it
itemHeaderConfiguration.Service is ItemHeaderConfiguration headerConfiguration && itemHeaderConfiguration.Service is ItemHeaderConfiguration headerConfiguration &&
itemConfigurationDecorator.Service is ItemConfiguration itemConfiguration) itemConfigurationDecorator.Service is ItemConfiguration itemConfiguration)
{ {
string? name = headerConfiguration?.Name; if (headerConfiguration?.Name is { Length: > 0 } name &&
if (name is not null) headerConfiguration.Category is { Length: > 0 } category)
{ {
publisher.Publish(Notify.As(new ItemHeader<string>(name))); IImageDescriptor? imageDescriptor = headerConfiguration.ImageDescriptor;
(Guid id, string _) = item.Value; publisher.Publish(Notify.As(new Item<string>(name)));
publisher.Publish(Notify.As(new Item<IImageDescriptor?>(imageDescriptor)));
(Guid id, _) = item.Value;
await mediator.Handle<UpdateEventArgs<Item<(Guid, string, string, IImageDescriptor?,
ItemConfiguration)>>, bool>(new UpdateEventArgs<Item<(Guid, string, string, IImageDescriptor?,
ItemConfiguration)>>(new Item<(Guid, string, string, IImageDescriptor?, ItemConfiguration)>((id,
name, category, imageDescriptor, itemConfiguration))));
Item<(Guid, string)> newItem = new((id, name)); Item<(Guid, string)> newItem = new((id, name));
publisher.Publish(Modified.As(item, newItem)); publisher.Publish(Modified.As(item, newItem));
itemDecorator.Set(newItem); itemDecorator.Set(newItem);
publisher.Publish(Changed.As(newItem));
await mediator.Handle<UpdateEventArgs<Item<(Guid, string, ItemConfiguration)>>, bool>(new UpdateEventArgs<Item<(Guid, string,
ItemConfiguration)>>(new Item<(Guid, string, ItemConfiguration)>((id, name, itemConfiguration))));
publisher.Publish(Changed.As(item));
} }
} }
} }
+1
View File
@@ -15,6 +15,7 @@ public class CreateItemHandler(IImageWriter imageWriter,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
(Guid id, string name, string category, IImageDescriptor? imageDescriptor, ItemConfiguration configuration) = args.Sender; (Guid id, string name, string category, IImageDescriptor? imageDescriptor, ItemConfiguration configuration) = args.Sender;
try try
{ {
string content = JsonSerializer.Serialize(configuration); string content = JsonSerializer.Serialize(configuration);
+44 -24
View File
@@ -41,7 +41,8 @@ public partial class ItemHeaderViewModel :
Value = value; Value = value;
ImageDescriptor = imageDescriptor; 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<Item> args) => public Task Handle(UpdateEventArgs<Item> args) =>
@@ -74,29 +75,6 @@ public partial class ItemHeaderViewModel :
return Task.CompletedTask; return Task.CompletedTask;
} }
[RelayCommand]
private async Task Import() => ImageDescriptor = await Mediator.Handle<CreateEventArgs<ProfileImage>,
IImageDescriptor>(Create.As<ProfileImage>());
[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<Item<IImageDescriptor>> args) public Task Handle(NotifyEventArgs<Item<IImageDescriptor>> args)
{ {
if (args.Sender is Item<IImageDescriptor> item) if (args.Sender is Item<IImageDescriptor> item)
@@ -106,4 +84,46 @@ public partial class ItemHeaderViewModel :
return Task.CompletedTask; return Task.CompletedTask;
} }
protected override void OnValueChanged()
{
if (configuration is not null)
{
configuration.Name = Value;
}
}
[RelayCommand]
private async Task Import() => ImageDescriptor = await Mediator.Handle<CreateEventArgs<ProfileImage>,
IImageDescriptor>(Create.As<ProfileImage>());
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;
} }
+5 -3
View File
@@ -25,7 +25,7 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
INotificationHandler<FavouriteEventArgs<Item>>, INotificationHandler<FavouriteEventArgs<Item>>,
INotificationHandler<UnfavouriteEventArgs<Item>>, INotificationHandler<UnfavouriteEventArgs<Item>>,
INotificationHandler<DeleteEventArgs<Item>>, INotificationHandler<DeleteEventArgs<Item>>,
INotificationHandler<NotifyEventArgs<ItemHeader<string>>>, INotificationHandler<NotifyEventArgs<Item<string>>>,
INotificationHandler<NotifyEventArgs<Item<IImageDescriptor>>>, INotificationHandler<NotifyEventArgs<Item<IImageDescriptor>>>,
IKeyed<Guid>, IKeyed<Guid>,
ISelectable, ISelectable,
@@ -45,11 +45,13 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
[ObservableProperty] [ObservableProperty]
private bool isArchived = isArchived; private bool isArchived = isArchived;
[ObservableProperty] [ObservableProperty]
private bool isAttached; private bool isAttached;
[ObservableProperty] [ObservableProperty]
private bool isFavourite = isFavourite; private bool isFavourite = isFavourite;
[ObservableProperty] [ObservableProperty]
private bool isSelected = isSelected; private bool isSelected = isSelected;
@@ -84,9 +86,9 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task Handle(NotifyEventArgs<ItemHeader<string>> args) public Task Handle(NotifyEventArgs<Item<string>> args)
{ {
if (args.Sender is ItemHeader<string> header) if (args.Sender is Item<string> header)
{ {
Name = header.Value; Name = header.Value;
} }
+3 -1
View File
@@ -37,6 +37,7 @@ public partial class ItemViewModel :
NamedComponent named, NamedComponent named,
IDecoratorService<ItemHeaderConfiguration> itemHeaderConfigurationDecorator, IDecoratorService<ItemHeaderConfiguration> itemHeaderConfigurationDecorator,
string name = "", string name = "",
string category = "",
ImageDescriptor? imageDescriptor = null, ImageDescriptor? imageDescriptor = null,
bool fromCategory = false, bool fromCategory = false,
bool favourite = false, bool favourite = false,
@@ -53,7 +54,8 @@ public partial class ItemViewModel :
ItemHeaderConfiguration configuration = new() ItemHeaderConfiguration configuration = new()
{ {
Name = name Name = name,
Category = category,
}; };
itemHeaderConfigurationDecorator.Set(configuration); itemHeaderConfigurationDecorator.Set(configuration);
+46 -6
View File
@@ -6,20 +6,22 @@ using Toolkit.Foundation;
namespace Wallet; namespace Wallet;
public class UpdateItemHander(IDbContextFactory<WalletContext> dbContextFactory) : public class UpdateItemHander(IDbContextFactory<WalletContext> dbContextFactory,
IHandler<UpdateEventArgs<Item<(Guid, string, ItemConfiguration)>>, bool> IImageWriter imageWriter) :
IHandler<UpdateEventArgs<Item<(Guid, string, string, IImageDescriptor?, ItemConfiguration)>>, bool>
{ {
public async Task<bool> Handle(UpdateEventArgs<Item<(Guid, string, ItemConfiguration)>> args, public async Task<bool> Handle(UpdateEventArgs<Item<(Guid, string, string, IImageDescriptor?, ItemConfiguration)>> args,
CancellationToken cancellationToken) 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 try
{ {
using WalletContext context = await dbContextFactory.CreateDbContextAsync(cancellationToken); using WalletContext context = await dbContextFactory.CreateDbContextAsync(cancellationToken);
ItemEntry? result = result = await context.Set<ItemEntry>().FindAsync([id], cancellationToken); ItemEntry? result = result = await context.Set<ItemEntry>()
.Include(x => x.Image).FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
if (result is not null) if (result is not null)
{ {
@@ -31,7 +33,45 @@ public class UpdateItemHander(IDbContextFactory<WalletContext> dbContextFactory)
Type = 0, 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.Name = name;
result.Category = category;
await context.SaveChangesAsync(cancellationToken); await context.SaveChangesAsync(cancellationToken);
} }
-1
View File
@@ -17,7 +17,6 @@ public partial class WalletHeaderViewModel(IServiceProvider provider,
public Task Handle(NotifyEventArgs<WalletCommandHeaderCollection> args) public Task Handle(NotifyEventArgs<WalletCommandHeaderCollection> args)
{ {
Clear(); Clear();
if (args.Sender is WalletCommandHeaderCollection commandCollection) if (args.Sender is WalletCommandHeaderCollection commandCollection)
{ {
foreach (IDisposable command in commandCollection) foreach (IDisposable command in commandCollection)