Winify – Diff between revs 28 and 29

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