Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
ChatItem.cs
1using System;
2using System.Text;
3using System.Windows;
4using System.Windows.Controls;
5using System.Windows.Documents;
6using System.Windows.Markup;
7using System.Windows.Media;
10using Waher.Events;
12using System.Threading.Tasks;
14
16{
17 public enum ChatItemType
18 {
19 Received,
20 Transmitted,
21 Event
22 }
23
27 public class ChatItem : ColorableItem
28 {
29 private readonly ChatItemType type;
30 private readonly DateTime timestamp;
31 private bool lastIsTable;
32 private readonly string threadId;
33 private string from;
34 private string fromStr;
35 private DateTime lastUpdated;
36 private string message;
37 private object formattedMessage;
38 private StringBuilder building = null;
39 private DateTime timer = DateTime.MinValue;
40
52 private ChatItem(ChatItemType Type, DateTime Timestamp, string Message, string From, string ThreadId,
55 {
56 this.type = Type;
57 this.timestamp = this.lastUpdated = Timestamp;
58 this.message = Message;
59 this.from = From;
60 this.fromStr = GetShortFrom(From);
61 this.threadId = ThreadId;
62 }
63
64 public static async Task<ChatItem> CreateAsync(ChatItemType Type, DateTime Timestamp, string Message, string From, MarkdownDocument Markdown, string ThreadId,
66 {
68
69 if (Markdown is null)
70 {
71 XamlSettings Settings = ChatView.GetXamlSettings();
72
73 Result.formattedMessage = new TextBlock()
74 {
75 TextWrapping = TextWrapping.Wrap,
76 Margin = new Thickness(Settings.ParagraphMarginLeft, Settings.ParagraphMarginTop, Settings.ParagraphMarginRight, Settings.ParagraphMarginBottom),
77 Text = Message
78 };
79
80 if (Result.formattedMessage is DependencyObject Root)
81 Result.AddEventHandlers(Root);
82
83 Result.lastIsTable = false;
84 }
85 else
86 {
87 await Result.ParseMarkdown(Markdown);
88
89 foreach (MarkdownElement E in Markdown)
90 Result.lastIsTable = E is Content.Markdown.Model.BlockElements.Table;
91 }
92
93 return Result;
94 }
95
96 internal bool LastIsTable => this.lastIsTable;
97
98 internal void Append(string Message, ListView ChatListView, MainWindow MainWindow)
99 {
100 if (this.building is null)
101 {
102 this.building = new StringBuilder(this.message);
103
104 if (!this.message.EndsWith("\n"))
105 this.building.Append(Environment.NewLine);
106 }
107
108 this.building.Append(Message);
109 if (!Message.EndsWith("\n"))
110 this.building.Append(Environment.NewLine);
111
112 if (this.timer > DateTime.MinValue)
113 {
114 MainWindow.Scheduler?.Remove(this.timer);
115 this.timer = DateTime.MinValue;
116 }
117
118 this.timer = MainWindow.Scheduler.Add(DateTime.Now.AddSeconds(1), this.Refresh, new object[] { ChatListView, MainWindow });
119 }
120
121 private async void Refresh(object P)
122 {
123 try
124 {
125 if (this.timer > DateTime.MinValue)
126 {
127 WPF.MainWindow.Scheduler?.Remove(this.timer);
128 this.timer = DateTime.MinValue;
129 }
130
131 object[] P2 = (object[])P;
132 ListView ChatListView = (ListView)P2[0];
134 string s = this.building.ToString();
135 this.building = null;
136
137 MarkdownDocument Markdown = await MarkdownDocument.CreateAsync(s, ChatView.GetMarkdownSettings());
138
139 MainWindow.UpdateGui(() => this.Refresh2(ChatListView, s, Markdown));
140 }
141 catch (Exception ex)
142 {
143 Log.Exception(ex);
144 }
145 }
146
147 private async Task Refresh2(ListView ChatListView, string s, MarkdownDocument Markdown)
148 {
149 try
150 {
151 await this.Update(s, Markdown);
152
153 ChatListView.Items.Refresh();
154 ChatListView.ScrollIntoView(this);
155 }
156 catch (Exception ex)
157 {
158 Log.Exception(ex);
159 }
160 }
161
162 private async Task ParseMarkdown(MarkdownDocument Markdown)
163 {
164 try
165 {
166 if (!(Markdown is null))
167 {
168 string XAML = await Markdown.GenerateXAML(ChatView.GetXamlSettings());
169 this.formattedMessage = XamlReader.Parse(XAML);
170
171 if (this.formattedMessage is DependencyObject Root)
172 this.AddEventHandlers(Root);
173 }
174 else
175 this.formattedMessage = this.Message;
176 }
177 catch (Exception)
178 {
179 this.formattedMessage = this.Message;
180 }
181 }
182
183 private void AddEventHandlers(DependencyObject Element)
184 {
185 int i, c = VisualTreeHelper.GetChildrenCount(Element);
186 DependencyObject Child;
187
188 if (Element is TextBlock TextBlock)
189 {
190 foreach (Inline Inline in TextBlock.Inlines)
191 {
192 if (Inline is Hyperlink Hyperlink)
193 Hyperlink.Click += this.Hyperlink_Click;
194 }
195 }
196
197 for (i = 0; i < c; i++)
198 {
199 Child = VisualTreeHelper.GetChild(Element, i);
200 this.AddEventHandlers(Child);
201 }
202 }
203
204 private void Hyperlink_Click(object Sender, RoutedEventArgs e)
205 {
206 if (!(e.Source is Hyperlink Link))
207 return;
208
209 string Uri = Link.NavigateUri.ToString();
210 System.Diagnostics.Process.Start(Uri);
211 }
212
213 public Task Update(string Message, MarkdownDocument Markdown)
214 {
215 this.message = Message;
216 this.lastUpdated = DateTime.Now;
217
218 return this.ParseMarkdown(Markdown);
219 }
220
224 public DateTime Timestamp => this.timestamp;
225
229 public DateTime LastUpdated => this.lastUpdated;
230
234 public ChatItemType Type => this.type;
235
239 public string From
240 {
241 get => this.from;
242 set
243 {
244 this.from = value;
245 this.fromStr = GetShortFrom(value);
246 }
247 }
248
252 public string ThreadId => this.threadId;
253
257 public string FromStr => this.fromStr;
258
259 internal static string GetShortFrom(string From)
260 {
261 int i = From.IndexOfAny(Content.CommonTypes.CRLF);
262 if (i >= 0)
263 {
264 StringBuilder sb = new StringBuilder();
265 bool First = true;
266
267 foreach (string Row in From.Split(Content.CommonTypes.CRLF, StringSplitOptions.RemoveEmptyEntries))
268 {
269 if (First)
270 First = false;
271 else
272 sb.AppendLine();
273
274 sb.Append(GetShortFrom(Row));
275 }
276
277 return sb.ToString();
278 }
279 else
280 {
281 if (From is null)
282 return string.Empty;
283
284 i = From.IndexOf('/');
285 if (i < 0)
286 return From;
287
288 return From.Substring(i + 1);
289 }
290 }
291
295 public string FromResource
296 {
297 get
298 {
299 int i = this.from?.IndexOf('/') ?? -1;
300 if (i < 0)
301 return string.Empty;
302 else
303 return this.from.Substring(i + 1);
304 }
305 }
306
310 public string Received
311 {
312 get
313 {
314 if (this.type == ChatItemType.Received || this.type == ChatItemType.Event)
315 return this.timestamp.ToLongTimeString();
316 else
317 return string.Empty;
318 }
319 }
320
324 public string Sent
325 {
326 get
327 {
328 if (this.type == ChatItemType.Transmitted)
329 return this.timestamp.ToLongTimeString();
330 else
331 return string.Empty;
332 }
333 }
334
338 public string Message => this.message;
339
343 public object FormattedMessage => this.formattedMessage;
344
345 }
346}
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
object FormattedMessage
Formatted Message
Definition: ChatItem.cs:343
DateTime LastUpdated
Timestamp when item was last updated.
Definition: ChatItem.cs:229
string FromStr
Nick-name of sender.
Definition: ChatItem.cs:257
string Sent
Time of day of transmission, as a string.
Definition: ChatItem.cs:325
string Received
Time of day of reception, as a string.
Definition: ChatItem.cs:311
string FromResource
Resource-name of who sent the message.
Definition: ChatItem.cs:296
Interaction logic for ChatView.xaml
Interaction logic for xaml
Abstract base class for selectable colorable item.
Color BackgroundColor
Background color
Color ForegroundColor
Foreground color
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,...
Abstract base class for all markdown elements.
Contains settings that the XAML export uses to customize XAML output.
Definition: XamlSettings.cs:10
int ParagraphMarginTop
Top margin for paragraphs.
int ParagraphMarginLeft
Left margin for paragraphs.
int ParagraphMarginBottom
Bottom margin for paragraphs.
int ParagraphMarginRight
Right margin for paragraphs.
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