Mass rename project for rebranding
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class AddItemNavigationViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
IItemEntryViewModel;
|
||||
@@ -0,0 +1,11 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class AllNavigationViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
string filter) : FilterWalletNavigationViewModel(provider, factory, mediator, publisher, subscriber, disposer, filter);
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record Archive
|
||||
{
|
||||
public static ArchiveEventArgs<TValue> As<TValue>(TValue value) =>
|
||||
new(value);
|
||||
|
||||
public static ArchiveEventArgs<TValue> As<TValue>() where TValue : new() =>
|
||||
new(new TValue());
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record ArchiveEventArgs<TValue>(TValue Value);
|
||||
@@ -0,0 +1,16 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class ArchiveItemActionViewModel(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(Archive.As<Item>());
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class ArchiveItemHandler(IDecoratorService<Item<(Guid, string)>> decoratorService,
|
||||
ICache<Item<(Guid, string)>> cache,
|
||||
IMediator mediator) :
|
||||
INotificationHandler<ArchiveEventArgs<Item>>
|
||||
{
|
||||
public async Task Handle(ArchiveEventArgs<Item> args)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (decoratorService.Service is Item<(Guid, string)> item)
|
||||
{
|
||||
if (cache.Contains(item))
|
||||
{
|
||||
(Guid id, string name) = item.Value;
|
||||
|
||||
await mediator.Handle<UpdateEventArgs<(Guid, int)>,
|
||||
bool>(new UpdateEventArgs<(Guid, int)>((id, 2)));
|
||||
|
||||
cache.Remove(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class ArchiveNavigationViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
string name) : FilterWalletNavigationViewModel(provider, factory, mediator, publisher, subscriber, disposer, name);
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record AttachmentEntryConfiguration :
|
||||
ItemEntryConfiguration
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class BackActionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
[ObservableProperty]
|
||||
private int index = 0;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class CategoriesNavigationViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
string name) : FilterWalletNavigationViewModel(provider, factory, mediator, publisher, subscriber, disposer, name);
|
||||
@@ -0,0 +1,10 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public record Closed
|
||||
{
|
||||
public static ChangedEventArgs<TValue> As<TValue>(TValue value) => new(value);
|
||||
|
||||
public static ChangedEventArgs<TValue> As<TValue>() where TValue : new() => new(new TValue());
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record ClosedEventArgs<TValue>(TValue? Value = default);
|
||||
@@ -0,0 +1,25 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class ConfirmCreateItemHandler(IMediator mediator,
|
||||
IDecoratorService<ItemConfiguration> itemConfigurationDecorator,
|
||||
IPublisher publisher) :
|
||||
INotificationHandler<ConfirmEventArgs<Item>>
|
||||
{
|
||||
public async Task Handle(ConfirmEventArgs<Item> args)
|
||||
{
|
||||
if (itemConfigurationDecorator.Service is ItemConfiguration configuration)
|
||||
{
|
||||
string? name = await mediator.Handle<ConfirmEventArgs<ItemHeader>, string>(Confirm.As<ItemHeader>());
|
||||
if (name is not null)
|
||||
{
|
||||
Guid id = Guid.NewGuid();
|
||||
publisher.Publish(Created.As(new Item<(Guid, string)>((id, name))));
|
||||
|
||||
await mediator.Handle<CreateEventArgs<(Guid, string, string,
|
||||
ItemConfiguration)>, bool>(new CreateEventArgs<(Guid, string, string, ItemConfiguration)>((id, name, "", configuration)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class ConfirmItemActionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
[RelayCommand]
|
||||
public void Invoke() => Publisher.Publish(Confirm.As<Item>());
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class ConfirmUpdateItemHandler(IDecoratorService<Item<(Guid, string)>> itemDecorator,
|
||||
IDecoratorService<ItemConfiguration> itemConfigurationDecorator,
|
||||
IMediator mediator,
|
||||
IPublisher publisher) :
|
||||
INotificationHandler<ConfirmEventArgs<Item>>
|
||||
{
|
||||
public async Task Handle(ConfirmEventArgs<Item> args)
|
||||
{
|
||||
if (itemDecorator?.Service is Item<(Guid, string)> item &&
|
||||
itemConfigurationDecorator.Service is ItemConfiguration configuration)
|
||||
{
|
||||
string? name = await mediator.Handle<ConfirmEventArgs<ItemHeader>,
|
||||
string>(Confirm.As<ItemHeader>());
|
||||
|
||||
if (name is not null)
|
||||
{
|
||||
publisher.Publish(Notify.As(new ItemHeader<string>(name)));
|
||||
|
||||
(Guid id, string _) = item.Value;
|
||||
|
||||
Item<(Guid, string)> newItem = new((id, name));
|
||||
publisher.Publish(Modified.As(item, newItem));
|
||||
|
||||
itemDecorator.Set(newItem);
|
||||
|
||||
await mediator.Handle<UpdateEventArgs<Item<(Guid, string, ItemConfiguration)>>, bool>(new UpdateEventArgs<Item<(Guid, string,
|
||||
ItemConfiguration)>>(new Item<(Guid, string, ItemConfiguration)>((id, name, configuration))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class CreateItemActionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
NamedComponent named) : Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
[ObservableProperty]
|
||||
private int index = 0;
|
||||
|
||||
[ObservableProperty]
|
||||
private string named = $"{named}";
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Wallet.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class CreateItemHandler(IDbContextFactory<WalletContext> dbContextFactory) :
|
||||
IHandler<CreateEventArgs<(Guid, string, string, ItemConfiguration)>, bool>
|
||||
{
|
||||
public async Task<bool> Handle(CreateEventArgs<(Guid, string, string, ItemConfiguration)> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is (Guid id, string name, string category, ItemConfiguration configuration))
|
||||
{
|
||||
try
|
||||
{
|
||||
string content = JsonSerializer.Serialize(configuration);
|
||||
ItemEntry itemEntry = new()
|
||||
{
|
||||
Id = id,
|
||||
Name = name,
|
||||
Category = category
|
||||
};
|
||||
|
||||
itemEntry.Blobs.Add(new()
|
||||
{
|
||||
Data = Encoding.UTF8.GetBytes(content),
|
||||
DateTime = DateTime.Now,
|
||||
Type = 0,
|
||||
});
|
||||
|
||||
using WalletContext context = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||
EntityEntry<ItemEntry>? result = await context.AddAsync(itemEntry, cancellationToken);
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
if (result is not null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System.Text;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class CreateWalletHandler(IWalletFactory componentFactory,
|
||||
IPublisher publisher) :
|
||||
IHandler<CreateEventArgs<Wallet<(string, string)>>, bool>
|
||||
{
|
||||
public async Task<bool> Handle(CreateEventArgs<Wallet<(string, string)>> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is Wallet <(string, string)> Wallet)
|
||||
{
|
||||
if (Wallet.Value is (string name, string password) &&
|
||||
name is { Length: > 0 } &&
|
||||
password is { Length: > 0 })
|
||||
{
|
||||
if (componentFactory.Create(name) is IComponentHost host)
|
||||
{
|
||||
ISecurityKeyFactory keyFactory = host.Services.GetRequiredService<ISecurityKeyFactory>();
|
||||
IDecoratorService<SecurityKey> secureKeyStore = host.Services.GetRequiredService<IDecoratorService<SecurityKey>>();
|
||||
IWalletStorageFactory WalletStorageFactory = host.Services.GetRequiredService<IWalletStorageFactory>();
|
||||
|
||||
if (keyFactory.Create(Encoding.UTF8.GetBytes(password)) is SecurityKey key)
|
||||
{
|
||||
secureKeyStore.Set(key);
|
||||
|
||||
if (await WalletStorageFactory.Create(name, key))
|
||||
{
|
||||
IWritableConfiguration<WalletConfiguration> configuration =
|
||||
host.Services.GetRequiredService<IWritableConfiguration<WalletConfiguration>>();
|
||||
|
||||
configuration.Write(args => args.Key = $"{Convert.ToBase64String(key.Salt)}:{Convert.ToBase64String(key.EncryptedKey)}:{Convert.ToBase64String(key.DecryptedKey)}");
|
||||
host.Start();
|
||||
|
||||
publisher.Publish(Activated.As(host), cancellationToken);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class CreateWalletNavigationViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) :
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
IMainNavigationViewModel;
|
||||
@@ -0,0 +1,26 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class CreateWalletViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IPublisher publisher,
|
||||
IMediator mediator,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) :
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
IPrimaryConfirmation
|
||||
{
|
||||
[MaybeNull]
|
||||
[ObservableProperty]
|
||||
private string name;
|
||||
|
||||
[MaybeNull]
|
||||
[ObservableProperty]
|
||||
private string password;
|
||||
|
||||
public async Task<bool> Confirm() =>
|
||||
await Mediator.Handle<CreateEventArgs<Wallet<(string, string)>>, bool>(Create.As(new Wallet<(string, string)>((Name, Password))));
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record CurrencyEntryConfiguration :
|
||||
ItemEntryConfiguration
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record DateEntryConfiguration :
|
||||
ItemEntryConfiguration
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class DateEntryViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
ItemState state,
|
||||
ItemEntryConfiguration configuration,
|
||||
string key,
|
||||
object value,
|
||||
double width) : ItemEntryViewModel(provider, factory, mediator, publisher, subscriber, disposer, state, configuration, key, value, width);
|
||||
@@ -0,0 +1,31 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class DateEntryViewModelHandler(IServiceFactory serviceFactory) :
|
||||
IHandler<CreateEventArgs<DateEntryConfiguration>, IItemEntryViewModel?>
|
||||
{
|
||||
public Task<IItemEntryViewModel?> Handle(CreateEventArgs<DateEntryConfiguration> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is DateEntryConfiguration configuration)
|
||||
{
|
||||
string? label = configuration.Label;
|
||||
|
||||
if (!DateTimeOffset.TryParse($"{configuration.Value}", out DateTimeOffset value))
|
||||
{
|
||||
value = DateTimeOffset.Now;
|
||||
}
|
||||
|
||||
double? width = configuration.Width;
|
||||
|
||||
if (serviceFactory.Create<DateEntryViewModel>([.. args.Parameters, configuration, label, value, width])
|
||||
is DateEntryViewModel viewModel)
|
||||
{
|
||||
return Task.FromResult<IItemEntryViewModel?>(viewModel);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult<IItemEntryViewModel?>(default);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class DeleteItemActionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
[RelayCommand]
|
||||
public void Invoke() => Publisher.Publish(Delete.As<Item>());
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class DigitRule :
|
||||
IPasswordRule
|
||||
{
|
||||
public int CalculateScore(string password) =>
|
||||
Regex().IsMatch(password) ? 2 : 0;
|
||||
|
||||
[GeneratedRegex(@"\d")]
|
||||
private static partial Regex Regex();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class DismissItemActionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
[RelayCommand]
|
||||
public void Invoke() => Publisher.Publish(Cancel.As<Item>());
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class DiversityBonusRule :
|
||||
IPasswordRule
|
||||
{
|
||||
public int CalculateScore(string password)
|
||||
{
|
||||
bool hasUppercase = UppercaseRegex().IsMatch(password);
|
||||
bool hasLowercase = LowercaseRegex().IsMatch(password);
|
||||
bool hasDigit = DigitRegex().IsMatch(password);
|
||||
bool hasSpecialChar = SpecialCharRegex().IsMatch(password);
|
||||
|
||||
return (hasUppercase && hasLowercase && hasDigit && hasSpecialChar) ? 2 : 0;
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"[A-Z]")]
|
||||
private static partial Regex UppercaseRegex();
|
||||
|
||||
[GeneratedRegex(@"[a-z]")]
|
||||
private static partial Regex LowercaseRegex();
|
||||
|
||||
[GeneratedRegex(@"\d")]
|
||||
private static partial Regex DigitRegex();
|
||||
|
||||
[GeneratedRegex(@"[^a-zA-Z0-9]")]
|
||||
private static partial Regex SpecialCharRegex();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public record DropdownEntryConfiguration :
|
||||
ItemEntryConfiguration
|
||||
{
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public IList<string> Values { get; set; } = new List<string>();
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class DropdownEntryViewModel :
|
||||
ItemEntryCollectionViewModel<DropdownValueViewModel>
|
||||
{
|
||||
public DropdownEntryViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
IEnumerable<DropdownValueViewModel> items,
|
||||
ItemState state,
|
||||
ItemEntryConfiguration configuration,
|
||||
string key,
|
||||
object value,
|
||||
double width,
|
||||
DropdownValueViewModel selectedItem) : base(provider, factory, mediator, publisher, subscriber, disposer, items, state, configuration, key, value, width)
|
||||
{
|
||||
SelectedItem = selectedItem;
|
||||
}
|
||||
|
||||
public DropdownEntryViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
IEnumerable<DropdownValueViewModel> items,
|
||||
ItemState state,
|
||||
ItemEntryConfiguration configuration,
|
||||
string key,
|
||||
object value,
|
||||
double width) : base(provider, factory, mediator, publisher, subscriber, disposer, items, state, configuration, key, value, width)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class DropdownEntryViewModelHandler(IServiceFactory serviceFactory) :
|
||||
IHandler<CreateEventArgs<DropdownEntryConfiguration>, IItemEntryViewModel?>
|
||||
{
|
||||
public Task<IItemEntryViewModel?> Handle(CreateEventArgs<DropdownEntryConfiguration> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is DropdownEntryConfiguration configuration)
|
||||
{
|
||||
List<DropdownValueViewModel> values = [];
|
||||
foreach (string item in configuration.Values)
|
||||
{
|
||||
values.Add(serviceFactory.Create<DropdownValueViewModel>(item));
|
||||
}
|
||||
|
||||
string? label = configuration.Label;
|
||||
object? value = configuration.Value ?? "";
|
||||
double? width = configuration.Width;
|
||||
|
||||
DropdownValueViewModel? selected = values.FirstOrDefault(x => x.Value is not null && x.Value.Equals($"{value}"));
|
||||
|
||||
if (serviceFactory.Create<DropdownEntryViewModel>([values, .. args.Parameters, configuration, label, value, width, selected])
|
||||
is DropdownEntryViewModel viewModel)
|
||||
{
|
||||
return Task.FromResult<IItemEntryViewModel?>(viewModel);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult<IItemEntryViewModel?>(default);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class DropdownValueViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
string? value = null) : Observable<string>(provider, factory, mediator, publisher, subscriber, disposer, value);
|
||||
@@ -0,0 +1,15 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class EditItemActionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
[RelayCommand]
|
||||
public void Invoke() => Publisher.Publish(Update.As<Item>());
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class EmptyItemCollectionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
NamedComponent named) : Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string named = $"{named}";
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Wallet;
|
||||
|
||||
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 Wallet;
|
||||
|
||||
public record FavouriteEventArgs<TValue>(TValue Value);
|
||||
@@ -0,0 +1,29 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
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,23 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class FavouriteItemHandler(IDecoratorService<Item<(Guid, string)>> decoratorService,
|
||||
IMediator mediator) :
|
||||
INotificationHandler<FavouriteEventArgs<Item>>
|
||||
{
|
||||
public async Task Handle(FavouriteEventArgs<Item> args)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (decoratorService.Service is Item<(Guid, string)> item)
|
||||
{
|
||||
(Guid id, string name) = item.Value;
|
||||
await mediator.Handle<UpdateEventArgs<(Guid, int)>, bool>(new UpdateEventArgs<(Guid, int)>((id, 1)));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record Filter(string? Value);
|
||||
@@ -0,0 +1,41 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class FilterWalletNavigationViewModel : Observable,
|
||||
IWalletNavigationViewModel,
|
||||
INotificationHandler<ActivatedEventArgs<Wallet>>,
|
||||
INotificationHandler<DeactivatedEventArgs<Wallet>>
|
||||
{
|
||||
[ObservableProperty]
|
||||
private bool activated;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? filter;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool selected;
|
||||
|
||||
public FilterWalletNavigationViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
string? filter = null) : base(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
Filter = filter;
|
||||
}
|
||||
|
||||
public Task Handle(DeactivatedEventArgs<Wallet> args) =>
|
||||
Task.FromResult(Activated = false);
|
||||
|
||||
public Task Handle(ActivatedEventArgs<Wallet> args) =>
|
||||
Task.FromResult(Activated = true);
|
||||
|
||||
[RelayCommand]
|
||||
public void Invoke() => Publisher.Publish(Notify.As(new Filter(Filter)),
|
||||
nameof(ItemCollectionViewModel));
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class FooterViewModel :
|
||||
ObservableCollection<IMainNavigationViewModel>
|
||||
{
|
||||
public FooterViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : base(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
Add<ManageNavigationViewModel>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record HyperlinkEntryConfiguration :
|
||||
ItemEntryConfiguration
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace Wallet;
|
||||
|
||||
public interface IItemConfigurationCollection :
|
||||
IReadOnlyDictionary<string, Func<ItemConfiguration>>;
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Wallet;
|
||||
|
||||
public interface IItemEntryConfiguration
|
||||
{
|
||||
string? Label { get; set; }
|
||||
|
||||
object? Value { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace Wallet;
|
||||
|
||||
public interface IItemEntryViewModel :
|
||||
IDisposable;
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Wallet;
|
||||
|
||||
public interface IMainNavigationViewModel : IDisposable;
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Wallet;
|
||||
|
||||
public interface IPasswordRule
|
||||
{
|
||||
int CalculateScore(string password);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Wallet;
|
||||
|
||||
public interface ISecurityKeyFactory
|
||||
{
|
||||
SecurityKey? Create(byte[] phrase,
|
||||
byte[]? encryptedKey = null,
|
||||
byte[]? salt = null);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public interface IWalletComponent : IComponent;
|
||||
@@ -0,0 +1,9 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet
|
||||
{
|
||||
public interface IWalletFactory
|
||||
{
|
||||
IComponentHost? Create(string name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public interface IWalletHost : IComponentHost;
|
||||
@@ -0,0 +1,9 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public interface IWalletHostCollection :
|
||||
IEnumerable<IComponentHost>
|
||||
{
|
||||
void Add(IComponentHost host);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public interface IWalletNavigationViewModel :
|
||||
ISelectable,
|
||||
IDisposable;
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Wallet;
|
||||
|
||||
public interface IWalletStorageFactory
|
||||
{
|
||||
Task<bool> Create(string name, SecurityKey key);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class IconViewModel : Observable
|
||||
{
|
||||
public IconViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) : base(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record ImageEntryConfiguration :
|
||||
ItemEntryConfiguration
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record Item<TValue>(TValue Value);
|
||||
|
||||
public record Item;
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record ItemCategory<TValue>(TValue Value);
|
||||
|
||||
public record ItemCategory;
|
||||
@@ -0,0 +1,28 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
[Notification(typeof(CreateEventArgs<ItemCategoryNavigationViewModel>), nameof(ItemCategoryCollectionViewModel))]
|
||||
public partial class ItemCategoryCollectionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
IContentTemplate template) :
|
||||
ObservableCollection<ItemCategoryNavigationViewModel>(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
[ObservableProperty]
|
||||
private IContentTemplate template = template;
|
||||
|
||||
public override Task OnActivated()
|
||||
{
|
||||
Publisher.Publish(Notify.As(Factory.Create<WalletCommandHeaderCollection>(new List<IDisposable>
|
||||
{
|
||||
Factory.Create<BackActionViewModel>(),
|
||||
})));
|
||||
|
||||
return base.OnActivated();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class ItemCategoryNavigationViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
string name,
|
||||
bool selected = false) :
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
ISelectable,
|
||||
IRemovable
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string name = name;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool selected = selected;
|
||||
|
||||
[RelayCommand]
|
||||
public void Invoke() => Publisher.Publish(Notify.As(new ItemCategory<string>(Name)));
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
[Notification(typeof(CreateEventArgs<ItemNavigationViewModel>), nameof(ItemCollectionViewModel))]
|
||||
[Notification(typeof(InsertEventArgs<ItemNavigationViewModel>), nameof(ItemCollectionViewModel))]
|
||||
[Notification(typeof(MoveToEventArgs<ItemNavigationViewModel>), nameof(ItemCollectionViewModel))]
|
||||
[Notification(typeof(NotifyEventArgs<Search<string>>), nameof(ItemCollectionViewModel))]
|
||||
public partial class ItemCollectionViewModel :
|
||||
ObservableCollection<ItemNavigationViewModel>,
|
||||
INotificationHandler<NotifyEventArgs<Filter>>,
|
||||
INotificationHandler<NotifyEventArgs<Search<string>>>,
|
||||
IBackStack
|
||||
{
|
||||
[ObservableProperty]
|
||||
public string? named;
|
||||
|
||||
private WalletViewModelConfiguration configuration;
|
||||
|
||||
public ItemCollectionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
IContentTemplate template,
|
||||
NamedComponent named,
|
||||
WalletViewModelConfiguration configuration,
|
||||
string? filter = null) : base(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
Template = template;
|
||||
Named = $"{named}";
|
||||
|
||||
this.configuration = configuration with { Filter = filter };
|
||||
}
|
||||
|
||||
public IContentTemplate Template { get; set; }
|
||||
|
||||
public Task Handle(NotifyEventArgs<Filter> args)
|
||||
{
|
||||
if (args.Value is Filter filter)
|
||||
{
|
||||
configuration = configuration with { Filter = filter.Value };
|
||||
Fetch(true);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Handle(NotifyEventArgs<Search<string>> args)
|
||||
{
|
||||
if (args.Value is Search<string> search)
|
||||
{
|
||||
configuration = configuration with { Query = search.Value };
|
||||
Fetch(true);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task OnActivated()
|
||||
{
|
||||
Publisher.Publish(Notify.As(Factory.Create<WalletCommandHeaderCollection>(new List<IDisposable>
|
||||
{
|
||||
Factory.Create<CreateItemActionViewModel>(),
|
||||
Factory.Create<SearchWalletActionViewModel>(),
|
||||
})));
|
||||
|
||||
return base.OnActivated();
|
||||
}
|
||||
|
||||
protected override SynchronizeExpression BuildAggregateExpression() =>
|
||||
new(Synchronize.As<ItemNavigationViewModel, WalletViewModelConfiguration>(configuration));
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class ItemCommandHeaderCollection(IList<IDisposable> list) :
|
||||
ReadOnlyCollection<IDisposable>(list);
|
||||
@@ -0,0 +1,31 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class ItemCommandHeaderViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
IContentTemplate template) :
|
||||
ObservableCollection(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
INotificationHandler<NotifyEventArgs<ItemCommandHeaderCollection>>
|
||||
{
|
||||
public IContentTemplate Template { get; set; } = template;
|
||||
|
||||
public Task Handle(NotifyEventArgs<ItemCommandHeaderCollection> args)
|
||||
{
|
||||
Clear();
|
||||
|
||||
if (args.Value is ItemCommandHeaderCollection commandCollection)
|
||||
{
|
||||
foreach (IDisposable command in commandCollection)
|
||||
{
|
||||
Add(command);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class ItemConfigurationCollection(IDictionary<string, Func<ItemConfiguration>> dictionary) :
|
||||
ReadOnlyDictionary<string, Func<ItemConfiguration>>(dictionary),
|
||||
IItemConfigurationCollection;
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record ItemContent;
|
||||
@@ -0,0 +1,30 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
[Notification(typeof(CreateEventArgs<ItemSectionViewModel>), nameof(ItemContentViewModel))]
|
||||
public partial class ItemContentViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory, IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
IContentTemplate template) :
|
||||
ObservableCollection<ItemSectionViewModel>(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
IItemEntryViewModel,
|
||||
INotificationHandler<NotifyEventArgs<ItemCategory<string>>>
|
||||
{
|
||||
public IContentTemplate Template { get; set; } = template;
|
||||
|
||||
public Task Handle(NotifyEventArgs<ItemCategory<string>> args)
|
||||
{
|
||||
if (args.Value is ItemCategory<string> category)
|
||||
{
|
||||
if (category.Value is string value)
|
||||
{
|
||||
Fetch(() => new SynchronizeExpression(new SynchronizeEventArgs<IItemEntryViewModel, string>(value)), true);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class ItemCreatedHandler(IServiceProvider serviceProvider,
|
||||
ICache<Item<(Guid, string)>> cache,
|
||||
IPublisher publisher) :
|
||||
INotificationHandler<CreatedEventArgs<Item<(Guid, string)>>>
|
||||
{
|
||||
public Task Handle(CreatedEventArgs<Item<(Guid, string)>> args)
|
||||
{
|
||||
if (args.Value is Item<(Guid, string)> item)
|
||||
{
|
||||
(Guid id, string name) = item.Value;
|
||||
|
||||
IServiceScope serviceScope = serviceProvider.CreateScope();
|
||||
IServiceFactory serviceFactory = serviceScope.ServiceProvider.GetRequiredService<IServiceFactory>();
|
||||
IDecoratorService<Item<(Guid, string)>> decoratorService = serviceScope.ServiceProvider.GetRequiredService<IDecoratorService<Item<(Guid, string)>>>();
|
||||
|
||||
if (serviceFactory.Create<ItemNavigationViewModel>(id, name, "Description", true)
|
||||
is ItemNavigationViewModel viewModel)
|
||||
{
|
||||
cache.Add(item);
|
||||
|
||||
int index = cache.IndexOf(item);
|
||||
decoratorService.Set(item);
|
||||
|
||||
publisher.Publish(Insert.As(index, viewModel),
|
||||
nameof(ItemCollectionViewModel));
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class ItemEntryCollectionViewModel<TItem> :
|
||||
ObservableCollection<TItem, string, object>,
|
||||
IItemEntryViewModel,
|
||||
INotificationHandler<UpdateEventArgs<Item>>,
|
||||
INotificationHandler<ConfirmEventArgs<Item>>,
|
||||
INotificationHandler<CancelEventArgs<Item>>
|
||||
where TItem : notnull,
|
||||
IDisposable
|
||||
{
|
||||
[ObservableProperty]
|
||||
private ItemState state;
|
||||
|
||||
private readonly ItemEntryConfiguration configuration;
|
||||
|
||||
public ItemEntryCollectionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
ItemState state,
|
||||
ItemEntryConfiguration configuration,
|
||||
string key,
|
||||
object value,
|
||||
double width) : base(provider, factory, mediator, publisher, subscriber, disposer, key, value)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
|
||||
State = state;
|
||||
Width = width;
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
private double width;
|
||||
|
||||
|
||||
public ItemEntryCollectionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
IEnumerable<TItem> items,
|
||||
ItemState state,
|
||||
ItemEntryConfiguration configuration,
|
||||
string key,
|
||||
object value,
|
||||
double width) : base(provider, factory, mediator, publisher, subscriber, disposer, items, key, value)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
|
||||
State = state;
|
||||
Width = width;
|
||||
}
|
||||
|
||||
protected override void OnValueChanged()
|
||||
{
|
||||
if (configuration is not null)
|
||||
{
|
||||
configuration.Value = Value;
|
||||
}
|
||||
}
|
||||
|
||||
public Task Handle(UpdateEventArgs<Item> args) =>
|
||||
Task.FromResult(State = ItemState.Write);
|
||||
|
||||
public Task Handle(CancelEventArgs<Item> args)
|
||||
{
|
||||
Revert();
|
||||
|
||||
State = ItemState.Read;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Handle(ConfirmEventArgs<Item> args)
|
||||
{
|
||||
Commit();
|
||||
|
||||
State = ItemState.Read;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
[JsonDerivedType(typeof(DropdownEntryConfiguration), typeDiscriminator: "Dropdown")]
|
||||
[JsonDerivedType(typeof(MaskedTextEntryConfiguration), typeDiscriminator: "MaskedText")]
|
||||
[JsonDerivedType(typeof(NumberEntryConfiguration), typeDiscriminator: "Number")]
|
||||
[JsonDerivedType(typeof(PasswordEntryConfiguration), typeDiscriminator: "Password")]
|
||||
[JsonDerivedType(typeof(TextEntryConfiguration), typeDiscriminator: "Text")]
|
||||
[JsonDerivedType(typeof(ImageEntryConfiguration), typeDiscriminator: "Image")]
|
||||
[JsonDerivedType(typeof(AttachmentEntryConfiguration), typeDiscriminator: "Attachment")]
|
||||
[JsonDerivedType(typeof(MultilineTextEntryConfiguration), typeDiscriminator: "MultilineText")]
|
||||
[JsonDerivedType(typeof(CurrencyEntryConfiguration), typeDiscriminator: "Currency")]
|
||||
[JsonDerivedType(typeof(DateEntryConfiguration), typeDiscriminator: "Date")]
|
||||
[JsonDerivedType(typeof(HyperlinkEntryConfiguration), typeDiscriminator: "Hyperlink")]
|
||||
[JsonDerivedType(typeof(PinEntryConfiguration), typeDiscriminator: "Pin")]
|
||||
public record ItemEntryConfiguration :
|
||||
IItemEntryConfiguration
|
||||
{
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? Label { get; set; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public object? Value { get; set; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public double? Width { get; set; } = 296;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class ItemEntryViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
ItemState state,
|
||||
ItemEntryConfiguration configuration,
|
||||
string key,
|
||||
object value,
|
||||
double width) :
|
||||
Observable<string, object>(provider, factory, mediator, publisher, subscriber, disposer, key, value),
|
||||
IItemEntryViewModel,
|
||||
INotificationHandler<UpdateEventArgs<Item>>,
|
||||
INotificationHandler<ConfirmEventArgs<Item>>,
|
||||
INotificationHandler<CancelEventArgs<Item>>
|
||||
{
|
||||
[ObservableProperty]
|
||||
private ItemState state = state;
|
||||
|
||||
[ObservableProperty]
|
||||
private double width = width;
|
||||
|
||||
public Task Handle(UpdateEventArgs<Item> args) =>
|
||||
Task.FromResult(State = ItemState.Write);
|
||||
|
||||
public Task Handle(CancelEventArgs<Item> args)
|
||||
{
|
||||
Revert();
|
||||
|
||||
State = ItemState.Read;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Handle(ConfirmEventArgs<Item> args)
|
||||
{
|
||||
Commit();
|
||||
|
||||
State = ItemState.Read;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected override void OnValueChanged() =>
|
||||
configuration.Value = Value;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record ItemHeader<TValue>(TValue Value);
|
||||
|
||||
public record ItemHeader;
|
||||
@@ -0,0 +1,74 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class ItemHeaderViewModel :
|
||||
Observable<string, string>,
|
||||
INotificationHandler<UpdateEventArgs<Item>>,
|
||||
INotificationHandler<ConfirmEventArgs<Item>>,
|
||||
INotificationHandler<CancelEventArgs<Item>>,
|
||||
IHandler<ValidationEventArgs<ItemHeader>, bool>,
|
||||
IHandler<ConfirmEventArgs<ItemHeader>, string?>,
|
||||
INotificationHandler<NotifyEventArgs<ItemCategory<string>>>
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string? category;
|
||||
|
||||
[ObservableProperty]
|
||||
private ItemState state;
|
||||
|
||||
public ItemHeaderViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
ItemState state,
|
||||
string key,
|
||||
string value) : base(provider, factory, mediator, publisher, subscriber, disposer, key, value)
|
||||
{
|
||||
State = state;
|
||||
Value = value;
|
||||
|
||||
Track(nameof(Value), () => Value, newValue => Value = newValue);
|
||||
}
|
||||
|
||||
public Task<bool> Handle(ValidationEventArgs<ItemHeader> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
public Task Handle(UpdateEventArgs<Item> args) =>
|
||||
Task.FromResult(State = ItemState.Write);
|
||||
|
||||
public Task Handle(CancelEventArgs<Item> args)
|
||||
{
|
||||
Revert();
|
||||
|
||||
State = ItemState.Read;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Handle(ConfirmEventArgs<Item> args)
|
||||
{
|
||||
Commit();
|
||||
|
||||
State = ItemState.Read;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Handle(NotifyEventArgs<ItemCategory<string>> args)
|
||||
{
|
||||
if (args.Value is ItemCategory<string> category)
|
||||
{
|
||||
Category = category.Value;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<string> Handle(ConfirmEventArgs<ItemHeader> args,
|
||||
CancellationToken cancellationToken) => Task.FromResult(Value);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class ItemModifiedHandler(IServiceProvider serviceProvider,
|
||||
IPublisher publisher) :
|
||||
INotificationHandler<ModifiedEventArgs<Item<(Guid, string)>>>
|
||||
{
|
||||
public Task Handle(ModifiedEventArgs<Item<(Guid, string)>> args)
|
||||
{
|
||||
Item<(Guid, string)> oldItem = args.OldView;
|
||||
Item<(Guid, string)> newItem = args.NewValue;
|
||||
|
||||
ICache<Item<(Guid, string)>> cache = serviceProvider.GetRequiredService<ICache<Item<(Guid, string)>>>();
|
||||
if (cache.TryGetValue(oldItem, out Item<(Guid, string)>? cachedItem))
|
||||
{
|
||||
if (cachedItem is not null)
|
||||
{
|
||||
IServiceScope serviceScope = serviceProvider.CreateScope();
|
||||
IDecoratorService<Item<(Guid, string)>> decoratorService = serviceScope.ServiceProvider.GetRequiredService<IDecoratorService<Item<(Guid, string)>>>();
|
||||
|
||||
int oldIndex = cache.IndexOf(cachedItem);
|
||||
cache.Remove(cachedItem);
|
||||
|
||||
cache.Add(newItem);
|
||||
|
||||
int newIndex = cache.IndexOf(newItem);
|
||||
decoratorService.Set(newItem);
|
||||
|
||||
publisher.Publish(MoveTo.As<ItemNavigationViewModel>(oldIndex, newIndex),
|
||||
nameof(ItemCollectionViewModel));
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class ItemNavigationViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
IContentTemplate template,
|
||||
NamedComponent named,
|
||||
Guid id,
|
||||
string name = "",
|
||||
string description = "",
|
||||
string category = "",
|
||||
bool selected = false,
|
||||
bool favourite = false,
|
||||
bool archived = false) :
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
INotificationHandler<ArchiveEventArgs<Item>>,
|
||||
INotificationHandler<UnarchiveEventArgs<Item>>,
|
||||
INotificationHandler<FavouriteEventArgs<Item>>,
|
||||
INotificationHandler<UnfavouriteEventArgs<Item>>,
|
||||
INotificationHandler<NotifyEventArgs<ItemHeader<string>>>,
|
||||
IKeyed<Guid>,
|
||||
ISelectable,
|
||||
IRemovable
|
||||
{
|
||||
[ObservableProperty]
|
||||
private bool archived = archived;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? category = category;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? description = description;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool favourite = favourite;
|
||||
|
||||
[ObservableProperty]
|
||||
private Guid id = id;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? name = name;
|
||||
|
||||
[ObservableProperty]
|
||||
private string named = $"{named}";
|
||||
|
||||
[ObservableProperty]
|
||||
private bool selected = selected;
|
||||
|
||||
public IContentTemplate Template { get; set; } = template;
|
||||
|
||||
public Task Handle(ArchiveEventArgs<Item> args) =>
|
||||
Task.Run(Dispose);
|
||||
|
||||
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);
|
||||
|
||||
public Task Handle(NotifyEventArgs<ItemHeader<string>> args)
|
||||
{
|
||||
if (args.Value is ItemHeader<string> header)
|
||||
{
|
||||
Name = header.Value;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record ItemSection;
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record ItemSectionConfiguration
|
||||
{
|
||||
public IList<ItemEntryConfiguration> Entries { get; set; } = new List<ItemEntryConfiguration>();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
[Notification(typeof(CreateEventArgs<IItemEntryViewModel>), nameof(Id))]
|
||||
public partial class ItemSectionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
IContentTemplate template,
|
||||
string id) : ObservableCollection<IItemEntryViewModel>(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
IKeyed<string>
|
||||
{
|
||||
public string Id => id;
|
||||
|
||||
public IContentTemplate Template { get; set; } = template;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Wallet;
|
||||
|
||||
public enum ItemState
|
||||
{
|
||||
New,
|
||||
Read,
|
||||
Write
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class ItemViewModel :
|
||||
ObservableCollection,
|
||||
INotificationHandler<ConfirmEventArgs<Item>>,
|
||||
INotificationHandler<UpdateEventArgs<Item>>,
|
||||
INotificationHandler<CancelEventArgs<Item>>
|
||||
{
|
||||
[ObservableProperty]
|
||||
private bool archived;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool favourite;
|
||||
|
||||
[ObservableProperty]
|
||||
private ItemState state;
|
||||
|
||||
[ObservableProperty]
|
||||
private string named;
|
||||
|
||||
[ObservableProperty]
|
||||
private string name;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool fromCategory;
|
||||
|
||||
public ItemViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
IContentTemplate template,
|
||||
NamedComponent named,
|
||||
ItemState state = ItemState.Read,
|
||||
bool fromCategory = false,
|
||||
string name = "",
|
||||
bool favourite = false,
|
||||
bool archived = false) : base(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
Template = template;
|
||||
Named = $"{named}";
|
||||
State = state;
|
||||
FromCategory = fromCategory;
|
||||
Favourite = favourite;
|
||||
Archived = archived;
|
||||
Name = name;
|
||||
|
||||
Add<ItemHeaderViewModel>("", name, state);
|
||||
Add<ItemContentViewModel>();
|
||||
}
|
||||
|
||||
public IContentTemplate Template { get; set; }
|
||||
|
||||
public Task Handle(UpdateEventArgs<Item> args)
|
||||
{
|
||||
Publisher.Publish(Notify.As(Factory.Create<ItemCommandHeaderCollection>(new List<IDisposable>
|
||||
{
|
||||
Factory.Create<ConfirmItemActionViewModel>(),
|
||||
Factory.Create<DismissItemActionViewModel>(),
|
||||
})));
|
||||
|
||||
State = ItemState.Write;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
Publisher.Publish(Notify.As(Factory.Create<ItemCommandHeaderCollection>(new
|
||||
List<IDisposable>())));
|
||||
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
public Task Handle(CancelEventArgs<Item> args)
|
||||
{
|
||||
Publisher.Publish(Notify.As(Factory.Create<ItemCommandHeaderCollection>(new List<IDisposable>
|
||||
{
|
||||
Factory.Create<EditItemActionViewModel>(),
|
||||
Factory.Create<ArchiveItemActionViewModel>(),
|
||||
})));
|
||||
|
||||
State = ItemState.Read;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Handle(ConfirmEventArgs<Item> args)
|
||||
{
|
||||
Publisher.Publish(Notify.As(Factory.Create<ItemCommandHeaderCollection>(new List<IDisposable>
|
||||
{
|
||||
Factory.Create<FavouriteItemActionViewModel>(Favourite),
|
||||
Factory.Create<EditItemActionViewModel>(),
|
||||
Factory.Create<ArchiveItemActionViewModel>(),
|
||||
})));
|
||||
|
||||
Publisher.Publish(Confirm.As<Item>(),
|
||||
State is ItemState.New ? nameof(ItemState.New) : nameof(ItemState.Write));
|
||||
|
||||
State = ItemState.Read;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task OnActivated()
|
||||
{
|
||||
if (Archived)
|
||||
{
|
||||
Publisher.Publish(Notify.As(Factory.Create<ItemCommandHeaderCollection>(new List<IDisposable>
|
||||
{
|
||||
Factory.Create<UnarchiveItemActionViewModel>(),
|
||||
})));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (State is ItemState.Write or ItemState.New)
|
||||
{
|
||||
Publisher.Publish(Notify.As(Factory.Create<ItemCommandHeaderCollection>(new List<IDisposable>
|
||||
{
|
||||
Factory.Create<ConfirmItemActionViewModel>(),
|
||||
Factory.Create<DismissItemActionViewModel>(),
|
||||
})));
|
||||
}
|
||||
else
|
||||
{
|
||||
Publisher.Publish(Notify.As(Factory.Create<ItemCommandHeaderCollection>(new List<IDisposable>
|
||||
{
|
||||
Factory.Create<FavouriteItemActionViewModel>(Favourite),
|
||||
Factory.Create<EditItemActionViewModel>(),
|
||||
Factory.Create<ArchiveItemActionViewModel>(),
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
return base.OnActivated();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Wallet;
|
||||
|
||||
public class LengthRule :
|
||||
IPasswordRule
|
||||
{
|
||||
public int CalculateScore(string password) =>
|
||||
password.Length >= 8 ? 5 : 0;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class LowercaseRule :
|
||||
IPasswordRule
|
||||
{
|
||||
public int CalculateScore(string password) =>
|
||||
Regex().IsMatch(password) ? 2 : 0;
|
||||
|
||||
|
||||
[GeneratedRegex(@"[a-z]")]
|
||||
private static partial Regex Regex();
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
[Notification(typeof(CreateEventArgs<IMainNavigationViewModel>), nameof(MainViewModel))]
|
||||
public partial class MainViewModel :
|
||||
ObservableCollection<IMainNavigationViewModel>
|
||||
{
|
||||
[ObservableProperty]
|
||||
private FooterViewModel footer;
|
||||
|
||||
public MainViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
IContentTemplate template,
|
||||
FooterViewModel footer) : base(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
Template = template;
|
||||
Footer = footer;
|
||||
}
|
||||
|
||||
public IContentTemplate Template { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class MainWindowViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) :
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer);
|
||||
@@ -0,0 +1,12 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class ManageNavigationViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) :
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer),
|
||||
IMainNavigationViewModel;
|
||||
@@ -0,0 +1,23 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class ManageViewModel :
|
||||
ObservableCollection,
|
||||
IMainNavigationViewModel
|
||||
{
|
||||
public ManageViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
IContentTemplate template) : base(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
Template = template;
|
||||
|
||||
Add<CreateWalletNavigationViewModel>();
|
||||
}
|
||||
|
||||
public IContentTemplate Template { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public record MaskedTextEntryConfiguration :
|
||||
ItemEntryConfiguration
|
||||
{
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? Pattern { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class MaskedTextEntryViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
ItemState state,
|
||||
ItemEntryConfiguration configuration,
|
||||
string pattern,
|
||||
string key,
|
||||
object value,
|
||||
double width) : ItemEntryViewModel(provider, factory, mediator, publisher, subscriber, disposer, state, configuration, key, value, width)
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string pattern = pattern;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class MaskedTextEntryViewModelHandler(IServiceFactory serviceFactory) :
|
||||
IHandler<CreateEventArgs<MaskedTextEntryConfiguration>, IItemEntryViewModel?>
|
||||
{
|
||||
public Task<IItemEntryViewModel?> Handle(CreateEventArgs<MaskedTextEntryConfiguration> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is MaskedTextEntryConfiguration configuration)
|
||||
{
|
||||
string? label = configuration.Label;
|
||||
object? value = configuration.Value ?? "";
|
||||
double? width = configuration.Width;
|
||||
|
||||
if (serviceFactory.Create<MaskedTextEntryViewModel>([.. args.Parameters, configuration, configuration.Pattern, label, value, width])
|
||||
is MaskedTextEntryViewModel viewModel)
|
||||
{
|
||||
return Task.FromResult<IItemEntryViewModel?>(viewModel);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult<IItemEntryViewModel?>(default);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record MultilineTextEntryConfiguration :
|
||||
ItemEntryConfiguration
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class MultilineTextEntryViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
ItemState state,
|
||||
ItemEntryConfiguration configuration,
|
||||
string key,
|
||||
object value,
|
||||
double width) : ItemEntryViewModel(provider, factory, mediator, publisher, subscriber, disposer, state, configuration, key, value, width);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class MultilineTextEntryViewModelHandler(IServiceFactory serviceFactory) :
|
||||
IHandler<CreateEventArgs<MultilineTextEntryConfiguration>, IItemEntryViewModel?>
|
||||
{
|
||||
public Task<IItemEntryViewModel?> Handle(CreateEventArgs<MultilineTextEntryConfiguration> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is MultilineTextEntryConfiguration configuration)
|
||||
{
|
||||
string? label = configuration.Label;
|
||||
object? value = configuration.Value ?? "";
|
||||
double? width = configuration.Width;
|
||||
|
||||
if (serviceFactory.Create<MultilineTextEntryViewModel>([.. args.Parameters, configuration, label, value, width])
|
||||
is MultilineTextEntryViewModel viewModel)
|
||||
{
|
||||
return Task.FromResult<IItemEntryViewModel?>(viewModel);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult<IItemEntryViewModel?>(default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record NumberEntryConfiguration :
|
||||
ItemEntryConfiguration
|
||||
{
|
||||
public int MinLength { get; set; }
|
||||
|
||||
public int MaxLength { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Text;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class OpenWalletHandler(IConfigurationDescriptor<WalletConfiguration> descriptor,
|
||||
ISecurityKeyFactory securityKeyFactory,
|
||||
IWalletStorageFactory WalletStorageFactory) :
|
||||
IHandler<ActivateEventArgs<Wallet<string>>, bool>
|
||||
{
|
||||
public async Task<bool> Handle(ActivateEventArgs<Wallet<string>> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is Wallet<string> Wallet &&
|
||||
descriptor.Name is { Length: > 0 } name &&
|
||||
Wallet.Value is { Length: > 0 } password)
|
||||
{
|
||||
WalletConfiguration configuration = descriptor.Value;
|
||||
if (configuration.Key?.Split(':') is { Length: >= 2 } keyPart)
|
||||
{
|
||||
byte[]? salt = Convert.FromBase64String(keyPart[0]);
|
||||
byte[]? encryptedKey = Convert.FromBase64String(keyPart[1]);
|
||||
|
||||
if (securityKeyFactory.Create(Encoding.UTF8.GetBytes(password), encryptedKey, salt) is SecurityKey key)
|
||||
{
|
||||
if (await WalletStorageFactory.Create(name, key))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class OpenWalletViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
string name) :
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string? name = name;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? password;
|
||||
|
||||
[RelayCommand]
|
||||
private async Task Invoke()
|
||||
{
|
||||
if (Password is { Length: > 0 })
|
||||
{
|
||||
if (await Mediator.Handle<ActivateEventArgs<Wallet<string>>, bool>(Activate.As(new Wallet<string>(Password))))
|
||||
{
|
||||
Publisher.Publish(Opened.As<Wallet>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record Opened
|
||||
{
|
||||
public static OpenedEventArgs<TValue> As<TValue>(TValue value) => new(value);
|
||||
|
||||
public static OpenedEventArgs<TValue> As<TValue>() where TValue : new() => new(new TValue());
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record OpenedEventArgs<TValue>(TValue? Value = default);
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Wallet;
|
||||
|
||||
public record PasswordEntryConfiguration :
|
||||
ItemEntryConfiguration
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public partial class PasswordEntryViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
ItemState state,
|
||||
ItemEntryConfiguration configuration,
|
||||
string key,
|
||||
object value,
|
||||
double width) : ItemEntryViewModel(provider, factory, mediator, publisher, subscriber, disposer, state, configuration, key, value, width);
|
||||
@@ -0,0 +1,26 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Wallet;
|
||||
|
||||
public class PasswordEntryViewModelHandler(IServiceFactory serviceFactory) :
|
||||
IHandler<CreateEventArgs<PasswordEntryConfiguration>, IItemEntryViewModel?>
|
||||
{
|
||||
public Task<IItemEntryViewModel?> Handle(CreateEventArgs<PasswordEntryConfiguration> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is PasswordEntryConfiguration configuration)
|
||||
{
|
||||
string? label = configuration.Label;
|
||||
object? value = configuration.Value ?? "";
|
||||
double? width = configuration.Width;
|
||||
|
||||
if (serviceFactory.Create<PasswordEntryViewModel>([.. args.Parameters, configuration, label, value, width])
|
||||
is PasswordEntryViewModel viewModel)
|
||||
{
|
||||
return Task.FromResult<IItemEntryViewModel?>(viewModel);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult<IItemEntryViewModel?>(default);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user