1using CommunityToolkit.Mvvm.ComponentModel;
2using CommunityToolkit.Mvvm.Input;
9using System.ComponentModel;
10using System.Globalization;
25 private readonly TaskCompletionSource<string?>? uriToSend =
null;
35 this.navigationArguments = Args;
36 this.shareQrCode = ShareQrCode;
41 if (Args?.Uri is not
null)
43 this.Uri = Args.
Uri.UriString;
44 this.Id = Args.
Uri.Id;
45 this.Amount = Args.
Uri.Amount;
46 this.AmountExtra = Args.
Uri.AmountExtra;
47 this.Currency = Args.
Uri.Currency;
48 this.Created = Args.
Uri.Created;
49 this.Expires = Args.
Uri.Expires;
50 this.ExpiresStr = this.Expires.ToShortDateString();
51 this.From = Args.
Uri.From;
52 this.FromType = Args.
Uri.FromType;
53 this.To = Args.
Uri.To;
54 this.ToType = Args.
Uri.ToType;
55 this.ToPreset = !
string.IsNullOrEmpty(Args.
Uri.To);
56 this.Complete = Args.
Uri.Complete;
61 this.AmountText = !this.Amount.HasValue || this.Amount.Value <= 0 ? string.Empty :
MoneyToString.
ToString(this.Amount.Value);
63 this.AmountPreset = !
string.IsNullOrEmpty(this.AmountText) && this.AmountOk;
64 this.AmountAndCurrency = this.AmountText +
" " + this.Currency;
66 this.AmountExtraText = this.AmountExtra.HasValue ?
MoneyToString.
ToString(this.AmountExtra.Value) :
string.Empty;
67 this.AmountExtraOk = !this.AmountExtra.HasValue || this.AmountExtra.Value >= 0;
68 this.AmountExtraPreset = this.AmountExtra.HasValue;
69 this.AmountExtraAndCurrency = this.AmountExtraText +
" " + this.Currency;
71 StringBuilder Url =
new();
73 Url.Append(
"https://");
74 Url.Append(this.From);
75 Url.Append(
"/Images/eDalerFront200.png");
77 this.EDalerFrontGlyph = Url.ToString();
80 Url.Append(
"https://");
82 Url.Append(
"/Images/eDalerBack200.png");
83 this.EDalerBackGlyph = Url.ToString();
89 await base.OnInitialize();
91 if (this.navigationArguments is not
null)
93 if (this.navigationArguments.Uri?.EncryptedMessage is not
null)
95 if (this.navigationArguments.Uri.EncryptionPublicKey is
null)
96 this.Message = Encoding.UTF8.GetString(this.navigationArguments.Uri.EncryptedMessage);
99 this.Message = await
ServiceRef.
XmppService.TryDecryptMessage(this.navigationArguments.Uri.EncryptedMessage,
100 this.navigationArguments.Uri.EncryptionPublicKey,
this.navigationArguments.Uri.Id,
this.navigationArguments.Uri.From);
102 this.HasMessage = !
string.IsNullOrEmpty(this.Message);
105 this.MessagePreset = !
string.IsNullOrEmpty(this.Message);
106 this.CanEncryptMessage = this.navigationArguments.Uri?.ToType ==
EntityType.LegalId;
107 this.EncryptMessage = this.CanEncryptMessage;
114 this.uriToSend?.TrySetResult(
null);
116 await base.OnDispose();
131 private decimal? amount;
137 [NotifyCanExecuteChangedFor(nameof(PayOnlineCommand))]
138 [NotifyCanExecuteChangedFor(nameof(GenerateQrCodeCommand))]
139 [NotifyCanExecuteChangedFor(nameof(SendPaymentCommand))]
140 private bool amountOk;
142 protected override void OnPropertyChanged(PropertyChangedEventArgs e)
144 base.OnPropertyChanged(e);
146 switch (e.PropertyName)
148 case nameof(this.IsConnected):
149 this.AcceptCommand.NotifyCanExecuteChanged();
150 this.PayOnlineCommand.NotifyCanExecuteChanged();
151 this.SubmitCommand.NotifyCanExecuteChanged();
154 case nameof(this.HasQrCode):
155 this.PayOnlineCommand.NotifyCanExecuteChanged();
156 this.GenerateQrCodeCommand.NotifyCanExecuteChanged();
157 this.ShareCommand.NotifyCanExecuteChanged();
160 case nameof(this.AmountText):
161 if (
CommonTypes.TryParse(this.AmountText, out decimal d) && d > 0)
164 this.AmountOk =
true;
167 this.AmountOk =
false;
169 this.AmountAndCurrency = this.AmountText +
" " + this.Currency;
172 case nameof(this.AmountExtraText):
173 if (string.IsNullOrEmpty(this.AmountExtraText))
175 this.AmountExtra =
null;
176 this.AmountExtraOk =
true;
180 this.AmountExtra = d;
181 this.AmountExtraOk =
true;
184 this.AmountExtraOk =
false;
186 this.AmountExtraAndCurrency = this.AmountExtraText +
" " + this.Currency;
195 [NotifyCanExecuteChangedFor(nameof(PayOnlineCommand))]
196 [NotifyCanExecuteChangedFor(nameof(GenerateQrCodeCommand))]
197 [NotifyCanExecuteChangedFor(nameof(SendPaymentCommand))]
198 private string? amountText;
204 private string? amountAndCurrency;
210 private bool amountPreset;
216 private decimal? amountExtra;
222 [NotifyCanExecuteChangedFor(nameof(PayOnlineCommand))]
223 [NotifyCanExecuteChangedFor(nameof(GenerateQrCodeCommand))]
224 [NotifyCanExecuteChangedFor(nameof(SendPaymentCommand))]
225 private bool amountExtraOk;
231 [NotifyCanExecuteChangedFor(nameof(PayOnlineCommand))]
232 [NotifyCanExecuteChangedFor(nameof(GenerateQrCodeCommand))]
233 [NotifyCanExecuteChangedFor(nameof(SendPaymentCommand))]
234 private string? amountExtraText;
240 private string? amountExtraAndCurrency;
246 private bool amountExtraPreset;
252 private string? currency;
258 private DateTime created;
264 private DateTime expires;
270 private string? expiresStr;
282 private string? from;
300 private bool toPreset;
312 private string? friendlyName;
318 private bool complete;
324 private string? message;
330 private bool encryptMessage;
336 private bool canEncryptMessage;
342 private bool hasMessage;
348 private bool messagePreset;
354 [NotifyCanExecuteChangedFor(nameof(PayOnlineCommand))]
355 [NotifyCanExecuteChangedFor(nameof(GenerateQrCodeCommand))]
356 [NotifyCanExecuteChangedFor(nameof(SendPaymentCommand))]
357 private bool notPaid;
363 private string? eDalerFrontGlyph;
369 private string? eDalerBackGlyph;
377 private async Task FromClick()
381 string? Value = this.From;
385 if ((Value.StartsWith(
"http://", StringComparison.CurrentCultureIgnoreCase) ||
386 Value.StartsWith(
"https://", StringComparison.CurrentCultureIgnoreCase)) &&
387 System.Uri.TryCreate(Value, UriKind.Absolute, out Uri? Uri) && await Launcher.TryOpenAsync(Uri))
392 if (System.Uri.TryCreate(
"https://" + Value, UriKind.Absolute, out Uri) && await Launcher.TryOpenAsync(Uri))
395 await Clipboard.SetTextAsync(Value);
409 [RelayCommand(CanExecute = nameof(IsConnected))]
410 private async Task Accept()
414 if (this.Uri is
null)
443 [RelayCommand(CanExecute = nameof(CanPayOnline))]
444 private async Task PayOnline()
460 if (this.EncryptMessage && this.ToType ==
EntityType.LegalId)
466 this.Currency ??
string.Empty, 3, this.Message ??
string.Empty);
476 MainThread.BeginInvokeOnMainThread(async () =>
479 this.To, Guid.NewGuid().ToString(),
ServiceRef.
Localizer[nameof(AppResources.EncryptedPayment)]));
493 Uri = await
ServiceRef.
XmppService.CreateFullEDalerPaymentUri(this.To!, this.Amount ?? 0, this.AmountExtra,
494 this.Currency!, 3, this.Message ??
string.Empty);
500 this.NotPaid =
false;
529 [RelayCommand(CanExecute = nameof(CanGenerateQrCode))]
530 private async Task GenerateQrCode()
546 if (this.EncryptMessage && this.ToType ==
EntityType.LegalId)
550 this.Currency ??
string.Empty, 3, this.Message ??
string.Empty);
554 Uri = await
ServiceRef.
XmppService.CreateFullEDalerPaymentUri(this.To ??
string.Empty, this.Amount ?? 0, this.AmountExtra,
555 this.Currency ??
string.Empty, 3, this.Message ??
string.Empty);
563 MainThread.BeginInvokeOnMainThread(async () =>
565 this.GenerateQrCode(Uri);
567 if (this.shareQrCode is not
null)
568 await this.shareQrCode.ShowQrCode();
579 private bool CanPayOnline => this.AmountOk && this.AmountExtraOk && !this.HasQrCode && this.IsConnected && this.NotPaid;
580 private bool CanGenerateQrCode => this.AmountOk && this.AmountExtraOk && !this.HasQrCode && this.NotPaid;
581 private bool CanShare => this.HasQrCode;
586 [RelayCommand(CanExecute = nameof(CanShare))]
587 private async Task Share()
589 if (this.QrCodeBin is
null)
594 string? Message = this.Message?? this.AmountAndCurrency;
596 ServiceRef.PlatformSpecific.ShareImage(this.QrCodeBin,
597 string.Format(CultureInfo.CurrentCulture, Message ??
string.Empty,
this.Amount,
this.Currency),
610 [RelayCommand(CanExecute = nameof(IsConnected))]
611 private async Task Submit()
613 if (this.Uri is
null)
643 private async Task ShowCode()
645 if (this.Uri is
null)
655 MainThread.BeginInvokeOnMainThread(async () =>
657 this.GenerateQrCode(this.Uri);
659 if (this.shareQrCode is not
null)
660 await this.shareQrCode.ShowQrCode();
671 private bool CanSendPayment()
673 return this.uriToSend is not
null && this.AmountOk && this.AmountExtraOk && this.NotPaid;
679 [RelayCommand(CanExecute = nameof(CanSendPayment))]
680 private async Task SendPayment()
696 if (this.EncryptMessage && this.ToType ==
EntityType.LegalId)
700 this.Currency!, 3, this.Message ??
string.Empty);
704 Uri = await
ServiceRef.
XmppService.CreateFullEDalerPaymentUri(this.To!, this.Amount ?? 0, this.AmountExtra,
705 this.Currency!, 3, this.Message ??
string.Empty);
711 this.uriToSend?.TrySetResult(Uri);
738 case "AmountExtraText":
751 #region ILinkableView
Represents a transaction in the eDaler network.
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.
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.
Converts values to strings.
static string ToString(decimal Money)
Converts a monetary value to a string, removing any round-off errors.
bool IsAppearing
Returns true if the view model is shown.
virtual async Task GoBack()
Method called when user wants to navigate to the previous screen.
Holds navigation parameters for the calculator.
A page that allows the user to calculate the value of a numerical input field.
A view model that holds the XMPP state.
Holds navigation parameters specific to eDaler URIs.
string? FriendlyName
Optional Friendly Name associated with URI
TaskCompletionSource< string?>? UriToSend
Task Completion Source in case the URI being built is to be returned to the parent page.
EDalerUri? Uri
The edaler URI
The view model to bind to for when displaying the contents of an eDaler URI.
override async Task OnInitialize()
Method called when view is initialized for the first time. Use this method to implement registration ...
async Task OpenCalculator(object Parameter)
Opens the calculator for calculating the value of a numerical property.
EDalerUriViewModel(IShareQrCode? ShareQrCode, EDalerUriNavigationArgs? Args)
The view model to bind to for when displaying the contents of an eDaler URI.
override Task< string > Title
Title of the current view
override async Task OnDispose()
Method called when the view is disposed, and will not be used more. Use this method to unregister eve...
Helps with parsing of commong data types.
static bool TryParse(string s, out double Value)
Tries to decode a string encoded double.
Abstract base class for contractual parameters
The requesting entity does not possess the necessary permissions to perform an action that only certa...
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 pages with a share button.
EntityType
Type of entity referred to in transaction.
BackMethod
Navigation Back Method
AuthenticationPurpose
Purpose for requesting the user to authenticate itself.
delegate string ToString(IElement Element)
Delegate for callback methods that convert an element value to a string.