1using CommunityToolkit.Mvvm.ComponentModel;
2using CommunityToolkit.Mvvm.Input;
9using System.Collections.ObjectModel;
21 private readonly PhotosLoader photosLoader;
22 private readonly
string? requestorFullJid;
23 private readonly
string? requestedIdentityId;
24 private readonly
string? petitionId;
25 private readonly
string? bareJid;
33 this.photosLoader =
new PhotosLoader(this.
Photos);
37 this.RequestorIdentity = Args.RequestorIdentity;
38 this.requestorFullJid = Args.RequestorFullJid;
39 this.requestedIdentityId = Args.RequestedIdentityId;
40 this.petitionId = Args.PetitionId;
41 this.Purpose = Args.Purpose;
42 this.ContentToSign = Args.ContentToSign;
44 if (!
string.IsNullOrEmpty(this.requestorFullJid))
46 else if (Args.RequestorIdentity is not
null)
47 this.bareJid = Args.RequestorIdentity.GetJid();
49 this.bareJid =
string.Empty;
58 View.BindingContext =
this;
59 this.stepViews[Step] = View;
71 private readonly SortedDictionary<ReviewStep, BaseContentView> stepViews = [];
76 await base.OnInitialize();
78 if (!
string.IsNullOrEmpty(this.bareJid))
85 Info.
LegalId !=
this.RequestorIdentity?.Id &&
90 Info.LegalId = this.LegalId;
98 this.ThirdPartyInContacts = Info is not
null;
101 this.AssignProperties();
102 this.NotifyCommandsCanExecuteChanged();
107 private async
void ReloadPhotos()
111 this.photosLoader.CancelLoadPhotos();
116 if (Attachments is not
null)
118 First = await this.photosLoader.LoadPhotos(Attachments,
SignWith.LatestApprovedId);
120 this.FirstPhotoSource = First?.Source;
121 this.FirstPhotoRotation = First?.Rotation ?? 0;
126 if (Attachments is not
null)
128 First = await this.photosLoader.LoadPhotos(Attachments,
SignWith.LatestApprovedId);
130 this.MyFirstPhotoSource = First?.Source;
131 this.MyFirstPhotoRotation = First?.Rotation ?? 0;
143 this.photosLoader.CancelLoadPhotos();
145 await base.OnDispose();
151 public ObservableCollection<Photo>
Photos {
get; } = [];
161 return MainThread.InvokeOnMainThreadAsync(async () =>
163 await base.XmppService_ConnectionStateChanged(Sender, NewState);
165 this.NotifyCommandsCanExecuteChanged();
171 base.SetIsBusy(IsBusy);
172 this.NotifyCommandsCanExecuteChanged();
175 private void NotifyCommandsCanExecuteChanged()
177 this.AcceptCommand.NotifyCanExecuteChanged();
178 this.DeclineCommand.NotifyCanExecuteChanged();
179 this.AuthenticateReviewerCommand.NotifyCanExecuteChanged();
189 if (!this.IsConnected || this.IsBusy || this.ContentToSign is
null)
192 if (this.
HasPhoto && !this.IsPhotoOk)
195 if (this.
HasName && !this.IsNameOk)
216 if (!this.AcknowledgeResponsibility || !this.ConsentProcessing || !this.ConfirmCorrect)
223 [RelayCommand(CanExecute = nameof(
CanAccept))]
224 private Task Accept()
226 return this.Accept(
true);
229 private async Task Accept(
bool GoBackIfOk)
239 this.petitionId!,
this.requestorFullJid!,
true);
242 if (Succeeded && GoBackIfOk)
249 public bool CanDecline => this.IsConnected && !this.IsBusy && this.ContentToSign is not
null;
251 [RelayCommand(CanExecute = nameof(
CanDecline))]
252 private Task Decline()
254 return this.Decline(
true);
257 private async Task Decline(
bool GoBackIfOk)
267 this.petitionId!,
this.requestorFullJid!,
false);
270 if (Succeeded && GoBackIfOk)
275 private async Task Ignore()
280 [RelayCommand(CanExecute = nameof(IsPhotoOk))]
281 private void AcceptPhoto()
287 [RelayCommand(CanExecute = nameof(IsNameOk))]
288 private void AcceptName()
294 [RelayCommand(CanExecute = nameof(IsPnrOk))]
295 private void AcceptPnr()
301 [RelayCommand(CanExecute = nameof(IsNationalityOk))]
302 private void AcceptNationality()
304 if (this.IsNationalityOk)
308 [RelayCommand(CanExecute = nameof(IsBirthDateOk))]
309 private void AcceptBirthDate()
311 if (this.IsBirthDateOk)
315 [RelayCommand(CanExecute = nameof(IsGenderOk))]
316 private void AcceptGender()
322 [RelayCommand(CanExecute = nameof(IsPersonalAddressInfoOk))]
323 private void AcceptPersonalAddressInfo()
325 if (this.IsPersonalAddressInfoOk)
329 [RelayCommand(CanExecute = nameof(IsOrganizationalInfoOk))]
330 private void AcceptOrganizationalInfo()
332 if (this.IsOrganizationalInfoOk)
337 private void AcceptConsent()
343 private void NextPage()
351 IsVisible = Current
switch
354 ReviewStep.Name => this.
HasName,
366 this.CurrentStep = Current;
369 private bool PrevPage()
380 IsVisible = Current
switch
383 ReviewStep.Name => this.
HasName,
395 this.CurrentStep = Current;
403 public bool HasPhoto => this.FirstPhotoSource is not
null;
408 public bool HasName => !
string.IsNullOrEmpty(this.FullName);
428 public bool HasGender => !
string.IsNullOrEmpty(this.Gender);
438 !
string.IsNullOrEmpty(this.Address) ||
439 !
string.IsNullOrEmpty(this.Address2) ||
440 !
string.IsNullOrEmpty(this.Area) ||
441 !
string.IsNullOrEmpty(this.City) ||
442 !
string.IsNullOrEmpty(this.Region) ||
443 !
string.IsNullOrEmpty(this.CountryCode);
455 !
string.IsNullOrEmpty(this.OrgName) ||
456 !
string.IsNullOrEmpty(this.OrgNumber) ||
457 !
string.IsNullOrEmpty(this.OrgDepartment) ||
458 !
string.IsNullOrEmpty(this.OrgRole) ||
459 !
string.IsNullOrEmpty(this.OrgAddress) ||
460 !
string.IsNullOrEmpty(this.OrgAddress2) ||
461 !
string.IsNullOrEmpty(this.OrgArea) ||
462 !
string.IsNullOrEmpty(this.OrgCity) ||
463 !
string.IsNullOrEmpty(this.OrgRegion) ||
464 !
string.IsNullOrEmpty(this.OrgCountryCode);
474 private DateTime created;
480 private DateTime? updated;
486 private string? legalId;
498 private DateTime? from;
504 private DateTime? to;
510 [NotifyPropertyChangedFor(nameof(FullName))]
515 private string? firstName;
521 [NotifyPropertyChangedFor(nameof(FullName))]
526 private string? middleNames;
532 [NotifyPropertyChangedFor(nameof(FullName))]
537 private string? lastNames;
544 private string? personalNumber;
553 if (
string.IsNullOrEmpty(this.CountryCode) ||
557 return this.PersonalNumber;
560 return Country.EmojiInfo.Unicode +
"\t" + this.PersonalNumber;
567 [System.Diagnostics.CodeAnalysis.SuppressMessage(
"Performance",
"CA1822:Mark members as static",
568 Justification =
"Must be instance property for view binding to work.")]
579 if (
string.IsNullOrEmpty(MyCountryCode) ||
583 return MyPersonalNumber;
586 return MyCountry.EmojiInfo.Unicode +
"\t" + MyPersonalNumber;
594 private string? address;
600 private string? address2;
606 private string? zipCode;
612 private string? area;
618 private string? city;
624 private string? region;
631 private string? countryCode;
638 private string? nationalityCode;
647 if (
string.IsNullOrEmpty(this.NationalityCode) ||
651 return this.NationalityCode;
654 return Country.EmojiInfo.Unicode +
"\t" + Country.Name;
663 private string? gender;
672 if (
string.IsNullOrEmpty(this.Gender) ||
687 private DateTime? birthDate;
693 private string? orgName;
699 private string? orgNumber;
705 private string? orgDepartment;
711 private string? orgRole;
717 private string? orgAddress;
723 private string? orgAddress2;
729 private string? orgZipCode;
735 private string? orgArea;
741 private string? orgCity;
747 private string? orgRegion;
753 private string? orgCountryCode;
765 public GridLength
OrgRowHeight => this.HasOrg ? GridLength.Auto :
new GridLength(0, GridUnitType.Absolute);
771 private string? phoneNr;
777 private string? eMail;
783 private string? deviceId;
789 private bool isApproved;
795 private string? purpose;
801 private byte[]? contentToSign;
807 private bool thirdPartyInContacts;
813 private ImageSource? firstPhotoSource;
819 private int firstPhotoRotation;
825 private ImageSource? myFirstPhotoSource;
831 private int myFirstPhotoRotation;
837 [System.Diagnostics.CodeAnalysis.SuppressMessage(
"Performance",
"CA1822:Mark members as static",
838 Justification =
"Must be instance property for view binding to work.")]
845 [NotifyCanExecuteChangedFor(nameof(AcceptPhotoCommand))]
846 private bool isPhotoOk;
852 [NotifyCanExecuteChangedFor(nameof(AcceptNameCommand))]
853 private bool isNameOk;
859 [NotifyCanExecuteChangedFor(nameof(AcceptPnrCommand))]
860 private bool isPnrOk;
866 [NotifyCanExecuteChangedFor(nameof(AcceptNationalityCommand))]
867 private bool isNationalityOk;
873 [NotifyCanExecuteChangedFor(nameof(AcceptBirthDateCommand))]
874 private bool isBirthDateOk;
880 [NotifyCanExecuteChangedFor(nameof(AcceptGenderCommand))]
881 private bool isGenderOk;
887 [NotifyCanExecuteChangedFor(nameof(AcceptPersonalAddressInfoCommand))]
888 private bool isPersonalAddressInfoOk;
894 [NotifyCanExecuteChangedFor(nameof(AcceptOrganizationalInfoCommand))]
895 private bool isOrganizationalInfoOk;
901 [NotifyCanExecuteChangedFor(nameof(AcceptConsentCommand))]
903 private bool acknowledgeResponsibility;
909 [NotifyCanExecuteChangedFor(nameof(AcceptConsentCommand))]
911 private bool consentProcessing;
917 [NotifyCanExecuteChangedFor(nameof(AcceptConsentCommand))]
919 private bool confirmCorrect;
925 private bool showDetails;
930 public bool IsConsentOk => this.AcknowledgeResponsibility && this.ConsentProcessing && this.ConfirmCorrect;
958 this.IsPhotoOk = !this.IsPhotoOk;
967 this.IsNameOk = !this.IsNameOk;
976 this.IsPnrOk = !this.IsPnrOk;
985 this.IsNationalityOk = !this.IsNationalityOk;
994 this.IsBirthDateOk = !this.IsBirthDateOk;
1003 this.IsGenderOk = !this.IsGenderOk;
1012 this.IsPersonalAddressInfoOk = !this.IsPersonalAddressInfoOk;
1021 this.IsOrganizationalInfoOk = !this.IsOrganizationalInfoOk;
1030 this.AcknowledgeResponsibility = !this.AcknowledgeResponsibility;
1039 this.ConsentProcessing = !this.ConsentProcessing;
1048 this.ConfirmCorrect = !this.ConfirmCorrect;
1057 this.ShowDetails = !this.ShowDetails;
1062 private void AssignProperties()
1090 if (!
string.IsNullOrEmpty(BirthDayStr) &&
int.TryParse(BirthDayStr, out
int BirthDay) &&
1091 !
string.IsNullOrEmpty(BirthMonthStr) &&
int.TryParse(BirthMonthStr, out
int BirthMonth) &&
1092 !
string.IsNullOrEmpty(BirthYearStr) &&
int.TryParse(BirthYearStr, out
int BirthYear))
1096 this.BirthDate =
new DateTime(BirthYear, BirthMonth, BirthDay);
1098 catch (Exception ex)
1101 this.BirthDate =
null;
1117 !
string.IsNullOrEmpty(this.OrgName) ||
1118 !
string.IsNullOrEmpty(this.OrgNumber) ||
1119 !
string.IsNullOrEmpty(this.OrgDepartment) ||
1120 !
string.IsNullOrEmpty(this.OrgRole) ||
1121 !
string.IsNullOrEmpty(this.OrgAddress) ||
1122 !
string.IsNullOrEmpty(this.OrgAddress2) ||
1123 !
string.IsNullOrEmpty(this.OrgZipCode) ||
1124 !
string.IsNullOrEmpty(this.OrgArea) ||
1125 !
string.IsNullOrEmpty(this.OrgCity) ||
1126 !
string.IsNullOrEmpty(this.OrgRegion) ||
1127 !
string.IsNullOrEmpty(this.OrgCountryCode);
1131 this.IsApproved = this.RequestorIdentity.State ==
IdentityState.Approved;
1135 this.Created = DateTime.MinValue;
1136 this.Updated =
null;
1154 this.BirthDate =
null;
1166 this.HasOrg =
false;
1170 this.IsApproved =
false;
1174 [RelayCommand(CanExecute = nameof(
CanAccept))]
1175 private async Task AuthenticateReviewer()
1181 await this.Accept(
false);
1185 catch (Exception ex)
1198 if (!this.PrevPage())
1199 await base.GoBack();
1208 return base.GoBack();
1211 #region ILinkableView
The Application class, representing an instance of the Neuro-Access app.
static Task< bool > AuthenticateUser(AuthenticationPurpose Purpose, bool Force=false)
Authenticates the user using the configured authentication method.
XMPP Protocol Properties.
const string PersonalNumber
Personal number
const string OrgAddress2
Organization Address line 2
const string DeviceId
Device ID
const string Country
Country
const string OrgArea
Organization Area
const string Region
Region
const string OrgRegion
Organization Region
const string Nationality
Nationality
const string ZipCode
Zip Code
const string BirthYear
Birth Year
const string OrgCity
Organization City
const string OrgRole
Organization Role
const string Phone
Phone number
const string EMail
e-Mail address
const string OrgZipCode
Organization Zip Code
const string MiddleNames
Middle names
const string BirthDay
Birth Day
const string OrgCountry
Organization Country
const string OrgDepartment
Organization Department
const string Address2
Address line 2
const string OrgAddress
Organization Address line 1
const string Address
Address line 1
const string LastNames
Last names
const string OrgNumber
Organization number
const string BirthMonth
Birth Month
const string FirstName
First name
const string Gender
Gender
const string OrgName
Organization name
A set of never changing property constants and helpful values.
const string NotAvailableValue
A generic "no value available" string.
Conversion between Country Names and ISO-3166-1 country codes.
static bool TryGetCountryByCode(string? CountryCode, [NotNullWhen(true)] out ISO_3166_Country? Country)
Tries to get the country, given its country code.
Static class containing ISO 5218 gender codes
static bool LetterToGender(string Letter, out ISO_5218_Gender? Gender)
Tries to get the gender label corresponding to an ISO 5218 gender code.
Base class that references services in the app.
static ILogService LogService
Log service.
static INetworkService NetworkService
Network service.
static IUiService UiService
Service serializing and managing UI-related tasks.
static ITagProfile TagProfile
TAG Profile service.
static IStringLocalizer Localizer
Localization service
static IXmppService XmppService
The XMPP service for XMPP communication.
The view model to bind to when displaying petitioning of an identity in a view or page.
string ReviewApproved
Information that peer review has been approved.
bool HasGender
If request contains gender
string? MyPersonalNumberWithFlag
Personal number of reviewer with country flag.
void ToggleAcknowledgeResponsibility()
Toggles AcknowledgeResponsibility
string PeerReviewConfirmCorrectText
Instruction to reviewer when confirming reviewed information is correct.
bool HasName
If request contains a full name
override async Task OnDispose()
Method called when the view is disposed, and will not be used more. Use this method to unregister eve...
string PhotoReviewText
Instruction to reviewer when reviewing photo.
void ToggleShowDetails()
Toggles ShowDetails
void ToggleIsPnrOk()
Toggles IsPnrOk
void ToggleIsOrganizationalInfoOk()
Toggles IsOrganizationalInfoOk
GridLength OrgRowHeight
If organization information is available.
bool CanAccept
If the user can accept the review.
override Task< string > Title
Title of the current view
override async Task OnInitialize()
Method called when view is initialized for the first time. Use this method to implement registration ...
bool HasBirthDate
If request contains birth date
string PeerReviewAuthenticationText
Instruction to reviewer when accepting peer review.
bool IsConsentOk
If proper consent and acknowledgement has been given.
void ToggleIsNationalityOk()
Toggles IsNationalityOk
string? NationalityWithFlag
Nationality with country flag.
bool HasPersonalAddressInfo
If request contains personal address information
string? PersonalNumberWithFlag
Personal number with country flag.
void AddView(ReviewStep Step, BaseContentView View)
Adds a view to the wizard dialog.
PetitionPeerReviewViewModel(PetitionPeerReviewNavigationArgs? Args)
Creates a new instance of the PetitionPeerReviewViewModel class.
void ToggleIsPhotoOk()
Toggles IsPhotoOk
override async Task GoBack()
Method called when user wants to navigate to the previous screen.
bool CanDecline
If the user can decline the review.
bool HasPersonalNumber
If request contains a personal number
string? GenderWithSymbol
Gender with Unicode symbol.
void ToggleIsGenderOk()
Toggles IsGenderOk
void ToggleIsNameOk()
Toggles IsNameOk
void ToggleIsBirthDateOk()
Toggles IsBirthDateOk
bool HasNationality
If request contains nationality
LegalIdentity? RequestorIdentity
The identity of the requestor.
override Task XmppService_ConnectionStateChanged(object? Sender, XmppState NewState)
Listens to connection state changes from the XMPP server.
override void SetIsBusy(bool IsBusy)
Sets the IsBusy property.
ObservableCollection< Photo > Photos
The list of photos related to the identity being petitioned.
void ToggleIsPersonalAddressInfoOk()
Toggles IsPersonalAddressInfoOk
void ToggleConsentProcessing()
Toggles ConsentProcessing
bool HasPhoto
If request contains a photo
void ToggleConfirmCorrect()
Toggles ConfirmCorrect
bool HasOrganizationalInfo
If request contains organizational information
Task Close()
Closes the view.
A view model that holds the XMPP state.
Contains a reference to an attachment assigned to a legal object.
DateTime From
From what point in time the legal identity is valid.
DateTime Updated
When the identity object was last updated
DateTime To
To what point in time the legal identity is valid.
DateTime Created
When the identity object was created
IdentityState State
Current state of identity
string Id
ID of the legal identity
Attachment[] Attachments
Attachments assigned to the legal identity.
Abstract base class of signatures
Manages an XMPP client connection. Implements XMPP, as defined in https://tools.ietf....
static string GetBareJID(string JID)
Gets the Bare JID from a JID, which may be a Full JID.
Static interface for database persistence. In order to work, a database provider has to be assigned t...
static IDatabaseProvider Provider
Registered database provider.
static async Task Update(object Object)
Updates an object in the database.
Task Flush()
Persists any pending changes.
class ISO_3166_Country(string Name, string Alpha2, string Alpha3, int NumericCode, string DialCode, EmojiInfo? EmojiInfo=null)
Representation of an ISO3166-1 Country
class ISO_5218_Gender(string Gender, int Code, string Letter, string LocalizedNameId, char Unicode)
Contains one record of the ISO 5218 data set.
class Photo(byte[] Binary, int Rotation)
Class containing information about a photo.
ReviewStep
Steps in the peer-review process
AuthenticationPurpose
Purpose for requesting the user to authenticate itself.
IdentityState
Lists recognized legal identity states.
SignWith
Options on what keys to use when signing data.
XmppState
State of XMPP connection.