Get favourites working
This commit is contained in:
@@ -2,8 +2,7 @@
|
||||
x:Class="Bitvault.Avalonia.App"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
RequestedThemeVariant="Default">
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls">
|
||||
<Application.Styles>
|
||||
<ThemeResources PreferSystemTheme="True" PreferUserAccentColor="True" />
|
||||
<Style Selector="ui|SettingsExpanderItem">
|
||||
|
||||
@@ -94,6 +94,7 @@ public partial class App : Application
|
||||
|
||||
services.AddTemplate<ItemCommandHeaderViewModel, ItemCommandHeaderView>("ItemCommandHeader");
|
||||
|
||||
services.AddTemplate<FavouriteItemActionViewModel, FavouriteItemActionView>();
|
||||
services.AddTemplate<ConfirmItemActionViewModel, ConfirmItemActionView>();
|
||||
services.AddTemplate<DismissItemActionViewModel, DismissItemActionView>();
|
||||
services.AddTemplate<ArchiveItemActionViewModel, ArchiveItemActionView>();
|
||||
@@ -108,7 +109,8 @@ public partial class App : Application
|
||||
services.AddHandler<ConfirmItemHandler>(ServiceLifetime.Scoped);
|
||||
services.AddHandler<ArchiveItemHandler>(ServiceLifetime.Scoped);
|
||||
services.AddHandler<UnarchiveItemHandler>(ServiceLifetime.Scoped);
|
||||
|
||||
services.AddHandler<FavouriteItemHandler>(ServiceLifetime.Scoped);
|
||||
services.AddHandler<UnfavouriteItemHandler>(ServiceLifetime.Scoped);
|
||||
});
|
||||
})!);
|
||||
|
||||
|
||||
@@ -17,6 +17,6 @@
|
||||
FontFamily="{DynamicResource FluentThemeFontFamily}"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource IconForegroundBrush}"
|
||||
Text="" />
|
||||
Text="" />
|
||||
</Button>
|
||||
</UserControl>
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="{DynamicResource FluentThemeFontFamily}"
|
||||
FontSize="18"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource IconForegroundBrush}"
|
||||
Text="" />
|
||||
Text="" />
|
||||
</Button>
|
||||
</UserControl>
|
||||
|
||||
@@ -16,6 +16,6 @@
|
||||
FontFamily="{DynamicResource FluentThemeFontFamily}"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource IconForegroundBrush}"
|
||||
Text="" />
|
||||
Text="" />
|
||||
</Button>
|
||||
</UserControl>
|
||||
|
||||
@@ -16,6 +16,6 @@
|
||||
FontFamily="{DynamicResource FluentThemeFontFamily}"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource IconForegroundBrush}"
|
||||
Text="" />
|
||||
Text="" />
|
||||
</Button>
|
||||
</UserControl>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<UserControl
|
||||
x:Class="Bitvault.Avalonia.FavouriteItemActionView"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:Bitvault"
|
||||
x:DataType="vm:FavouriteItemActionViewModel">
|
||||
<Button
|
||||
Width="{StaticResource ButtonWidth}"
|
||||
Height="{StaticResource ButtonHeight}"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding InvokeCommand}"
|
||||
ToolTip.Tip="Edit">
|
||||
<Grid>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="{DynamicResource FluentThemeFontFamily}"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource IconForegroundBrush}"
|
||||
IsVisible="{Binding !Value}"
|
||||
Text="" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="{DynamicResource FluentThemeFontFamily}"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource IconForegroundBrush}"
|
||||
IsVisible="{Binding Value}"
|
||||
Text="" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,8 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace Bitvault.Avalonia;
|
||||
|
||||
public partial class FavouriteItemActionView : UserControl
|
||||
{
|
||||
public FavouriteItemActionView() => InitializeComponent();
|
||||
}
|
||||
@@ -5,6 +5,9 @@
|
||||
xmlns:vm="using:Bitvault"
|
||||
x:DataType="vm:ItemNavigationViewModel"
|
||||
IsSelected="{Binding Selected}">
|
||||
<ListBoxItem.Resources>
|
||||
<SolidColorBrush x:Key="StarredIconForegroundBrush" Color="#FFEDB120" />
|
||||
</ListBoxItem.Resources>
|
||||
<Interaction.Behaviors>
|
||||
<DataTriggerBehavior Binding="{Binding Selected}" Value="True">
|
||||
<NavigateAction
|
||||
@@ -17,6 +20,7 @@
|
||||
Scope="self">
|
||||
<NavigateAction.ParameterBindings>
|
||||
<ParameterBinding Key="Archived" Value="{Binding Archived}" />
|
||||
<ParameterBinding Key="Favourite" Value="{Binding Favourite}" />
|
||||
</NavigateAction.ParameterBindings>
|
||||
</NavigateAction>
|
||||
</DataTriggerBehavior>
|
||||
@@ -25,8 +29,17 @@
|
||||
<PersonPicture
|
||||
Grid.Column="0"
|
||||
Height="34"
|
||||
Margin="0"
|
||||
DisplayName="{Binding Name}" />
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
Margin="0,0,-2,10"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
FontFamily="{DynamicResource FluentThemeFontFamily}"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource StarredIconForegroundBrush}"
|
||||
IsVisible="{Binding Favourite}"
|
||||
Text="" />
|
||||
<StackPanel Grid.Column="1" Margin="12,12,6,12">
|
||||
<TextBlock FontWeight="SemiBold" Text="{Binding Name}" />
|
||||
<TextBlock Opacity="0.7" Text="{Binding Name}" />
|
||||
|
||||
@@ -18,19 +18,19 @@ public class AggerateContainerViewModelHandler(IMediator mediator,
|
||||
bool selected = true;
|
||||
|
||||
if (await mediator.Handle<RequestEventArgs<QueryContainerConfiguration>,
|
||||
IReadOnlyCollection<(int Id, string? Name)>>(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)> results)
|
||||
})) is IReadOnlyCollection<(int Id, string? Name, bool Favourite, bool Archived)> results)
|
||||
{
|
||||
foreach ((int Id, string? Name) in results)
|
||||
foreach ((int Id, string? Name, bool Favourite, bool Archived) in results)
|
||||
{
|
||||
IServiceScope serviceScope = serviceProvider.CreateScope();
|
||||
IServiceFactory serviceFactory = serviceScope.ServiceProvider.GetRequiredService<IServiceFactory>();
|
||||
IValueStore<Item> valueStore = serviceScope.ServiceProvider.GetRequiredService<IValueStore<Item>>();
|
||||
|
||||
if (serviceFactory.Create<ItemNavigationViewModel>(Id, Name, "Description", selected, configuration.Filter == "Archive") is ItemNavigationViewModel viewModel)
|
||||
if (serviceFactory.Create<ItemNavigationViewModel>(Id, Name, "Description", selected, Favourite, Archived) is ItemNavigationViewModel viewModel)
|
||||
{
|
||||
Item item = new() { Id = Id, Name = Name };
|
||||
valueStore.Set(item);
|
||||
|
||||
@@ -13,5 +13,4 @@ public partial class ArchiveItemActionViewModel(IServiceProvider provider,
|
||||
{
|
||||
[RelayCommand]
|
||||
public void Invoke() => Publisher.Publish(Archive.As<Item>());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Bitvault;
|
||||
|
||||
public record Favourite
|
||||
{
|
||||
public static FavouriteEventArgs<TValue> As<TValue>(TValue value) =>
|
||||
new(value);
|
||||
|
||||
public static FavouriteEventArgs<TValue> As<TValue>() where TValue : new() =>
|
||||
new(new TValue());
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Bitvault;
|
||||
|
||||
public record FavouriteEventArgs<TValue>(TValue Value);
|
||||
@@ -0,0 +1,30 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public partial class FavouriteItemActionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
bool value = false) : Observable<bool>(provider, factory, mediator, publisher, subscriber, disposer, value),
|
||||
IRemovable
|
||||
{
|
||||
[RelayCommand]
|
||||
public void Invoke()
|
||||
{
|
||||
if (!Value)
|
||||
{
|
||||
Value = true;
|
||||
Publisher.Publish(Favourite.As<Item>());
|
||||
}
|
||||
else
|
||||
{
|
||||
Value = false;
|
||||
Publisher.Publish(Unfavourite.As<Item>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using Bitvault.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class FavouriteItemHandler(IValueStore<Item> valueStore,
|
||||
IDbContextFactory<ContainerDbContext> dbContextFactory) :
|
||||
INotificationHandler<FavouriteEventArgs<Item>>
|
||||
{
|
||||
public async Task Handle(FavouriteEventArgs<Item> args)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (valueStore.Value is Item item)
|
||||
{
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
using ContainerDbContext context = await dbContextFactory.CreateDbContextAsync();
|
||||
|
||||
if (await context.FindAsync<ItemEntry>(item.Id) is ItemEntry result)
|
||||
{
|
||||
result.State = 1;
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,13 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
|
||||
string name,
|
||||
string description,
|
||||
bool selected,
|
||||
bool favourite,
|
||||
bool archived) :
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
INotificationHandler<ArchiveEventArgs<Item>>,
|
||||
INotificationHandler<UnarchiveEventArgs<Item>>,
|
||||
INotificationHandler<FavouriteEventArgs<Item>>,
|
||||
INotificationHandler<UnfavouriteEventArgs<Item>>,
|
||||
ISelectable,
|
||||
IRemovable
|
||||
{
|
||||
@@ -28,6 +31,9 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
|
||||
[ObservableProperty]
|
||||
private string? description = description;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool favourite = favourite;
|
||||
|
||||
[ObservableProperty]
|
||||
private int id = id;
|
||||
|
||||
@@ -42,15 +48,15 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
|
||||
|
||||
public IContentTemplate Template { get; set; } = template;
|
||||
|
||||
public Task Handle(ArchiveEventArgs<Item> args)
|
||||
{
|
||||
Dispose();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
public Task Handle(ArchiveEventArgs<Item> args) =>
|
||||
Task.Run(Dispose);
|
||||
|
||||
public Task Handle(UnarchiveEventArgs<Item> args)
|
||||
{
|
||||
Dispose();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
public Task Handle(UnarchiveEventArgs<Item> args) =>
|
||||
Task.Run(Dispose);
|
||||
|
||||
public Task Handle(FavouriteEventArgs<Item> args) =>
|
||||
Task.FromResult(Favourite = true);
|
||||
|
||||
public Task Handle(UnfavouriteEventArgs<Item> args) =>
|
||||
Task.FromResult(Favourite = false);
|
||||
}
|
||||
@@ -18,6 +18,7 @@ public partial class ItemViewModel :
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
IContentTemplate template,
|
||||
bool favourite = false,
|
||||
bool archived = false) : base(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
Template = template;
|
||||
@@ -27,6 +28,7 @@ public partial class ItemViewModel :
|
||||
{
|
||||
Publisher.Publish(Notify.As(Factory.Create<CommandCollection>(new List<IDisposable>
|
||||
{
|
||||
Factory.Create<FavouriteItemActionViewModel>(favourite),
|
||||
Factory.Create<EditItemActionViewModel>(),
|
||||
Factory.Create<ArchiveItemActionViewModel>(),
|
||||
})));
|
||||
|
||||
@@ -6,12 +6,12 @@ using Toolkit.Foundation;
|
||||
namespace Bitvault;
|
||||
|
||||
public class QueryContainerHandler(IDbContextFactory<ContainerDbContext> dbContextFactory) :
|
||||
IHandler<RequestEventArgs<QueryContainerConfiguration>, IReadOnlyCollection<(int Id, string? Name)>>
|
||||
IHandler<RequestEventArgs<QueryContainerConfiguration>, IReadOnlyCollection<(int Id, string? Name, bool Favourite, bool Archived)>>
|
||||
{
|
||||
public async Task<IReadOnlyCollection<(int Id, string? Name)>> Handle(RequestEventArgs<QueryContainerConfiguration> args,
|
||||
public async Task<IReadOnlyCollection<(int Id, string? Name, bool Favourite, bool Archived)>> Handle(RequestEventArgs<QueryContainerConfiguration> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
List<(int Id, string? Name)> items = [];
|
||||
List<(int Id, string? Name, bool Favourite, bool Archived)> items = [];
|
||||
|
||||
if (args.Value is QueryContainerConfiguration queryConfiguration)
|
||||
{
|
||||
@@ -44,13 +44,15 @@ public class QueryContainerHandler(IDbContextFactory<ContainerDbContext> dbConte
|
||||
return await context.Set<ItemEntry>().Where(predicate).Select(x => new
|
||||
{
|
||||
x.Id,
|
||||
x.Name
|
||||
x.Name,
|
||||
Favourite = x.State == 1,
|
||||
Archived = x.State == 2
|
||||
}).OrderBy(x => x.Name).ToListAsync();
|
||||
});
|
||||
|
||||
foreach (var result in results)
|
||||
{
|
||||
items.Add(new(result.Id, result.Name));
|
||||
items.Add(new(result.Id, result.Name, result.Favourite, result.Archived));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Bitvault;
|
||||
|
||||
public record Unfavourite
|
||||
{
|
||||
public static UnfavouriteEventArgs<TValue> As<TValue>(TValue value) =>
|
||||
new(value);
|
||||
|
||||
public static UnfavouriteEventArgs<TValue> As<TValue>() where TValue : new() =>
|
||||
new(new TValue());
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Bitvault;
|
||||
|
||||
public record UnfavouriteEventArgs<TValue>(TValue Value);
|
||||
@@ -0,0 +1,17 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public partial class UnfavouriteItemActionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
IRemovable
|
||||
{
|
||||
[RelayCommand]
|
||||
public void Invoke() => Publisher.Publish(Unfavourite.As<Item>());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using Bitvault.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class UnfavouriteItemHandler(IValueStore<Item> valueStore,
|
||||
IDbContextFactory<ContainerDbContext> dbContextFactory) :
|
||||
INotificationHandler<UnfavouriteEventArgs<Item>>
|
||||
{
|
||||
public async Task Handle(UnfavouriteEventArgs<Item> args)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (valueStore.Value is Item item)
|
||||
{
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
using ContainerDbContext context = await dbContextFactory.CreateDbContextAsync();
|
||||
|
||||
if (await context.FindAsync<ItemEntry>(item.Id) is ItemEntry result)
|
||||
{
|
||||
result.State = 0;
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user