1using CommunityToolkit.Mvvm.ComponentModel;
2using CommunityToolkit.Mvvm.Input;
25using System.ComponentModel;
26using System.Globalization;
48 private readonly SortedDictionary<string, LinkedListNode<MessageRecord>> messagesByObjectId = [];
49 private readonly LinkedList<MessageRecord> messages = [];
50 private readonly LinkedList<MessageFrame> frames = [];
52 private readonly
object synchObject =
new();
53 private TaskCompletionSource<bool> waitUntilBound =
new();
54 private IView? scrollTo;
59 public LinkedListNode<MessageFrame> FrameNode = FrameNode;
61 public DateTime Created => this.Message.
Created;
74 this.LegalId = Args?.
LegalId ??
string.Empty;
75 this.BareJid = Args?.
BareJid ??
string.Empty;
85 this.HyperlinkClicked =
new Command(async
Parameter => await ExecuteHyperlinkClicked(
Parameter));
123 private static async Task ExecuteHyperlinkClicked(
object Parameter)
128 await
App.OpenUrlAsync(Url);
135 await base.OnInitializeAsync();
137 this.scrollTo = await this.LoadMessagesAsync(
false);
139 this.waitUntilBound.TrySetResult(
true);
148 await base.OnDisposeAsync();
150 this.waitUntilBound =
new TaskCompletionSource<bool>();
153 private Task Page_OnAfterAppearing(
object Sender, EventArgs e)
155 if (this.scrollTo is Element)
160 this.scrollTo =
null;
163 return Task.CompletedTask;
170 private string? uniqueId;
176 private string? bareJid;
182 private string? legalId;
188 private string? friendlyName;
194 [NotifyCanExecuteChangedFor(nameof(SendCommand))]
195 [NotifyCanExecuteChangedFor(nameof(CancelCommand))]
196 private string markdownInput =
string.Empty;
201 base.OnPropertyChanged(e);
203 switch (e.PropertyName)
205 case nameof(this.MarkdownInput):
206 this.IsWriting = !
string.IsNullOrEmpty(this.MarkdownInput);
209 case nameof(this.MessageId):
210 this.IsWriting = !
string.IsNullOrEmpty(this.MessageId);
213 case nameof(this.IsWriting):
214 this.IsButtonExpanded =
false;
217 case nameof(this.IsRecordingAudio):
221 this.IsWriting = this.IsRecordingAudio;
233 this.CancelCommand.NotifyCanExecuteChanged();
236 case nameof(this.IsConnected):
237 this.SendCommand.NotifyCanExecuteChanged();
238 this.CancelCommand.NotifyCanExecuteChanged();
239 this.RecordAudioCommand.NotifyCanExecuteChanged();
240 this.TakePhotoCommand.NotifyCanExecuteChanged();
241 this.EmbedFileCommand.NotifyCanExecuteChanged();
242 this.EmbedIdCommand.NotifyCanExecuteChanged();
243 this.EmbedContractCommand.NotifyCanExecuteChanged();
244 this.EmbedMoneyCommand.NotifyCanExecuteChanged();
245 this.EmbedTokenCommand.NotifyCanExecuteChanged();
246 this.EmbedThingCommand.NotifyCanExecuteChanged();
255 private string? messageId;
261 [NotifyCanExecuteChangedFor(nameof(LoadMoreMessagesCommand))]
262 private bool existsMoreMessages;
268 [NotifyCanExecuteChangedFor(nameof(RecordAudioCommand))]
269 [NotifyCanExecuteChangedFor(nameof(TakePhotoCommand))]
270 [NotifyCanExecuteChangedFor(nameof(EmbedFileCommand))]
271 [NotifyCanExecuteChangedFor(nameof(EmbedIdCommand))]
272 [NotifyCanExecuteChangedFor(nameof(EmbedContractCommand))]
273 [NotifyCanExecuteChangedFor(nameof(EmbedMoneyCommand))]
274 [NotifyCanExecuteChangedFor(nameof(EmbedTokenCommand))]
275 [NotifyCanExecuteChangedFor(nameof(EmbedThingCommand))]
276 private bool isWriting;
282 [NotifyCanExecuteChangedFor(nameof(SendCommand))]
283 private bool isRecordingAudio;
289 private bool isRecordingPaused;
316 MainThread.BeginInvokeOnMainThread(async () =>
318 IView? View = await this.MessageAddedMainThread(Message,
true);
322 await Task.Delay(25);
323 double Width = this.page.ScrollView.ScrollX;
324 double Height = this.page.ScrollView.ContentSize.Height;
325 await this.page.ScrollView.ScrollToAsync(Width, Height,
true);
330 private async Task<IView?> MessageAddedMainThread(
ChatMessage Message,
bool Historic)
332 this.HasMessages =
true;
334 TaskCompletionSource<IView?> Result =
new();
341 lock (this.synchObject)
343 LinkedListNode<MessageRecord>? MessageNode = Historic ? this.messages.Last : this.messages.First;
344 LinkedListNode<MessageFrame>? FrameNode;
349 if (MessageNode is
null)
354 this.page.Messages.Add(Frame);
356 FrameNode = this.frames.AddLast(Frame);
358 Rec =
new(Message, FrameNode);
359 MessageNode = this.messages.AddLast(Rec);
363 while (MessageNode is not
null && Message.
Created > MessageNode.Value.Created)
364 MessageNode = MessageNode.Next;
365 if (MessageNode is
null)
367 FrameNode = this.frames.Last!;
369 if (FrameNode.Value.MessageType != Message.
MessageType)
372 this.page.Messages.Add(FrameNode.Value);
375 View = FrameNode.Value.AddLast(Message);
377 Rec =
new(Message, FrameNode);
378 MessageNode = this.messages.AddLast(Rec);
388 while (MessageNode is not
null && Message.
Created < MessageNode.Value.Created)
389 MessageNode = MessageNode.Previous;
391 if (MessageNode is
null)
393 FrameNode = this.frames.First!;
395 if (FrameNode.Value.MessageType != Message.
MessageType)
398 this.page.Messages.Insert(0, FrameNode.Value);
401 View = FrameNode.Value.AddFirst(Message);
403 Rec =
new(Message, FrameNode);
404 MessageNode = this.messages.AddFirst(Rec);
413 Result.TrySetResult(View);
441 this.messagesByObjectId[Message.ObjectId ??
string.Empty] = MessageNode;
446 Result.TrySetException(Ex);
449 return await Result.Task;
468 if (Message.
ParsedXaml is not IView MessageXaml ||
string.IsNullOrEmpty(Message.
ObjectId))
471 MainThread.BeginInvokeOnMainThread(() =>
475 lock (this.synchObject)
479 if (this.messagesByObjectId.TryGetValue(Message.
ObjectId, out LinkedListNode<MessageRecord>? Node) &&
480 Node.Value.Message.ParsedXaml is IView PrevMessageXaml &&
481 PrevMessageXaml.Parent is VerticalStackLayout Parent &&
482 (Index = Parent.IndexOf(PrevMessageXaml)) >= 0)
484 Parent.RemoveAt(Index);
485 Parent.Insert(Index, MessageXaml);
487 Node.Value.Message = Message;
500 private async Task<IView?> LoadMessagesAsync(
bool LoadMore =
true)
502 IEnumerable<ChatMessage>? Messages =
null;
509 this.ExistsMoreMessages =
false;
511 lock (this.synchObject)
513 LastTime = LoadMore && this.messages.First is not
null ? this.messages.First.Value.Created : DateTime.MaxValue;
529 this.ExistsMoreMessages =
false;
533 TaskCompletionSource<IView?> Result =
new();
535 MainThread.BeginInvokeOnMainThread(async () =>
542 Last = await this.MessageAddedMainThread(Message,
true);
544 this.ExistsMoreMessages = C <= 0;
546 Result.TrySetResult(Last);
550 Result.TrySetException(Ex);
554 return await Result.Task;
558 private bool hasMessages =
false;
564 private bool isButtonExpanded;
570 private void ExpandButtons()
572 this.IsButtonExpanded = !this.IsButtonExpanded;
578 [RelayCommand(CanExecute = nameof(CanExecuteLoadMoreMessages))]
579 private Task<IView?> LoadMoreMessages()
581 return this.LoadMessagesAsync(
true);
584 private bool CanExecuteLoadMoreMessages()
586 return this.ExistsMoreMessages && this.page.Messages.Count > 0;
589 private bool CanExecuteSendMessage()
591 return this.IsConnected && (!
string.IsNullOrEmpty(this.MarkdownInput) || this.IsRecordingAudio);
597 [RelayCommand(CanExecute = nameof(CanExecuteSendMessage))]
598 private async Task Send()
600 if (this.IsRecordingAudio)
623 await this.ExecuteSendMessage(this.MessageId, this.MarkdownInput);
628 private Task ExecuteSendMessage(
string? ReplaceObjectId,
string MarkdownInput)
630 return ExecuteSendMessage(ReplaceObjectId, MarkdownInput, this.BareJid!,
this);
641 return ExecuteSendMessage(ReplaceObjectId, MarkdownInput, BareJid,
null);
655 if (
string.IsNullOrEmpty(MarkdownInput))
660 AllowScriptTag =
false,
662 AudioAutoplay =
false,
663 AudioControls =
false,
664 ParseMetaData =
false,
665 VideoAutoplay =
false,
666 VideoControls =
false
673 Created = DateTime.UtcNow,
674 RemoteBareJid = BareJid,
675 RemoteObjectId =
string.Empty,
680 Markdown = MarkdownInput
683 StringBuilder Xml =
new();
685 Xml.Append(
"<content xmlns=\"urn:xmpp:content\" type=\"text/markdown\">");
687 Xml.Append(
"</content><html xmlns='http://jabber.org/protocol/xhtml-im'><body xmlns='http://www.w3.org/1999/xhtml'>");
689 HtmlDocument HtmlDoc =
new(
"<root>" + Message.Html +
"</root>");
691 foreach (
HtmlNode N
in (HtmlDoc.Body ?? HtmlDoc.Root).Children)
694 Xml.Append(
"</body></html>");
696 if (!
string.IsNullOrEmpty(ReplaceObjectId))
698 Xml.Append(
"<replace id='");
699 Xml.Append(ReplaceObjectId);
700 Xml.Append(
"' xmlns='urn:xmpp:message-correct:0'/>");
703 if (
string.IsNullOrEmpty(ReplaceObjectId))
716 ReplaceObjectId =
null;
725 Old.Html = Message.
Html;
738 BareJid, Xml.ToString(), Message.
PlainText,
string.Empty,
string.Empty,
string.Empty,
string.Empty,
null,
null);
749 [RelayCommand(CanExecute = nameof(CanExecutePauseResume))]
750 private Task PauseResume()
761 return Task.CompletedTask;
764 private static bool CanExecutePauseResume()
772 private bool CanExecuteCancelMessage()
774 return this.IsConnected && (!
string.IsNullOrEmpty(this.MarkdownInput) || this.IsRecordingAudio);
780 [RelayCommand(CanExecute = nameof(CanExecuteCancelMessage))]
781 private Task Cancel()
783 if (this.IsRecordingAudio)
802 this.MarkdownInput =
string.Empty;
803 this.MessageId =
string.Empty;
806 return Task.CompletedTask;
825 private bool CanExecuteRecordAudio()
830 private void OnAudioRecorderTimer(
object? source, ElapsedEventArgs e)
839 [RelayCommand(CanExecute = nameof(CanExecuteRecordAudio))]
840 private async Task RecordAudio()
851 PermissionStatus Status = await Permissions.RequestAsync<Permissions.Microphone>();
853 if (Status == PermissionStatus.Granted)
867 private bool CanExecuteTakePhoto()
875 [RelayCommand(CanExecute = nameof(CanExecuteTakePhoto))]
876 private async Task TakePhoto()
889 if (DeviceInfo.Platform == DevicePlatform.iOS)
891 FileResult? CapturedPhoto;
895 CapturedPhoto = await MediaPicker.Default.CapturePhotoAsync(
new MediaPickerOptions()
907 if (CapturedPhoto is not
null)
911 await this.EmbedMedia(CapturedPhoto.FullPath,
true);
921 FileResult? CapturedPhoto;
925 CapturedPhoto = await MediaPicker.CapturePhotoAsync();
926 if (CapturedPhoto is
null)
936 if (CapturedPhoto is not
null)
940 await this.EmbedMedia(CapturedPhoto.FullPath,
true);
950 private async Task EmbedMedia(
string FilePath,
bool DeleteFile)
954 byte[] Bin = File.ReadAllBytes(FilePath);
973 string FileName = Path.GetFileName(FilePath);
977 using RandomNumberGenerator Rnd = RandomNumberGenerator.Create();
978 byte[] Key =
new byte[16];
979 byte[] IV =
new byte[16];
984 Aes Aes = Aes.Create();
987 Aes.Mode = CipherMode.CBC;
988 Aes.Padding = PaddingMode.PKCS7;
990 using ICryptoTransform Transform = Aes.CreateEncryptor(Key, IV);
991 Bin = Transform.TransformFinalBlock(Bin, 0, Bin.Length);
995 StringBuilder Xml =
new();
997 Xml.Append(
"<prepare xmlns='http://waher.se/Schema/EncryptedStorage.xsd' filename='");
999 Xml.Append(
"' size='");
1000 Xml.Append(Bin.Length.ToString(CultureInfo.InvariantCulture));
1001 Xml.Append(
"' content-type='application/octet-stream'/>");
1009 FileName,
"application/octet-stream", Bin.Length);
1012 throw Slot.StanzaError ??
new Exception(Slot.
ErrorText);
1020 StringBuilder Markdown =
new();
1022 Markdown.Append(
";
1026 Markdown.Append(
':');
1027 Markdown.Append(Convert.ToBase64String(Key));
1028 Markdown.Append(
':');
1029 Markdown.Append(Convert.ToBase64String(IV));
1030 Markdown.Append(
':');
1031 Markdown.Append(ContentType);
1032 Markdown.Append(
':');
1033 Markdown.Append(Slot.
GetUrl);
1035 SKImageInfo ImageInfo = SKBitmap.DecodeBounds(Bin);
1036 if (!ImageInfo.IsEmpty)
1038 Markdown.Append(
' ');
1039 Markdown.Append(ImageInfo.Width.ToString(CultureInfo.InvariantCulture));
1040 Markdown.Append(
' ');
1041 Markdown.Append(ImageInfo.Height.ToString(CultureInfo.InvariantCulture));
1044 Markdown.Append(
')');
1046 await this.ExecuteSendMessage(
string.Empty, Markdown.ToString());
1051 File.Delete(FilePath);
1053 catch (Exception Ex)
1061 private bool CanExecuteEmbedFile()
1069 [RelayCommand(CanExecute = nameof(CanExecuteEmbedFile))]
1070 private async Task EmbedFile()
1078 FileResult? PickedPhoto = await MediaPicker.PickPhotoAsync();
1080 if (PickedPhoto is not
null)
1081 await this.EmbedMedia(PickedPhoto.FullPath,
false);
1084 private bool CanExecuteEmbedId()
1086 return this.IsConnected && !this.IsWriting;
1092 [RelayCommand(CanExecute = nameof(CanExecuteEmbedId))]
1093 private async Task EmbedId()
1095 TaskCompletionSource<ContactInfoModel?> SelectedContact =
new();
1098 CanScanQrCode =
true
1104 if (Contact is
null)
1107 await this.waitUntilBound.Task;
1111 StringBuilder Markdown =
new();
1113 Markdown.Append(
"```");
1118 Markdown.AppendLine();
1119 Markdown.AppendLine(
"```");
1121 await this.ExecuteSendMessage(
string.Empty, Markdown.ToString());
1125 if (!
string.IsNullOrEmpty(Contact.
LegalId))
1131 if (!
string.IsNullOrEmpty(Contact.
BareJid))
1138 private bool CanExecuteEmbedContract()
1140 return this.IsConnected && !this.IsWriting;
1146 [RelayCommand(CanExecute = nameof(CanExecuteEmbedContract))]
1147 private async Task EmbedContract()
1149 TaskCompletionSource<Contract?> SelectedContract =
new();
1158 await this.waitUntilBound.Task;
1160 StringBuilder Markdown =
new();
1162 Markdown.Append(
"```");
1167 Markdown.AppendLine();
1168 Markdown.AppendLine(
"```");
1170 await this.ExecuteSendMessage(
string.Empty, Markdown.ToString());
1173 private bool CanExecuteEmbedMoney()
1175 return this.IsConnected && !this.IsWriting;
1181 [RelayCommand(CanExecute = nameof(CanExecuteEmbedMoney))]
1182 private async Task EmbedMoney()
1184 StringBuilder Sb =
new();
1186 Sb.Append(
"edaler:");
1188 if (!
string.IsNullOrEmpty(this.LegalId))
1191 Sb.Append(this.LegalId);
1193 else if (!
string.IsNullOrEmpty(this.BareJid))
1196 Sb.Append(this.BareJid);
1204 Sb.Append(CurrentBalance.
Currency);
1209 TaskCompletionSource<string?> UriToSend =
new();
1214 string? Uri = await UriToSend.Task;
1218 await this.waitUntilBound.Task;
1223 if (Parsed.AmountExtra.HasValue)
1231 Sb.Append(Parsed.Currency);
1233 await this.ExecuteSendMessage(
string.Empty,
"");
1236 private bool CanExecuteEmbedToken()
1238 return this.IsConnected && !this.IsWriting;
1244 [RelayCommand(CanExecute = nameof(CanExecuteEmbedToken))]
1245 private async Task EmbedToken()
1253 if (Selected is
null)
1256 StringBuilder Markdown =
new();
1258 Markdown.AppendLine(
"```nfeat");
1262 Markdown.AppendLine();
1263 Markdown.AppendLine(
"```");
1265 await this.ExecuteSendMessage(
string.Empty, Markdown.ToString());
1268 private bool CanExecuteEmbedThing()
1270 return this.IsConnected && !this.IsWriting;
1276 [RelayCommand(CanExecute = nameof(CanExecuteEmbedThing))]
1277 private async Task EmbedThing()
1279 TaskCompletionSource<ContactInfoModel?> ThingToShare =
new();
1288 await this.waitUntilBound.Task;
1290 StringBuilder Sb =
new();
1294 Sb.Append(
"](iotdisco:JID=");
1297 if (!
string.IsNullOrEmpty(Thing.
SourceId))
1303 if (!
string.IsNullOrEmpty(Thing.
Partition))
1309 if (!
string.IsNullOrEmpty(Thing.
NodeId))
1317 await this.ExecuteSendMessage(
string.Empty, Sb.ToString());
1324 private Task MessageSelected(
object Parameter)
1339 switch (Message.MessageType)
1343 this.MessageId = Message.ObjectId;
1344 this.MarkdownInput = Message.Markdown;
1349 string S = Message.Markdown;
1350 if (
string.IsNullOrEmpty(S))
1353 string[] Rows = S.Replace(
"\r\n",
"\n").Replace(
"\r",
"\n").Split(
'\n');
1355 StringBuilder Quote =
new();
1357 foreach (
string Row
in Rows)
1360 Quote.AppendLine(Row);
1365 this.MessageId =
string.Empty;
1366 this.MarkdownInput = Quote.ToString();
1371 return Task.CompletedTask;
1387 int I = Uri.IndexOf(
':');
1391 string S = Uri[(I + 1)..].Trim();
1392 if (S.StartsWith(
'<') && S.EndsWith(
'>'))
1394 XmlDocument Doc =
new()
1396 PreserveWhitespace =
true
1404 ViewIdentityNavigationArgs ViewIdentityArgs =
new(Id);
1418 if (ParsedToken is
null)
1437 catch (Exception Ex)
1450 int I = Uri.IndexOf(
':');
1454 string Jid = Uri[(I + 1)..].TrimStart();
1457 I = Jid.IndexOf(
'?');
1459 Command =
"subscribe";
1462 Command = Jid[(I + 1)..].TrimStart();
1463 Jid = Jid[..I].TrimEnd();
1466 Jid =
System.Web.HttpUtility.UrlDecode(Jid);
1469 switch (Command.ToLower(CultureInfo.InvariantCulture))
1478 if (SubscribeTo.HasValue && SubscribeTo.Value)
1483 IdXml =
string.Empty;
1486 StringBuilder Xml =
new();
1488 IdXml = Xml.ToString();
1509 #region ILinkableView
1524 public string Link => Constants.UriSchemes.Xmpp +
":" + this.BareJid;
1529 public Task<string>
Title => Task.FromResult<
string>(this.FriendlyName ??
string.Empty);
Contains information about a balance.
CaseInsensitiveString Currency
Currency of amount.
Abstract base class for eDaler URIs
static bool TryParse(string Uri, out EDalerUri Result)
Tries to parse an eDaler URI
Represents an instance of the Neuro-Access app.
const int MessageBatchSize
Number of messages to load in a single batch.
static readonly TimeSpan XmppConnect
XMPP Connect timeout
static readonly TimeSpan UploadFile
Upload file timeout
const string IotSc
The IoT Smart Contract URI Scheme (iotsc)
const string Aes256
AES-256-encrypted data.
const string IotId
The IoT ID URI Scheme (iotid)
A set of never changing property constants and helpful values.
A strongly-typed resource class, for looking up localized strings, etc.
static string PickPhoto
Looks up a localized string similar to Pick photo.
static string TakePhoto
Looks up a localized string similar to Take photo.
static string SelectingAPhotoIsNotSupported
Looks up a localized string similar to Selecting a photo is not supported on this device.
static string InvalidNeuroFeatureToken
Looks up a localized string similar to Invalid Neuro-Feature token..
static string ServerDoesNotSupportFileUpload
Looks up a localized string similar to The server does not seem to support File Uploading....
static string UnableToConnectTo
Looks up a localized string similar to Unable to connect to {0}.
static string PhotoIsTooLarge
Looks up a localized string similar to Photo is too large.
static string TakingAPhotoIsNotSupported
Looks up a localized string similar to Taking a photo is not supported on this device.
static string SelectContactToPay
Looks up a localized string similar to Below are all contacts in your contact book....
static string TakePhotoToShare
Looks up a localized string similar to Take a photo to share.
static string ErrorTitle
Looks up a localized string similar to An error has occurred.
Base class that references services in the app.
static ILogService LogService
Log service.
static IUiService UiService
Service serializing and managing UI-related tasks.
static INavigationService NavigationService
The navigation service for navigating between pages.
static INotificationService NotificationService
Service for managing notifications for the user.
static IPopupService PopupService
Popup service for presenting application popups.
static ITagProfile TagProfile
TAG Profile service.
static IReportingStringLocalizer Localizer
Localization service
static IXmppService XmppService
The XMPP service for XMPP communication.
static IPermissionService PermissionService
Permission Service
string? UniqueId
An unique view identifier used to search the args of similar view types.
Helper class to perform scanning of QR Codes by displaying the UI and handling async results.
static Task< bool > OpenUrl(string Url)
Scans a QR Code, and depending on the actual result, takes different actions. This typically means na...
Converts values to strings.
static string ToString(decimal Money)
Converts a monetary value to a string, removing any round-off errors.
async Task GenerateXaml(IChatView View)
Parses the XAML in the message.
object? ParsedXaml
Parsed XAML
DateTime Created
When message was created
string Html
HTML of message
MessageType MessageType
Message Type
string PlainText
Plain text of message
string Markdown
Markdown of message
string? ObjectId
Object ID
Holds navigation parameters specific to views displaying a list of contacts.
string? FriendlyName
Friendly name
string? BareJid
Bare JID of remote chat party
string? LegalId
Legal ID, if available.
A page that displays a list of the current user's contacts.
The view model to bind to when displaying the list of contacts.
byte?[] Media
Encoded media, if available.
Command XmppUriClicked
Command executed when a multi-media-link with the xmpp URI scheme is clicked.
static string RecordingTime
If the audio recording is paused
Command HyperlinkClicked
Command executed when a hyperlink in rendered markdown has been clicked.
bool IsLinkable
If the current view is linkable.
override async Task OnDisposeAsync()
Method called when the view is disposed, and will not be used more. Use this method to unregister eve...
bool EncodeAppLinks
If App links should be encoded with the link.
Command EDalerUriClicked
Command executed when a multi-media-link with the edaler URI scheme is clicked.
bool HasMedia
If linkable view has media associated with link.
string Link
Link to the current view
static async Task ExecuteSendMessage(string? ReplaceObjectId, string MarkdownInput, string BareJid, ChatViewModel? ChatViewModel)
Sends a Markdown-formatted chat message
Task< string > Title
Title of the current view
static async Task< bool > ProcessXmppUri(string Uri)
Processes an XMPP URI
Command IotScUriClicked
Command executed when a multi-media-link with the iotsc URI scheme is clicked.
Command NeuroFeatureUriClicked
Command executed when a multi-media-link with the nfeat URI scheme is clicked.
async Task ExecuteUriClicked(string Uri, UriScheme Scheme)
Called when a Multi-media URI link using the XMPP URI scheme.
async Task MessageAddedAsync(ChatMessage Message)
External message has been received
override async Task OnInitializeAsync()
Method called when view is initialized for the first time. Use this method to implement registration ...
override void OnPropertyChanged(PropertyChangedEventArgs e)
static Task ExecuteSendMessage(string? ReplaceObjectId, string MarkdownInput, string BareJid)
Sends a Markdown-formatted chat message
async Task MessageUpdatedAsync(ChatMessage Message)
External message has been updated
string? MediaContentType
Content-Type of associated media.
ChatViewModel(ChatPage Page, ChatNavigationArgs? Args)
Creates an instance of the ChatViewModel class.
Command IotDiscoUriClicked
Command executed when a multi-media-link with the iotdisco URI scheme is clicked.
Command IotIdUriClicked
Command executed when a multi-media-link with the iotid URI scheme is clicked.
Border containing sent messages.
static MessageFrame Create(ChatMessage Message)
Creates a message frame for a given message.
IView AddLast(ChatMessage Message)
Adds a message to the frame.
Contact Information model, including related notification information.
LegalIdentity? LegalIdentity
Legal Identity object.
string? Partition
Partition
string? SourceId
Source ID
CaseInsensitiveString? LegalId
Legal ID of contact.
string? FriendlyName
Friendly name.
CaseInsensitiveString? BareJid
Bare JID 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.
Holds navigation parameters specific to views displaying a list of contacts.
A page that displays a list of the current user's contracts.
A page that displays a specific contract.
A page to display when the user wants to view an identity.
Holds navigation parameters specific to viewing things.
A page that displays a list of the current user's things.
Holds navigation parameters specific to eDaler URIs.
Holds navigation parameters for viewing tokens.
TaskCompletionSource< TokenItem?> TokenItemProvider
Task completion source; can be used to wait for a result.
A page that allows the user to view its tokens.
Encapsulates a Token object.
A page that allows the user to realize payments.
Holds navigation parameters specific to a token.
A page that allows the user to view information about a token.
A view model that holds the XMPP state.
static async Task< Token > TryParse(XmlElement Xml)
Tries to parse a Token.
void Serialize(StringBuilder Xml)
Serializes the Token, in normalized form.
static string GetBody(string Html)
Extracts the contents of the BODY element in a HTML string.
Base class for all HTML nodes.
abstract void Export(XmlWriter Output, Dictionary< string, string > Namespaces)
Exports the HTML document to XML.
Static class managing encoding and decoding of internet content.
static bool TryGetContentType(string FileExtension, out string ContentType)
Tries to get the content type of an item, given its file extension.
Contains a markdown document. This markdown document class supports original markdown,...
static string Encode(string s)
Encodes all special characters in a string so that it can be included in a markdown document without ...
async Task< string > GeneratePlainText()
Generates Plain Text from the markdown text.
async Task< string > GenerateHTML()
Generates HTML from the markdown text.
static Task< MarkdownDocument > CreateAsync(string MarkdownText, params Type[] TransparentExceptionTypes)
Contains a markdown document. This markdown document class supports original markdown,...
Contains settings that the Markdown parser uses to customize its behavior.
Helps with common XML-related tasks.
static string Encode(string s)
Encodes a string for use in XML.
Contains the definition of a contract
static Task< ParsedContract > Parse(XmlDocument Xml)
Validates a contract XML Document, and returns the contract definition in it.
void Serialize(StringBuilder Xml, bool IncludeNamespace, bool IncludeIdAttribute, bool IncludeClientSignatures, bool IncludeAttachments, bool IncludeStatus, bool IncludeServerSignature, bool IncludeAttachmentReferences)
Serializes the Contract, in normalized form.
Adds support for legal identities, smart contracts and signatures to an XMPP client.
static string LegalIdUriString(string LegalId)
Legal identity URI, as a string.
void Serialize(StringBuilder Xml, bool IncludeNamespace, bool IncludeIdAttribute, bool IncludeClientSignature, bool IncludeAttachments, bool IncludeStatus, bool IncludeServerSignature, bool IncludeAttachmentReferences)
Serializes the identity to XML
static LegalIdentity Parse(string Xml)
Parses an identity from its XML representation
Abstract base class for contractual parameters
Contains information about a parsed contract.
Contract Contract
Contract object
bool Ok
If the response is an OK result response (true), or an error response (false).
string ErrorText
Any error specific text.
Event arguments for HTTP File Upload callback methods.
Task PUT(byte[] Content, string ContentType, int Timeout)
Uploads file content to the server.
Manages an XMPP client connection. Implements XMPP, as defined in https://tools.ietf....
static string GetBareJID(string JID)
Gets the Bare JID from a JID, which may be a Full JID.
Static interface for database persistence. In order to work, a database provider has to be assigned t...
static async Task Update(object Object)
Updates an object in the database.
static Task< IEnumerable< object > > Find(string Collection, params string[] SortOrder)
Finds objects in a given collection.
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
static Task< object > TryLoadObject(string CollectionName, object ObjectId)
Tries to load an object given its Object ID ObjectId and its collection name CollectionName .
This filter selects objects that conform to all child-filters provided.
This filter selects objects that have a named field equal to a given value.
This filter selects objects that have a named field lesser than a given value.
Task DeleteEvents(NotificationEventType Type, CaseInsensitiveString Category)
Deletes events for a given button and category.
bool TryGetNotificationEvents(NotificationEventType Type, CaseInsensitiveString Category, [NotNullWhen(true)] out NotificationEvent[]? Events)
Tries to get available notification events.
Task GoToAsync(string Route)
Navigates to the specified route and pushes the page onto the navigation stack.
Task DisplayException(Exception Exception, string? Title=null)
Displays an alert/message box to the user.
Task< bool > DisplayAlert(string Title, string Message, string? Accept=null, string? Cancel=null)
Displays an alert/message box to the user.
Interfaces for views displaying markdown
Interface for linkable views.
abstract class NotificationEvent()
Abstract base class of notification events.
NotificationEventType
Button on which event is to be displayed.
BackMethod
Navigation Back Method
ContractsListMode
What list of contracts to display
QoSLevel
Quality of Service Level for asynchronous messages. Support for QoS Levels must be supported by the r...
MessageType
Type of message received.
ContentType
DTLS Record content type.