1using CommunityToolkit.Mvvm.ComponentModel;
2using CommunityToolkit.Mvvm.Input;
19using System.Collections.ObjectModel;
20using System.ComponentModel;
36 private readonly SortedDictionary<CaseInsensitiveString, ParameterInfo> parametersByName = [];
37 private readonly LinkedList<ParameterInfo> parametersInOrder =
new();
38 private readonly Dictionary<CaseInsensitiveString, object> presetParameterValues = [];
40 private readonly
string? templateId;
42 private bool saveStateWhileScanning;
43 private Contract? stateTemplateWhileScanning;
44 private readonly Dictionary<CaseInsensitiveString, string> parts = [];
47 private Timer? populateTimer =
null;
60 this.template = Args.Template;
61 this.suppressedProposalIds = Args.SuppressedProposalLegalIds;
63 if (Args.ParameterValues is not
null)
64 this.presetParameterValues = Args.ParameterValues;
66 if (Args.SetVisibility)
67 this.initialVisibility = Args.Template?.Visibility;
69 if (this.
template is not
null)
70 this.template.FormatParameterDisplay += this.Template_FormatParameterDisplay;
72 else if (this.stateTemplateWhileScanning is not
null)
74 this.template = this.stateTemplateWhileScanning;
75 this.stateTemplateWhileScanning =
null;
77 this.template.FormatParameterDisplay += this.Template_FormatParameterDisplay;
80 this.templateId = this.
template?.ContractId ??
string.Empty;
81 this.IsTemplate = this.
template?.CanActAsTemplate ??
false;
95 GC.SuppressFinalize(
this);
101 protected virtual void Dispose(
bool Disposing)
103 if (this.populateTimer is not
null)
107 this.populateTimer.Dispose();
115 this.populateTimer =
null;
123 await base.OnInitialize();
125 await this.PopulateTemplateForm(this.initialVisibility);
132 if (this.
template is not
null)
133 this.template.FormatParameterDisplay -= this.Template_FormatParameterDisplay;
137 this.ClearTemplate(
false);
139 if (!this.saveStateWhileScanning)
146 await base.OnDispose();
158 await base.DoSaveState();
160 if (this.SelectedContractVisibilityItem is not
null)
165 if (this.SelectedRole is not
null)
178 private bool HasParts => this.parts.Count > 0;
183 if (this.saveStateWhileScanning)
190 string? SelectedRole = this.
AvailableRoles.FirstOrDefault(x => x.Equals(LastRole, StringComparison.Ordinal));
192 if (!
string.IsNullOrWhiteSpace(SelectedRole))
193 this.SelectedRole = SelectedRole;
196 if (LastParts is not
null)
197 this.Parts = LastParts;
201 foreach (KeyValuePair<CaseInsensitiveString, string>
Part in this.parts)
202 await this.AddRole(
Part.Key,
Part.Value);
205 await this.DeleteState();
208 this.saveStateWhileScanning =
false;
209 await base.DoRestoreState();
212 private async Task DeleteState()
225 [NotifyCanExecuteChangedFor(nameof(ProposeCommand))]
226 private bool isProposing;
232 private bool isTemplate;
248 base.OnPropertyChanging(e);
250 switch (e.PropertyName)
252 case nameof(this.SelectedRole):
253 if (this.SelectedRole is not
null)
264 base.OnPropertyChanged(e);
266 switch (e.PropertyName)
268 case nameof(this.SelectedContractVisibilityItem):
269 if (this.
template is not
null && this.SelectedContractVisibilityItem is not
null)
270 this.template.Visibility = this.SelectedContractVisibilityItem.Visibility;
273 case nameof(this.SelectedRole):
274 if (this.
template is not
null && !
string.IsNullOrWhiteSpace(this.SelectedRole))
289 private bool visibilityIsEnabled;
305 private string? selectedRole;
311 private VerticalStackLayout? roles;
317 private VerticalStackLayout? parameters;
323 private VerticalStackLayout? humanReadableText;
329 private bool hasRoles;
335 private bool hasParameters;
341 [NotifyCanExecuteChangedFor(nameof(ProposeCommand))]
342 private bool parametersOk;
348 private bool hasHumanReadableText;
354 private bool canAddParts;
359 public Dictionary<string, object>
Parts
363 Dictionary<string, object> Result = [];
365 foreach (KeyValuePair<CaseInsensitiveString, string>
Part in this.parts)
366 Result[
Part.Key.Value] =
Part.Value;
375 foreach (KeyValuePair<string, object> P
in value)
376 this.parts[P.Key] = P.Value?.ToString() ??
string.Empty;
382 private void ClearTemplate(
bool propertiesOnly)
385 this.template =
null;
387 this.SelectedRole =
null;
391 this.HasRoles =
false;
393 this.Parameters =
null;
394 this.HasParameters =
false;
396 this.HumanReadableText =
null;
397 this.HasHumanReadableText =
false;
399 this.CanAddParts =
false;
400 this.VisibilityIsEnabled =
false;
403 private void RemoveRole(
string Role,
string LegalId)
405 Label? ToRemove =
null;
407 if (this.Roles is
null)
410 if (this.
template?.
Parts is not
null)
412 List<Part>
Parts = [];
414 foreach (
Part Part in this.
template.Parts)
420 this.template.Parts = [..
Parts];
423 if (this.Roles is not
null)
425 foreach (IView FrameView
in this.Roles.Children)
427 if (FrameView is Frame RoleFrame && RoleFrame.Content is VerticalStackLayout RoleLayout)
431 foreach (IView View
in RoleLayout.Children)
436 if (View is Label Label && Label.StyleId ==
Role)
443 if (ToRemove is not
null)
445 RoleLayout.Children.Remove(ToRemove);
446 Button.IsEnabled =
true;
450 else if (View is Label Label2 && Label2.StyleId == LegalId)
460 private async Task AddRole(
string Role,
string LegalId)
462 Contract? contractToUse = this.template ?? this.stateTemplateWhileScanning;
464 if ((contractToUse is
null) || (this.Roles is
null))
467 Role? RoleObj =
null;
481 if (this.
template is not
null)
483 List<Part>
Parts = [];
485 if (this.
template.Parts is not
null)
487 foreach (
Part Part in this.
template.Parts)
500 this.template.Parts = [..
Parts];
503 if (this.Roles is not
null)
508 bool LegalIdAdded =
false;
510 foreach (IView FrameView
in this.Roles.Children)
512 if (FrameView is Frame RoleFrame && RoleFrame.Content is VerticalStackLayout RoleLayout)
517 foreach (IView View
in RoleLayout.Children)
519 if (View is Label Label)
521 if (Label.StyleId ==
Role)
528 if (Label.StyleId == LegalId)
546 FontAttributes = FontAttributes.Bold,
548 Style = AppStyles.ClickableValueLabel
551 TapGestureRecognizer OpenLegalId =
new();
552 OpenLegalId.Tapped += this.LegalId_Tapped;
554 Label.GestureRecognizers.Add(OpenLegalId);
556 RoleLayout.Insert(i, Label);
560 Button.IsEnabled =
false;
562 if (FriendlyName == LegalId)
564 await Task.Run(async () =>
569 if (Identity is not
null)
571 MainThread.BeginInvokeOnMainThread(() =>
574 Label.Text = FriendlyName;
586 LegalIdAdded =
false;
598 private async
void LegalId_Tapped(
object? Sender, EventArgs e)
602 if (Sender is Label label && !
string.IsNullOrEmpty(label.StyleId))
615 private async
void AddPartButton_Clicked(
object? Sender, EventArgs e)
621 this.saveStateWhileScanning =
true;
622 this.stateTemplateWhileScanning = this.
template;
626 bool HasContacts =
false;
636 TaskCompletionSource<ContactInfoModel?> Selected =
new();
639 CanScanQrCode =
true,
654 if (
string.IsNullOrEmpty(Code))
660 if (
string.IsNullOrEmpty(LegalId))
664 this.parts[Button.StyleId] = LegalId;
667 foreach (KeyValuePair<CaseInsensitiveString, string> part
in this.parts)
668 await this.AddRole(part.Key, part.Value);
679 private async
void Parameter_DateChanged(
object? Sender, NullableDateChangedEventArgs e)
683 if (Sender is not
ExtendedDatePicker Picker || !this.parametersByName.TryGetValue(Picker.StyleId, out ParameterInfo? ParameterInfo))
688 if (e.NewDate is not
null)
689 DP.Value = e.NewDate;
697 await this.ValidateParameters();
698 await this.PopulateHumanReadableText();
706 private async
void Parameter_TextChanged(
object? Sender, TextChangedEventArgs e)
710 if (Sender is not Entry Entry ||
711 !this.parametersByName.TryGetValue(Entry.StyleId, out ParameterInfo? ParameterInfo))
720 SP.Value = e.NewTextValue;
725 if (Ok = decimal.TryParse(e.NewTextValue, out decimal d))
735 if (Ok = DateTime.TryParse(e.NewTextValue, out DateTime TP))
740 if (Ok = TimeSpan.TryParse(e.NewTextValue, out TimeSpan TS))
745 if (Ok = (ParameterInfo.DurationValue !=
Duration.
Zero))
746 DP.Value = ParameterInfo.DurationValue;
760 Entry.BackgroundColor = BgColor;
762 if (compositeEntry is not
null)
764 compositeEntry.BackgroundColor = BgColor;
765 compositeEntry.Border.BackgroundColor = BgColor;
773 await this.ValidateParameters();
774 if (this.populateTimer is not
null)
778 this.populateTimer.Dispose();
786 this.populateTimer =
null;
789 this.populateTimer =
new Timer(this.PopulateTimer_Callback,
null, 3000, Timeout.Infinite);
797 private async
void PopulateTimer_Callback(
object? obj)
799 this.populateTimer?.Dispose();
801 this.populateTimer =
null;
802 await this.PopulateHumanReadableText();
805 private async
void Parameter_CheckedChanged(
object? Sender, CheckedChangedEventArgs e)
809 if (Sender is not CheckBox CheckBox || !this.parametersByName.TryGetValue(CheckBox.StyleId, out ParameterInfo? ParameterInfo))
815 await this.ValidateParameters();
816 await this.PopulateHumanReadableText();
824 private async Task ValidateParameters()
830 if (this.
template is not
null)
831 Variables[
"Duration"] = this.
template.Duration;
833 foreach (ParameterInfo P
in this.parametersInOrder)
836 foreach (ParameterInfo P
in this.parametersInOrder)
855 if (P.Control is not
null)
856 P.Control.BackgroundColor = Color;
858 if (P.AltColorElement is View Label)
859 Label.BackgroundColor = Color;
862 this.ParametersOk = Ok;
865 [RelayCommand(CanExecute = nameof(CanPropose))]
866 private async Task Propose()
868 if (this.
template is
null)
871 List<Part>
Parts = [];
873 string Role =
string.Empty;
879 this.IsProposing =
true;
882 if (this.Roles is not
null)
884 foreach (IView FrameView
in this.Roles.Children)
886 if (FrameView is Frame RoleFrame && RoleFrame.Content is VerticalStackLayout RoleLayout)
890 foreach (IView View
in RoleLayout.Children)
895 if (View is Label Label && !
string.IsNullOrEmpty(Label.StyleId))
897 Role = Label.StyleId;
901 foreach (
Role R
in this.
template.Roles)
933 else if (View is Label Label2 && !
string.IsNullOrEmpty(
Role))
938 LegalId = Label2.StyleId
950 if (this.Parameters is not
null)
952 foreach (IView View
in this.Parameters.Children)
954 if (View is Entry Entry)
970 int i = this.SelectedContractVisibilityItem is
null ? -1 : this.
ContractVisibilityItems.IndexOf(this.SelectedContractVisibilityItem);
995 if (this.SelectedRole is
null)
1012 if (Created.
Parts is not
null)
1020 if (Info is
null ||
string.IsNullOrEmpty(Info.
BareJid))
1030 if (!
string.IsNullOrEmpty(Proposal))
1035 catch (Exception ex)
1042 this.IsProposing =
false;
1044 if (Created is not
null)
1046 ViewContractNavigationArgs Args =
new(Created,
false);
1054 internal static IView ParseXaml(
string Xaml)
1056 VerticalStackLayout VerticalLayout =
new VerticalStackLayout().LoadFromXaml(Xaml);
1058 IView? First =
null;
1060 foreach (IView Element
in VerticalLayout.Children)
1065 return VerticalLayout;
1068 return First ?? VerticalLayout;
1071 internal static void Populate(VerticalStackLayout Layout,
string Xaml)
1073 VerticalStackLayout VerticalLayout =
new VerticalStackLayout().LoadFromXaml(Xaml);
1075 foreach (IView Element
in VerticalLayout.Children)
1076 Layout.Children.Add(Element);
1079 internal static void Populate(HorizontalStackLayout Layout,
string Xaml)
1081 VerticalStackLayout VerticalLayout =
new VerticalStackLayout().LoadFromXaml(Xaml);
1083 foreach (IView Element
in VerticalLayout.Children)
1084 Layout.Children.Add(Element);
1089 this.ClearTemplate(
true);
1091 if (this.
template is
null)
1094 await this.PopulateHumanReadableText();
1096 this.HasRoles = (this.
template.Roles?.Length ?? 0) > 0;
1097 this.VisibilityIsEnabled =
true;
1099 VerticalStackLayout RolesLayout = [];
1100 if (this.
template.Roles is not
null)
1102 foreach (
Role Role in this.
template.Roles)
1107 VerticalStackLayout RoleLayout =
1117 Populate(RoleLayout, await
Role.ToMauiXaml(
this.template.DeviceLanguage(),
this.template));
1126 Margin = AppStyles.SmallBottomMargins
1128 Button.Clicked += this.AddPartButton_Clicked;
1130 RoleLayout.Children.Add(Button);
1133 Frame RoleFrame =
new()
1136 Content = RoleLayout
1139 RolesLayout.Children.Add(RoleFrame);
1143 this.Roles = RolesLayout;
1145 VerticalStackLayout ParametersLayout = [];
1147 this.parametersByName.Clear();
1148 this.parametersInOrder.Clear();
1154 CheckBox CheckBox =
new()
1157 IsChecked = BP.Value.HasValue && BP.Value.Value,
1158 VerticalOptions = LayoutOptions.Center
1165 new ColumnDefinition(GridLength.Auto)
1169 new RowDefinition(GridLength.Auto),
1170 new RowDefinition(GridLength.Star)
1172 Margin = AppStyles.SmallBottomMargins
1175 IView Label = ParseXaml(await
Parameter.ToMauiXaml(
this.template.DeviceLanguage(),
this.template));
1177 Layout.Add(CheckBox, 0, 0);
1178 Layout.Add(Label, 1, 0);
1179 ParametersLayout.Children.Add(Layout);
1181 CheckBox.CheckedChanged += this.Parameter_CheckedChanged;
1183 ParameterInfo PI =
new(
Parameter, CheckBox, Layout);
1185 this.parametersInOrder.AddLast(PI);
1187 if (this.presetParameterValues.TryGetValue(
Parameter.
Name, out
object? PresetValue))
1191 if (PresetValue is
bool b ||
CommonTypes.
TryParse(PresetValue?.ToString() ??
string.Empty, out b))
1192 CheckBox.IsChecked = b;
1197 ParameterInfo PI =
new(
Parameter,
null);
1199 this.parametersInOrder.AddLast(PI);
1205 Populate(ParametersLayout, await
Parameter.ToMauiXaml(
this.template.DeviceLanguage(),
this.template));
1207 Border Border =
new()
1209 StrokeThickness = 2,
1211 Margin = AppStyles.SmallBottomMargins
1217 NullableDate = Parameter.ObjectValue as DateTime?,
1218 Placeholder = Parameter.Guide
1221 Border.Content = Picker;
1222 ParametersLayout.Children.Add(Border);
1224 Picker.NullableDateSelected += this.Parameter_DateChanged;
1226 ParameterInfo PI =
new(
Parameter, Picker, Border);
1228 this.parametersInOrder.AddLast(PI);
1230 if (this.presetParameterValues.TryGetValue(
Parameter.
Name, out
object? PresetValue))
1234 if (PresetValue is DateTime TP ||
XML.
TryParse(PresetValue?.ToString() ??
string.Empty, out TP))
1240 Populate(ParametersLayout, await
Parameter.ToMauiXaml(
this.template.DeviceLanguage(),
this.template));
1248 Margin = AppStyles.SmallBottomMargins
1260 Height = GridLength.Auto
1265 new ColumnDefinition()
1267 Width = GridLength.Star
1269 new ColumnDefinition()
1271 Width = GridLength.Auto
1276 Padding =
new Thickness(0),
1277 Margin =
new Thickness(0),
1278 VerticalOptions = LayoutOptions.Center
1281 Entry.VerticalOptions = LayoutOptions.Center;
1282 Grid.Add(Entry, 0, 0);
1289 HorizontalOptions = LayoutOptions.Center,
1290 VerticalOptions = LayoutOptions.Center
1294 CalcButton.Clicked += this.CalcButton_Clicked;
1296 CalcButton.Clicked += this.DurationButton_Clicked;
1298 Grid.Add(CalcButton, 1, 0);
1300 ParametersLayout.Children.Add(Grid);
1304 ParametersLayout.Children.Add(Entry);
1307 Entry.Entry.TextChanged += this.Parameter_TextChanged;
1309 ParameterInfo ParameterInfo =
new(
Parameter, Entry);
1313 Entry.IsReadOnly =
true;
1315 Entry.BindingContext = ParameterInfo;
1319 this.parametersInOrder.AddLast(ParameterInfo);
1321 if (this.presetParameterValues.TryGetValue(
Parameter.
Name, out
object? PresetValue))
1324 Entry.EntryData = PresetValue?.ToString() ??
string.Empty;
1329 this.Parameters = ParametersLayout;
1330 this.HasParameters = this.Parameters.Children.Count > 0;
1332 if (this.
template.Parts is not
null)
1334 foreach (
Part Part in this.
template.Parts)
1343 if (this.presetParameterValues.TryGetValue(
"Visibility", out
object? Obj) &&
1344 (Obj is
ContractVisibility Visibility2 || Enum.TryParse(Obj?.ToString() ??
string.Empty, out Visibility2)))
1346 Visibility = Visibility2;
1347 this.presetParameterValues.Remove(
"Visibility");
1350 if (Visibility.HasValue)
1351 this.SelectedContractVisibilityItem = this.
ContractVisibilityItems.FirstOrDefault(x => x.Visibility == Visibility.Value);
1357 if (this.presetParameterValues.TryGetValue(
Role, out Obj) && Obj is
string LegalId)
1359 int i = LegalId.IndexOf(
'@');
1360 if (i < 0 || !Guid.TryParse(LegalId[..i], out _))
1363 await this.AddRole(
Role, LegalId);
1364 this.presetParameterValues.Remove(
Role);
1366 else if (this.
template.Parts is not
null)
1368 foreach (
Part Part in this.
template.Parts)
1377 if (this.presetParameterValues.TryGetValue(
"Role", out Obj) && Obj is
string SelectedRole)
1379 this.SelectedRole = SelectedRole;
1380 this.presetParameterValues.Remove(
"Role");
1383 await this.ValidateParameters();
1386 private async Task PopulateHumanReadableText()
1388 VerticalStackLayout humanReadableTextLayout = [];
1390 if (this.
template is not
null)
1391 Populate(humanReadableTextLayout, await this.
template.ToMauiXaml(this.
template.DeviceLanguage()));
1394 this.HumanReadableText = humanReadableTextLayout;
1395 this.HasHumanReadableText = humanReadableTextLayout.Children.Count > 0;
1400 private bool CanPropose()
1403 this.template is not
null &&
1404 this.ParametersOk &&
1408 private async
void CalcButton_Clicked(
object? Sender, EventArgs e)
1412 if (Sender is not Controls.ImageButton CalcButton)
1415 if (!this.parametersByName.TryGetValue(CalcButton.StyleId, out ParameterInfo? ParameterInfo))
1424 catch (Exception ex)
1430 private async
void DurationButton_Clicked(
object? Sender, EventArgs e)
1434 if (Sender is not Controls.ImageButton CalcButton)
1437 if (!this.parametersByName.TryGetValue(CalcButton.StyleId, out ParameterInfo? ParameterInfo))
1443 DurationNavigationArgs Args =
new(Entry.Entry);
1446 catch (Exception ex)
1452 #region ILinkableView
1471 StringBuilder Url =
new();
1476 Url.Append(this.
template?.ContractId);
1478 foreach (KeyValuePair<CaseInsensitiveString, ParameterInfo> P
in this.parametersByName)
1491 if (P.Value.Control is Entry Entry)
1492 Url.Append(Entry.Text);
1493 else if (P.Value.Control is CheckBox CheckBox)
1494 Url.Append(CheckBox.IsChecked ?
'1' :
'0');
1498 Url.Append(
XML.
Encode(Picker.Date,
true));
1500 Url.Append(
XML.
Encode(Picker.Date,
false));
1503 P.Value.Parameter.ObjectValue?.ToString();
1506 return Url.ToString();
1532 #region Contract Options
1540 if (Options.Length == 0)
1543 if (Options.Length == 1)
1544 this.ShowSingleContractOptions(Options[0]);
1546 this.ShowMultipleContractOptions(Options);
1548 await this.ValidateParameters();
1551 private void ShowSingleContractOptions(IDictionary<CaseInsensitiveString, object> Option)
1553 foreach (KeyValuePair<CaseInsensitiveString, object>
Parameter in Option)
1559 if (ParameterName.StartsWith(
"Max(", StringComparison.CurrentCultureIgnoreCase) && ParameterName.EndsWith(
')'))
1561 if (!this.parametersByName.TryGetValue(ParameterName[4..^1].Trim(), out ParameterInfo? Info))
1566 else if (ParameterName.StartsWith(
"Min(", StringComparison.CurrentCultureIgnoreCase) && ParameterName.EndsWith(
')'))
1568 if (!this.parametersByName.TryGetValue(ParameterName[4..^1].Trim(), out ParameterInfo? Info))
1571 Info.Parameter.SetMinValue(
Parameter.Value,
true);
1575 if (!this.parametersByName.TryGetValue(ParameterName, out ParameterInfo? Info))
1578 Info.Parameter.SetValue(
Parameter.Value);
1580 if (Info.Control is Entry Entry)
1581 Entry.Text =
Parameter.Value?.ToString() ??
string.Empty;
1582 else if (Info.Control is CheckBox CheckBox)
1585 CheckBox.IsChecked = b;
1587 CheckBox.IsChecked = i != 0;
1589 CheckBox.IsChecked = d != 0;
1591 CheckBox.IsChecked = d2 != 0;
1593 CheckBox.IsChecked = b;
1597 new KeyValuePair<string, object?>(
"Parameter", ParameterName),
1598 new KeyValuePair<string, object?>(
"Value",
Parameter.Value),
1599 new KeyValuePair<string, object?>(
"Type",
Parameter.Value?.GetType().FullName ??
string.Empty));
1605 Picker.NullableDate = TP;
1606 else if (
Parameter.Value is
string s && (DateTime.TryParse(s, out TP) ||
XML.
TryParse(s, out TP)))
1607 Picker.NullableDate = TP;
1611 new KeyValuePair<string, object?>(
"Parameter", ParameterName),
1612 new KeyValuePair<string, object?>(
"Value",
Parameter.Value),
1613 new KeyValuePair<string, object?>(
"Type",
Parameter.Value?.GetType().FullName ??
string.Empty));
1618 catch (Exception ex)
1621 new KeyValuePair<string, object?>(
"Parameter", ParameterName),
1622 new KeyValuePair<string, object?>(
"Value",
Parameter.Value),
1623 new KeyValuePair<string, object?>(
"Type",
Parameter.Value?.GetType().FullName ??
string.Empty));
1630 private void ShowMultipleContractOptions(IDictionary<CaseInsensitiveString, object>[] Options)
1636 ServiceRef.
LogService.LogWarning(
"Options not displayed. No primary key could be established. Using only first option.");
1638 foreach (IDictionary<CaseInsensitiveString, object> Option
in Options)
1640 this.ShowSingleContractOptions(Option);
1647 if (!this.parametersByName.TryGetValue(PrimaryKey, out ParameterInfo? Info))
1649 ServiceRef.
LogService.LogWarning(
"Options not displayed. Primary key not available in contract.");
1653 if (Info.Control is not Entry Entry)
1655 ServiceRef.
LogService.LogWarning(
"Options not displayed. Parameter control not of a type that allows a selection control to be created.");
1659 int EntryIndex = this.Parameters?.Children.IndexOf(Entry) ?? -1;
1670 foreach (IDictionary<CaseInsensitiveString, object> Option
in Options)
1672 string Name = Option[PrimaryKey]?.
ToString() ??
string.Empty;
1677 if (Name == Entry.Text)
1681 Picker Picker =
new()
1683 StyleId = Info.Parameter.
Name,
1685 Title = Info.Parameter.Guide
1688 this.Parameters?.Children.RemoveAt(EntryIndex);
1689 this.Parameters?.Children.Insert(EntryIndex, Picker);
1691 Picker.SelectedIndexChanged += this.Parameter_OptionSelectionChanged;
1692 Info.Control = Picker;
1694 if (SelectedOption is not
null)
1695 Picker.SelectedItem = SelectedOption;
1698 private async
void Parameter_OptionSelectionChanged(
object? Sender, EventArgs e)
1700 if (Sender is not Picker Picker)
1708 foreach (KeyValuePair<CaseInsensitiveString, object> P
in Option.Option)
1710 string ParameterName = P.Key;
1714 if (ParameterName.StartsWith(
"Max(", StringComparison.CurrentCultureIgnoreCase) && ParameterName.EndsWith(
')'))
1716 if (!this.parametersByName.TryGetValue(ParameterName[4..^1].Trim(), out ParameterInfo? Info))
1719 Info.Parameter.SetMaxValue(P.Value,
true);
1721 else if (ParameterName.StartsWith(
"Min(", StringComparison.CurrentCultureIgnoreCase) && ParameterName.EndsWith(
')'))
1723 if (!this.parametersByName.TryGetValue(ParameterName[4..^1].Trim(), out ParameterInfo? Info))
1726 Info.Parameter.SetMinValue(P.Value,
true);
1730 if (!this.parametersByName.TryGetValue(ParameterName, out ParameterInfo? Info))
1733 Entry? Entry = Info.Control as Entry;
1737 string s = P.Value?.
ToString() ??
string.Empty;
1741 if (Entry is not
null)
1753 if (Entry is not
null)
1758 if (Entry is not
null)
1764 CheckBox? CheckBox = Info.Control as CheckBox;
1768 if (P.Value is
bool b2)
1774 if (CheckBox is not
null)
1780 if (CheckBox is not
null)
1785 if (CheckBox is not
null)
1791 Picker? Picker2 = Info.Control as Picker;
1793 if (P.Value is DateTime TP ||
1794 (P.Value is
string s && (DateTime.TryParse(s, out TP) ||
XML.
TryParse(s, out TP))))
1798 if (Picker2 is not
null)
1803 if (Picker2 is not
null)
1809 if (P.Value is TimeSpan TS ||
1810 (P.Value is
string s && TimeSpan.TryParse(s, out TS)))
1814 if (Entry is not
null)
1819 if (Entry is not
null)
1830 if (Entry is not
null)
1835 if (Entry is not
null)
1843 catch (Exception ex)
1849 await this.ValidateParameters();
1850 await this.PopulateHumanReadableText();
1852 catch (Exception ex)
1860 Dictionary<CaseInsensitiveString, Dictionary<string, bool>> ByKeyAndValue = [];
1861 LinkedList<CaseInsensitiveString> Keys =
new();
1864 foreach (IDictionary<CaseInsensitiveString, object> Option
in Options)
1866 foreach (KeyValuePair<CaseInsensitiveString, object> P
in Option)
1868 if (!ByKeyAndValue.TryGetValue(P.Key, out Dictionary<string, bool>? Values))
1871 ByKeyAndValue[P.Key] = Values;
1872 Keys.AddLast(P.Key);
1875 Values[P.Value?.ToString() ??
string.Empty] =
true;
1881 if (ByKeyAndValue[Key].Count == c &&
1882 this.parametersByName.TryGetValue(Key, out ParameterInfo? Info) &&
1883 Info.Control is Entry)
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.
const string IotSc
The IoT Smart Contract URI Scheme (iotsc)
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 ILogService LogService
Log service.
static IUiService UiService
Service serializing and managing UI-related tasks.
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.
static ISettingsService SettingsService
Settings service.
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....
Static class that gives access to app-specific themed colors
static Color ErrorBackground
Error Background Color.
Static class that gives access to app-specific styles
static Style RegularCompositeEntry
Style for borders in a regular composte entry control.
static Style ImageOnlyButton
Style for buttons containing only an image.
static Style FrameSubSet
Style for frame subsets.
static Style SectionTitleLabel
Style of section title labels
static Thickness SmallBottomMargins
Bottom-only small margins
static Style RegularCompositeEntryBorder
Style for borders in a regular composte entry control.
static Style FilledTextButton
Style for filled text buttons.
static readonly BindableProperty EntryDataProperty
Bindable property for the Entry data.
Extended DatePicker for nullable values with text placeholder
Converts an input control OK state to a background color.
static ? Color ToColor(bool Ok)
Converts a control state to a representative color.
Converts a Duration value to a String value.
static string ToString(Duration Duration)
Converts a Duration to a human-readable text.
Static class containing SVG Paths for symbols used in the app.
static readonly Geometry DurationPath
Duration button glyph
A base class for all view models, inheriting from the BindableObject. NOTE: using this class requir...
string GetSettingsKey(string PropertyName)
Helper method for getting a unique settings key for a given property.
Contact Information model, including related notification information.
CaseInsensitiveString? LegalId
Legal ID of contact.
Holds navigation parameters specific to views displaying a list of contacts.
A page that displays a list of the current user's contacts.
The data model for a contract.
static async Task< string > GetName(Contract? Contract)
Gets a displayable name for a contract.
A page that allows the user to create a new contract.
The view model to bind to when displaying a new contract view or page.
override async Task DoSaveState()
Override this method to do view model specific saving of state when it's parent page/view disappears ...
override async void OnPropertyChanged(PropertyChangedEventArgs e)
override async Task DoRestoreState()
Override this method to do view model specific restoring of state when it's parent page/view appears ...
Task< string > Title
Title of the current view
bool IsLinkable
If the current view is linkable.
void Dispose()
IDisposable.Dispose
virtual void Dispose(bool Disposing)
IDisposable.Dispose
string? MediaContentType
Content-Type of associated media.
override async Task OnDispose()
Method called when the view is disposed, and will not be used more. Use this method to unregister eve...
string Link
Link to the current view
bool EncodeAppLinks
If App links should be encoded with the link.
ObservableCollection< string > AvailableRoles
The different roles available to choose from when creating a contract.
NewContractViewModel(NewContractPage Page, NewContractNavigationArgs? Args)
The view model to bind to when displaying a new contract view or page.
byte?[] Media
Encoded media, if available.
bool HasMedia
If linkable view has media associated with link.
Dictionary< string, object > Parts
Parts dictionary that can be persisted in the object database.
ObservableCollection< ContractVisibilityModel > ContractVisibilityItems
A list of valid visibility items to choose from for this contract.
ObservableCollection< ContractOption > ParameterOptions
The different parameter options available to choose from when creating a contract.
async Task ShowContractOptions(IDictionary< CaseInsensitiveString, object >[] Options)
Method called (from main thread) when contract options are made available.
override async Task OnInitialize()
Method called when view is initialized for the first time. Use this method to implement registration ...
override void OnPropertyChanging(System.ComponentModel.PropertyChangingEventArgs e)
The data model for contract visibility.
override string ToString()
Returns the string representation, i.e. name, of this contract option.
string Name
The contract name.
The data model for contract visibility.
A page that displays a specific contract.
Holds navigation parameters for the calculator.
A page that allows the user to calculate the value of a numerical input field.
A page that allows the user to duration the value of a numerical input field.
Helps with parsing of commong data types.
static bool TryParse(string s, out double Value)
Tries to decode a string encoded double.
Helps with common XML-related tasks.
static string Encode(string s)
Encodes a string for use in XML.
static bool TryParse(string s, out DateTime Value)
Tries to decode a string encoded DateTime.
Boolean contractual parameter
Calculation contractual parameter
Contains the definition of a contract
Role[] Roles
Roles defined in the smart contract.
string ContractId
Contract identity
Part[] Parts
Defined parts for the smart contract.
Adds support for legal identities, smart contracts and signatures to an XMPP client.
Date contractual parameter
Date and Time contractual parameter
Duration contractual parameter
Numerical contractual parameter
Abstract base class for contractual parameters
void SetMaxValue(object Value)
Sets the maximum value allowed by the parameter.
string Name
Parameter name
abstract object ObjectValue
Parameter value.
string Guide
Parameter guide text
Class defining a part in a contract
string LegalId
Legal identity of part
string Role
Role of the part in the contract
int MaxCount
Largest amount of signatures of this role required for a legally binding contract.
int MinCount
Smallest amount of signatures of this role required for a legally binding contract.
string Name
Name of the role.
Role-reference contractual parameter
String-valued contractual parameter
Time contractual parameter
Represents a case-insensitive string.
static readonly CaseInsensitiveString Empty
Empty case-insensitive string
int Length
Gets the number of characters in the current CaseInsensitiveString object.
static bool IsNullOrEmpty(CaseInsensitiveString value)
Indicates whether the specified string is null or an CaseInsensitiveString.Empty 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.
Class managing a script expression.
static decimal ToDecimal(object Object)
Converts an object to a double value.
Task< string?> DisplayPrompt(string Title, string Message, string? Accept, string? Cancel)
Prompts the user for some input.
Task DisplayException(Exception Exception, string? Title=null)
Displays an alert/message box to the user.
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.
Interface for linkable views.
BackMethod
Navigation Back Method
AuthenticationPurpose
Purpose for requesting the user to authenticate itself.
TextAlignment
Text alignment of contents.
ContractParts
How the parts of the contract are defined.
ContractVisibility
Visibility types for contracts.
Represents a duration value, as defined by the xsd:duration data type: http://www....
static Duration FromYears(int Years)
Creates a Duration object from a given number of years.
static bool TryParse(string s, out Duration Result)
Tries to parse a duration value.
static readonly Duration Zero
Zero value