Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
MucService.cs
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Threading.Tasks;
5using System.Windows;
6using System.Windows.Input;
7using System.Windows.Media;
8using System.Xml;
20
22{
24 {
25 private readonly Dictionary<string, RoomNode> roomByJid = new Dictionary<string, RoomNode>();
26 private readonly MultiUserChatClient mucClient;
27 private bool handlersAdded;
28
29 public MucService(TreeNode Parent, string JID, string Name, string Node, Dictionary<string, bool> Features,
30 MultiUserChatClient MucClient)
31 : base(Parent, JID, Name, Node, Features)
32 {
33 this.mucClient = MucClient;
34
35 this.children = new SortedDictionary<string, TreeNode>()
36 {
37 { string.Empty, new Loading(this) }
38 };
39
40 this.mucClient.OccupantPresence += this.MucClient_OccupantPresence;
41 this.mucClient.OccupantRequest += this.MucClient_OccupantRequest;
42 this.mucClient.PrivateMessageReceived += this.MucClient_PrivateMessageReceived;
43 this.mucClient.RegistrationRequest += this.MucClient_RegistrationRequest;
44 this.mucClient.RoomDeclinedInvitationReceived += this.MucClient_RoomDeclinedInvitationReceived;
45 this.mucClient.RoomDestroyed += this.MucClient_RoomDestroyed;
46 this.mucClient.RoomInvitationReceived += this.MucClient_RoomInvitationReceived;
47 this.mucClient.RoomMessage += this.MucClient_RoomMessage;
48 this.mucClient.RoomOccupantMessage += this.MucClient_RoomOccupantMessage;
49 this.mucClient.RoomPresence += this.MucClient_RoomPresence;
50 this.mucClient.RoomSubject += this.MucClient_RoomSubject;
51 this.handlersAdded = true;
52 }
53
54 public override bool RemoveChild(TreeNode Node)
55 {
56 if (Node is RoomNode RoomNode)
57 {
58 lock (this.roomByJid)
59 {
60 this.roomByJid.Remove(RoomNode.RoomId + "@" + RoomNode.Domain);
61 }
62 }
63
64 return base.RemoveChild(Node);
65 }
66
67 public override void Removed(MainWindow Window)
68 {
69 this.UnregisterHandlers();
70 }
71
72 public override void Dispose()
73 {
74 this.UnregisterHandlers();
75 base.Dispose();
76 }
77
78 private void UnregisterHandlers()
79 {
80 if (this.handlersAdded)
81 {
82 this.mucClient.OccupantPresence -= this.MucClient_OccupantPresence;
83 this.mucClient.OccupantRequest -= this.MucClient_OccupantRequest;
84 this.mucClient.PrivateMessageReceived -= this.MucClient_PrivateMessageReceived;
85 this.mucClient.RegistrationRequest -= this.MucClient_RegistrationRequest;
86 this.mucClient.RoomDeclinedInvitationReceived -= this.MucClient_RoomDeclinedInvitationReceived;
87 this.mucClient.RoomDestroyed -= this.MucClient_RoomDestroyed;
88 this.mucClient.RoomInvitationReceived -= this.MucClient_RoomInvitationReceived;
89 this.mucClient.RoomMessage -= this.MucClient_RoomMessage;
90 this.mucClient.RoomOccupantMessage -= this.MucClient_RoomOccupantMessage;
91 this.mucClient.RoomPresence -= this.MucClient_RoomPresence;
92 this.mucClient.RoomSubject -= this.MucClient_RoomSubject;
93 this.handlersAdded = false;
94 }
95 }
96
97 public MultiUserChatClient MucClient => this.mucClient;
98
99 public override ImageSource ImageResource => XmppAccountNode.chatBubble;
100 public override bool CanRecycle => true;
101
102 public override async Task Recycle(MainWindow Window)
103 {
104 if (!(this.children is null))
105 {
106 foreach (TreeNode Node in this.children.Values)
107 {
108 if (Node.CanRecycle)
109 await Node.Recycle(Window);
110 }
111 }
112 }
113
114 public override string ToolTip => "Multi-User Chat Service";
115
116 private bool loadingChildren = false;
117
118 protected override void LoadChildren()
119 {
120 if (!this.loadingChildren && !this.IsLoaded)
121 {
122 Mouse.OverrideCursor = Cursors.Wait;
123
124 this.loadingChildren = true;
125 this.Account.Client.SendServiceItemsDiscoveryRequest(this.mucClient.ComponentAddress, async (Sender, e) =>
126 {
127 this.loadingChildren = false;
128 MainWindow.MouseDefault();
129
130 if (e.Ok)
131 {
132 SortedDictionary<string, TreeNode> Children = new SortedDictionary<string, TreeNode>();
133
134 this.NodesRemoved(this.children.Values, this);
135
136 lock (this.roomByJid)
137 {
138 foreach (KeyValuePair<string, RoomNode> P in this.roomByJid)
139 Children[P.Key] = P.Value;
140 }
141
142 foreach (Item Item in e.Items)
143 {
144 string RoomId;
145 string Domain;
146 int i = Item.JID.IndexOf('@');
147
148 if (i < 0)
149 {
150 RoomId = string.Empty;
151 Domain = Item.JID;
152 }
153 else
154 {
155 RoomId = Item.JID.Substring(0, i);
156 Domain = Item.JID.Substring(i + 1);
157 }
158
159 string Jid = RoomId + "@" + Domain;
160
161 string Prefix = this.mucClient.Client.BareJID + "." + Jid;
162 string NickName = await RuntimeSettings.GetAsync(Prefix + ".Nick", string.Empty);
163 string Password = await RuntimeSettings.GetAsync(Prefix + ".Pwd", string.Empty);
164
165 lock (this.roomByJid)
166 {
167 if (!this.roomByJid.TryGetValue(Jid, out RoomNode Node))
168 {
169 Node = new RoomNode(this, RoomId, Domain, NickName, Password, Item.Name, false);
170 this.roomByJid[Jid] = Node;
171 Children[Item.JID] = Node;
172 }
173 }
174 }
175
176 this.children = new SortedDictionary<string, TreeNode>(Children);
177 this.OnUpdated();
178 this.NodesAdded(Children.Values, this);
179 }
180 else
181 MainWindow.ErrorBox(string.IsNullOrEmpty(e.ErrorText) ? "Unable to get rooms." : e.ErrorText);
182
183 }, null);
184 }
185
186 base.LoadChildren();
187 }
188
189 public override bool CanAddChildren => true;
190
191 public override void Add()
192 {
193 EnterRoomForm Dialog = new EnterRoomForm(this.mucClient.ComponentAddress)
194 {
195 Owner = MainWindow.currentInstance
196 };
197
198 bool? Result = Dialog.ShowDialog();
199
200 if (Result.HasValue && Result.Value)
201 {
202 string RoomId = Dialog.RoomID.Text;
203 string Domain = Dialog.Domain.Text;
204 string NickName = Dialog.NickName.Text;
205 string Password = Dialog.Password.Password;
206 string Prefix = this.mucClient.Client.BareJID + "." + RoomId + "@" + Domain;
207 DataForm Form = null;
208
209 this.mucClient.EnterRoom(RoomId, Domain, NickName, Password, async (Sender, e) =>
210 {
211 if (e.Ok)
212 {
213 if (e.HasStatus(MucStatus.Created))
214 {
215 await this.mucClient.GetRoomConfiguration(RoomId, Domain, (sender2, e2) =>
216 {
217 if (e2.Ok)
218 {
219 Form = e2.Form;
220
221 if (!string.IsNullOrEmpty(Password))
222 {
223 Field PasswordProtectionField = Form["muc#roomconfig_passwordprotectedroom"];
224 PasswordProtectionField?.SetValue("true");
225
226 Field PasswordField = Form["muc#roomconfig_roomsecret"];
227 PasswordField?.SetValue(Password);
228 }
229
230 MainWindow.currentInstance.ShowDataForm(e2.Form);
231 }
232 else
233 MainWindow.ErrorBox(e2.ErrorText);
234
235 return Task.CompletedTask;
236 }, async (sender2, e2) =>
237 {
238 if (e2.Ok)
239 {
240 await RuntimeSettings.SetAsync(Prefix + ".Nick", NickName);
241 await RuntimeSettings.SetAsync(Prefix + ".Pwd", Password);
242
243 Field NameField = Form["muc#roomconfig_roomname"];
244 string Name = NameField?.ValueString ?? RoomId;
245
246 this.AddRoomNode(RoomId, Domain, NickName, Password, Name, true);
247 }
248 }, null);
249 }
250 else
251 {
252 await RuntimeSettings.SetAsync(Prefix + ".Nick", NickName);
253 await RuntimeSettings.SetAsync(Prefix + ".Pwd", Password);
254
255 this.AddRoomNode(RoomId, Domain, NickName, Password, string.Empty, true);
256
257 await this.MucClient_OccupantPresence(this, e);
258 }
259 }
260 else
261 MainWindow.ErrorBox(string.IsNullOrEmpty(e.ErrorText) ? "Unable to add room." : e.ErrorText);
262 }, null);
263 }
264 }
265
266 private RoomNode AddRoomNode(string RoomId, string Domain, string NickName, string Password, string Name, bool Entered)
267 {
268 RoomNode Node = new RoomNode(this, RoomId, Domain, NickName, Password, Name, Entered);
269
270 lock (this.roomByJid)
271 {
272 this.roomByJid[RoomId + "@" + Domain] = Node;
273 }
274
275 if (this.IsLoaded)
276 {
277 if (this.children is null)
278 this.children = new SortedDictionary<string, TreeNode>() { { Node.Key, Node } };
279 else
280 {
281 lock (this.children)
282 {
283 this.children[Node.Key] = Node;
284 }
285 }
286
287 MainWindow.UpdateGui(() =>
288 {
289 this.Account?.View?.NodeAdded(this, Node);
290
291 foreach (TreeNode Node2 in Node.Children)
292 this.Account?.View?.NodeAdded(Node, Node2);
293
294 this.OnUpdated();
295
296 return Task.CompletedTask;
297 });
298 }
299
300 return Node;
301 }
302
303 private Task MucClient_RoomInvitationReceived(object Sender, RoomInvitationMessageEventArgs e)
304 {
306 {
307 Owner = MainWindow.currentInstance,
308 InviteTo = XmppClient.GetBareJID(e.To),
309 InviteFrom = XmppClient.GetBareJID(e.InviteFrom),
310 InvitationReason = e.Reason,
311 RoomName = e.RoomId,
312 RoomJid = e.RoomId + "@" + e.Domain
313 };
314
315 this.mucClient.GetRoomInformation(e.RoomId, e.Domain, (sender2, e2) =>
316 {
317 if (e2.Ok)
318 {
319 foreach (Identity Id in e2.Identities)
320 {
321 if (Id.Category == "conference" && Id.Type == "text")
322 {
323 Form.RoomName = Id.Name;
324 break;
325 }
326 }
327
328 Form.MembersOnly = e2.MembersOnly;
329 Form.Moderated = e2.Moderated;
330 Form.NonAnonymous = e2.NonAnonymous;
331 Form.Open = e2.Open;
332 Form.PasswordProtected = e2.PasswordProtected;
333 Form.Persistent = e2.Persistent;
334 Form.Public = e2.Public;
335 Form.SemiAnonymous = e2.SemiAnonymous;
336 Form.Temporary = e2.Temporary;
337 Form.Unmoderated = e2.Unmoderated;
338 Form.Unsecured = e2.Unsecured;
339 }
340
341 MainWindow.UpdateGui(() =>
342 {
343 this.ShowInvitationForm(Form, e, e2);
344 return Task.CompletedTask;
345 });
346
347 return Task.CompletedTask;
348 }, null);
349
350 return Task.CompletedTask;
351 }
352
354 {
355 bool? b = Form.ShowDialog();
356
357 if (b.HasValue)
358 {
359 if (b.Value)
360 {
361 e.Accept(Form.NickName.Text, (sender2, e3) =>
362 {
363 if (!e3.Ok)
364 {
365 MainWindow.UpdateGui(() =>
366 {
367 MessageBox.Show(MainWindow.currentInstance,
368 string.IsNullOrEmpty(e3.ErrorText) ? "Unable to process invitation." : e3.ErrorText,
369 "Error", MessageBoxButton.OK, MessageBoxImage.Error);
370
371 RoomInvitationReceivedForm Form2 = new RoomInvitationReceivedForm()
372 {
373 Owner = MainWindow.currentInstance,
374 InviteTo = XmppClient.GetBareJID(e.To),
375 InviteFrom = XmppClient.GetBareJID(e.InviteFrom),
376 InvitationReason = e.Reason,
377 RoomName = Form.RoomName,
378 RoomJid = e.RoomId + "@" + e.Domain,
379 MembersOnly = e2.MembersOnly,
380 Moderated = e2.Moderated,
381 NonAnonymous = e2.NonAnonymous,
382 Open = e2.Open,
383 PasswordProtected = e2.PasswordProtected,
384 Persistent = e2.Persistent,
385 Public = e2.Public,
386 SemiAnonymous = e2.SemiAnonymous,
387 Temporary = e2.Temporary,
388 Unmoderated = e2.Unmoderated,
389 Unsecured = e2.Unsecured
390 };
391
392 this.ShowInvitationForm(Form2, e, e2);
393
394 return Task.CompletedTask;
395 });
396 }
397
398 return Task.CompletedTask;
399 }, null);
400 }
401 else
402 e.Decline(Form.Reason.Text);
403 }
404 }
405
406 private Task MucClient_RoomDeclinedInvitationReceived(object Sender, RoomDeclinedMessageEventArgs e)
407 {
408 StringBuilder sb = new StringBuilder();
409
410 sb.Append("Your invitation sent to ");
411 sb.Append(e.DeclinedFrom);
412 sb.Append(" to join the room ");
413 sb.Append(e.RoomId);
414 sb.Append("@");
415 sb.Append(e.Domain);
416 sb.Append(" was declined.");
417
418 if (!string.IsNullOrEmpty(e.Reason))
419 {
420 sb.Append(" Reason: ");
421 sb.Append(e.Reason);
422 }
423
424 MainWindow.MessageBox(sb.ToString(), "Invitation declined", MessageBoxButton.OK, MessageBoxImage.Exclamation);
425
426 return Task.CompletedTask;
427 }
428
429 private async Task<RoomNode> GetRoomNode(string RoomId, string Domain)
430 {
431 RoomNode Result;
432 string Jid = RoomId + "@" + Domain;
433
434 lock (this.roomByJid)
435 {
436 if (this.roomByJid.TryGetValue(Jid, out Result))
437 return Result;
438 }
439
440 string Prefix = this.mucClient.Client.BareJID + "." + Jid;
441 string NickName = await RuntimeSettings.GetAsync(Prefix + ".Nick", string.Empty);
442 string Password = await RuntimeSettings.GetAsync(Prefix + ".Pwd", string.Empty);
443
444 Result = this.AddRoomNode(RoomId, Domain, NickName, Password, string.Empty, false);
445
446 return Result;
447 }
448
449 private async Task MucClient_RoomOccupantMessage(object Sender, RoomOccupantMessageEventArgs e)
450 {
451 RoomNode RoomNode = await this.GetRoomNode(e.RoomId, e.Domain);
452 string NickName = XmppClient.GetResource(e.From);
453 ChatItemType Type = ChatItemType.Received;
454
455 if (!string.IsNullOrEmpty(NickName) && RoomNode.NickName == NickName)
456 {
457 bool HasDelay = false;
458
459 foreach (XmlNode N in e.Message.ChildNodes)
460 {
461 if (N is XmlElement E && E.LocalName == "delay")
462 {
463 HasDelay = true;
464 break;
465 }
466 }
467
468 if (!HasDelay)
469 return;
470
471 Type = ChatItemType.Transmitted;
472 }
473
474 RoomNode.EnterIfNotAlready(true);
475
476 MainWindow.ParseChatMessage(e, out string Message, out bool IsMarkdown, out DateTime Timestamp);
477
478 MainWindow.UpdateGui(async () =>
479 {
480 await MainWindow.currentInstance.MucGroupChatMessage(e.From, XmppClient.GetBareJID(e.To), Message, e.ThreadID,
481 IsMarkdown, Timestamp, Type, RoomNode, RoomNode.Header);
482 });
483 }
484
485 private async Task MucClient_RoomSubject(object Sender, RoomOccupantMessageEventArgs e)
486 {
487 RoomNode RoomNode = await this.GetRoomNode(e.RoomId, e.Domain);
488 if (!RoomNode.Entered)
489 return;
490
491 MainWindow.UpdateGui(() =>
492 {
493 MainWindow.currentInstance.MucChatSubject(e.From, XmppClient.GetBareJID(e.To), RoomNode, e.Subject);
494 return Task.CompletedTask;
495 });
496 }
497
498 private Task MucClient_RegistrationRequest(object Sender, MessageFormEventArgs e)
499 {
500 MainWindow.UpdateGui(async () =>
501 {
503 Dialog.ShowDialog();
504 });
505
506 return Task.CompletedTask;
507 }
508
509 private Task MucClient_OccupantRequest(object Sender, MessageFormEventArgs e)
510 {
511 MainWindow.UpdateGui(async () =>
512 {
514 Dialog.ShowDialog();
515 });
516
517 return Task.CompletedTask;
518 }
519
520 internal async Task MucClient_OccupantPresence(object Sender, UserPresenceEventArgs e)
521 {
522 RoomNode RoomNode = await this.GetRoomNode(e.RoomId, e.Domain);
523 OccupantNode OccupantNode = RoomNode.GetOccupantNode(e.NickName, e.Affiliation, e.Role, e.FullJid);
524 ChatView View = null;
525
526 if (!OccupantNode.Availability.HasValue || e.Availability != OccupantNode.Availability.Value)
527 {
528 OccupantNode.Availability = e.Availability;
529 OccupantNode.OnUpdated();
530
531 View = MainWindow.currentInstance.FindRoomView(e.From, XmppClient.GetBareJID(e.To));
532
533 if (!(View is null))
534 {
535 switch (OccupantNode.Availability)
536 {
537 case Availability.Online:
538 View.Event("Online.", e.NickName, string.Empty);
539 break;
540
541 case Availability.Offline:
542 View.Event("Offline.", e.NickName, string.Empty);
543 break;
544
545 case Availability.Away:
546 View.Event("Away.", e.NickName, string.Empty);
547 break;
548
549 case Availability.Chat:
550 View.Event("Ready to chat.", e.NickName, string.Empty);
551 break;
552
553 case Availability.DoNotDisturb:
554 View.Event("Busy.", e.NickName, string.Empty);
555 break;
556
557 case Availability.ExtendedAway:
558 View.Event("Away (extended).", e.NickName, string.Empty);
559 break;
560 }
561 }
562 }
563
564 await this.MucClient_RoomPresence(Sender, e, View);
565 }
566
567 private Task MucClient_RoomPresence(object Sender, UserPresenceEventArgs e)
568 {
569 return this.MucClient_RoomPresence(Sender, e, null);
570 }
571
572 private async Task MucClient_RoomPresence(object _, UserPresenceEventArgs e, ChatView View)
573 {
574 if ((e.MucStatus?.Length ?? 0) > 0 || e.RoomDestroyed)
575 {
576 RoomNode RoomNode = await this.GetRoomNode(e.RoomId, e.Domain);
577
578 if (View is null)
579 View = MainWindow.currentInstance.FindRoomView(e.From, XmppClient.GetBareJID(e.To));
580
581 if (!(View is null))
582 {
583 foreach (MucStatus Status in e.MucStatus ?? new MucStatus[0])
584 {
585 switch (Status)
586 {
587 case MucStatus.AffiliationChanged:
588 if (e.Affiliation.HasValue)
589 View.Event("New affiliation: " + e.Affiliation.ToString(), e.NickName, string.Empty);
590 break;
591
592 case MucStatus.LoggingEnabled:
593 View.Event("This room logs messages.", e.NickName, string.Empty);
594 break;
595
596 case MucStatus.LoggingDisabled:
597 View.Event("This room does not log messages.", e.NickName, string.Empty);
598 break;
599
600 case MucStatus.NickModified:
601 View.Event("Nick-name changed.", e.NickName, string.Empty);
602 break;
603
604 case MucStatus.RoomNonAnonymous:
605 View.Event("This room does not anonymous.", e.NickName, string.Empty);
606 break;
607
608 case MucStatus.RoomSemiAnonymous:
609 View.Event("This room is semi-anonymous.", e.NickName, string.Empty);
610 break;
611
612 case MucStatus.RoomAnonymous:
613 View.Event("This room does anonymous.", e.NickName, string.Empty);
614 break;
615
616 case MucStatus.FullJidVisisble:
617 View.Event("All participants in this room have access to the full JID of each other.", e.NickName, string.Empty);
618 break;
619
620 case MucStatus.ShowsUnavailableMembers:
621 View.Event("This room displays unavailable members.", e.NickName, string.Empty);
622 break;
623
624 case MucStatus.DoesNotShowUnavailableMembers:
625 View.Event("This room hieds unavailable members.", e.NickName, string.Empty);
626 break;
627
628 case MucStatus.NonPrivacyRelatedConfigurationChange:
629 View.Event("A configuration that does not affect privacy changed.", e.NickName, string.Empty);
630 break;
631
632 case MucStatus.OwnPresence:
633 break;
634
635 case MucStatus.Created:
636 View.Event("Room created.", e.NickName, string.Empty);
637 break;
638
639 case MucStatus.Banned:
640 View.Event("Banned from the room.", e.NickName, string.Empty);
641 break;
642
643 case MucStatus.NewRoomNickName:
644 View.Event("New room nick-name.", e.NickName, string.Empty);
645 break;
646
647 case MucStatus.Kicked:
648 View.Event("Temporarily kicked from the room.", e.NickName, string.Empty);
649 break;
650
651 case MucStatus.RemovedDueToAffiliationChange:
652 View.Event("Removed from the room due to an affiliation change.", e.NickName, string.Empty);
653 break;
654
655 case MucStatus.RemovedDueToNonMembership:
656 View.Event("Removed from the room, since no longer member.", e.NickName, string.Empty);
657 break;
658
659 case MucStatus.RemovedDueToSystemShutdown:
660 View.Event("Removed from the room due to system shutdown.", e.NickName, string.Empty);
661 break;
662
663 case MucStatus.RemovedDueToFailure:
664 View.Event("Removed from the room due to technical problems.", e.NickName, string.Empty);
665 break;
666 }
667 }
668 }
669
670 if (e.RoomDestroyed)
671 {
672 View?.Event("Room has been destroyed on the host.", e.NickName, string.Empty);
673
674 RoomNode.Parent.RemoveChild(RoomNode);
675 RoomNode.Parent.OnUpdated();
676 }
677 }
678 }
679
680 private async Task MucClient_RoomDestroyed(object Sender, UserPresenceEventArgs e)
681 {
682 await this.MucClient_RoomPresence(Sender, e);
683 }
684
685 private async Task MucClient_PrivateMessageReceived(object Sender, RoomOccupantMessageEventArgs e)
686 {
687 RoomNode RoomNode = await this.GetRoomNode(e.RoomId, e.Domain);
688 OccupantNode Occupant = RoomNode.GetOccupantNode(e.NickName, null, null, null);
689
690 MainWindow.ParseChatMessage(e, out string Message, out bool IsMarkdown, out DateTime Timestamp);
691
692 MainWindow.UpdateGui(async () =>
693 {
694 await MainWindow.currentInstance.MucPrivateChatMessage(e.From, XmppClient.GetBareJID(e.To), Message, e.ThreadID,
695 IsMarkdown, Timestamp, Occupant, e.From);
696 });
697 }
698
699 private async Task MucClient_RoomMessage(object Sender, RoomMessageEventArgs e)
700 {
701 await this.GetRoomNode(e.RoomId, e.Domain);
702 ChatView View = MainWindow.currentInstance.FindRoomView(e.From, XmppClient.GetBareJID(e.To));
703 MainWindow.ParseChatMessage(e, out string Message, out bool IsMarkdown, out DateTime Timestamp);
704
705 if (IsMarkdown)
706 View?.Event(Message, string.Empty, await MarkdownDocument.CreateAsync(Message, ChatView.GetMarkdownSettings()), Timestamp, e.ThreadID);
707 else
708 View?.Event(Message, string.Empty, e.ThreadID);
709 }
710
711 }
712}
Interaction logic for ChatView.xaml
Interaction logic for EnterRoomForm.xaml
Interaction logic for RoomInvitationReceivedForm.xaml
Interaction logic for ParameterDialog.xaml
static async Task< ParameterDialog > CreateAsync(DataForm Form)
Interaction logic for ParameterDialog.xaml
Interaction logic for xaml
Represents a data source in a concentrator.
Definition: Loading.cs:11
override bool RemoveChild(TreeNode Node)
Removes a child node.
Definition: MucService.cs:54
override async Task Recycle(MainWindow Window)
Is called when the user wants to recycle the node.
Definition: MucService.cs:102
override void Dispose()
Disposes of the node and its resources.
Definition: MucService.cs:72
override void LoadChildren()
Method is called to make sure children are loaded.
Definition: MucService.cs:118
override void Add()
Is called when the user wants to add a node to the current node.
Definition: MucService.cs:191
override void Removed(MainWindow Window)
Is called when the node has been removed from the main window.
Definition: MucService.cs:67
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
TreeNode[] Children
Children of the node. If null, children are not loaded.
Definition: TreeNode.cs:72
abstract bool CanRecycle
If the node can be recycled.
Definition: TreeNode.cs:433
TreeNode Parent
Parent node. May be null if a root node.
Definition: TreeNode.cs:107
virtual Task Recycle(MainWindow Window)
Is called when the user wants to recycle the node.
Definition: TreeNode.cs:442
virtual void OnUpdated()
Raises the Updated event.
Definition: TreeNode.cs:224
Contains a markdown document. This markdown document class supports original markdown,...
static Task< MarkdownDocument > CreateAsync(string MarkdownText, params Type[] TransparentExceptionTypes)
Contains a markdown document. This markdown document class supports original markdown,...
Implements support for data forms. Data Forms are defined in the following XEPs:
Definition: DataForm.cs:42
string From
From where the message was received.
string To
To whom the message was sent.
string From
From where the presence was received.
Availability Availability
Resource availability.
string To
To whom the presence was sent.
Client managing communication with a Multi-User-Chat service. https://xmpp.org/extensions/xep-0045....
Message from a MUC room containing a declined invitation.
string DeclinedFrom
JID of entity sending the declined invitation.
Room information response event arguments.
Task Decline()
Declines the invitation, and enters the room.
Task Accept(string NickName, EventHandlerAsync< UserPresenceEventArgs > Callback, object State)
Accepts the invitation, and enters the room.
Event arguments for user presence events.
string FullJid
Full JID, if privileges allow (null otherwise).
Affiliation? Affiliation
User Affiliation in room, if provided.
override string NickName
Nick-Name of user sending presence.
Role? Role
User role in room, if provided.
MucStatus[] MucStatus
Any status codes informing about changes to status.
Contains information about an item of an entity.
Definition: Item.cs:11
Manages an XMPP client connection. Implements XMPP, as defined in https://tools.ietf....
Definition: XmppClient.cs:59
static string GetBareJID(string JID)
Gets the Bare JID from a JID, which may be a Full JID.
Definition: XmppClient.cs:6901
static string GetResource(string JID)
Gets the resource part of a full JID. If no resource part is available, the empty string is returned.
Definition: XmppClient.cs:6915
Task SendServiceItemsDiscoveryRequest(string To, EventHandlerAsync< ServiceItemsDiscoveryEventArgs > Callback, object State)
Sends a service items discovery request
Definition: XmppClient.cs:6061
Static class managing persistent settings.
static async Task< string > GetAsync(string Key, string DefaultValue)
Gets a string-valued setting.
MucStatus
MUC Status, as defined in https://xmpp.org/registrar/mucstatus.html
Definition: MucStatus.cs:11
Availability
Resource availability.
Definition: Availability.cs:7
Prefix
SI prefixes. http://physics.nist.gov/cuu/Units/prefixes.html
Definition: Prefixes.cs:11