1using System.ComponentModel;
 
    2using System.Globalization;
 
    3using CommunityToolkit.Mvvm.ComponentModel;
 
    4using CommunityToolkit.Mvvm.Input;
 
   28            await base.OnInitialize();
 
   30            LocalizationManager.Current.PropertyChanged += this.LocalizationManagerEventHandler;
 
   34                this.CountDownTimer = 
App.
Current.Dispatcher.CreateTimer();
 
   35                this.CountDownTimer.Interval = TimeSpan.FromMilliseconds(1000);
 
   36                this.CountDownTimer.Tick += this.CountDownEventHandler;
 
   45                        new KeyValuePair<string, string>(
"Accept", 
"application/json"));
 
   47                    if ((Result is Dictionary<string, object> Response) &&
 
   48                        Response.TryGetValue(
"CountryCode", out 
object? cc) &&
 
   49                        (cc is 
string CountryCode))
 
   52                            this.SelectedCountry = Country;
 
   65            LocalizationManager.Current.PropertyChanged -= this.LocalizationManagerEventHandler;
 
   67            if (this.CountDownTimer is not 
null)
 
   69                this.CountDownTimer.Stop();
 
   70                this.CountDownTimer.Tick -= this.CountDownEventHandler;
 
   71                this.CountDownTimer = 
null;
 
   74            await base.OnDispose();
 
   80            await base.DoAssignProperties();
 
   84            if (
string.IsNullOrEmpty(PhoneNumber))
 
   90                        new KeyValuePair<string, string>(
"Accept", 
"application/json"));
 
   92                    if ((Result is Dictionary<string, object> Response) &&
 
   93                        Response.TryGetValue(
"CountryCode", out 
object? cc) &&
 
   94                        (cc is 
string CountryCode))
 
   97                            this.SelectedCountry = Country;
 
  111                    this.SelectedCountry = Country;
 
  112                    this.PhoneNumber = PhoneNumber[(Country.DialCode.Length + 1)..];
 
  113                    this.SendCodeCommand.NotifyCanExecuteChanged();
 
  118        protected override void OnPropertyChanged(PropertyChangedEventArgs e)
 
  120            base.OnPropertyChanged(e);
 
  122            if (e.PropertyName == nameof(this.IsBusy))
 
  123                this.SendCodeCommand.NotifyCanExecuteChanged();
 
  126        public void LocalizationManagerEventHandler(
object? sender, PropertyChangedEventArgs e)
 
  128            this.OnPropertyChanged(nameof(this.LocalizedSendCodeText));
 
  129            this.OnPropertyChanged(nameof(this.LocalizedValidationError));
 
  136        [NotifyCanExecuteChangedFor(nameof(SendCodeCommand))]
 
  140        [NotifyPropertyChangedFor(nameof(LocalizedValidationError))]
 
  144        [NotifyPropertyChangedFor(nameof(LocalizedValidationError))]
 
  148        [NotifyPropertyChangedFor(nameof(LocalizedSendCodeText))]
 
  149        [NotifyCanExecuteChangedFor(nameof(SendCodeCommand))]
 
  150        [NotifyCanExecuteChangedFor(nameof(ResendCodeCommand))]
 
  151        private int countDownSeconds;
 
  154        private IDispatcherTimer? countDownTimer;
 
  156        public string LocalizedSendCodeText
 
  160                if (this.CountDownSeconds > 0)
 
  167        public string LocalizedValidationError
 
  171                if (!this.TypeIsValid)
 
  174                if (!this.LengthIsValid)
 
  185        private string phoneNumber = 
string.Empty;
 
  187        public bool CanSendCode => this.NumberIsValid && !this.IsBusy &&
 
  188            (this.PhoneNumber.Length > 0) && (this.CountDownSeconds <= 0);
 
  190        public bool CanResendCode => this.CountDownSeconds <= 0;
 
  193        private async Task SelectPhoneCode()
 
  196            await MopupService.Instance.PushAsync(Page);
 
  200            if (Result is not 
null)
 
  201                this.SelectedCountry = Result;
 
  206        [RelayCommand(CanExecute = nameof(CanSendCode))]
 
  207        private async Task SendCode()
 
  220                string FullPhoneNumber = $
"+{this.SelectedCountry.DialCode}{this.PhoneNumber}";
 
  222                if (this.SelectedCountry.DialCode == 
"46") 
 
  223                    FullPhoneNumber = $
"+{this.SelectedCountry.DialCode}{this.PhoneNumber.TrimStart('0')}";
 
  227                    new Dictionary<string, object>()
 
  229                        { 
"Nr", FullPhoneNumber },
 
  230                        { 
"AppName", Constants.Application.Name },
 
  231                        { 
"Language", CultureInfo.CurrentCulture.TwoLetterISOLanguageName }
 
  232                    }, 
new KeyValuePair<string, string>(
"Accept", 
"application/json"));
 
  234                if (SendResult is Dictionary<string, object> SendResponse &&
 
  235                    SendResponse.TryGetValue(
"Status", out 
object? Obj) && Obj is 
bool SendStatus && SendStatus &&
 
  236                    SendResponse.TryGetValue(
"IsTemporary", out Obj) && Obj is 
bool SendIsTemporary)
 
  248                        VerifyCodeNavigationArgs 
NavigationArgs = 
new(
this, FullPhoneNumber);
 
  252                        if (!
string.IsNullOrEmpty(Code))
 
  263                                new Dictionary<string, object>()
 
  265                                    { 
"Nr", FullPhoneNumber },
 
  266                                    { 
"Code", 
int.Parse(Code, NumberStyles.None, CultureInfo.InvariantCulture) },
 
  268                                }, 
new KeyValuePair<string, string>(
"Accept", 
"application/json"));
 
  271                            if (VerifyResult is Dictionary<string, object> VerifyResponse &&
 
  272                                VerifyResponse.TryGetValue(
"Status", out Obj) && Obj is 
bool VerifyStatus && VerifyStatus &&
 
  273                                VerifyResponse.TryGetValue(
"Domain", out Obj) && Obj is 
string VerifyDomain &&
 
  274                                VerifyResponse.TryGetValue(
"Key", out Obj) && Obj is 
string VerifyKey &&
 
  275                                VerifyResponse.TryGetValue(
"Secret", out Obj) && Obj is 
string VerifySecret &&
 
  276                                VerifyResponse.TryGetValue(
"Temporary", out Obj) && Obj is 
bool VerifyIsTemporary)
 
  280                                ServiceRef.TagProfile.TestOtpTimestamp = VerifyIsTemporary ? DateTime.Now : 
null;
 
  288                                    bool DefaultConnectivity;
 
  292                                        (
string HostName, 
int PortNumber, 
bool IsIpAddress) = await 
ServiceRef.
NetworkService.LookupXmppHostnameAndPort(VerifyDomain);
 
  297                                        DefaultConnectivity = 
false;
 
  302                                if (VerifyIsTemporary)
 
  338        [RelayCommand(CanExecute = nameof(CanResendCode))]
 
  339        private async Task ResendCode()
 
  351                string FullPhoneNumber = $
"+{this.SelectedCountry.DialCode}{this.PhoneNumber}";
 
  353                if (this.SelectedCountry.DialCode == 
"46") 
 
  354                    FullPhoneNumber = $
"+{this.SelectedCountry.DialCode}{this.PhoneNumber.TrimStart('0')}";
 
  358                    new Dictionary<string, object>()
 
  360                        { 
"Nr", FullPhoneNumber },
 
  361                        { 
"AppName", Constants.Application.Name },
 
  362                        { 
"Language", CultureInfo.CurrentCulture.TwoLetterISOLanguageName }
 
  363                    }, 
new KeyValuePair<string, string>(
"Accept", 
"application/json"));
 
  365                if (SendResult is Dictionary<string, object> SendResponse &&
 
  366                    SendResponse.TryGetValue(
"Status", out 
object? Obj) && Obj is 
bool SendStatus && SendStatus)
 
  387        private void StartTimer()
 
  389            if (this.CountDownTimer is not 
null)
 
  391                this.CountDownSeconds = 300;
 
  393                if (!this.CountDownTimer.IsRunning)
 
  394                    this.CountDownTimer.Start();
 
  398        private void CountDownEventHandler(
object? sender, EventArgs e)
 
  400            if (this.CountDownTimer is not 
null)
 
  402                if (this.CountDownSeconds > 0)
 
  403                    this.CountDownSeconds--;
 
  405                    this.CountDownTimer.Stop();
 
The Application class, representing an instance of the Neuro-Access app.
 
static new? App Current
Gets the current application, type casted to App.
 
const string IdDomain
Neuro-Access domain.
 
A set of never changing property constants and helpful values.
 
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 ISO_3166_Country DefaultCountry
This collection built from Wikipedia entry on ISO3166-1 on 9th Feb 2016
 
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
 
An base class holding page specific navigation parameters.
 
override async Task OnInitialize()
 
override async Task OnDispose()
 
override async Task DoAssignProperties()
 
Static class managing encoding and decoding of internet content.
 
static Task< object > PostAsync(Uri Uri, object Data, params KeyValuePair< string, string >[] Headers)
Posts to a resource, using a Uniform Resource Identifier (or Locator).
 
Class containing credentials for an XMPP client connection.
 
const int DefaultPort
Default XMPP Server port.
 
void SetDomain(string DomainName, bool DefaultXmppConnectivity, string Key, string Secret)
Set the domain name to connect to.
 
string? SelectedCountry
Selected country. Some countries have the same phone code, so we want to save the selected country
 
PurposeUse Purpose
Purpose for using the app.
 
void SetPhone(string Country, string PhoneNumber)
Sets the phone number used for contacting the user.
 
string? PhoneNumber
Verified phone number.
 
void SetPurpose(bool IsTest, PurposeUse Purpose)
Set if the user choose the educational or experimental purpose.
 
string? Domain
The domain this profile is connected to.
 
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.
 
class ISO_3166_Country(string Name, string Alpha2, string Alpha3, int NumericCode, string DialCode, EmojiInfo? EmojiInfo=null)
Representation of an ISO3166-1 Country
 
RegistrationStep
The different steps of a TAG Profile registration journey.
 
PurposeUse
For what purpose the app will be used
 
BackMethod
Navigation Back Method