12using System.Collections.ObjectModel;
13using CommunityToolkit.Mvvm.ComponentModel;
15using Microsoft.Maui.Controls.Shapes;
25 private readonly Dictionary<string, Contract> contractsMap = [];
27 private readonly TaskCompletionSource<Contract?>? selection;
28 private Contract? selectedContract =
null;
41 this.contractsListMode = Args.
Mode;
45 switch (this.contractsListMode)
59 this.Description =
ServiceRef.
Localizer[nameof(AppResources.TokenCreationTemplatesInfoText)];
68 await base.OnInitialize();
71 this.ShowContractsMissing =
false;
73 await this.LoadContracts();
75 ServiceRef.NotificationService.OnNewNotification += this.NotificationService_OnNewNotification;
76 ServiceRef.NotificationService.OnNotificationsDeleted += this.NotificationService_OnNotificationsDeleted;
82 await base.OnAppearing();
84 if (this.selection is not
null && this.selection.Task.IsCompleted)
94 ServiceRef.NotificationService.OnNewNotification -= this.NotificationService_OnNewNotification;
95 ServiceRef.NotificationService.OnNotificationsDeleted -= this.NotificationService_OnNotificationsDeleted;
99 this.ShowContractsMissing =
false;
100 this.contractsMap.Clear();
103 this.selection?.TrySetResult(this.selectedContract);
105 await base.OnDispose();
112 private string? title;
118 private string? description;
130 private bool showContractsMissing;
135 public ObservableCollection<IUniqueItem>
Categories {
get; } = [];
142 MainThread.BeginInvokeOnMainThread(() =>
146 int Index = this.
Categories.IndexOf(Category);
149 this.Categories.Insert(++Index,
Contract);
163 MainThread.BeginInvokeOnMainThread(async () =>
169 case SelectContractAction.ViewContract:
170 if (this.contractsListMode == ContractsListMode.Contracts)
174 Contract updatedContract = await ServiceRef.XmppService.GetContract(ContractId);
175 ViewContractNavigationArgs Args = new(updatedContract, false);
176 await ServiceRef.UiService.GoToAsync(nameof(ViewContractPage), Args, BackMethod.Pop);
178 catch (ItemNotFoundException)
180 if(await ServiceRef.UiService.DisplayAlert(
181 ServiceRef.Localizer[nameof(AppResources.ErrorTitle)], ServiceRef.Localizer[nameof(AppResources.ContractCouldNotBeFound)],
182 ServiceRef.Localizer[nameof(AppResources.Yes)],
183 ServiceRef.Localizer[nameof(AppResources.No)]))
185 await Database.FindDelete<ContractReference>(new FilterFieldEqualTo(
"ContractId", ContractId));
186 await this.LoadContracts();
191 ServiceRef.LogService.LogException(ex);
192 await ServiceRef.UiService.DisplayAlert(
193 ServiceRef.Localizer[nameof(AppResources.ErrorTitle)], ex.Message,
194 ServiceRef.Localizer[nameof(AppResources.Ok)]);
199 await ServiceRef.ContractOrchestratorService.OpenContract(ContractId, ServiceRef.Localizer[nameof(AppResources.ReferencedID)], null);
205 case SelectContractAction.Select:
206 this.selectedContract = Contract;
208 this.selection?.TrySetResult(Contract);
215 private async Task LoadContracts()
219 IEnumerable<ContractReference> ContractReferences;
220 bool ShowAdditionalEvents;
223 switch (this.contractsListMode)
230 ShowAdditionalEvents =
true;
238 ShowAdditionalEvents =
false;
246 Dictionary<CaseInsensitiveString, bool> ContractIds = [];
247 LinkedList<ContractReference> TokenCreationTemplates = [];
254 TokenCreationTemplates.AddLast(Ref);
260 if (!ContractIds.ContainsKey(TokenTemplateId))
267 ContractId = Contract.ContractId
278 TokenCreationTemplates.AddLast(Ref);
284 ContractReferences = TokenCreationTemplates;
285 ShowAdditionalEvents =
false;
292 SortedDictionary<string, List<ContractModel>> ContractsByCategory =
new(StringComparer.CurrentCultureIgnoreCase);
321 List<NotificationEvent> Events2 = [];
322 List<NotificationEvent>? Petitions =
null;
329 Petitions.Add(Petition);
335 if (Petitions is not
null)
336 EventsByCategory[Ref.
ContractId] = [.. Petitions];
338 Events = [.. Events2];
346 if (!ContractsByCategory.TryGetValue(Category, out List<ContractModel>? Contracts2))
349 ContractsByCategory[Category] = Contracts2;
352 Contracts2.Add(Item);
355 List<IUniqueItem> NewCategories = [];
357 if (ShowAdditionalEvents)
363 Geometry Icon = await Event.GetCategoryIcon();
364 string Description = await Event.GetDescription();
366 NewCategories.Add(
new EventModel(Event.Received, Icon, Description, Event));
371 foreach (KeyValuePair<
string, List<ContractModel>> P
in ContractsByCategory)
378 P.Value.Sort(
new DateTimeDesc());
379 NewCategories.Add(
new HeaderModel(P.Key, P.Value.ToArray(), Nr));
382 MainThread.BeginInvokeOnMainThread(() =>
384 this.Categories.Clear();
387 this.Categories.Add(Item);
389 this.ShowContractsMissing = !Found;
398 private class DateTimeDesc : IComparer<ContractModel>
418 MainThread.BeginInvokeOnMainThread(() =>
422 if (Event.Type != NotificationEventType.Contracts)
425 HeaderModel? LastHeader = null;
427 foreach (IUniqueItem Group in this.Categories)
429 if (Group is HeaderModel Header)
431 else if (Group is ContractModel Contract && Contract.ContractId == Event.Category)
433 if (Contract.RemoveEvent(Event) && LastHeader is not null)
434 LastHeader.NrEvents--;
448 MainThread.BeginInvokeOnMainThread(() =>
454 if (Group is HeaderModel Header)
458 if (Contract.AddEvent(e.Event) && LastHeader is not null)
459 LastHeader.NrEvents++;
static readonly string[] TokenCreationTemplates
Array of contract templates for creating tokens.
A set of never changing property constants and helpful values.
Contains a local reference to a contract that the user has created or signed.
DateTime Created
When object was created
async Task< Contract?> GetContract()
Gets a parsed contract.
async Task SetContract(Contract Contract)
Sets a parsed contract.
bool IsTokenCreationTemplate
If the contract represents a token creation template
CaseInsensitiveString? ContractId
Contract reference
Notification event for contract petitions.
Base class that references services in the app.
static ILogService LogService
Log service.
static INotificationService NotificationService
Service for managing notifications for the user.
static ITagProfile TagProfile
TAG Profile service.
static IStringLocalizer Localizer
Localization service
static IXmppService XmppService
The XMPP service for XMPP communication.
A base class for all view models, inheriting from the BindableObject. NOTE: using this class requir...
virtual async Task GoBack()
Method called when user wants to navigate to the previous screen.
Holds navigation parameters specific to views displaying a list of contacts.
SelectContractAction Action
Action to take when a contact has been selected.
ContractsListMode Mode
What list of contracts to display.
TaskCompletionSource< Contract?>? Selection
Selection source, if selecting identity.
The view model to bind to when displaying 'my' contracts.
ObservableCollection< IUniqueItem > Categories
Holds the list of contracts to display, ordered by category.
override async Task OnDispose()
Method called when the view is disposed, and will not be used more. Use this method to unregister eve...
MyContractsViewModel(MyContractsNavigationArgs? Args)
Creates an instance of the MyContractsViewModel class.
override async Task OnAppearing()
Method called when view is appearing on the screen.
void ContractSelected(string ContractId)
Add or remove the contracts from the collection
override async Task OnInitialize()
Method called when view is initialized for the first time. Use this method to implement registration ...
void AddOrRemoveContracts(HeaderModel Category, bool Expanded)
Add or remove the contracts from the collection
The data model for a contract.
static async Task< ContractModel > Create(string ContractId, DateTime Timestamp, Contract Contract, NotificationEvent[] Events)
Creates an instance of the ContractModel class.
int NrEvents
Number of notification events associated with the contract.
string Category
Displayable category for the contract.
DateTime Timestamp
The created timestamp of the contract.
Contains the definition of a contract
string ContractId
Contract identity
Represents a case-insensitive string.
Static interface for database persistence. In order to work, a database provider has to be assigned t...
static Task< IEnumerable< object > > Find(string Collection, params string[] SortOrder)
Finds objects in a given collection.
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
This filter selects objects that conform to all child-filters provided.
This filter selects objects that have a named field equal to a given value.
SortedDictionary< CaseInsensitiveString, NotificationEvent[]> GetEventsByCategory(NotificationEventType Type)
Gets available notification events for a button, sorted by category.
abstract class NotificationEvent()
Abstract base class of notification events.
class NotificationEventsArgs(NotificationEvent[] Events)
Event argument for notification events.
class NotificationEventArgs(NotificationEvent Event)
Event argument for notification events.
NotificationEventType
Button on which event is to be displayed.
ContractsListMode
What list of contracts to display
SelectContractAction
Actions to take when a contact has been selected.
class HeaderModel(string Label)
Represents a header