Winify – Blame information for rev 29

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using System;
25 office 2 using System.Collections.Concurrent;
1 office 3 using System.ComponentModel;
4 using System.Configuration;
19 office 5 using System.Diagnostics;
4 office 6 using System.IO;
15 office 7 using System.Text;
19 office 8 using System.Threading;
4 office 9 using System.Threading.Tasks;
1 office 10 using System.Windows.Forms;
11 using AutoUpdaterDotNET;
18 office 12 using Serilog;
15 office 13 using Servers;
29 office 14 using Toasts;
1 office 15 using Winify.Gotify;
8 office 16 using Winify.Servers.Serialization;
25 office 17 using Winify.Settings;
15 office 18 using Winify.Utilities;
1 office 19  
20 namespace Winify
21 {
22 public partial class Form1 : Form
23 {
24 #region Private Delegates, Events, Enums, Properties, Indexers and Fields
25  
24 office 26 private readonly TaskScheduler _uiTaskScheduler;
14 office 27  
1 office 28 private AboutForm _aboutForm;
29  
25 office 30 private ConcurrentBag<GotifyConnection> _gotifyConnections;
1 office 31  
32 private SettingsForm _settingsForm;
33  
34 #endregion
35  
36 #region Constructors, Destructors and Finalizers
37  
19 office 38 public Form1(Mutex mutex)
1 office 39 {
40 InitializeComponent();
41  
18 office 42 Log.Logger = new LoggerConfiguration()
43 .MinimumLevel.Debug()
44 .WriteTo.File(Path.Combine(Constants.UserApplicationDirectory, "Logs", $"{Constants.AssemblyName}.log"),
45 rollingInterval: RollingInterval.Day)
46 .CreateLogger();
47  
1 office 48 // Upgrade settings if required.
49 if (!ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).HasFile)
25 office 50 if (Properties.Settings.Default.UpdateRequired)
19 office 51 {
25 office 52 Properties.Settings.Default.Upgrade();
53 Properties.Settings.Default.Reload();
19 office 54  
25 office 55 Properties.Settings.Default.UpdateRequired = false;
56 Properties.Settings.Default.Save();
19 office 57  
58 mutex.ReleaseMutex();
59 Process.Start(Application.ExecutablePath);
60 Environment.Exit(0);
61 }
1 office 62  
63 // Bind to settings changed event.
25 office 64 Properties.Settings.Default.SettingsLoaded += Default_SettingsLoaded;
65 Properties.Settings.Default.SettingsSaving += Default_SettingsSaving;
66 Properties.Settings.Default.PropertyChanged += Default_PropertyChanged;
1 office 67  
25 office 68 // Store UI thread context.
24 office 69 _uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
11 office 70  
14 office 71 LoadServers().ContinueWith(async task =>
4 office 72 {
14 office 73 var restoredServers = await task;
4 office 74  
25 office 75 _gotifyConnections = new ConcurrentBag<GotifyConnection>();
76  
7 office 77 foreach (var server in restoredServers.Server)
78 {
25 office 79 var gotifyConnection = new GotifyConnection(server);
80 gotifyConnection.GotifyNotification += GotifyConnection_GotifyNotification;
81 gotifyConnection.Start();
82 _gotifyConnections.Add(gotifyConnection);
7 office 83 }
4 office 84 });
15 office 85  
19 office 86 // Start application update.
87 AutoUpdater.Start("http://winify.grimore.org/update/winify.xml");
1 office 88 }
89  
90 /// <summary>
91 /// Clean up any resources being used.
92 /// </summary>
93 /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
94 protected override void Dispose(bool disposing)
95 {
96 if (disposing && components != null)
97 {
25 office 98 Properties.Settings.Default.SettingsLoaded -= Default_SettingsLoaded;
99 Properties.Settings.Default.SettingsSaving -= Default_SettingsSaving;
100 Properties.Settings.Default.PropertyChanged -= Default_PropertyChanged;
7 office 101  
1 office 102 components.Dispose();
103 }
104  
105 base.Dispose(disposing);
106 }
107  
108 #endregion
109  
110 #region Event Handlers
111  
25 office 112 private static void Default_PropertyChanged(object sender, PropertyChangedEventArgs e)
21 office 113 {
25 office 114 Properties.Settings.Default.Save();
21 office 115 }
116  
25 office 117 private static void Default_SettingsSaving(object sender, CancelEventArgs e)
21 office 118 {
119 }
120  
25 office 121 private static void Default_SettingsLoaded(object sender, SettingsLoadedEventArgs e)
15 office 122 {
123 }
124  
25 office 125 private async void SettingsToolStripMenuItem_Click(object sender, EventArgs e)
11 office 126 {
28 office 127 if (_settingsForm != null) return;
25 office 128  
129 var servers = await LoadServers();
130 var announcements = await LoadAnnouncements();
131  
132 _settingsForm = new SettingsForm(servers, announcements);
133 _settingsForm.Save += SettingsForm_Save;
134 _settingsForm.Closing += SettingsForm_Closing;
135 _settingsForm.Show();
136 }
137  
138 private async void SettingsForm_Save(object sender, SettingsSavedEventArgs e)
139 {
140 // Save the servers.
141 await Task.WhenAll(SaveServers(e.Servers), SaveAnnouncements(e.Announcements));
142  
143 // Update connections to gotify servers.
144 while (_gotifyConnections.TryTake(out var gotifyConnection))
145 {
146 gotifyConnection.GotifyNotification -= GotifyConnection_GotifyNotification;
147 gotifyConnection.Stop();
148 gotifyConnection.Dispose();
149 gotifyConnection = null;
150 }
151  
152 foreach (var server in e.Servers.Server)
153 {
154 var gotifyConnection = new GotifyConnection(server);
155 gotifyConnection.GotifyNotification += GotifyConnection_GotifyNotification;
156 gotifyConnection.Start();
157 _gotifyConnections.Add(gotifyConnection);
158 }
159 }
160  
161 private void GotifyConnection_GotifyNotification(object sender, GotifyNotificationEventArgs e)
162 {
163 Task.Factory.StartNew(async () =>
164 {
165 var announcements = await LoadAnnouncements();
166  
167 foreach (var announcement in announcements.Announcement)
24 office 168 if (announcement.AppId == e.Notification.AppId)
169 {
29 office 170 var configuredNotification = new ToastForm(
25 office 171 $"{e.Notification.Title} ({e.Notification.Server.Name}/{e.Notification.AppId})",
29 office 172 e.Notification.Message, announcement.LingerTime, e.Image);
24 office 173  
174 configuredNotification.Show();
175  
176 return;
177 }
178  
29 office 179 var notification = new ToastForm(
25 office 180 $"{e.Notification.Title} ({e.Notification.Server.Name}/{e.Notification.AppId})",
29 office 181 e.Notification.Message, 5000, e.Image);
24 office 182  
183 notification.Show();
25 office 184 }, CancellationToken.None, TaskCreationOptions.LongRunning, _uiTaskScheduler);
11 office 185 }
186  
1 office 187 private void SettingsForm_Closing(object sender, CancelEventArgs e)
188 {
28 office 189 if (_settingsForm == null) return;
6 office 190  
25 office 191 _settingsForm.Save -= SettingsForm_Save;
1 office 192 _settingsForm.Closing -= SettingsForm_Closing;
193 _settingsForm.Dispose();
194 _settingsForm = null;
195 }
196  
197 private void AboutToolStripMenuItem_Click(object sender, EventArgs e)
198 {
28 office 199 if (_aboutForm != null) return;
1 office 200  
201 _aboutForm = new AboutForm();
202 _aboutForm.Closing += AboutForm_Closing;
203 _aboutForm.Show();
204 }
205  
206 private void AboutForm_Closing(object sender, CancelEventArgs e)
207 {
28 office 208 if (_aboutForm == null) return;
1 office 209  
210 _aboutForm.Closing -= AboutForm_Closing;
211 _aboutForm.Dispose();
212 _aboutForm = null;
213 }
214  
215 private void QuitToolStripMenuItem_Click(object sender, EventArgs e)
216 {
17 office 217 Close();
218  
219 Environment.Exit(0);
1 office 220 }
221  
9 office 222 private void UpdateToolStripMenuItem_Click(object sender, EventArgs e)
223 {
224 AutoUpdater.Start("http://winify.grimore.org/update/winify.xml");
225 }
226  
1 office 227 #endregion
4 office 228  
229 #region Private Methods
230  
25 office 231 private static async Task SaveAnnouncements(Announcements.Announcements announcements)
21 office 232 {
25 office 233 switch (await ServersSerialization.Serialize(announcements, Constants.AnnouncementsFile, "Announcements",
28 office 234 "<!ATTLIST Announcements xmlns:xsi CDATA #IMPLIED xsi:noNamespaceSchemaLocation CDATA #IMPLIED>"))
21 office 235 {
236 case SerializationFailure serializationFailure:
237 Log.Warning(serializationFailure.Exception, "Unable to serialize announcements.");
238 break;
239 }
240 }
241  
25 office 242 private static async Task SaveServers(global::Servers.Servers servers)
21 office 243 {
244 // Encrypt password for all servers.
245 var deviceId = Miscellaneous.GetMachineGuid();
246 var @protected = new global::Servers.Servers
247 {
248 Server = new BindingListWithCollectionChanged<Server>()
249 };
25 office 250 foreach (var server in servers.Server)
21 office 251 {
252 var encrypted = AES.Encrypt(Encoding.UTF8.GetBytes(server.Password), deviceId);
253 var armored = Convert.ToBase64String(encrypted);
254  
255 @protected.Server.Add(new Server(server.Name, server.Url, server.Username, armored));
256 }
257  
258 switch (await ServersSerialization.Serialize(@protected, Constants.ServersFile, "Servers",
28 office 259 "<!ATTLIST Servers xmlns:xsi CDATA #IMPLIED xsi:noNamespaceSchemaLocation CDATA #IMPLIED>"))
21 office 260 {
261 case SerializationFailure serializationFailure:
262 Log.Warning(serializationFailure.Exception, "Unable to serialize servers.");
263 break;
264 }
265 }
266  
15 office 267 private static async Task<Announcements.Announcements> LoadAnnouncements()
268 {
269 if (!Directory.Exists(Constants.UserApplicationDirectory))
270 Directory.CreateDirectory(Constants.UserApplicationDirectory);
271  
272 var deserializationResult =
25 office 273 await ServersSerialization.Deserialize<Announcements.Announcements>(Constants.AnnouncementsFile,
15 office 274 "urn:winify-announcements-schema", "Announcements.xsd");
275  
276 switch (deserializationResult)
277 {
278 case SerializationSuccess<Announcements.Announcements> serializationSuccess:
279 return serializationSuccess.Result;
21 office 280 case SerializationFailure serializationFailure:
281 Log.Warning(serializationFailure.Exception, "Unable to load announcements.");
282 return new Announcements.Announcements();
15 office 283 default:
284 return new Announcements.Announcements();
285 }
286 }
287  
8 office 288 private static async Task<global::Servers.Servers> LoadServers()
4 office 289 {
290 if (!Directory.Exists(Constants.UserApplicationDirectory))
291 Directory.CreateDirectory(Constants.UserApplicationDirectory);
292  
15 office 293 var deserializationResult =
294 await ServersSerialization.Deserialize<global::Servers.Servers>(Constants.ServersFile,
295 "urn:winify-servers-schema", "Servers.xsd");
4 office 296  
297 switch (deserializationResult)
298 {
15 office 299 case SerializationSuccess<global::Servers.Servers> serializationSuccess:
300 // Decrypt password.
301 var deviceId = Miscellaneous.GetMachineGuid();
302 var @protected = new global::Servers.Servers
303 {
304 Server = new BindingListWithCollectionChanged<Server>()
305 };
306 foreach (var server in serializationSuccess.Result.Server)
307 {
308 var unarmored = Convert.FromBase64String(server.Password);
309 var decrypted = Encoding.UTF8.GetString(AES.Decrypt(unarmored, deviceId));
4 office 310  
15 office 311 @protected.Server.Add(new Server(server.Name, server.Url, server.Username, decrypted));
312 }
313  
314 return @protected;
315  
21 office 316 case SerializationFailure serializationFailure:
317 Log.Warning(serializationFailure.Exception, "Unable to load servers.");
318 return new global::Servers.Servers();
319  
4 office 320 default:
8 office 321 return new global::Servers.Servers();
4 office 322 }
323 }
324  
325 #endregion
1 office 326 }
327 }