Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
ObservableParameter.cs
1using System.ComponentModel;
2using System.Globalization;
3using CommunityToolkit.Mvvm.ComponentModel;
4using CommunityToolkit.Mvvm.Input;
10using Waher.Content;
14
16{
21 public partial class ObservableParameter : ObservableObject
22 {
23 #region Constructor
24 protected ObservableParameter(Parameter parameter)
25 {
26 this.Parameter = parameter;
27 }
28 #endregion
29
30 #region Initialization
34 private async Task InitializeAsync(Contract contract)
35 {
36 try
37 {
38 string UntrimmedDescription = await contract.ToPlainText(this.Parameter.Descriptions, contract.DeviceLanguage());
39 this.Description = UntrimmedDescription.Trim();
40 }
41 catch (Exception E)
42 {
43 ServiceRef.LogService.LogException(E);
44 }
45 }
46
53 public static async Task<ObservableParameter> CreateAsync(Parameter parameter, Contract contract)
54 {
55 ObservableParameter ParameterInfo = parameter switch
56 {
68 _ => new ObservableParameter(parameter)
69 };
70
71 await ParameterInfo.InitializeAsync(contract);
72
73 if(ParameterInfo.Parameter is RoleParameter RP)
74 {
75 if(RP.Value is not null && RP.Value is string RoleValue && string.IsNullOrEmpty(RoleValue))
76 {
77 RP.SetValue(null);
78 }
79 }
80 else if (ParameterInfo.Parameter is CalcParameter CP)
81 {
82 if (string.IsNullOrEmpty(CP.StringValue))
83 CP.SetValue(null);
84 }
85
86 return ParameterInfo;
87 }
88 #endregion
89
90 #region Properties
94 public Parameter Parameter { get; private set; }
95
99 public string Name => this.Parameter.Name;
100
104 public string Guide => string.IsNullOrEmpty(this.Parameter.Guide) ? this.Name : this.Parameter.Guide;
105
109 public string Label
110 {
111 get
112 {
113 if (string.IsNullOrEmpty(this.Description))
114 {
115 if (string.IsNullOrEmpty(this.Guide))
116 {
117 return this.Name;
118 }
119 return this.Guide;
120 }
121 return this.Description;
122 }
123 }
124
128 public string Description
129 {
130 get => this.description;
131 private set
132 {
133 if (this.SetProperty(ref this.description, value))
134 this.OnPropertyChanged(nameof(this.Label));
135 }
136 }
137 private string description = string.Empty;
138
142 public bool IsValid
143 {
144 get => this.isValid;
145 set => this.SetProperty(ref this.isValid, value);
146 }
147 private bool isValid = true;
148
152 public string ValidationText
153 {
154 get => this.validationText;
155 set
156 {
157 this.SetProperty(ref this.validationText, value);
158 this.OnPropertyChanged(nameof(this.CanShowError));
159 this.ShowErrorCommand.NotifyCanExecuteChanged();
160 }
161 }
162 private string validationText = string.Empty;
163
167 private object? value;
168 public object? Value
169 {
170 get => this.value;
171 set
172 {
173 if (value is null)
174 return;
175 try
176 {
177 this.Parameter.SetValue(value);
178 }
179 catch (Exception E)
180 {
181 ServiceRef.LogService.LogException(E);
182 }
183 this.value = value;
184 this.OnPropertyChanged(nameof(this.Value));
185 this.OnPropertyChanged(nameof(this.CanReadValue));
186 }
187 }
188
192 public bool IsTransient => this.Parameter.Protection == ProtectionLevel.Transient;
193
197 public bool IsEncrypted => this.Parameter.Protection == ProtectionLevel.Encrypted;
198
202 public bool IsProtected => this.IsTransient || this.IsEncrypted;
203
208 public bool CanReadValue => this.IsProtected ? this.Parameter.ObjectValue is not null : this.Parameter.CanSerializeValue;
209 #endregion
210
211 public bool CanShowError => !string.IsNullOrEmpty(this.ValidationText);
212 #region Commands
213
214
215 [RelayCommand(CanExecute = nameof(CanShowError), AllowConcurrentExecutions = false)]
216 private async Task ShowError()
217 {
218 if (string.IsNullOrEmpty(this.ValidationText))
219 return;
220 ShowInfoPopup Popup = new ShowInfoPopup(this.Parameter.ErrorReason?.ToString() ?? ServiceRef.Localizer[nameof(AppResources.Error)], this.ValidationText);
221 await ServiceRef.PopupService.PushAsync(Popup);
222 }
223 #endregion
224
225 #region Property Change Handling
226 protected override void OnPropertyChanged(PropertyChangedEventArgs e)
227 {
228 base.OnPropertyChanged(e);
229 }
230 #endregion
231 }
232
233 #region ObservableParameter Subclasses
235 {
236 public ObservableBooleanParameter(BooleanParameter parameter) : base(parameter)
237 {
238 this.Value = parameter.ObjectValue is true;
239 }
240
241 public bool BooleanValue
242 {
243 get => this.Value as bool? ?? false;
244 set => this.Value = value;
245 }
246
247 [RelayCommand]
248 private void ToggleBooleanValue()
249 {
250 MainThread.BeginInvokeOnMainThread(() =>
251 {
252 this.BooleanValue = !this.BooleanValue;
253 this.OnPropertyChanged(nameof(this.BooleanValue));
254 });
255 }
256 }
257
259 {
260 public ObservableDateParameter(DateParameter parameter) : base(parameter)
261 {
262 this.Value = parameter.ObjectValue as DateTime?;
263 }
264
265 public DateTime? DateValue
266 {
267 get => this.Value as DateTime?;
268 set => this.Value = value;
269 }
270 }
271
273 {
274 public ObservableNumericalParameter(NumericalParameter parameter) : base(parameter)
275 {
276 this.Value = parameter.ObjectValue is decimal DecimalValue ? DecimalValue : null;
277 }
278
279 public decimal? DecimalValue
280 {
281 get => this.Value as decimal?;
282 set => this.Value = value;
283 }
284 }
285
287 {
288 public ObservableStringParameter(StringParameter parameter) : base(parameter)
289 {
290 this.Value = parameter.ObjectValue as string ?? string.Empty;
291 }
292
293 public string StringValue
294 {
295 get => this.Value as string ?? string.Empty;
296 set => this.Value = value;
297 }
298 }
299
301 {
302 public ObservableTimeParameter(TimeParameter parameter) : base(parameter)
303 {
304 this.Value = parameter.ObjectValue is TimeSpan TimeSpan ? TimeSpan : TimeSpan.Zero;
305 }
306
307 public TimeSpan TimeSpanValue
308 {
309 get => this.Value as TimeSpan? ?? TimeSpan.Zero;
310 set => this.Value = value;
311 }
312 }
313
315 {
316 public ObservableDurationParameter(DurationParameter parameter) : base(parameter)
317 {
318 this.Value = parameter.ObjectValue is Duration Duration ? Duration : Duration.Zero;
319 }
320
321 public string StringValue
322 {
323 get => this.Value?.ToString() ?? string.Empty;
324 set
325 {
326 if (Duration.TryParse(value, out Duration DurationValue))
327 this.Value = DurationValue;
328 else
329 this.Value = null;
330 }
331 }
332
333 public Duration DurationValue
334 {
335 get => this.Value as Duration? ?? Duration.Zero;
336 set
337 {
338 if (Duration.TryParse(value.ToString(), out Duration DurationValue))
339 this.Value = DurationValue;
340 else
341 this.Value = null;
342
343 }
344 }
345 }
346
348 {
349 public ObservableRoleParameter(RoleParameter parameter) : base(parameter)
350 {
351 this.Value = parameter.ObjectValue as string ?? string.Empty;
352 }
353
354 public string RoleValue
355 {
356 get => this.Value as string ?? string.Empty;
357 set => this.Value = value;
358 }
359 }
360
362 {
363 public ObservableCalcParameter(CalcParameter parameter) : base(parameter)
364 {
365 this.Value = parameter.ObjectValue;
366 }
367
368 public object? CalcValue
369 {
370 get => this.Value;
371 set => this.Value = value;
372 }
373
374 public string CalcString
375 {
376 get
377 {
378 if (this.Value is null)
379 this.Value = this.Parameter.StringValue;
380
381 CultureInfo Culture = CultureInfo.CurrentCulture;
382
383 Console.WriteLine(this.Value.GetType().Name);
384
385 return this.Value switch
386 {
387 decimal DecimalValue => DecimalValue.ToString("N", Culture), // Number format with localization
388 DateTime DateTimeValue => DateTimeValue.ToString("G", Culture), // Localized date format
389 TimeSpan TimeSpanValue => TimeSpanValue.ToString(@"hh\:mm\:ss", Culture), // Time format
390 string StringValue => string.IsNullOrEmpty(StringValue) ? "-" : StringValue,
391 _ => this.Value.ToString() ?? string.Empty // Fallback for unknown types
392 };
393 }
394 }
395 }
396
398 {
399 public ObservableDateTimeParameter(DateTimeParameter parameter) : base(parameter)
400 {
401 // Extract initial value from parameter
402 if (parameter.ObjectValue is DateTime Dt)
403 this.Value = Dt;
404 else
405 this.Value = parameter.Min; // or DateTime.MinValue as a fallback
406 }
407
412 public DateTime? DateTimeValue
413 {
414 get => this.Value as DateTime?;
415 set => this.Value = value;
416 }
417
421 public DateTime? SelectedDate
422 {
423 get => this.DateTimeValue?.Date;
424 set
425 {
426 if (value.HasValue)
427 {
428 DateTime Current = this.DateTimeValue ?? DateTime.MinValue;
429 this.DateTimeValue = new DateTime(value.Value.Year, value.Value.Month, value.Value.Day, Current.Hour, Current.Minute, Current.Second);
430 }
431 else
432 {
433 this.DateTimeValue = null;
434 }
435 }
436 }
437
441 public TimeSpan SelectedTime
442 {
443 get => this.DateTimeValue?.TimeOfDay ?? TimeSpan.Zero;
444 set
445 {
446 DateTime Current = this.DateTimeValue ?? DateTime.MinValue;
447 this.DateTimeValue = Current.Date + value;
448 }
449 }
450 }
451
453 {
454 public ObservableContractReferenceParameter(ContractReferenceParameter parameter) : base(parameter)
455 {
456 ServiceRef.LogService.LogDebug($"{this.Value} - {this.Parameter.ObjectValue}");
457 this.Value = this.Parameter.ObjectValue;
458 //this.Value = parameter.ObjectValue as string ?? string.Empty;
459 }
460
461 public string ContractReferenceValue
462 {
463 get => this.Value?.ToString() ?? string.Empty;
464 set => this.Value = value;
465 }
466
467 [RelayCommand(AllowConcurrentExecutions = false)]
468 private async Task OpenContract()
469 {
470 if (string.IsNullOrEmpty(this.ContractReferenceValue))
471 {
472 return;
473 }
474 try
475 {
476 await ServiceRef.ContractOrchestratorService.OpenContract(this.ContractReferenceValue, ServiceRef.Localizer[nameof(AppResources.RequestToAccessContract)], null);
477 }
478 catch (Exception Ex)
479 {
480 ServiceRef.LogService.LogException(Ex);
481 }
482 }
483
484 [RelayCommand(AllowConcurrentExecutions = false)]
485 private async Task PickContractReferenceAsync()
486 {
487 try
488 {
489 TaskCompletionSource<Contract?> TaskCompletionSource = new();
490 MyContractsNavigationArgs Args = new MyContractsNavigationArgs(ContractsListMode.Contracts, TaskCompletionSource);
491 await ServiceRef.NavigationService.GoToAsync(nameof(MyContractsPage), Args);
492 Contract? Contract = await TaskCompletionSource.Task;
493
494 MainThread.BeginInvokeOnMainThread(() =>
495 {
496 if (Contract is null)
497 return;
498 this.ContractReferenceValue = Contract?.ContractId ?? string.Empty;
499 this.OnPropertyChanged(nameof(this.ContractReferenceValue));
500 });
501 }
502 catch (Exception E)
503 {
504 ServiceRef.LogService.LogException(E);
505 }
506 }
507 }
508
509 // Class for ObservableGeoParameter
511 {
512 public ObservableGeoParameter(GeoParameter parameter) : base(parameter)
513 {
514 this.Value = parameter.ObjectValue;
515 }
516
517 public GeoPosition? GeoValue
518 {
519 get => this.Value as GeoPosition;
520 set => this.Value = value;
521 }
522
523 public string GeoString
524 {
525 get => this.GeoValue?.ToString() ?? string.Empty;
526 set
527 {
528 if (GeoPosition.TryParse(value, out GeoPosition? GeoValue))
529 this.Value = GeoValue;
530 else
531 this.Value = null;
532 }
533 }
534
535 [ObservableProperty]
536 bool isCheckinglocation;
537
538 [RelayCommand(AllowConcurrentExecutions = false)]
539 private async Task SetCurrentLocationAsync()
540 {
541 try
542 {
543 MainThread.BeginInvokeOnMainThread(() => this.IsCheckinglocation = true);
544
545 GeolocationRequest Request = new GeolocationRequest(GeolocationAccuracy.Best, TimeSpan.FromSeconds(10));
546 Location? Location = await Geolocation.Default.GetLocationAsync(Request);
547
548 if (Location is not null)
549 {
550 MainThread.BeginInvokeOnMainThread(() =>
551 {
552 this.GeoValue = new GeoPosition(Location.Latitude, Location.Longitude);
553 this.OnPropertyChanged(nameof(this.GeoString));
554 });
555 }
556 }
557 catch
558 {
559 // Ignore this case
560 // Display an alert requesting permission
561 await ServiceRef.UiService.DisplayAlert(
565 );
566 }
567 finally
568 {
569 MainThread.BeginInvokeOnMainThread(() => this.IsCheckinglocation = false);
570 }
571 }
572 }
573}
574#endregion
A strongly-typed resource class, for looking up localized strings, etc.
static string RequestToAccessContract
Looks up a localized string similar to Request to access contract.
static string Ok
Looks up a localized string similar to OK.
static string LocationError
Looks up a localized string similar to There was an error getting your location. Make sure location p...
static string Error
Looks up a localized string similar to Error.
Base class that references services in the app.
Definition: ServiceRef.cs:43
static ILogService LogService
Log service.
Definition: ServiceRef.cs:214
static IUiService UiService
Service serializing and managing UI-related tasks.
Definition: ServiceRef.cs:130
static INavigationService NavigationService
The navigation service for navigating between pages.
Definition: ServiceRef.cs:178
static IPopupService PopupService
Popup service for presenting application popups.
Definition: ServiceRef.cs:142
static IContractOrchestratorService ContractOrchestratorService
Contract orchestrator service.
Definition: ServiceRef.cs:238
static IReportingStringLocalizer Localizer
Localization service
Definition: ServiceRef.cs:370
Holds navigation parameters specific to views displaying a list of contacts.
A page that displays a list of the current user's contracts.
DateTime? DateTimeValue
The DateTime value of the parameter. When changed, updates the underlying parameter value.
TimeSpan SelectedTime
Helper to get or set just the Time portion.
DateTime? SelectedDate
Helper to get or set just the Date portion.
An observable object that wraps a Waher.Networking.XMPP.Contracts.Parameter object....
static async Task< ObservableParameter > CreateAsync(Parameter parameter, Contract contract)
Creates a new instance of ObservableParameter based on the type of the parameter.
bool IsProtected
If the parameter is protected, either encrypted or transient
string Description
The localized description of the parameter
string Label
Label that determines the displayed text for the parameter.
bool CanReadValue
If the parameter can be read, for example encrypted parameters cannot be read if you don't have the k...
Calculation contractual parameter
override object ObjectValue
Parameter value.
Contains the definition of a contract
Definition: Contract.cs:22
Task< string > ToPlainText(string Language)
Creates a human-readable Plain Trext document for the contract.
Definition: Contract.cs:2081
string ContractId
Contract identity
Definition: Contract.cs:65
Geo-spatial contractual parameter
Definition: GeoParameter.cs:17
override object ObjectValue
Parameter value.
Definition: GeoParameter.cs:96
HumanReadableText[] Descriptions
Discriptions of the object, in different languages.
Abstract base class for contractual parameters
Definition: Parameter.cs:17
bool CanSerializeValue
If the value can be serialized in the clear.
Definition: Parameter.cs:81
abstract string StringValue
String representation of value.
Definition: Parameter.cs:110
abstract void SetValue(object Value)
Sets the parameter value.
abstract object ObjectValue
Parameter value.
Definition: Parameter.cs:104
string Guide
Parameter guide text
Definition: Parameter.cs:40
ParameterErrorReason? ErrorReason
After IsParameterValid(Variables) or IsParameterValid(Variables, ContractsClient) has been execited,...
Definition: Parameter.cs:120
override object ObjectValue
Parameter value.
Role-reference contractual parameter
String-valued contractual parameter
Contains information about a position in a geo-spatial coordinate system.
Definition: GeoPosition.cs:17
static bool TryParse(string s, out GeoPosition Value)
Tries to parse a string representation of a GeoPosition. If first attempts the XML format....
Definition: GeoPosition.cs:154
Definition: ImplTypes.g.cs:58
ProtectionLevel
Parameter protection levels
Represents a duration value, as defined by the xsd:duration data type: http://www....
Definition: Duration.cs:14
static bool TryParse(string s, out Duration Result)
Tries to parse a duration value.
Definition: Duration.cs:86
static readonly Duration Zero
Zero value
Definition: Duration.cs:577