Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
ValidateEmailViewModel.cs
1using System.ComponentModel;
2using System.Globalization;
3using CommunityToolkit.Mvvm.ComponentModel;
4using CommunityToolkit.Mvvm.Input;
11using Waher.Content;
12
14{
15 public partial class ValidateEmailViewModel : BaseRegistrationViewModel, ICodeVerification
16 {
18 : base(RegistrationStep.ValidateEmail)
19 {
20 }
21
23 protected override async Task OnInitialize()
24 {
25 await base.OnInitialize();
26
27 LocalizationManager.Current.PropertyChanged += this.LocalizationManagerEventHandler;
28
29 if (App.Current is not null)
30 {
31 this.CountDownTimer = App.Current.Dispatcher.CreateTimer();
32 this.CountDownTimer.Interval = TimeSpan.FromMilliseconds(1000);
33 this.CountDownTimer.Tick += this.CountDownEventHandler;
34 }
35 }
36
38 protected override async Task OnDispose()
39 {
40 LocalizationManager.Current.PropertyChanged -= this.LocalizationManagerEventHandler;
41
42 if (this.CountDownTimer is not null)
43 {
44 this.CountDownTimer.Stop();
45 this.CountDownTimer.Tick -= this.CountDownEventHandler;
46 this.CountDownTimer = null;
47 }
48
49 await base.OnDispose();
50 }
51
53 public override async Task DoAssignProperties()
54 {
55 await base.DoAssignProperties();
56
57 if (!string.IsNullOrEmpty(ServiceRef.TagProfile.EMail))
58 {
59 this.EmailText = ServiceRef.TagProfile.EMail;
60 this.SendCodeCommand.NotifyCanExecuteChanged();
61 }
62 }
63
64 protected override void OnPropertyChanged(PropertyChangedEventArgs e)
65 {
66 base.OnPropertyChanged(e);
67
68 if (e.PropertyName == nameof(this.IsBusy))
69 this.SendCodeCommand.NotifyCanExecuteChanged();
70 }
71
72 public void LocalizationManagerEventHandler(object? sender, PropertyChangedEventArgs e)
73 {
74 this.OnPropertyChanged(nameof(this.LocalizedSendCodeText));
75 this.OnPropertyChanged(nameof(this.LocalizedValidationError));
76 }
77
78 [ObservableProperty]
79 [NotifyCanExecuteChangedFor(nameof(SendCodeCommand))]
80 [NotifyPropertyChangedFor(nameof(LocalizedValidationError))]
81 bool emailIsValid;
82
83 [ObservableProperty]
84 [NotifyPropertyChangedFor(nameof(LocalizedSendCodeText))]
85 [NotifyCanExecuteChangedFor(nameof(SendCodeCommand))]
86 [NotifyCanExecuteChangedFor(nameof(ResendCodeCommand))]
87 private int countDownSeconds;
88
89 [ObservableProperty]
90 private IDispatcherTimer? countDownTimer;
91
92 public string LocalizedSendCodeText
93 {
94 get
95 {
96 if (this.CountDownSeconds > 0)
97 return ServiceRef.Localizer[nameof(AppResources.SendCodeSeconds), this.CountDownSeconds];
98
99 return ServiceRef.Localizer[nameof(AppResources.SendCode)];
100 }
101 }
102
103 public string LocalizedValidationError
104 {
105 get
106 {
107 if (!this.EmailIsValid)
108 return ServiceRef.Localizer[nameof(AppResources.EmailValidationFormat)];
109
110 return string.Empty;
111 }
112 }
113
117 [ObservableProperty]
118 private string emailText = string.Empty;
119
120 public bool CanSendCode => this.EmailIsValid && !this.IsBusy &&
121 (this.EmailText.Length > 0) && (this.CountDownSeconds <= 0);
122
123 public bool CanResendCode => this.CountDownSeconds <= 0;
124
125 [RelayCommand(CanExecute = nameof(CanSendCode))]
126 private async Task SendCode()
127 {
128 this.IsBusy = true;
129
130 try
131 {
132 if (!ServiceRef.NetworkService.IsOnline)
133 {
135 ServiceRef.Localizer[nameof(AppResources.ErrorTitle)],
136 ServiceRef.Localizer[nameof(AppResources.NetworkSeemsToBeMissing)]);
137 return;
138 }
139
140 object SendResult = await InternetContent.PostAsync(
141 new Uri("https://" + Constants.Domains.IdDomain + "/ID/SendVerificationMessage.ws"),
142 new Dictionary<string, object>()
143 {
144 { "EMail", this.EmailText },
145 { "AppName", Constants.Application.Name },
146 { "Language", CultureInfo.CurrentCulture.TwoLetterISOLanguageName }
147 }, new KeyValuePair<string, string>("Accept", "application/json"));
148
149
150 if (SendResult is Dictionary<string, object> SendResponse &&
151 SendResponse.TryGetValue("Status", out object? Obj) && Obj is bool SendStatus && SendStatus)
152 {
153 this.StartTimer();
154
155 VerifyCodeNavigationArgs NavigationArgs = new(this, this.EmailText);
157 string? Code = await NavigationArgs.VarifyCode!.Task;
158
159 if (!string.IsNullOrEmpty(Code))
160 {
161 object VerifyResult = await InternetContent.PostAsync(
162 new Uri("https://" + Constants.Domains.IdDomain + "/ID/VerifyNumber.ws"),
163 new Dictionary<string, object>()
164 {
165 { "EMail", this.EmailText },
166 { "Code", int.Parse(Code, NumberStyles.None, CultureInfo.InvariantCulture) }
167 }, new KeyValuePair<string, string>("Accept", "application/json"));
168
169
170 if (VerifyResult is Dictionary<string, object> VerifyResponse &&
171 VerifyResponse.TryGetValue("Status", out Obj) && Obj is bool VerifyStatus && VerifyStatus)
172 {
173 ServiceRef.TagProfile.EMail = this.EmailText;
174 if(string.IsNullOrEmpty(ServiceRef.TagProfile.Account))
175 GoToRegistrationStep(RegistrationStep.NameEntry);
176 else
177 GoToRegistrationStep(RegistrationStep.CreateAccount);
178 }
179 else
180 {
182 ServiceRef.Localizer[nameof(AppResources.ErrorTitle)],
183 ServiceRef.Localizer[nameof(AppResources.UnableToVerifyCode)],
184 ServiceRef.Localizer[nameof(AppResources.Ok)]);
185 }
186 }
187 }
188 else
189 {
191 ServiceRef.Localizer[nameof(AppResources.ErrorTitle)],
192 ServiceRef.Localizer[nameof(AppResources.SomethingWentWrongWhenSendingPhoneCode)]);
193 }
194 }
195 catch (Exception ex)
196 {
197 ServiceRef.LogService.LogException(ex);
198
200 ServiceRef.Localizer[nameof(AppResources.ErrorTitle)], ex.Message,
201 ServiceRef.Localizer[nameof(AppResources.Ok)]);
202 }
203 finally
204 {
205 this.IsBusy = false;
206 }
207 }
208
209 [RelayCommand(CanExecute = nameof(CanResendCode))]
210 private async Task ResendCode()
211 {
212 try
213 {
214 if (!ServiceRef.NetworkService.IsOnline)
215 {
217 ServiceRef.Localizer[nameof(AppResources.ErrorTitle)],
218 ServiceRef.Localizer[nameof(AppResources.NetworkSeemsToBeMissing)]);
219 return;
220 }
221
222 object SendResult = await InternetContent.PostAsync(
223 new Uri("https://" + Constants.Domains.IdDomain + "/ID/SendVerificationMessage.ws"),
224 new Dictionary<string, object>()
225 {
226 { "EMail", this.EmailText },
227 { "AppName", Constants.Application.Name },
228 { "Language", CultureInfo.CurrentCulture.TwoLetterISOLanguageName }
229 }, new KeyValuePair<string, string>("Accept", "application/json"));
230
231 if (SendResult is Dictionary<string, object> SendResponse &&
232 SendResponse.TryGetValue("Status", out object? Obj) && Obj is bool SendStatus && SendStatus)
233 {
234 this.StartTimer();
235 }
236 else
237 {
239 ServiceRef.Localizer[nameof(AppResources.ErrorTitle)],
240 ServiceRef.Localizer[nameof(AppResources.SomethingWentWrongWhenSendingPhoneCode)]);
241 }
242 }
243 catch (Exception ex)
244 {
245 ServiceRef.LogService.LogException(ex);
246
248 ServiceRef.Localizer[nameof(AppResources.ErrorTitle)], ex.Message,
249 ServiceRef.Localizer[nameof(AppResources.Ok)]);
250 }
251 }
252
253 private void StartTimer()
254 {
255 if (this.CountDownTimer is not null)
256 {
257 this.CountDownSeconds = 30;
258
259 if (!this.CountDownTimer.IsRunning)
260 this.CountDownTimer.Start();
261 }
262 }
263
264 private void CountDownEventHandler(object? sender, EventArgs e)
265 {
266 if (this.CountDownTimer is not null)
267 {
268 if (this.CountDownSeconds > 0)
269 this.CountDownSeconds--;
270 else
271 this.CountDownTimer.Stop();
272 }
273 }
274 }
275}
The Application class, representing an instance of the Neuro-Access app.
Definition: App.xaml.cs:69
static new? App Current
Gets the current application, type casted to App.
Definition: App.xaml.cs:99
const string IdDomain
Neuro-Access domain.
Definition: Constants.cs:253
A set of never changing property constants and helpful values.
Definition: Constants.cs:7
Base class that references services in the app.
Definition: ServiceRef.cs:31
static ILogService LogService
Log service.
Definition: ServiceRef.cs:91
static INetworkService NetworkService
Network service.
Definition: ServiceRef.cs:103
static IUiService UiService
Service serializing and managing UI-related tasks.
Definition: ServiceRef.cs:55
static ITagProfile TagProfile
TAG Profile service.
Definition: ServiceRef.cs:79
static IStringLocalizer Localizer
Localization service
Definition: ServiceRef.cs:235
An base class holding page specific navigation parameters.
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).
string? Account
The account name for this profile
Definition: ITagProfile.cs:101
string? EMail
Verified e-mail address.
Definition: ITagProfile.cs:96
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.
RegistrationStep
The different steps of a TAG Profile registration journey.
BackMethod
Navigation Back Method
Definition: BackMethod.cs:7