Korero – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using System;
2 using System.ComponentModel;
3 using System.Configuration;
4 using System.Diagnostics;
5 using System.Drawing;
6 using System.IO;
7 using System.Net;
8 using System.Threading;
9 using System.Threading.Tasks;
10 using System.Windows.Forms;
11 using Korero.Chat;
12 using Korero.Communication;
13 using Korero.Database;
14 using Korero.Economy;
15 using Korero.Friendship;
16 using Korero.Heartbeat;
17 using Korero.Inventory;
18 using Korero.Land;
19 using Korero.Notifications;
20 using Korero.Properties;
21 using Korero.Teleport;
22 using Korero.Utilities;
23 using NetSparkleUpdater.Enums;
24 using NetSparkleUpdater.Interfaces;
25 using NetSparkleUpdater.SignatureVerifiers;
26 using NetSparkleUpdater;
27 using NetSparkleUpdater.UI.WinForms;
28 using Serilog;
29 using System.Reflection;
30  
31 namespace Korero
32 {
33 public partial class MainForm : Form
34 {
35 #region Public Enums, Properties and Fields
36  
37 public ChatForm ChatForm { get; set; }
38  
39 public MessageDatabase MessageDatabase { get; set; }
40  
41 public MqttCommunication MqttCommunication { get; set; }
42  
43 #endregion
44  
45 #region Private Delegates, Events, Enums, Properties, Indexers and Fields
46  
47 private readonly Task _autoAwayTask;
48  
49 private readonly CancellationTokenSource _cancellationTokenSource;
50  
51 private readonly Task _mqttCommunicationTask;
52  
53 private readonly NotificationManager _notificationManager;
54  
55 private AboutForm _aboutForm;
56  
57 private EconomyForm _economyForm;
58  
59 private FriendshipForm _friendsForm;
60  
61 private HeartbeatForm _heartbeatForm;
62  
63 private InventoryForm _inventoryForm;
64  
65 private LandForm _mapForm;
66  
67 private SettingsForm _settingsForm;
68  
69 private TeleportForm _teleportForm;
70 private readonly SparkleUpdater _sparkle;
71  
72 #endregion
73  
74 #region Constructors, Destructors and Finalizers
75  
76 public MainForm(Mutex mutex)
77 {
78 InitializeComponent();
79  
80 Log.Logger = new LoggerConfiguration()
81 .MinimumLevel.Debug()
82 .WriteTo.File(Path.Combine(Constants.UserApplicationDirectory, "Logs", $"{Constants.AssemblyName}.log"),
83 rollingInterval: RollingInterval.Day)
84 .CreateLogger();
85  
86 // Upgrade settings if required.
87 if (!ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).HasFile)
88 {
89 if (Settings.Default.UpdateRequired)
90 {
91 Settings.Default.Upgrade();
92 Settings.Default.Reload();
93  
94 Settings.Default.UpdateRequired = false;
95 Settings.Default.Save();
96  
97 mutex.ReleaseMutex();
98 Process.Start(Application.ExecutablePath);
99 Environment.Exit(0);
100 }
101 }
102  
103 // Bind to settings changed event.
104 Settings.Default.SettingsLoaded += Default_SettingsLoaded;
105 Settings.Default.SettingsSaving += Default_SettingsSaving;
106 Settings.Default.PropertyChanged += Default_PropertyChanged;
107  
108 _cancellationTokenSource = new CancellationTokenSource();
109  
110 _notificationManager = new NotificationManager(TaskScheduler.FromCurrentSynchronizationContext());
111  
112 MqttCommunication = new MqttCommunication();
113 MqttCommunication.NotificationReceived += MqttCommunication_NotificationReceived;
114 MqttCommunication.Connected += MqttCommunication_Connected;
115 MqttCommunication.Disconnected += MqttCommunication_Disconnected;
116  
117 MessageDatabase = new MessageDatabase();
118 _mqttCommunicationTask = MqttCommunication.Start();
119  
120 _autoAwayTask = AutoAway(_cancellationTokenSource.Token);
121  
122 // Start application update.
123 var manifestModuleName = Assembly.GetEntryAssembly().ManifestModule.FullyQualifiedName;
124 var icon = Icon.ExtractAssociatedIcon(manifestModuleName);
125  
126 _sparkle = new SparkleUpdater("https://korero.grimore.org/update/appcast.xml",
127 new Ed25519Checker(SecurityMode.Strict, "LonrgxVjSF0GnY4hzwlRJnLkaxnDn2ikdmOifILzLJY="))
128 {
129 UIFactory = new UIFactory(icon),
130 RelaunchAfterUpdate = true,
131 SecurityProtocolType = SecurityProtocolType.Tls12
132 };
133 _sparkle.StartLoop(true, true);
134 }
135  
136 #endregion
137  
138 #region Event Handlers
139  
140 private void MqttCommunication_Disconnected(object sender, MqttDisconnectedEventArgs e)
141 {
142 _notificationManager.ShowNotification("Korero: Connection", "Disconnected from the MQTT broker.",
143 Settings.Default.ToasterTimeout);
144 }
145  
146 private void MqttCommunication_Connected(object sender, MqttConnectedEventArgs e)
147 {
148 _notificationManager.ShowNotification("Korero: Connection",
149 "Connection to the MQTT broker succeeded.",
150 Settings.Default.ToasterTimeout);
151 }
152  
153 private async void MqttCommunication_NotificationReceived(object sender, MqttNotificationEventArgs e)
154 {
155 // Add message to database.
156 switch (e.Notification["notification"])
157 {
158 case "group":
159 var databaseGroupMessage = new DatabaseMessageGroup(e.Notification["firstname"],
160 e.Notification["lastname"], e.Notification["message"], e.Notification["group"], DateTime.Now);
161 await MessageDatabase.SaveGroupMessage(databaseGroupMessage);
162 await MessageDatabase.MarkConversationSeen($"{databaseGroupMessage.Group}", false);
163  
164 _notificationManager.ShowNotification("Korero: Group Message",
165 $"{e.Notification["firstname"]} {e.Notification["lastname"]} says {e.Notification["message"]}",
166 Resources.comm,
167 Settings.Default.ToasterTimeout, ShowChatForm);
168  
169 break;
170 case "message":
171 var databaseMessage = new DatabaseMessage(e.Notification["firstname"], e.Notification["lastname"],
172 e.Notification["message"], DateTime.Now);
173 await MessageDatabase.SaveMessage(databaseMessage);
174 await MessageDatabase.MarkConversationSeen(
175 $"{databaseMessage.FirstName} {databaseMessage.LastName}", false);
176  
177 _notificationManager.ShowNotification("Korero: Instant Message",
178 $"{e.Notification["firstname"]} {e.Notification["lastname"]} says {e.Notification["message"]}",
179 Resources.comm,
180 Settings.Default.ToasterTimeout, ShowChatForm);
181 break;
182 }
183  
184 switch (e.Notification["notification"])
185 {
186 case "balance":
187 _notificationManager.ShowNotification("Korero: Balance Update",
188 $"The current balance has changed and is now: {e.Notification["balance"]}", Resources.money,
189 Settings.Default.ToasterTimeout);
190 break;
191 }
192 }
193  
194 private static void Default_PropertyChanged(object sender, PropertyChangedEventArgs e)
195 {
196 Settings.Default.Save();
197 }
198  
199 private static void Default_SettingsSaving(object sender, CancelEventArgs e)
200 {
201 }
202  
203 private static void Default_SettingsLoaded(object sender, SettingsLoadedEventArgs e)
204 {
205 }
206  
207 private void QuitToolStripMenuItem_Click(object sender, EventArgs e)
208 {
209 Close();
210  
211 Environment.Exit(0);
212 }
213  
214 private void AboutToolStripMenuItem_Click(object sender, EventArgs e)
215 {
216 if (_aboutForm != null)
217 {
218 return;
219 }
220  
221 _aboutForm = new AboutForm();
222 _aboutForm.Closing += AboutForm_Closing;
223 _aboutForm.Show();
224 }
225  
226 private void AboutForm_Closing(object sender, CancelEventArgs e)
227 {
228 if (_aboutForm == null)
229 {
230 return;
231 }
232  
233 _aboutForm.Closing -= AboutForm_Closing;
234 _aboutForm.Dispose();
235 _aboutForm = null;
236 }
237  
238 private void SettingsToolStripMenuItem_Click(object sender, EventArgs e)
239 {
240 if (_settingsForm != null)
241 {
242 return;
243 }
244  
245 _settingsForm = new SettingsForm(MqttCommunication);
246 _settingsForm.Closing += SettingsForm_Closing;
247 _settingsForm.Show();
248 }
249  
250 private void SettingsForm_Closing(object sender, CancelEventArgs e)
251 {
252 if (_settingsForm == null)
253 {
254 return;
255 }
256  
257 _settingsForm.Closing -= SettingsForm_Closing;
258 _settingsForm.Dispose();
259 _settingsForm = null;
260 }
261  
262 private void ChatForm_Closing(object sender, CancelEventArgs e)
263 {
264 if (ChatForm == null)
265 {
266 return;
267 }
268  
269 ChatForm.Closing -= ChatForm_Closing;
270 ChatForm.Dispose();
271 ChatForm = null;
272 }
273  
274 private void ChatToolStripMenuItem_Click(object sender, EventArgs e)
275 {
276 ShowChatForm();
277 }
278  
279 private void MapToolStripMenuItem_Click(object sender, EventArgs e)
280 {
281 if (_mapForm != null)
282 {
283 return;
284 }
285  
286 _mapForm = new LandForm(this, MqttCommunication);
287 _mapForm.Closing += MapForm_Closing;
288 _mapForm.Show();
289 }
290  
291 private void MapForm_Closing(object sender, CancelEventArgs e)
292 {
293 if (_mapForm == null)
294 {
295 return;
296 }
297  
298 _mapForm.Closing -= MapForm_Closing;
299 _mapForm.Dispose();
300 _mapForm = null;
301 }
302  
303 private void TeleportToolStripMenuItem_Click(object sender, EventArgs e)
304 {
305 if (_teleportForm != null)
306 {
307 return;
308 }
309  
310 _teleportForm = new TeleportForm(this, MqttCommunication);
311 _teleportForm.Closing += TeleportForm_Closing;
312 _teleportForm.Show();
313 }
314  
315 private void TeleportForm_Closing(object sender, CancelEventArgs e)
316 {
317 if (_teleportForm == null)
318 {
319 return;
320 }
321  
322 _teleportForm.Closing -= TeleportForm_Closing;
323 _teleportForm.Dispose();
324 _teleportForm = null;
325 }
326  
327 private void FriendsToolStripMenuItem_Click(object sender, EventArgs e)
328 {
329 if (_friendsForm != null)
330 {
331 return;
332 }
333  
334 _friendsForm = new FriendshipForm(this, MqttCommunication);
335 _friendsForm.Closing += FriendsForm_Closing;
336 _friendsForm.Show();
337 }
338  
339 private void FriendsForm_Closing(object sender, CancelEventArgs e)
340 {
341 if (_friendsForm == null)
342 {
343 return;
344 }
345  
346 _friendsForm.Closing -= FriendsForm_Closing;
347 _friendsForm.Dispose();
348 _friendsForm = null;
349 }
350  
351 private void EconomyToolStripMenuItem_Click(object sender, EventArgs e)
352 {
353 if (_economyForm != null)
354 {
355 return;
356 }
357  
358 _economyForm = new EconomyForm(this, MqttCommunication);
359 _economyForm.Closing += EconomyForm_Closing;
360 _economyForm.Show();
361 }
362  
363 private void EconomyForm_Closing(object sender, CancelEventArgs e)
364 {
365 if (_economyForm == null)
366 {
367 return;
368 }
369  
370 _economyForm.Closing -= EconomyForm_Closing;
371 _economyForm.Dispose();
372 _economyForm = null;
373 }
374  
375 private void InventoryToolStripMenuItem_Click(object sender, EventArgs e)
376 {
377 if (_inventoryForm != null)
378 {
379 return;
380 }
381  
382 _inventoryForm = new InventoryForm(this, MqttCommunication);
383 _inventoryForm.Closing += InventoryForm_Closing;
384 _inventoryForm.Show();
385 }
386  
387 private void InventoryForm_Closing(object sender, CancelEventArgs e)
388 {
389 if (_inventoryForm == null)
390 {
391 return;
392 }
393  
394 _inventoryForm.Closing -= InventoryForm_Closing;
395 _inventoryForm.Dispose();
396 _inventoryForm = null;
397 }
398  
399 private async void UpdateToolStripMenuItem_Click(object sender, EventArgs e)
400 {
401 // Manually check for updates, this will not show a ui
402 var result = await _sparkle.CheckForUpdatesQuietly();
403 var updates = result.Updates;
404 if (result.Status == UpdateStatus.UpdateAvailable)
405 {
406 // if update(s) are found, then we have to trigger the UI to show it gracefully
407 _sparkle.ShowUpdateNeededUI();
408 return;
409 }
410  
411 MessageBox.Show("No updates available at this time.", "Korero", MessageBoxButtons.OK,
412 MessageBoxIcon.Asterisk,
413 MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly, false);
414 }
415  
416 private void HeartbeatToolStripMenuItem_Click(object sender, EventArgs e)
417 {
418 if (_heartbeatForm != null)
419 {
420 return;
421 }
422  
423 _heartbeatForm = new HeartbeatForm(this, MqttCommunication);
424 _heartbeatForm.Closing += HeartbeatForm_Closing;
425 _heartbeatForm.Show();
426 }
427  
428 private void HeartbeatForm_Closing(object sender, CancelEventArgs e)
429 {
430 if (_heartbeatForm == null)
431 {
432 return;
433 }
434  
435 _heartbeatForm.Closing -= HeartbeatForm_Closing;
436 _heartbeatForm.Dispose();
437 _heartbeatForm = null;
438 }
439  
440 #endregion
441  
442 #region Public Methods
443  
444 public async Task AutoAway(CancellationToken cancellationToken)
445 {
446 try
447 {
448 do
449 {
450 await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken);
451  
452 if (!Settings.Default.AutoAwayEnabled)
453 {
454 continue;
455 }
456  
457 if (Miscellaneous.GetIdleTime() < TimeSpan.FromMinutes((int) Settings.Default.AutoAwayMinutes))
458 {
459 continue;
460 }
461  
462 Settings.Default.CurrentStatus = Resources.Away;
463 } while (cancellationToken.IsCancellationRequested);
464 }
465 catch (Exception ex) when (ex is ObjectDisposedException || ex is OperationCanceledException)
466 {
467 }
468 catch (Exception ex)
469 {
470 Log.Warning(ex, "Error while setting auto-away.");
471 }
472 }
473  
474 #endregion
475  
476 #region Private Methods
477  
478 private void ShowChatForm()
479 {
480 if (ChatForm != null)
481 {
482 return;
483 }
484  
485 ChatForm = new ChatForm(this, MqttCommunication);
486 ChatForm.Closing += ChatForm_Closing;
487 ChatForm.Show();
488 }
489  
490 #endregion
491 }
492 }