Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
ChatView.xaml.cs
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Reflection;
5using System.Security.Cryptography;
6using System.Text;
7using System.Threading.Tasks;
8using System.Xml;
9using System.Xml.Schema;
10using System.Xml.Xsl;
11using System.Windows;
12using System.Windows.Controls;
13using System.Windows.Documents;
14using System.Windows.Input;
15using System.Windows.Media;
16using Microsoft.Win32;
17using Waher.Content;
24using Waher.Events;
30
32{
36 public partial class ChatView : UserControl, ITabView
37 {
38 private static readonly RandomNumberGenerator rnd = RandomNumberGenerator.Create();
39 private static Emoji1LocalFiles emoji1_24x24 = null;
40
41 private readonly Dictionary<string, Consolidator> threads = new Dictionary<string, Consolidator>();
42 private readonly TreeNode node;
43 private DateTime timer = DateTime.MinValue;
44 private bool muc;
45 private bool consolidate = true;
46
47 public ChatView(TreeNode Node, bool Muc)
48 {
49 this.node = Node;
50 this.muc = Muc;
51
53
54 if (Muc)
55 {
56 double w = this.ReceivedColumn.Width * 2;
57 this.FromColumn.Width = w;
58 this.ContentColumn.Width -= w;
59
60 this.timer = MainWindow.Scheduler.Add(DateTime.Now.AddMinutes(1), this.MucSelfPing, null);
61 }
62
63 this.DataContext = this;
64 }
65
66 public bool Muc => this.muc;
67
68 public bool Consolidate
69 {
70 get => this.consolidate;
71 set => this.consolidate = value;
72 }
73
74 internal static void InitEmojis()
75 {
76 if (emoji1_24x24 is null)
77 {
78 string Folder = Assembly.GetExecutingAssembly().Location;
79 if (string.IsNullOrEmpty(Folder))
80 Folder = AppDomain.CurrentDomain.BaseDirectory;
81
82 emoji1_24x24 = new Emoji1LocalFiles(Emoji1SourceFileType.Png64, 24, 24,
83 Path.Combine(MainWindow.AppDataFolder, "Graphics", "Emoji1", ImageCodec.FileExtensionPng, "64x64", "%FILENAME%"),
84 Path.Combine(Path.GetDirectoryName(Folder), "Graphics", "Emoji1.zip"),
85 Path.Combine(MainWindow.AppDataFolder, "Graphics"));
86 }
87 }
88
89 public static Emoji1LocalFiles Emoji1_24x24
90 {
91 get { return emoji1_24x24; }
92 }
93
94 public void Dispose()
95 {
96 if (this.timer > DateTime.MinValue)
97 {
98 MainWindow.Scheduler?.Remove(this.timer);
99 this.timer = DateTime.MinValue;
100 }
101
102 this.Node?.ViewClosed();
103 }
104
105 public TreeNode Node => this.node;
106
107 private void UserControl_SizeChanged(object Sender, SizeChangedEventArgs e)
108 {
109 if (this.ChatListView.View is GridView GridView)
110 {
111 GridView.Columns[2].Width = Math.Max(this.ActualWidth - GridView.Columns[0].ActualWidth -
112 GridView.Columns[1].ActualWidth - GridView.Columns[3].ActualWidth -
113 SystemParameters.VerticalScrollBarWidth - 8, 10);
114 }
115
116 this.Input.Width = Math.Max(this.ActualWidth - this.SendButton.ActualWidth - 16, 10);
117 }
118
119 public static MarkdownSettings GetMarkdownSettings()
120 {
121 return new MarkdownSettings(Emoji1_24x24, false);
122 }
123
124 public static HtmlSettings GetHtmlSettings()
125 {
126 return new HtmlSettings()
127 {
128 XmlEntitiesOnly = true
129 };
130 }
131
132 public static XamlSettings GetXamlSettings()
133 {
134 return new XamlSettings()
135 {
136 TableCellRowBackgroundColor1 = "#20404040",
137 TableCellRowBackgroundColor2 = "#10808080"
138 };
139 }
140
141 private async void Send_Click(object Sender, RoutedEventArgs e)
142 {
143 try
144 {
145 string Msg = this.Input.Text;
146 string ThreadId;
147
148 this.Input.Text = string.Empty;
149 this.Input.Focus();
150
151 if (this.muc)
152 {
153 byte[] Bin = new byte[16];
154
155 lock (rnd)
156 {
157 rnd.GetBytes(Bin);
158 }
159
160 ThreadId = Convert.ToBase64String(Bin);
161 }
162 else
163 ThreadId = string.Empty;
164
165 MarkdownDocument Markdown = await this.ChatMessageTransmitted(Msg, ThreadId);
166 await this.node.SendChatMessage(Msg, ThreadId, Markdown);
167 }
168 catch (Exception ex)
169 {
170 MainWindow.ErrorBox(ex.Message);
171 }
172 }
173
174 public async Task<MarkdownDocument> ChatMessageTransmitted(string Message, string ThreadId)
175 {
176 MarkdownDocument Markdown;
177
178 if (Message.IndexOf('|') >= 0)
179 {
180 string s;
181 int c = this.ChatListView.Items.Count;
182
183 if (c > 0 &&
184 this.ChatListView.Items[c - 1] is ChatItem Item &&
185 Item.Type == ChatItemType.Transmitted &&
186 string.IsNullOrWhiteSpace(Item.From) &&
187 (DateTime.Now - Item.LastUpdated).TotalSeconds < 10 &&
188 (s = Item.Message).IndexOf('|') >= 0)
189 {
190 try
191 {
192 if (!s.EndsWith("\n"))
193 s += Environment.NewLine;
194
195 s += Message;
196 Markdown = await MarkdownDocument.CreateAsync(s, GetMarkdownSettings());
197 await Item.Update(s, Markdown);
198 this.ChatListView.Items.Refresh();
199 this.ChatListView.ScrollIntoView(Item);
200 return Markdown;
201 }
202 catch (Exception)
203 {
204 // Ignore.
205 }
206 }
207 }
208
209 try
210 {
211 new Waher.Script.Expression(Message);
212 Markdown = null; // Expressions should not be parsed as markdown.
213 }
214 catch (Exception)
215 {
216 try
217 {
218 Markdown = await MarkdownDocument.CreateAsync(Message, GetMarkdownSettings());
219 }
220 catch (Exception)
221 {
222 Markdown = null;
223 }
224 }
225
226 this.AddItem(ChatItemType.Transmitted, DateTime.Now, Message, string.Empty, Markdown, ThreadId, Colors.Black, Colors.Honeydew);
227
228 return Markdown;
229 }
230
231 private async void AddItem(ChatItemType Type, DateTime Timestamp, string Message, string From, MarkdownDocument Markdown, string ThreadId, Color FgColor, Color BgColor)
232 {
233 try
234 {
235 if (this.muc && !string.IsNullOrEmpty(ThreadId))
236 {
237 switch (Type)
238 {
239 case ChatItemType.Transmitted:
240 int N;
241
242 if (this.node is RoomNode RoomNode)
243 N = RoomNode.NrOccupants;
244 else
245 N = 12;
246
247 lock (this.threads)
248 {
249 if (!this.threads.ContainsKey(ThreadId))
250 {
251 this.threads[ThreadId] = new Consolidator(ThreadId, N)
252 {
253 Tag = new ConsolidationTag()
254 };
255 }
256 }
257 break;
258
259 case ChatItemType.Received:
260 Consolidator Consolidation;
261
262 if (!this.consolidate)
263 break;
264
265 lock (this.threads)
266 {
267 if (!this.threads.TryGetValue(ThreadId, out Consolidation))
268 break;
269 }
270
271 ConsolidationTag Rec = (ConsolidationTag)Consolidation.Tag;
272 MainWindow.Scheduler?.Remove(Rec.UpdateTP);
273
274 await Consolidation.Add(ChatItem.GetShortFrom(From), Markdown);
275
276 Rec.UpdateTP = MainWindow.Scheduler.Add(DateTime.Now.AddMilliseconds(100), async (_) =>
277 {
278 StringBuilder sb = new StringBuilder();
279 bool First = true;
280
281 Message = await Consolidation.GenerateMarkdownAsync();
282 Markdown = await MarkdownDocument.CreateAsync(Message, Markdown.Settings, Markdown.TransparentExceptionTypes);
283
284 foreach (string Source in await Consolidation.GetSources())
285 {
286 if (First)
287 First = false;
288 else
289 sb.AppendLine();
290
291 sb.Append(Source);
292 }
293
294 MainWindow.UpdateGui(async () =>
295 {
296 bool Added;
297
298 if (Added = (Rec.Item is null))
299 Rec.Item = await ChatItem.CreateAsync(Type, Timestamp, string.Empty, string.Empty, null, ThreadId, FgColor, BgColor);
300
301 Rec.Item.From = sb.ToString();
302 await Rec.Item.Update(Message, Markdown);
303
304 if (Added)
305 Rec.ListViewIndex = this.AddListItem(Rec.Item);
306 else
307 this.ChatListView.Items[Rec.ListViewIndex] = this.CreateItem(Rec.Item);
308 });
309
310 }, null);
311
312 return;
313 }
314 }
315
316 this.AddListItem(await ChatItem.CreateAsync(Type, Timestamp, Message, From, Markdown, ThreadId, FgColor, BgColor));
317 }
318 catch (Exception ex)
319 {
320 Log.Exception(ex);
321 }
322 }
323
324 private class ConsolidationTag
325 {
326 public ChatItem Item = null;
327 public DateTime UpdateTP = DateTime.MinValue;
328 public int ListViewIndex;
329 }
330
331 private int AddListItem(ChatItem Item)
332 {
333 ListViewItem ListViewItem = this.CreateItem(Item);
334 int Index = this.ChatListView.Items.Add(ListViewItem);
335 this.ChatListView.ScrollIntoView(ListViewItem);
336
337 return Index;
338 }
339
340 private ListViewItem CreateItem(ChatItem Item)
341 {
342 return new ListViewItem()
343 {
344 Content = Item,
345 Foreground = new SolidColorBrush(Item.ForegroundColor),
346 Background = new SolidColorBrush(Item.BackgroundColor),
347 Margin = new Thickness(0)
348 };
349 }
350
351 public async Task ChatMessageReceived(string Message, string From, string ThreadId, bool IsMarkdown, DateTime Timestamp, MainWindow MainWindow)
352 {
353 MarkdownDocument Markdown;
354
355 if (IsMarkdown)
356 {
357 if (Message.IndexOf('|') >= 0)
358 {
359 int c = this.ChatListView.Items.Count;
360
361 if (c > 0 &&
362 this.ChatListView.Items[c - 1] is ChatItem Item &&
363 Item.Type == ChatItemType.Received &&
364 Item.From == From &&
365 (DateTime.Now - Item.LastUpdated).TotalSeconds < 10 &&
366 Item.LastIsTable)
367 {
368 Item.Append(Message, this.ChatListView, MainWindow);
369 return;
370 }
371 }
372
373 try
374 {
375 Markdown = await MarkdownDocument.CreateAsync(Message, GetMarkdownSettings());
376 }
377 catch (Exception)
378 {
379 Markdown = null;
380 }
381 }
382 else
383 Markdown = null;
384
385 MainWindow.UpdateGui(() =>
386 {
387 this.AddItem(ChatItemType.Received, Timestamp, Message, From, Markdown, ThreadId, Colors.Black, Colors.AliceBlue);
388 return Task.CompletedTask;
389 });
390 }
391
392 private void UserControl_GotFocus(object Sender, RoutedEventArgs e)
393 {
394 this.Input.Focus();
395 }
396
397 public void NewButton_Click(object Sender, RoutedEventArgs e)
398 {
399 this.ChatListView.Items.Clear();
400 }
401
402 public void SaveButton_Click(object Sender, RoutedEventArgs e)
403 {
404 this.SaveAsButton_Click(Sender, e);
405 }
406
407 public void SaveAsButton_Click(object Sender, RoutedEventArgs e)
408 {
409 SaveFileDialog Dialog = new SaveFileDialog()
410 {
411 AddExtension = true,
412 CheckPathExists = true,
413 CreatePrompt = false,
414 DefaultExt = "html",
415 Filter = "XML Files (*.xml)|*.xml|HTML Files (*.html,*.htm)|*.html,*.htm|All Files (*.*)|*.*",
416 Title = "Save chat session"
417 };
418
419 bool? Result = Dialog.ShowDialog(MainWindow.FindWindow(this));
420
421 if (Result.HasValue && Result.Value)
422 {
423 try
424 {
425 if (Dialog.FilterIndex == 2)
426 {
427 StringBuilder Xml = new StringBuilder();
428 using (XmlWriter w = XmlWriter.Create(Xml, XML.WriterSettings(true, true)))
429 {
430 this.SaveAsXml(w);
431 }
432
433 string Html = XSL.Transform(Xml.ToString(), chatToHtml);
434
435 File.WriteAllText(Dialog.FileName, Html, System.Text.Encoding.UTF8);
436 }
437 else
438 {
439 using (FileStream f = File.Create(Dialog.FileName))
440 {
441 using (XmlWriter w = XmlWriter.Create(f, XML.WriterSettings(true, false)))
442 {
443 this.SaveAsXml(w);
444 }
445 }
446 }
447 }
448 catch (Exception ex)
449 {
450 MessageBox.Show(MainWindow.FindWindow(this), ex.Message, "Unable to save file.", MessageBoxButton.OK, MessageBoxImage.Error);
451 }
452 }
453 }
454
455 private static readonly XslCompiledTransform chatToHtml = XSL.LoadTransform("Waher.Client.WPF.Transforms.ChatToHTML.xslt");
456 private static readonly XmlSchema schema = XSL.LoadSchema("Waher.Client.WPF.Schema.Chat.xsd");
457 private const string chatNamespace = "http://waher.se/Schema/Chat.xsd";
458 private const string chatRoot = "Chat";
459
460 private void SaveAsXml(XmlWriter w)
461 {
462 w.WriteStartElement(chatRoot, chatNamespace);
463 w.WriteAttributeString("muc", CommonTypes.Encode(this.muc));
464
465 foreach (ListViewItem Item in this.ChatListView.Items)
466 {
467 if (Item.Content is ChatItem ChatItem)
468 {
469 w.WriteStartElement(ChatItem.Type.ToString());
470 w.WriteAttributeString("timestamp", XML.Encode(ChatItem.Timestamp));
471
472 if (!string.IsNullOrEmpty(ChatItem.From))
473 w.WriteAttributeString("from", ChatItem.FromStr);
474
475 if (!string.IsNullOrEmpty(ChatItem.ThreadId))
476 w.WriteAttributeString("thread", ChatItem.ThreadId);
477
478 w.WriteValue(ChatItem.Message);
479 w.WriteEndElement();
480 }
481 }
482
483 w.WriteEndElement();
484 w.Flush();
485 }
486
487 public async void OpenButton_Click(object Sender, RoutedEventArgs e)
488 {
489 try
490 {
491 OpenFileDialog Dialog = new OpenFileDialog()
492 {
493 AddExtension = true,
494 CheckFileExists = true,
495 CheckPathExists = true,
496 DefaultExt = "xml",
497 Filter = "XML Files (*.xml)|*.xml|All Files (*.*)|*.*",
498 Multiselect = false,
499 ShowReadOnly = true,
500 Title = "Open chat session"
501 };
502
503 bool? Result = Dialog.ShowDialog(MainWindow.FindWindow(this));
504
505 if (Result.HasValue && Result.Value)
506 {
507 XmlDocument Xml = new XmlDocument()
508 {
509 PreserveWhitespace = true
510 };
511 Xml.Load(Dialog.FileName);
512
513 await this.Load(Xml, Dialog.FileName);
514 }
515 }
516 catch (Exception ex)
517 {
518 ex = Log.UnnestException(ex);
519 MessageBox.Show(ex.Message, "Unable to load file.", MessageBoxButton.OK, MessageBoxImage.Error);
520 }
521 }
522
523 public async Task Load(XmlDocument Xml, string FileName)
524 {
525 MarkdownDocument Markdown;
526 XmlElement E;
527 DateTime Timestamp;
528 Color ForegroundColor;
529 Color BackgroundColor;
530 string From;
531 string ThreadId;
532
533 XSL.Validate(FileName, Xml, chatRoot, chatNamespace, schema);
534
535 this.ChatListView.Items.Clear();
536
537 bool PrevMuc = this.muc;
538 this.muc = XML.Attribute(Xml.DocumentElement, "muc", this.muc);
539
540 if (this.muc != PrevMuc)
541 {
542 if (this.muc)
543 {
544 double w = this.ReceivedColumn.Width * 2;
545 this.FromColumn.Width = w;
546 this.ContentColumn.Width -= w;
547 }
548 else
549 {
550 this.ContentColumn.Width += this.FromColumn.Width;
551 this.FromColumn.Width = 0;
552 }
553 }
554
555 foreach (XmlNode N in Xml.DocumentElement.ChildNodes)
556 {
557 E = N as XmlElement;
558 if (E is null)
559 continue;
560
561 if (!Enum.TryParse(E.LocalName, out ChatItemType Type))
562 continue;
563
564 Timestamp = XML.Attribute(E, "timestamp", DateTime.MinValue);
565 From = XML.Attribute(E, "from");
566 ThreadId = XML.Attribute(E, "thread");
567
568 switch (Type)
569 {
570 case ChatItemType.Received:
571 ForegroundColor = Colors.Black;
572 BackgroundColor = Colors.AliceBlue;
573 break;
574
575 case ChatItemType.Transmitted:
576 ForegroundColor = Colors.Black;
577 BackgroundColor = Colors.Honeydew;
578 break;
579
580 case ChatItemType.Event:
581 ForegroundColor = EventFgColor;
582 BackgroundColor = EventBgColor;
583 break;
584
585 default:
586 continue;
587 }
588
589 try
590 {
591 Markdown = await MarkdownDocument.CreateAsync(E.InnerText, GetMarkdownSettings());
592 }
593 catch (Exception)
594 {
595 Markdown = null;
596 }
597
598 this.AddItem(Type, Timestamp, E.InnerText, From, Markdown, ThreadId, ForegroundColor, BackgroundColor);
599 }
600 }
601
602 private void Input_PreviewKeyDown(object Sender, KeyEventArgs e)
603 {
604 if (e.Key == Key.Enter)
605 {
606 if (!Keyboard.Modifiers.HasFlag(ModifierKeys.Control) && !Keyboard.Modifiers.HasFlag(ModifierKeys.Shift))
607 {
608 this.Send_Click(Sender, e);
609 e.Handled = true;
610 }
611 }
612 }
613
614 private void ChatListView_PreviewMouseLeftButtonUp(object Sender, MouseButtonEventArgs e)
615 {
616 if (this.ChatListView.SelectedItem is ListViewItem ListViewItem &&
617 ListViewItem.Content is ChatItem Item)
618 {
619 this.Input.Text = Item.Message;
620 e.Handled = true;
621 }
622 else if (e.OriginalSource is Run Run)
623 {
624 this.Input.Text = Run.Text;
625 e.Handled = true;
626 }
627 else if (e.OriginalSource is TextBlock TextBlock)
628 {
629 this.Input.Text = TextBlock.Text;
630 e.Handled = true;
631 }
632 }
633
634 private void Hyperlink_Click(object Sender, RoutedEventArgs e)
635 {
636 string Uri = ((Hyperlink)Sender).NavigateUri.ToString();
637 System.Diagnostics.Process.Start(Uri);
638 }
639
640 public void Event(string Message, string From, string ThreadId)
641 {
642 this.Event(Message, From, null, DateTime.Now, ThreadId);
643 }
644
645 public void Event(string Message, string From, MarkdownDocument Markdown, DateTime Timestamp, string ThreadId)
646 {
647 MainWindow.UpdateGui(() =>
648 {
649 this.AddItem(ChatItemType.Event, Timestamp, Message, From, Markdown, ThreadId, EventFgColor, EventBgColor);
650 return Task.CompletedTask;
651 });
652 }
653
654 public static readonly Color EventFgColor = Color.FromRgb(32, 32, 32);
655 public static readonly Color EventBgColor = Color.FromRgb(240, 240, 240);
656
657 private void MucSelfPing(object State)
658 {
659 this.timer = MainWindow.Scheduler.Add(DateTime.Now.AddMinutes(1), this.MucSelfPing, null);
660
661 if (this.node is RoomNode RoomNode)
662 {
663 RoomNode.MucClient.SelfPing(RoomNode.RoomId, RoomNode.Domain, RoomNode.NickName, (Sender, e) =>
664 {
665 if (!e.Ok)
666 {
667 if (e.StanzaError is Networking.XMPP.StanzaErrors.NotAcceptableException) // Need to reconnect with room.
668 {
669 RoomNode.MucClient.EnterRoom(RoomNode.RoomId, RoomNode.Domain, RoomNode.NickName, RoomNode.Password, (sender2, e2) =>
670 {
671 if (e2.Ok)
672 RoomNode.MucClient.SetPresence(RoomNode.RoomId, RoomNode.Domain, RoomNode.NickName, Networking.XMPP.Availability.Chat, null, null);
673
674 return Task.CompletedTask;
675 }, null);
676 }
677 }
678
679 return Task.CompletedTask;
680 }, null);
681 }
682 }
683
684 public bool ContainsThread(string ThreadId)
685 {
686 return this.threads.ContainsKey(ThreadId);
687 }
688
689 }
690}
Represents one item in a chat.
Definition: ChatItem.cs:28
ChatItemType Type
Chat item type.
Definition: ChatItem.cs:234
string From
Who sent the message.
Definition: ChatItem.cs:240
DateTime Timestamp
Timestamp of item.
Definition: ChatItem.cs:224
DateTime LastUpdated
Timestamp when item was last updated.
Definition: ChatItem.cs:229
string FromStr
Nick-name of sender.
Definition: ChatItem.cs:257
Interaction logic for ChatView.xaml
void InitializeComponent()
InitializeComponent
Definition: ChatView.g.cs:106
Interaction logic for xaml
Color BackgroundColor
Background color
Color ForegroundColor
Foreground color
Represents a room hosted by a Multi-User Chat service.
Definition: RoomNode.cs:25
Abstract base class for tree nodes in the connection view.
Definition: TreeNode.cs:24
virtual void ViewClosed()
Method called when the view has been closed.
Definition: TreeNode.cs:865
Helps with parsing of commong data types.
Definition: CommonTypes.cs:13
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
Definition: CommonTypes.cs:594
Provides emojis from Emoji One (http://emojione.com/) stored as local files.
Image encoder/decoder.
Definition: ImageCodec.cs:14
const string FileExtensionPng
png
Definition: ImageCodec.cs:75
Consolidates Markdown from multiple sources, sharing the same thread.
Definition: Consolidator.cs:18
object Tag
External tag object that can be tagged to the object by its owner.
async Task< string[]> GetSources()
Consolidated sources.
Definition: Consolidator.cs:51
async Task< string > GenerateMarkdownAsync()
Generates consolidated markdown from all sources.
Task< bool > Add(string Source, MarkdownDocument Markdown)
Adds incoming markdown information.
Contains a markdown document. This markdown document class supports original markdown,...
MarkdownSettings Settings
Markdown settings.
Type[] TransparentExceptionTypes
If an exception is thrown when processing script in markdown, and the exception is of any of these ty...
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.
Contains settings that the HTML export uses to customize HTML output.
Definition: HtmlSettings.cs:7
Contains settings that the XAML export uses to customize XAML output.
Definition: XamlSettings.cs:10
Helps with common XML-related tasks.
Definition: XML.cs:19
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
Definition: XML.cs:914
static string Encode(string s)
Encodes a string for use in XML.
Definition: XML.cs:27
static XmlWriterSettings WriterSettings(bool Indent, bool OmitXmlDeclaration)
Gets an XML writer settings object.
Definition: XML.cs:1177
Static class managing loading of XSL resources stored as embedded resources or in content files.
Definition: XSL.cs:15
static XmlSchema LoadSchema(string ResourceName)
Loads an XML schema from an embedded resource.
Definition: XSL.cs:23
static XslCompiledTransform LoadTransform(string ResourceName)
Loads an XSL transformation from an embedded resource.
Definition: XSL.cs:70
static string Transform(string XML, XslCompiledTransform Transform)
Transforms an XML document using an XSL transform.
Definition: XSL.cs:162
static void Validate(string ObjectID, XmlDocument Xml, params XmlSchema[] Schemas)
Validates an XML document given a set of XML schemas.
Definition: XSL.cs:118
Class representing an event.
Definition: Event.cs:10
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:13
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Definition: Log.cs:1647
static Exception UnnestException(Exception Exception)
Unnests an exception, to extract the relevant inner exception.
Definition: Log.cs:818
Class managing a script expression.
Definition: Expression.cs:39
Interface for tab view user controls in the client.
Definition: ITabView.cs:10
Emoji1SourceFileType
What source files to use when displaying emoji.
Definition: App.xaml.cs:4