1using CommunityToolkit.Mvvm.ComponentModel;
9using System.Collections.ObjectModel;
10using System.Globalization;
12using System.ComponentModel;
19using CommunityToolkit.Mvvm.Input;
29 private readonly Dictionary<CaseInsensitiveString, List<ContactInfoModel>> byBareJid;
30 private readonly TaskCompletionSource<ContactInfoModel?>? selection;
39 this.navigationArguments = Args;
50 this.AnonymousText =
string.IsNullOrEmpty(Args.
AnonymousText) ?
57 this.selection =
null;
64 await base.OnInitialize();
66 await this.UpdateContactList(this.navigationArguments?.
Contacts);
68 ServiceRef.XmppService.OnPresence += this.Xmpp_OnPresence;
69 ServiceRef.NotificationService.OnNewNotification += this.NotificationService_OnNewNotification;
70 ServiceRef.NotificationService.OnNotificationsDeleted += this.NotificationService_OnNotificationsDeleted;
76 await base.OnAppearing();
78 if (this.selection is not
null && this.selection.Task.IsCompleted)
84 this.SelectedContact =
null;
87 private async Task UpdateContactList(IEnumerable<ContactInfo>?
Contacts)
89 SortedDictionary<CaseInsensitiveString, ContactInfo> Sorted = [];
90 Dictionary<CaseInsensitiveString, bool> Jids = [];
109 if (Jids.ContainsKey(Item.
BareJid))
126 this.Contacts.Clear();
127 this.ShowContactsMissing = Sorted.Count == 0;
133 if (Sorted.TryGetValue(Category, out
ContactInfo? Info))
134 Sorted.Remove(Category);
139 if (Info is not
null)
140 Remove(Sorted, Info.FriendlyName, Info);
146 FriendlyName = Category,
152 this.Contacts.Add(
new ContactInfoModel(Info, Events));
161 this.Contacts.Add(
new ContactInfoModel(Info, Events));
164 this.byBareJid.Clear();
166 foreach (ContactInfoModel? Contact
in this.Contacts)
168 if (
string.IsNullOrEmpty(Contact?.BareJid))
171 if (!this.byBareJid.TryGetValue(Contact.BareJid, out List<ContactInfoModel>? Contacts2))
174 this.byBareJid[Contact.BareJid] = Contacts2;
177 Contacts2.Add(Contact);
183 if (Sorted.ContainsKey(Name))
190 Suffix =
" " + (++i).
ToString(CultureInfo.InvariantCulture);
192 while (Sorted.ContainsKey(Name + Suffix));
194 Sorted[Name + Suffix] = Info;
203 string Suffix =
string.Empty;
205 while (Sorted.TryGetValue(Name + Suffix, out
ContactInfo? Info2))
207 if (Info2.BareJid == Info.
BareJid &&
210 Info2.NodeId == Info.
NodeId &&
213 Sorted.Remove(Name + Suffix);
216 string Suffix2 =
" " + i.ToString(CultureInfo.InvariantCulture);
218 while (Sorted.TryGetValue(Name + Suffix2, out Info2))
220 Sorted[Name + Suffix] = Info2;
221 Sorted.Remove(Name + Suffix2);
224 Suffix2 =
" " + i.ToString(CultureInfo.InvariantCulture);
231 Suffix =
" " + i.ToString(CultureInfo.InvariantCulture);
238 ServiceRef.XmppService.OnPresence -= this.Xmpp_OnPresence;
239 ServiceRef.NotificationService.OnNewNotification -= this.NotificationService_OnNewNotification;
240 ServiceRef.NotificationService.OnNotificationsDeleted -= this.NotificationService_OnNotificationsDeleted;
244 this.ShowContactsMissing =
false;
245 this.Contacts.Clear();
248 this.selection?.TrySetResult(this.SelectedContact);
250 return base.OnDispose();
257 private bool showContactsMissing;
263 private string? description;
269 private bool canScanQrCode;
275 private bool allowAnonymous;
281 private string? anonymousText;
292 public ObservableCollection<ContactInfoModel?>
Contacts {
get; }
303 base.OnPropertyChanged(e);
305 switch (e.PropertyName)
307 case nameof(this.SelectedContact):
310 if (Contact is not
null)
312 MainThread.BeginInvokeOnMainThread(async () =>
314 this.IsOverlayVisible =
true;
321 StringBuilder sb =
new();
323 sb.Append(
"edaler:");
336 if (!
string.IsNullOrEmpty(Contact.
LegalId))
341 else if (!
string.IsNullOrEmpty(Contact.
BareJid))
365 ViewIdentityNavigationArgs ViewIdentityArgs =
new(Contact.
LegalIdentity);
369 else if (!
string.IsNullOrEmpty(Contact.
LegalId))
374 else if (!
string.IsNullOrEmpty(Contact.
BareJid) && Contact.Contact is not
null)
383 this.SelectedContact = Contact;
385 this.selection?.TrySetResult(Contact);
391 this.IsOverlayVisible =
false;
403 private async Task ScanQrCode()
406 if (
string.IsNullOrEmpty(Code))
416 else if (!
string.IsNullOrEmpty(Code))
427 private void Anonymous()
429 this.SelectedContact =
new ContactInfoModel(
null, []);
432 private Task Xmpp_OnPresence(
object? Sender, PresenceEventArgs e)
434 if (this.byBareJid.TryGetValue(e.FromBareJID, out List<ContactInfoModel>?
Contacts))
436 foreach (ContactInfoModel Contact
in Contacts)
437 Contact.PresenceUpdated();
440 return Task.CompletedTask;
446 this.UpdateNotifications(e.Event.Category ??
string.Empty);
449 private void UpdateNotifications()
452 this.UpdateNotifications(Category);
457 if (this.byBareJid.TryGetValue(Category, out List<ContactInfoModel>?
Contacts))
462 foreach (ContactInfoModel Contact
in Contacts)
463 Contact.NotificationsUpdated(Events);
469 Dictionary<CaseInsensitiveString, bool> Categories = [];
472 Categories[Event.Category ??
string.Empty] =
true;
475 this.UpdateNotifications(Category);
Contains information about a balance.
CaseInsensitiveString Currency
Currency of amount.
Abstract base class for eDaler URIs
static bool TryParse(string Uri, out EDalerUri Result)
Tries to parse an eDaler URI
static bool StartsWithIdScheme(string Url)
Checks if the specified code starts with the IoT ID scheme.
static ? string RemoveScheme(string Url)
Removes the URI Schema from an URL.
const string IotId
The IoT ID URI Scheme (iotid)
A set of never changing property constants and helpful values.
Base class that references services in the app.
static IUiService UiService
Service serializing and managing UI-related tasks.
static INotificationService NotificationService
Service for managing notifications for the user.
static ITagProfile TagProfile
TAG Profile service.
static IStringLocalizer Localizer
Localization service
static IContractOrchestratorService ContractOrchestratorService
Contract orchestrator service.
static IXmppService XmppService
The XMPP service for XMPP communication.
Helper class to perform scanning of QR Codes by displaying the UI and handling async results.
static async Task< string?> ScanQrCode(string? QrTitle, string[] AllowedSchemas)
Navigates to the Scan QR Code Page, waits for scan to complete, and returns the result....
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.
A page that displays a list of the current user's contacts.
Contact Information model, including related notification information.
LegalIdentity? LegalIdentity
Legal Identity object.
CaseInsensitiveString? LegalId
Legal ID of contact.
ContactInfo? Contact
Contact Information object in database.
CaseInsensitiveString? BareJid
Bare JID of contact.
Holds navigation parameters specific to views displaying a list of contacts.
SelectContactAction? Action
Action to take when a contact has been selected.
TaskCompletionSource< ContactInfoModel?>? Selection
Selection source, if selecting identity.
string? AnonymousText
String to display on the anonymous button
string? Description
Description presented to user.
bool AllowAnonymous
If user is allowed to select an Anonymous option.
bool CanScanQrCode
If the user should be able to scane QR Codes.
The view model to bind to when displaying the list of contacts.
override async Task OnAppearing()
Method called when view is appearing on the screen.
override void OnPropertyChanged(PropertyChangedEventArgs e)
ContactListViewModel(ContactListNavigationArgs? Args)
Creates an instance of the ContactListViewModel class.
ObservableCollection< ContactInfoModel?> Contacts
Holds the list of contacts to display.
override async Task OnInitialize()
Method called when view is initialized for the first time. Use this method to implement registration ...
override Task OnDispose()
Method called when the view is disposed, and will not be used more. Use this method to unregister eve...
A page to display when the user wants to view an identity.
Holds navigation parameters specific to eDaler URIs.
A page that allows the user to realize payments.
Maintains information about an item in the roster.
string NameOrBareJid
Returns the name of the contact, or the Bare JID, if there's no name provided.
string BareJid
Bare JID of the roster item.
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.
bool TryGetNotificationEvents(NotificationEventType Type, CaseInsensitiveString Category, [NotNullWhen(true)] out NotificationEvent[]? Events)
Tries to get available notification events.
CaseInsensitiveString[] GetCategories(NotificationEventType Type)
Gets available categories for a button.
Task GoToAsync(string Route, BackMethod BackMethod=BackMethod.Inherited, string? UniqueId=null)
Navigates the AppShell to the specified route, with page arguments to match.
Task< bool > DisplayAlert(string Title, string Message, string? Accept=null, string? Cancel=null)
Displays an alert/message box to the user.
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.
BackMethod
Navigation Back Method
SelectContactAction
Actions to take when a contact has been selected.
delegate string ToString(IElement Element)
Delegate for callback methods that convert an element value to a string.