diff --git a/MacroDeck.Setup/Macro Deck.iss b/MacroDeck.Setup/Macro Deck.iss index fe74dc35..dc308547 100644 --- a/MacroDeck.Setup/Macro Deck.iss +++ b/MacroDeck.Setup/Macro Deck.iss @@ -102,5 +102,5 @@ Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: de [Run] Filename: "{tmp}\VC_redist.x64.exe"; StatusMsg: "Installing VC2019 redist..."; Parameters: "/quiet"; Check: VC2019RedistNeedsInstall ; Flags: waituntilterminated -Filename: "{app}\{#MyAppExeName}"; Parameters: "--show"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent +Filename: "{app}\{#MyAppExeName}"; Parameters: "--show"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall diff --git a/MacroDeck.sln b/MacroDeck.sln index ed8fccc5..b7a0ee20 100644 --- a/MacroDeck.sln +++ b/MacroDeck.sln @@ -5,7 +5,7 @@ VisualStudioVersion = 17.3.32811.315 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MacroDeck", "MacroDeck\MacroDeck.csproj", "{119E86B4-9738-4684-AF88-CDBBF0315BBF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MacroDeck.Tests", "MacroDeck.Tests\MacroDeck.Tests.csproj", "{49F1CAC2-158D-45AC-B07C-52394B10A7E2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MacroDeck.Tests", "MacroDeck.Tests\MacroDeck.Tests.csproj", "{49F1CAC2-158D-45AC-B07C-52394B10A7E2}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{A87511C0-A46B-40E0-A47A-81AEE2097F5D}" ProjectSection(SolutionItems) = preProject @@ -13,6 +13,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{ .github\workflows\tests.yml = .github\workflows\tests.yml EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MacroDeck.Setup", "MacroDeck.Setup", "{8C1FC7A7-364F-4CE5-B59D-9A7EFC88CFDC}" + ProjectSection(SolutionItems) = preProject + MacroDeck.Setup\Macro Deck.iss = MacroDeck.Setup\Macro Deck.iss + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/MacroDeck/DataTypes/Core/Version.cs b/MacroDeck/DataTypes/Core/Version.cs new file mode 100644 index 00000000..ddff9071 --- /dev/null +++ b/MacroDeck/DataTypes/Core/Version.cs @@ -0,0 +1,73 @@ +using System.Text.RegularExpressions; + +namespace SuchByte.MacroDeck.DataTypes.Core; + +public partial struct Version +{ + public int Major { get; set; } + public int Minor { get; set; } + public int Patch { get; set; } + public int? BetaNo { get; set; } + + public Version(int major, int minor, int patch, int? betaNo = null) + { + Major = major; + Minor = minor; + Patch = patch; + BetaNo = betaNo; + } + + public bool IsBetaVersion => BetaNo.HasValue; + + public string VersionName => BetaNo.HasValue + ? $"{Major}.{Minor}.{Patch}-b{BetaNo}" + : $"{Major}.{Minor}.{Patch}"; + + public override string ToString() + { + return VersionName; + } + + public static bool TryParse(string versionString, out Version result) + { + try + { + result = Parse(versionString); + return true; + } + catch + { + result = default; + return false; + } + } + + public static Version Parse(string? versionString) + { + if (string.IsNullOrWhiteSpace(versionString)) + { + throw new FormatException("Version string was empty"); + } + + var match = VersionRegex().Match(versionString); + if (!match.Success) + { + throw new FormatException("Invalid version string"); + } + + var major = int.Parse(match.Groups["major"].Value); + var minor = int.Parse(match.Groups["minor"].Value); + var patch = int.Parse(match.Groups["patch"].Value); + + int? previewNo = null; + if (match.Groups["beta"].Success) + { + previewNo = int.Parse(match.Groups["beta"].Value); + } + + return new Version(major, minor, patch, previewNo); + } + + [GeneratedRegex("^(?\\d+)\\.(?\\d+)\\.(?\\d+)(-b(?\\d+))?$")] + private static partial Regex VersionRegex(); +} diff --git a/MacroDeck/DataTypes/FileDownloader/DownloadProgressInfo.cs b/MacroDeck/DataTypes/FileDownloader/DownloadProgressInfo.cs new file mode 100644 index 00000000..34ed8da4 --- /dev/null +++ b/MacroDeck/DataTypes/FileDownloader/DownloadProgressInfo.cs @@ -0,0 +1,9 @@ +namespace SuchByte.MacroDeck.DataTypes.FileDownloader; + +public class DownloadProgressInfo +{ + public int Percentage { get; set; } = 0; + public long TotalBytes { get; set; } = 0; + public long DownloadedBytes { get; set; } = 0; + public double DownloadSpeed { get; set; } = 0; +} \ No newline at end of file diff --git a/MacroDeck/DataTypes/Updater/UpdateApiCheckResult.cs b/MacroDeck/DataTypes/Updater/UpdateApiCheckResult.cs new file mode 100644 index 00000000..b09e7ad2 --- /dev/null +++ b/MacroDeck/DataTypes/Updater/UpdateApiCheckResult.cs @@ -0,0 +1,7 @@ +namespace SuchByte.MacroDeck.DataTypes.Updater; + +public class UpdateApiCheckResult +{ + public bool? NewerVersionAvailable { get; set; } + public UpdateApiVersionInfo? Version { get; set; } +} \ No newline at end of file diff --git a/MacroDeck/DataTypes/Updater/UpdateApiVersionFileInfo.cs b/MacroDeck/DataTypes/Updater/UpdateApiVersionFileInfo.cs new file mode 100644 index 00000000..633fea9b --- /dev/null +++ b/MacroDeck/DataTypes/Updater/UpdateApiVersionFileInfo.cs @@ -0,0 +1,8 @@ +namespace SuchByte.MacroDeck.DataTypes.Updater; + +public class UpdateApiVersionFileInfo +{ + public string? DownloadUrl { get; set; } + public string? FileHash { get; set; } + public long FileSize { get; set; } +} \ No newline at end of file diff --git a/MacroDeck/DataTypes/Updater/UpdateApiVersionInfo.cs b/MacroDeck/DataTypes/Updater/UpdateApiVersionInfo.cs new file mode 100644 index 00000000..8e6729fa --- /dev/null +++ b/MacroDeck/DataTypes/Updater/UpdateApiVersionInfo.cs @@ -0,0 +1,11 @@ +using SuchByte.MacroDeck.Enums; + +namespace SuchByte.MacroDeck.DataTypes.Updater; + +public class UpdateApiVersionInfo +{ + public string? Version { get; set; } + public bool? IsBeta { get; set; } + public string? ChangeNotesUrl { get; set; } + public Dictionary? Platforms { get; set; } +} \ No newline at end of file diff --git a/MacroDeck/DataTypes/Updater/UpdateServiceProgress.cs b/MacroDeck/DataTypes/Updater/UpdateServiceProgress.cs new file mode 100644 index 00000000..71251c2a --- /dev/null +++ b/MacroDeck/DataTypes/Updater/UpdateServiceProgress.cs @@ -0,0 +1,8 @@ +namespace SuchByte.MacroDeck.DataTypes.Updater; + +public class UpdateServiceProgress +{ + public int Percentage { get; set; } = 0; + public long TotalBytes { get; set; } = 0; + public long DownloadedBytes { get; set; } = 0; +} \ No newline at end of file diff --git a/MacroDeck/Enums/PlatformIdentifier.cs b/MacroDeck/Enums/PlatformIdentifier.cs new file mode 100644 index 00000000..14ef7d32 --- /dev/null +++ b/MacroDeck/Enums/PlatformIdentifier.cs @@ -0,0 +1,11 @@ +namespace SuchByte.MacroDeck.Enums; + +public enum PlatformIdentifier +{ + WinX64 = 1000, + MacX64 = 2000, + MacArm64 = 2100, + LinuxX64 = 3000, + LinuxArm64 = 3100, + LinuxArm32 = 3110 +} \ No newline at end of file diff --git a/MacroDeck/Extension/DoubleExtensions.cs b/MacroDeck/Extension/DoubleExtensions.cs new file mode 100644 index 00000000..f77e128d --- /dev/null +++ b/MacroDeck/Extension/DoubleExtensions.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SuchByte.MacroDeck.Extension; + +public static class DoubleExtensions +{ + public static double ConvertBytesToMegabytes(this double bytes) + { + return bytes / 1024.0f / 1024.0f; + } +} diff --git a/MacroDeck/Extension/LongExtensions.cs b/MacroDeck/Extension/LongExtensions.cs new file mode 100644 index 00000000..a5c6bec8 --- /dev/null +++ b/MacroDeck/Extension/LongExtensions.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SuchByte.MacroDeck.Extension; + +public static class LongExtensions +{ + public static double ConvertBytesToMegabytes(this long bytes) + { + return bytes / 1024f / 1024f; + } +} diff --git a/MacroDeck/Extension/StreamExtensions.cs b/MacroDeck/Extension/StreamExtensions.cs new file mode 100644 index 00000000..c0e75fcc --- /dev/null +++ b/MacroDeck/Extension/StreamExtensions.cs @@ -0,0 +1,32 @@ +using System.IO; +using System.Security.Cryptography; +using System; + +namespace SuchByte.MacroDeck.Extension; + +public static class StreamExtensions +{ + public static async ValueTask CalculateSha256Hash(this Stream stream) + { + stream.Position = 0; + + var bufferedStream = new BufferedStream(stream); + using var sha256 = SHA256.Create(); + + var buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = await bufferedStream.ReadAsync(buffer)) > 0) + { + sha256.TransformBlock(buffer, 0, bytesRead, buffer, 0); + } + sha256.TransformFinalBlock(buffer, 0, 0); + + if (sha256.Hash == null) + { + throw new InvalidOperationException("Hash was null"); + } + + stream.Position = 0; + return BitConverter.ToString(sha256.Hash).Replace("-", "").ToLower(); + } +} \ No newline at end of file diff --git a/MacroDeck/Extension/StringExtensions.cs b/MacroDeck/Extension/StringExtensions.cs new file mode 100644 index 00000000..01a20178 --- /dev/null +++ b/MacroDeck/Extension/StringExtensions.cs @@ -0,0 +1,24 @@ +using System.Security.Cryptography; + +namespace SuchByte.MacroDeck.Extension; + +public static class StringExtensions +{ + public static bool EqualsCryptographically(this string? str1, string? str2) + { + if (str1 == null || str2 == null) + { + return false; + } + + var hash1 = SHA256.HashData(Encoding.UTF8.GetBytes(str1)); + var hash2 = SHA256.HashData(Encoding.UTF8.GetBytes(str2)); + + if (hash1.Length != hash2.Length) + { + return false; + } + + return !hash1.Where((t, i) => t != hash2[i]).Any(); + } +} \ No newline at end of file diff --git a/MacroDeck/GUI/CustomControls/ButtonPrimary.cs b/MacroDeck/GUI/CustomControls/ButtonPrimary.cs index a9569845..25238ccc 100644 --- a/MacroDeck/GUI/CustomControls/ButtonPrimary.cs +++ b/MacroDeck/GUI/CustomControls/ButtonPrimary.cs @@ -35,6 +35,8 @@ public Image Icon public bool Spinner = false; + public bool WriteProgress { get; set; } = true; + //This method begins the animation. public void AnimateImage() @@ -242,13 +244,14 @@ protected override void OnPaint(PaintEventArgs pe) Region = new Region(pathSurface); pe.Graphics.DrawPath(penSurface, pathSurface); var flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.WordBreak; - if (progress > 0) + if (progress > 0 && WriteProgress) { TextRenderer.DrawText(pe.Graphics, string.Format("{0}%", progress), Font, ClientRectangle, ForeColor, flags); } else { TextRenderer.DrawText(pe.Graphics, text, Font, ClientRectangle, ForeColor, flags); } + if (Spinner) { AnimateImage(); diff --git a/MacroDeck/GUI/CustomControls/Settings/UpdateAvailableControl.Designer.cs b/MacroDeck/GUI/CustomControls/Settings/UpdateAvailableControl.Designer.cs deleted file mode 100644 index 65be7ddc..00000000 --- a/MacroDeck/GUI/CustomControls/Settings/UpdateAvailableControl.Designer.cs +++ /dev/null @@ -1,141 +0,0 @@ - -using System; -using System.ComponentModel; -using System.Drawing; -using System.Windows.Forms; -using SuchByte.MacroDeck.Properties; - -namespace SuchByte.MacroDeck.GUI.CustomControls.Settings -{ - partial class UpdateAvailableControl - { - /// - /// Erforderliche Designervariable. - /// - private IContainer components = null; - - /// - /// Verwendete Ressourcen bereinigen. - /// - /// True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False. - protected override void Dispose(bool disposing) - { - - Updater.Updater.OnProgressChanged -= ProgressChanged; - Updater.Updater.OnError -= Error; - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Vom Komponenten-Designer generierter Code - - /// - /// Erforderliche Methode für die Designerunterstützung. - /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden. - /// - private void InitializeComponent() - { - this.pictureBox2 = new PictureBox(); - this.lblVersion = new Label(); - this.changelogPanel = new FlowLayoutPanel(); - this.btnInstall = new ButtonPrimary(); - this.lblSize = new Label(); - ((ISupportInitialize)(this.pictureBox2)).BeginInit(); - this.SuspendLayout(); - // - // pictureBox2 - // - this.pictureBox2.BackgroundImage = Resources.Macro_Deck_2021_update; - this.pictureBox2.BackgroundImageLayout = ImageLayout.Stretch; - this.pictureBox2.Location = new Point(3, 3); - this.pictureBox2.Name = "pictureBox2"; - this.pictureBox2.Size = new Size(50, 50); - this.pictureBox2.TabIndex = 5; - this.pictureBox2.TabStop = false; - // - // lblVersion - // - this.lblVersion.Font = new Font("Tahoma", 15.75F, FontStyle.Regular, GraphicsUnit.Point); - this.lblVersion.Location = new Point(62, 3); - this.lblVersion.Name = "lblVersion"; - this.lblVersion.Size = new Size(919, 34); - this.lblVersion.TabIndex = 6; - this.lblVersion.Text = "Version {0} is now available"; - this.lblVersion.TextAlign = ContentAlignment.MiddleLeft; - this.lblVersion.UseMnemonic = false; - // - // changelogPanel - // - this.changelogPanel.AutoScroll = true; - this.changelogPanel.BackColor = Color.FromArgb(((int)(((byte)(35)))), ((int)(((byte)(35)))), ((int)(((byte)(35))))); - this.changelogPanel.Location = new Point(3, 59); - this.changelogPanel.Name = "changelogPanel"; - this.changelogPanel.Padding = new Padding(5); - this.changelogPanel.Size = new Size(975, 300); - this.changelogPanel.TabIndex = 12; - // - // btnInstall - // - this.btnInstall.Anchor = ((AnchorStyles)((AnchorStyles.Bottom | AnchorStyles.Right))); - this.btnInstall.BorderRadius = 8; - this.btnInstall.Cursor = Cursors.Hand; - this.btnInstall.FlatAppearance.BorderSize = 0; - this.btnInstall.FlatStyle = FlatStyle.Flat; - this.btnInstall.Font = new Font("Tahoma", 9.75F, FontStyle.Regular, GraphicsUnit.Point); - this.btnInstall.ForeColor = Color.White; - this.btnInstall.HoverColor = Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(89)))), ((int)(((byte)(184))))); - this.btnInstall.Icon = null; - this.btnInstall.Location = new Point(349, 365); - this.btnInstall.Name = "btnInstall"; - this.btnInstall.Progress = 0; - this.btnInstall.ProgressColor = Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(46)))), ((int)(((byte)(94))))); - this.btnInstall.Size = new Size(283, 32); - this.btnInstall.TabIndex = 13; - this.btnInstall.Text = "Download and install"; - this.btnInstall.UseMnemonic = false; - this.btnInstall.UseVisualStyleBackColor = false; - this.btnInstall.UseWindowsAccentColor = true; - this.btnInstall.Click += new EventHandler(this.BtnInstall_Click); - // - // lblSize - // - this.lblSize.Font = new Font("Tahoma", 12F, FontStyle.Regular, GraphicsUnit.Point); - this.lblSize.Location = new Point(62, 37); - this.lblSize.Name = "lblSize"; - this.lblSize.Size = new Size(309, 19); - this.lblSize.TabIndex = 14; - this.lblSize.Text = "0,00MB"; - this.lblSize.TextAlign = ContentAlignment.MiddleLeft; - this.lblSize.UseMnemonic = false; - // - // UpdateAvailableControl - // - this.AutoScaleDimensions = new SizeF(96F, 96F); - this.AutoScaleMode = AutoScaleMode.Dpi; - this.BackColor = Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(45))))); - this.Controls.Add(this.lblSize); - this.Controls.Add(this.btnInstall); - this.Controls.Add(this.changelogPanel); - this.Controls.Add(this.lblVersion); - this.Controls.Add(this.pictureBox2); - this.Font = new Font("Tahoma", 9F, FontStyle.Regular, GraphicsUnit.Point); - this.ForeColor = Color.White; - this.Name = "UpdateAvailableControl"; - this.Size = new Size(981, 418); - ((ISupportInitialize)(this.pictureBox2)).EndInit(); - this.ResumeLayout(false); - - } - - #endregion - - private PictureBox pictureBox2; - private Label lblVersion; - private FlowLayoutPanel changelogPanel; - private ButtonPrimary btnInstall; - private Label lblSize; - } -} diff --git a/MacroDeck/GUI/CustomControls/Settings/UpdateAvailableControl.cs b/MacroDeck/GUI/CustomControls/Settings/UpdateAvailableControl.cs deleted file mode 100644 index 9c5c930d..00000000 --- a/MacroDeck/GUI/CustomControls/Settings/UpdateAvailableControl.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System.Drawing; -using System.Windows.Forms; -using System.Xml; -using SuchByte.MacroDeck.Backups; -using SuchByte.MacroDeck.Language; -using SuchByte.MacroDeck.Updater; - -namespace SuchByte.MacroDeck.GUI.CustomControls.Settings; - -public partial class UpdateAvailableControl : UserControl -{ - public UpdateAvailableControl() - { - InitializeComponent(); - - lblVersion.Text = string.Format(LanguageManager.Strings.VersionXIsNowAvailable, Updater.Updater.UpdateObject["version"], Updater.Updater.UpdateObject["channel"]); - btnInstall.Text = LanguageManager.Strings.DownloadAndInstall; - lblSize.Text = Updater.Updater.UpdateSizeMb.ToString("0.##") + "MB"; - //this.lblStatus.Text = Language.LanguageManager.Strings.ReadyToDownloadUpdate; - - Updater.Updater.OnProgressChanged += ProgressChanged; - Updater.Updater.OnError += Error; - - var changelogXml = Updater.Updater.UpdateObject["changelog"].ToString(); - - if (!string.IsNullOrWhiteSpace(changelogXml)) - { - try - { - var doc = new XmlDocument(); - doc.LoadXml(changelogXml); - foreach (XmlNode node in doc.DocumentElement.ChildNodes) - { - if (node.HasChildNodes) - { - var title = new Label - { - AutoSize = true, - MinimumSize = new Size(880, 0), - MaximumSize = new Size(880, 0), - Font = new Font("Tahoma", 14F, FontStyle.Bold, GraphicsUnit.Point), - ForeColor = Color.White, - Text = node.Name - }; - changelogPanel.Controls.Add(title); - foreach (XmlNode childNode in node.ChildNodes) - { - if (childNode.Name == "Text") - { - var text = new Label - { - AutoSize = true, - MinimumSize = new Size(880, 0), - MaximumSize = new Size(880, 0), - Font = new Font("Tahoma", 12F, FontStyle.Regular, GraphicsUnit.Point), - ForeColor = Color.White, - Text = "● " + childNode.InnerText - }; - changelogPanel.Controls.Add(text); - } - } - var spacer = new Panel - { - AutoSize = true, - MinimumSize = new Size(880, 15), - MaximumSize = new Size(880, 15) - }; - changelogPanel.Controls.Add(spacer); - } - } - } catch { } - } - - - - if (Updater.Updater.Downloading) - { - btnInstall.Enabled = false; - btnInstall.Progress = Updater.Updater.ProgressPercentage; - } - GC.Collect(); - GC.WaitForPendingFinalizers(); - GC.Collect(); - } - - private void BtnInstall_Click(object sender, EventArgs e) - { - btnInstall.Enabled = false; - btnInstall.Spinner = true; - var createBackup = false; - using (var msgBox = new MessageBox()) - { - if (msgBox.ShowDialog(LanguageManager.Strings.Backup, LanguageManager.Strings.CreateBackupBeforeUpdate, MessageBoxButtons.YesNo) == DialogResult.Yes) - { - createBackup = true; - } - } - if (createBackup) - { - btnInstall.Text = LanguageManager.Strings.CreatingBackup; - BackupManager.CreateBackup(); - } - Updater.Updater.DownloadUpdate(); - - } - - private void ProgressChanged(object sender, ProgressChangedEventArgs e) - { - btnInstall.Enabled = false; - btnInstall.Spinner = true; - btnInstall.Progress = e.ProgressPercentage; - } - - private void Error(object sender, EventArgs e) - { - btnInstall.Progress = 0; - btnInstall.Enabled = true; - btnInstall.Spinner = false; - } - - - -} \ No newline at end of file diff --git a/MacroDeck/GUI/Dialogs/UpdateAvailableDialog.Designer.cs b/MacroDeck/GUI/Dialogs/UpdateAvailableDialog.Designer.cs new file mode 100644 index 00000000..bd0e875e --- /dev/null +++ b/MacroDeck/GUI/Dialogs/UpdateAvailableDialog.Designer.cs @@ -0,0 +1,155 @@ +namespace SuchByte.MacroDeck.GUI.Dialogs +{ + partial class UpdateAvailableDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + lblSize = new System.Windows.Forms.Label(); + btnInstall = new CustomControls.ButtonPrimary(); + lblVersion = new System.Windows.Forms.Label(); + pictureBox2 = new System.Windows.Forms.PictureBox(); + lblInstalledVersion = new System.Windows.Forms.Label(); + lblShowChangeNotes = new System.Windows.Forms.LinkLabel(); + ((System.ComponentModel.ISupportInitialize)pictureBox2).BeginInit(); + SuspendLayout(); + // + // lblSize + // + lblSize.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + lblSize.Location = new System.Drawing.Point(158, 97); + lblSize.Name = "lblSize"; + lblSize.Size = new System.Drawing.Size(309, 19); + lblSize.TabIndex = 18; + lblSize.Text = "0,00MB"; + lblSize.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + lblSize.UseMnemonic = false; + // + // btnInstall + // + btnInstall.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; + btnInstall.BorderRadius = 8; + btnInstall.Cursor = System.Windows.Forms.Cursors.Hand; + btnInstall.FlatAppearance.BorderSize = 0; + btnInstall.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + btnInstall.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + btnInstall.ForeColor = System.Drawing.Color.White; + btnInstall.HoverColor = System.Drawing.Color.FromArgb(0, 89, 184); + btnInstall.Icon = null; + btnInstall.Location = new System.Drawing.Point(171, 220); + btnInstall.Name = "btnInstall"; + btnInstall.Progress = 0; + btnInstall.ProgressColor = System.Drawing.Color.FromArgb(0, 46, 94); + btnInstall.Size = new System.Drawing.Size(283, 32); + btnInstall.TabIndex = 17; + btnInstall.Text = "Download and install"; + btnInstall.UseMnemonic = false; + btnInstall.UseVisualStyleBackColor = false; + btnInstall.UseWindowsAccentColor = true; + btnInstall.WriteProgress = false; + btnInstall.Click += BtnInstall_Click; + // + // lblVersion + // + lblVersion.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + lblVersion.Location = new System.Drawing.Point(64, 4); + lblVersion.Name = "lblVersion"; + lblVersion.Size = new System.Drawing.Size(496, 50); + lblVersion.TabIndex = 16; + lblVersion.Text = "Version {0} is now available"; + lblVersion.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + lblVersion.UseMnemonic = false; + // + // pictureBox2 + // + pictureBox2.BackgroundImage = Properties.Resources.Macro_Deck_2021_update; + pictureBox2.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; + pictureBox2.Location = new System.Drawing.Point(8, 86); + pictureBox2.Name = "pictureBox2"; + pictureBox2.Size = new System.Drawing.Size(100, 100); + pictureBox2.TabIndex = 15; + pictureBox2.TabStop = false; + // + // lblInstalledVersion + // + lblInstalledVersion.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + lblInstalledVersion.Location = new System.Drawing.Point(158, 116); + lblInstalledVersion.Name = "lblInstalledVersion"; + lblInstalledVersion.Size = new System.Drawing.Size(309, 19); + lblInstalledVersion.TabIndex = 19; + lblInstalledVersion.Text = "Installed version: 2.0.0"; + lblInstalledVersion.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + lblInstalledVersion.UseMnemonic = false; + // + // lblShowChangeNotes + // + lblShowChangeNotes.AutoSize = true; + lblShowChangeNotes.LinkColor = System.Drawing.Color.DeepSkyBlue; + lblShowChangeNotes.Location = new System.Drawing.Point(255, 160); + lblShowChangeNotes.Name = "lblShowChangeNotes"; + lblShowChangeNotes.Size = new System.Drawing.Size(115, 16); + lblShowChangeNotes.TabIndex = 20; + lblShowChangeNotes.TabStop = true; + lblShowChangeNotes.Text = "View change notes"; + lblShowChangeNotes.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + lblShowChangeNotes.LinkClicked += LblShowChangeNotes_LinkClicked; + // + // UpdateAvailableDialog + // + AutoScaleDimensions = new System.Drawing.SizeF(7F, 16F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + ClientSize = new System.Drawing.Size(624, 272); + Controls.Add(lblShowChangeNotes); + Controls.Add(lblInstalledVersion); + Controls.Add(lblSize); + Controls.Add(btnInstall); + Controls.Add(lblVersion); + Controls.Add(pictureBox2); + Location = new System.Drawing.Point(0, 0); + Name = "UpdateAvailableDialog"; + Text = "UpdateAvailableDialog"; + Load += UpdateAvailableDialog_Load; + Controls.SetChildIndex(pictureBox2, 0); + Controls.SetChildIndex(lblVersion, 0); + Controls.SetChildIndex(btnInstall, 0); + Controls.SetChildIndex(lblSize, 0); + Controls.SetChildIndex(lblInstalledVersion, 0); + Controls.SetChildIndex(lblShowChangeNotes, 0); + ((System.ComponentModel.ISupportInitialize)pictureBox2).EndInit(); + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private System.Windows.Forms.Label lblSize; + private CustomControls.ButtonPrimary btnInstall; + private System.Windows.Forms.Label lblVersion; + private System.Windows.Forms.PictureBox pictureBox2; + private System.Windows.Forms.Label lblInstalledVersion; + private System.Windows.Forms.LinkLabel lblShowChangeNotes; + } +} \ No newline at end of file diff --git a/MacroDeck/GUI/Dialogs/UpdateAvailableDialog.cs b/MacroDeck/GUI/Dialogs/UpdateAvailableDialog.cs new file mode 100644 index 00000000..cf42b974 --- /dev/null +++ b/MacroDeck/GUI/Dialogs/UpdateAvailableDialog.cs @@ -0,0 +1,92 @@ +using SuchByte.MacroDeck.DataTypes.FileDownloader; +using SuchByte.MacroDeck.DataTypes.Updater; +using SuchByte.MacroDeck.Extension; +using SuchByte.MacroDeck.GUI.CustomControls; +using SuchByte.MacroDeck.Language; +using SuchByte.MacroDeck.Logging; +using SuchByte.MacroDeck.Services; +using System.Diagnostics; +using System.Windows.Forms; + +namespace SuchByte.MacroDeck.GUI.Dialogs; + +public partial class UpdateAvailableDialog : DialogForm +{ + private readonly UpdateApiVersionInfo _availableUpdate; + private readonly UpdateApiVersionFileInfo? _updateApiVersionFileInfo; + + public UpdateAvailableDialog(UpdateApiVersionInfo availableUpdate) + { + InitializeComponent(); + _availableUpdate = availableUpdate; + _updateApiVersionFileInfo = _availableUpdate.Platforms?[UpdateService.PlatformIdentifier]; + } + + private void UpdateAvailableDialog_Load(object sender, EventArgs e) + { + lblVersion.Text = string.Format(LanguageManager.Strings.VersionXIsNowAvailable, + _availableUpdate.Version, + _availableUpdate.IsBeta == true ? "Beta" : "Release"); + btnInstall.Text = LanguageManager.Strings.DownloadAndInstall; + lblSize.Text = $"Download size: {_updateApiVersionFileInfo?.FileSize.ConvertBytesToMegabytes().ToString("0.##")}MB"; + lblInstalledVersion.Text = $"Installed version: {MacroDeck.Version}"; + } + + private async void BtnInstall_Click(object sender, EventArgs e) + { + SetCloseIconVisible(false); + btnInstall.Enabled = false; + try + { + await UpdateService.Instance().DownloadAndInstallVersion( + _availableUpdate, + new Progress(UpdateProgress)); + } + catch (Exception ex) + { + MacroDeckLogger.Error($"Failed to download and install update\n{ex}"); + + using var msgBox = new CustomControls.MessageBox(); + msgBox.ShowDialog( + LanguageManager.Strings.Error, + "An error occured during the update. Check the logs for more information.", + MessageBoxButtons.OK); + } + finally + { + Close(); + } + } + + private void UpdateProgress(DownloadProgressInfo downloadProgressInfo) + { + if (InvokeRequired) + { + Invoke(() => UpdateProgress(downloadProgressInfo)); + return; + } + + btnInstall.Progress = downloadProgressInfo.Percentage; + btnInstall.Text = $"{downloadProgressInfo.Percentage}% - " + + $"{downloadProgressInfo.DownloadedBytes.ConvertBytesToMegabytes().ToString("0.##")}MB /" + + $"{downloadProgressInfo.TotalBytes.ConvertBytesToMegabytes().ToString("0.##")}MB " + + $" @{downloadProgressInfo.DownloadSpeed.ConvertBytesToMegabytes().ToString("0.##")}MB/s"; + } + + private void LblShowChangeNotes_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + var changeNotesUrl = _availableUpdate?.ChangeNotesUrl; + if (changeNotesUrl == null) + { + return; + } + + new Process + { + StartInfo = new ProcessStartInfo(changeNotesUrl) + { + UseShellExecute = true + } + }.Start(); + } +} diff --git a/MacroDeck/GUI/CustomControls/Settings/UpdateAvailableControl.resx b/MacroDeck/GUI/Dialogs/UpdateAvailableDialog.resx similarity index 100% rename from MacroDeck/GUI/CustomControls/Settings/UpdateAvailableControl.resx rename to MacroDeck/GUI/Dialogs/UpdateAvailableDialog.resx diff --git a/MacroDeck/GUI/MainWindow.Designer.cs b/MacroDeck/GUI/MainWindow.Designer.cs index 8acd098c..14b98250 100644 --- a/MacroDeck/GUI/MainWindow.Designer.cs +++ b/MacroDeck/GUI/MainWindow.Designer.cs @@ -7,6 +7,7 @@ using SuchByte.MacroDeck.Notifications; using SuchByte.MacroDeck.Plugins; using SuchByte.MacroDeck.Server; +using SuchByte.MacroDeck.Services; namespace SuchByte.MacroDeck.GUI { @@ -34,7 +35,7 @@ protected override void Dispose(bool disposing) this.Controls.Remove(this.notificationsList); } LanguageManager.LanguageChanged -= LanguageChanged; - Updater.Updater.OnUpdateAvailable -= UpdateAvailable; + UpdateService.Instance().UpdateAvailable -= UpdateAvailable; MacroDeckServer.OnDeviceConnectionStateChanged -= this.OnClientsConnectedChanged; MacroDeckServer.OnServerStateChanged -= this.OnServerStateChanged; PluginManager.OnPluginsChange -= this.OnPluginsChanged; diff --git a/MacroDeck/GUI/MainWindow.cs b/MacroDeck/GUI/MainWindow.cs index 019f4f6f..d4dfb356 100644 --- a/MacroDeck/GUI/MainWindow.cs +++ b/MacroDeck/GUI/MainWindow.cs @@ -1,18 +1,19 @@ -using System.Diagnostics; -using System.Drawing; +using System.Drawing; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Windows.Forms; +using SuchByte.MacroDeck.DataTypes.Updater; using SuchByte.MacroDeck.ExtensionStore; using SuchByte.MacroDeck.GUI.CustomControls; +using SuchByte.MacroDeck.GUI.Dialogs; using SuchByte.MacroDeck.GUI.MainWindowContents; using SuchByte.MacroDeck.GUI.MainWindowViews; using SuchByte.MacroDeck.Icons; using SuchByte.MacroDeck.Language; -using SuchByte.MacroDeck.Logging; using SuchByte.MacroDeck.Notifications; using SuchByte.MacroDeck.Plugins; using SuchByte.MacroDeck.Server; +using SuchByte.MacroDeck.Services; using SuchByte.MacroDeck.Startup; using Form = SuchByte.MacroDeck.GUI.CustomControls.Form; using MessageBox = SuchByte.MacroDeck.GUI.CustomControls.MessageBox; @@ -43,10 +44,15 @@ public MainWindow() btnNotifications.BackColor = Color.Transparent; UpdateTranslation(); LanguageManager.LanguageChanged += LanguageChanged; - Updater.Updater.OnUpdateAvailable += UpdateAvailable; + UpdateService.Instance().UpdateAvailable += UpdateAvailable; _deckView ??= new DeckView(); } + private void UpdateAvailable(object? sender, UpdateApiVersionInfo e) + { + using var updateAvailableDialog = new UpdateAvailableDialog(e); + updateAvailableDialog.ShowDialog(); + } private void UpdateTranslation() { @@ -59,12 +65,6 @@ private void LanguageChanged(object sender, EventArgs e) DeckView?.UpdateTranslation(); } - - private void UpdateAvailable(object sender, EventArgs e) - { - btnSettings.SetNotification(Updater.Updater.UpdateAvailable); - } - public void SelectContentButton(Control control) { foreach (var contentButton in contentButtonPanel.Controls.OfType().Where(x => x != control && x.Selected)) @@ -109,12 +109,10 @@ public void SetView(Control view) } } - private void MainWindow_Load(object sender, EventArgs e) { - - lblVersion.Text = "Macro Deck " + MacroDeck.Version.VersionString; - + lblVersion.Text = $"Macro Deck {MacroDeck.Version}"; + PluginManager.OnPluginsChange += OnPluginsChanged; IconManager.OnIconPacksChanged += OnPluginsChanged; IconManager.OnUpdateCheckFinished += OnPackageManagerUpdateCheckFinished; @@ -137,7 +135,7 @@ private void MainWindow_Load(object sender, EventArgs e) btnExtensions.SetNotification(PluginManager.PluginsUpdateAvailable.Count > 0 || IconManager.IconPacksUpdateAvailable.Count > 0); navigation.Visible = true; - btnSettings.SetNotification(Updater.Updater.UpdateAvailable); + btnSettings.SetNotification(UpdateService.Instance().VersionInfo != null); SetView(DeckView); @@ -147,6 +145,13 @@ private void MainWindow_Load(object sender, EventArgs e) ExtensionStoreHelper.OnInstallationFinished += ExtensionStoreHelper_OnInstallationFinished; CenterToScreen(); btnNotifications.NotificationCount = NotificationManager.Notifications.Count; + + var updateApiVersionInfo = UpdateService.Instance().VersionInfo; + if (updateApiVersionInfo != null) + { + using var updateAvailableDialog = new UpdateAvailableDialog(updateApiVersionInfo); + updateAvailableDialog.ShowDialog(); + } } private void LoadHosts() @@ -188,7 +193,6 @@ private void RefreshPluginsLabels() { btnExtensions.SetNotification(PluginManager.PluginsUpdateAvailable.Count > 0 || IconManager.IconPacksUpdateAvailable.Count > 0); }); - } private void OnServerStateChanged(object sender, EventArgs e) @@ -249,19 +253,6 @@ private void BtnVariables_Click(object sender, EventArgs e) SetView(new VariablesView()); } - private void LblErrorsWarnings_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) - { - var p = new Process - { - StartInfo = new ProcessStartInfo(MacroDeckLogger.CurrentFilename) - { - UseShellExecute = true, - } - }; - p.Start(); - } - - private void BtnNotifications_Click(object sender, EventArgs e) { if (notificationsList == null || notificationsList.IsDisposed) @@ -284,8 +275,6 @@ private void BtnNotifications_Click(object sender, EventArgs e) Controls.Add(notificationsList); notificationsList.BringToFront(); } - - } private void Hosts_SelectedIndexChanged(object sender, EventArgs e) diff --git a/MacroDeck/GUI/MainWindowViews/SettingsView.Designer.cs b/MacroDeck/GUI/MainWindowViews/SettingsView.Designer.cs index ccc3966e..41ab85b0 100644 --- a/MacroDeck/GUI/MainWindowViews/SettingsView.Designer.cs +++ b/MacroDeck/GUI/MainWindowViews/SettingsView.Designer.cs @@ -20,7 +20,6 @@ partial class SettingsView /// True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False. protected override void Dispose(bool disposing) { - Updater.Updater.OnUpdateAvailable -= UpdateAvailable; if (disposing && (components != null)) { components.Dispose(); @@ -36,744 +35,709 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.components = new Container(); + components = new Container(); ComponentResourceManager resources = new ComponentResourceManager(typeof(SettingsView)); - this.verticalTabControl = new VerticalTabControl(); - this.tabGeneral = new TabPage(); - this.checkIconCache = new CheckBox(); - this.language = new RoundedComboBox(); - this.lblLanguage = new Label(); - this.checkStartWindows = new CheckBox(); - this.lblBehaviour = new Label(); - this.lblGeneral = new Label(); - this.tabConnection = new TabPage(); - this.btnChangePort = new ButtonPrimary(); - this.groupConnectionInfo = new GroupBox(); - this.lblConnectionInfo = new Label(); - this.port = new NumericUpDown(); - this.lblPort = new Label(); - this.lblIpAddessLabel = new Label(); - this.lblIpAddress = new Label(); - this.networkAdapter = new RoundedComboBox(); - this.lblNetworkAdapter = new Label(); - this.lblConnection = new Label(); - this.tabUpdater = new TabPage(); - this.checkAutoUpdate = new CheckBox(); - this.checkInstallBetaVersions = new CheckBox(); - this.updaterPanel = new Panel(); - this.btnCheckUpdates = new ButtonPrimary(); - this.lblInstalledVersion = new Label(); - this.lblInstalledVersionLabel = new Label(); - this.lblUpdates = new Label(); - this.tabBackups = new TabPage(); - this.btnCreateBackup = new ButtonPrimary(); - this.backupsPanel = new FlowLayoutPanel(); - this.lblBackups = new Label(); - this.tabAbout = new TabPage(); - this.btnGitHub = new PictureButton(); - this.lblBuild = new Label(); - this.lblBuildLabel = new Label(); - this.label1 = new Label(); - this.lblTranslationBy = new Label(); - this.btnLicenses = new ButtonPrimary(); - this.lblPluginAPIVersion = new Label(); - this.lblWebsocketAPIVersion = new Label(); - this.lblPluginAPILabel = new Label(); - this.lblWebSocketAPILabel = new Label(); - this.lblInstalledPlugins = new Label(); - this.lblInstalledPluginsLabel = new Label(); - this.lblDeveloped = new Label(); - this.lblMacroDeck = new Label(); - this.pictureBox1 = new PictureBox(); - this.tabIcons = new ImageList(this.components); - this.verticalTabControl.SuspendLayout(); - this.tabGeneral.SuspendLayout(); - this.tabConnection.SuspendLayout(); - this.groupConnectionInfo.SuspendLayout(); - ((ISupportInitialize)(this.port)).BeginInit(); - this.tabUpdater.SuspendLayout(); - this.tabBackups.SuspendLayout(); - this.tabAbout.SuspendLayout(); - ((ISupportInitialize)(this.btnGitHub)).BeginInit(); - ((ISupportInitialize)(this.pictureBox1)).BeginInit(); - this.SuspendLayout(); + verticalTabControl = new VerticalTabControl(); + tabGeneral = new TabPage(); + checkIconCache = new CheckBox(); + language = new RoundedComboBox(); + lblLanguage = new Label(); + checkStartWindows = new CheckBox(); + lblBehaviour = new Label(); + lblGeneral = new Label(); + tabConnection = new TabPage(); + btnChangePort = new ButtonPrimary(); + groupConnectionInfo = new GroupBox(); + lblConnectionInfo = new Label(); + port = new NumericUpDown(); + lblPort = new Label(); + lblIpAddessLabel = new Label(); + lblIpAddress = new Label(); + networkAdapter = new RoundedComboBox(); + lblNetworkAdapter = new Label(); + lblConnection = new Label(); + tabUpdater = new TabPage(); + label2 = new Label(); + checkAutoUpdate = new CheckBox(); + checkInstallBetaVersions = new CheckBox(); + btnCheckUpdates = new ButtonPrimary(); + lblInstalledVersion = new Label(); + lblInstalledVersionLabel = new Label(); + lblUpdates = new Label(); + tabBackups = new TabPage(); + btnCreateBackup = new ButtonPrimary(); + backupsPanel = new FlowLayoutPanel(); + lblBackups = new Label(); + tabAbout = new TabPage(); + btnGitHub = new PictureButton(); + label1 = new Label(); + lblTranslationBy = new Label(); + btnLicenses = new ButtonPrimary(); + lblPluginAPIVersion = new Label(); + lblWebsocketAPIVersion = new Label(); + lblPluginAPILabel = new Label(); + lblWebSocketAPILabel = new Label(); + lblInstalledPlugins = new Label(); + lblInstalledPluginsLabel = new Label(); + lblDeveloped = new Label(); + lblMacroDeck = new Label(); + pictureBox1 = new PictureBox(); + tabIcons = new ImageList(components); + verticalTabControl.SuspendLayout(); + tabGeneral.SuspendLayout(); + tabConnection.SuspendLayout(); + groupConnectionInfo.SuspendLayout(); + ((ISupportInitialize)port).BeginInit(); + tabUpdater.SuspendLayout(); + tabBackups.SuspendLayout(); + tabAbout.SuspendLayout(); + ((ISupportInitialize)btnGitHub).BeginInit(); + ((ISupportInitialize)pictureBox1).BeginInit(); + SuspendLayout(); // // verticalTabControl // - this.verticalTabControl.Alignment = TabAlignment.Left; - this.verticalTabControl.Anchor = ((AnchorStyles)((((AnchorStyles.Top | AnchorStyles.Bottom) - | AnchorStyles.Left) - | AnchorStyles.Right))); - this.verticalTabControl.Controls.Add(this.tabGeneral); - this.verticalTabControl.Controls.Add(this.tabConnection); - this.verticalTabControl.Controls.Add(this.tabUpdater); - this.verticalTabControl.Controls.Add(this.tabBackups); - this.verticalTabControl.Controls.Add(this.tabAbout); - this.verticalTabControl.Font = new Font("Tahoma", 12F, FontStyle.Regular, GraphicsUnit.Point); - this.verticalTabControl.ImageList = this.tabIcons; - this.verticalTabControl.ItemSize = new Size(44, 200); - this.verticalTabControl.Location = new Point(3, 3); - this.verticalTabControl.Multiline = true; - this.verticalTabControl.Name = "verticalTabControl"; - this.verticalTabControl.SelectedIndex = 0; - this.verticalTabControl.SelectedTabColor = Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(103)))), ((int)(((byte)(225))))); - this.verticalTabControl.Size = new Size(1131, 534); - this.verticalTabControl.SizeMode = TabSizeMode.Fixed; - this.verticalTabControl.TabIndex = 12; + verticalTabControl.Alignment = TabAlignment.Left; + verticalTabControl.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; + verticalTabControl.Controls.Add(tabGeneral); + verticalTabControl.Controls.Add(tabConnection); + verticalTabControl.Controls.Add(tabUpdater); + verticalTabControl.Controls.Add(tabBackups); + verticalTabControl.Controls.Add(tabAbout); + verticalTabControl.Font = new Font("Tahoma", 12F, FontStyle.Regular, GraphicsUnit.Point); + verticalTabControl.ImageList = tabIcons; + verticalTabControl.ItemSize = new Size(44, 200); + verticalTabControl.Location = new Point(3, 3); + verticalTabControl.Multiline = true; + verticalTabControl.Name = "verticalTabControl"; + verticalTabControl.SelectedIndex = 0; + verticalTabControl.SelectedTabColor = Color.FromArgb(0, 103, 225); + verticalTabControl.Size = new Size(1131, 534); + verticalTabControl.SizeMode = TabSizeMode.Fixed; + verticalTabControl.TabIndex = 12; // // tabGeneral // - this.tabGeneral.BackColor = Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(45))))); - this.tabGeneral.Controls.Add(this.checkIconCache); - this.tabGeneral.Controls.Add(this.language); - this.tabGeneral.Controls.Add(this.lblLanguage); - this.tabGeneral.Controls.Add(this.checkStartWindows); - this.tabGeneral.Controls.Add(this.lblBehaviour); - this.tabGeneral.Controls.Add(this.lblGeneral); - this.tabGeneral.Font = new Font("Tahoma", 12F, FontStyle.Regular, GraphicsUnit.Point); - this.tabGeneral.ForeColor = Color.White; - this.tabGeneral.Location = new Point(204, 4); - this.tabGeneral.Name = "tabGeneral"; - this.tabGeneral.Padding = new Padding(3); - this.tabGeneral.Size = new Size(923, 526); - this.tabGeneral.TabIndex = 0; - this.tabGeneral.Text = "General"; + tabGeneral.BackColor = Color.FromArgb(45, 45, 45); + tabGeneral.Controls.Add(checkIconCache); + tabGeneral.Controls.Add(language); + tabGeneral.Controls.Add(lblLanguage); + tabGeneral.Controls.Add(checkStartWindows); + tabGeneral.Controls.Add(lblBehaviour); + tabGeneral.Controls.Add(lblGeneral); + tabGeneral.Font = new Font("Tahoma", 12F, FontStyle.Regular, GraphicsUnit.Point); + tabGeneral.ForeColor = Color.White; + tabGeneral.Location = new Point(204, 4); + tabGeneral.Name = "tabGeneral"; + tabGeneral.Padding = new Padding(3); + tabGeneral.Size = new Size(923, 526); + tabGeneral.TabIndex = 0; + tabGeneral.Text = "General"; // // checkIconCache // - this.checkIconCache.AutoSize = true; - this.checkIconCache.Location = new Point(13, 112); - this.checkIconCache.Name = "checkIconCache"; - this.checkIconCache.Size = new Size(375, 23); - this.checkIconCache.TabIndex = 14; - this.checkIconCache.Text = "Enable icon cache (faster; higher memory usage)"; - this.checkIconCache.UseMnemonic = false; - this.checkIconCache.UseVisualStyleBackColor = true; - this.checkIconCache.CheckedChanged += new EventHandler(this.CheckIconCache_CheckedChanged); + checkIconCache.AutoSize = true; + checkIconCache.Location = new Point(13, 112); + checkIconCache.Name = "checkIconCache"; + checkIconCache.Size = new Size(375, 23); + checkIconCache.TabIndex = 14; + checkIconCache.Text = "Enable icon cache (faster; higher memory usage)"; + checkIconCache.UseMnemonic = false; + checkIconCache.UseVisualStyleBackColor = true; + checkIconCache.CheckedChanged += CheckIconCache_CheckedChanged; // // language // - this.language.BackColor = Color.FromArgb(((int)(((byte)(65)))), ((int)(((byte)(65)))), ((int)(((byte)(65))))); - this.language.Cursor = Cursors.Hand; - this.language.DropDownStyle = ComboBoxStyle.DropDownList; - this.language.Font = new Font("Tahoma", 12F, FontStyle.Regular, GraphicsUnit.Point); - this.language.ForeColor = Color.White; - this.language.Icon = null; - this.language.Location = new Point(12, 222); - this.language.Name = "language"; - this.language.Padding = new Padding(8, 2, 8, 2); - this.language.SelectedIndex = -1; - this.language.SelectedItem = null; - this.language.Size = new Size(253, 31); - this.language.TabIndex = 4; - this.language.SelectedIndexChanged += new EventHandler(this.Language_SelectedIndexChanged); + language.BackColor = Color.FromArgb(65, 65, 65); + language.Cursor = Cursors.Hand; + language.DropDownStyle = ComboBoxStyle.DropDownList; + language.Font = new Font("Tahoma", 12F, FontStyle.Regular, GraphicsUnit.Point); + language.ForeColor = Color.White; + language.Icon = null; + language.Location = new Point(12, 222); + language.Name = "language"; + language.Padding = new Padding(8, 2, 8, 2); + language.SelectedIndex = -1; + language.SelectedItem = null; + language.Size = new Size(253, 31); + language.TabIndex = 4; + language.SelectedIndexChanged += Language_SelectedIndexChanged; // // lblLanguage // - this.lblLanguage.AutoSize = true; - this.lblLanguage.Font = new Font("Tahoma", 14.25F, FontStyle.Regular, GraphicsUnit.Point); - this.lblLanguage.ForeColor = Color.Gray; - this.lblLanguage.Location = new Point(3, 198); - this.lblLanguage.Name = "lblLanguage"; - this.lblLanguage.Size = new Size(93, 23); - this.lblLanguage.TabIndex = 3; - this.lblLanguage.Text = "Language"; - this.lblLanguage.UseMnemonic = false; + lblLanguage.AutoSize = true; + lblLanguage.Font = new Font("Tahoma", 14.25F, FontStyle.Regular, GraphicsUnit.Point); + lblLanguage.ForeColor = Color.Gray; + lblLanguage.Location = new Point(3, 198); + lblLanguage.Name = "lblLanguage"; + lblLanguage.Size = new Size(93, 23); + lblLanguage.TabIndex = 3; + lblLanguage.Text = "Language"; + lblLanguage.UseMnemonic = false; // // checkStartWindows // - this.checkStartWindows.AutoSize = true; - this.checkStartWindows.Location = new Point(13, 89); - this.checkStartWindows.Name = "checkStartWindows"; - this.checkStartWindows.Size = new Size(165, 23); - this.checkStartWindows.TabIndex = 2; - this.checkStartWindows.Text = "Start with Windows"; - this.checkStartWindows.UseMnemonic = false; - this.checkStartWindows.UseVisualStyleBackColor = true; - this.checkStartWindows.CheckedChanged += new EventHandler(this.CheckStartWindows_CheckedChanged); + checkStartWindows.AutoSize = true; + checkStartWindows.Location = new Point(13, 89); + checkStartWindows.Name = "checkStartWindows"; + checkStartWindows.Size = new Size(165, 23); + checkStartWindows.TabIndex = 2; + checkStartWindows.Text = "Start with Windows"; + checkStartWindows.UseMnemonic = false; + checkStartWindows.UseVisualStyleBackColor = true; + checkStartWindows.CheckedChanged += CheckStartWindows_CheckedChanged; // // lblBehaviour // - this.lblBehaviour.AutoSize = true; - this.lblBehaviour.Font = new Font("Tahoma", 14.25F, FontStyle.Regular, GraphicsUnit.Point); - this.lblBehaviour.ForeColor = Color.Gray; - this.lblBehaviour.Location = new Point(3, 63); - this.lblBehaviour.Name = "lblBehaviour"; - this.lblBehaviour.Size = new Size(82, 23); - this.lblBehaviour.TabIndex = 1; - this.lblBehaviour.Text = "Behavior"; - this.lblBehaviour.UseMnemonic = false; + lblBehaviour.AutoSize = true; + lblBehaviour.Font = new Font("Tahoma", 14.25F, FontStyle.Regular, GraphicsUnit.Point); + lblBehaviour.ForeColor = Color.Gray; + lblBehaviour.Location = new Point(3, 63); + lblBehaviour.Name = "lblBehaviour"; + lblBehaviour.Size = new Size(82, 23); + lblBehaviour.TabIndex = 1; + lblBehaviour.Text = "Behavior"; + lblBehaviour.UseMnemonic = false; // // lblGeneral // - this.lblGeneral.AutoSize = true; - this.lblGeneral.Font = new Font("Tahoma", 15.75F, FontStyle.Regular, GraphicsUnit.Point); - this.lblGeneral.Location = new Point(3, 0); - this.lblGeneral.Name = "lblGeneral"; - this.lblGeneral.Size = new Size(84, 25); - this.lblGeneral.TabIndex = 0; - this.lblGeneral.Text = "General"; - this.lblGeneral.UseMnemonic = false; + lblGeneral.AutoSize = true; + lblGeneral.Font = new Font("Tahoma", 15.75F, FontStyle.Regular, GraphicsUnit.Point); + lblGeneral.Location = new Point(3, 0); + lblGeneral.Name = "lblGeneral"; + lblGeneral.Size = new Size(84, 25); + lblGeneral.TabIndex = 0; + lblGeneral.Text = "General"; + lblGeneral.UseMnemonic = false; // // tabConnection // - this.tabConnection.BackColor = Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(45))))); - this.tabConnection.Controls.Add(this.btnChangePort); - this.tabConnection.Controls.Add(this.groupConnectionInfo); - this.tabConnection.Controls.Add(this.port); - this.tabConnection.Controls.Add(this.lblPort); - this.tabConnection.Controls.Add(this.lblIpAddessLabel); - this.tabConnection.Controls.Add(this.lblIpAddress); - this.tabConnection.Controls.Add(this.networkAdapter); - this.tabConnection.Controls.Add(this.lblNetworkAdapter); - this.tabConnection.Controls.Add(this.lblConnection); - this.tabConnection.Font = new Font("Tahoma", 9F, FontStyle.Regular, GraphicsUnit.Point); - this.tabConnection.ForeColor = Color.White; - this.tabConnection.Location = new Point(204, 4); - this.tabConnection.Name = "tabConnection"; - this.tabConnection.Size = new Size(923, 526); - this.tabConnection.TabIndex = 3; - this.tabConnection.Text = "Connection"; + tabConnection.BackColor = Color.FromArgb(45, 45, 45); + tabConnection.Controls.Add(btnChangePort); + tabConnection.Controls.Add(groupConnectionInfo); + tabConnection.Controls.Add(port); + tabConnection.Controls.Add(lblPort); + tabConnection.Controls.Add(lblIpAddessLabel); + tabConnection.Controls.Add(lblIpAddress); + tabConnection.Controls.Add(networkAdapter); + tabConnection.Controls.Add(lblNetworkAdapter); + tabConnection.Controls.Add(lblConnection); + tabConnection.Font = new Font("Tahoma", 9F, FontStyle.Regular, GraphicsUnit.Point); + tabConnection.ForeColor = Color.White; + tabConnection.Location = new Point(204, 4); + tabConnection.Name = "tabConnection"; + tabConnection.Size = new Size(923, 526); + tabConnection.TabIndex = 3; + tabConnection.Text = "Connection"; // // btnChangePort // - this.btnChangePort.BorderRadius = 8; - this.btnChangePort.Cursor = Cursors.Hand; - this.btnChangePort.FlatAppearance.BorderSize = 0; - this.btnChangePort.FlatStyle = FlatStyle.Flat; - this.btnChangePort.Font = new Font("Tahoma", 9.75F, FontStyle.Regular, GraphicsUnit.Point); - this.btnChangePort.ForeColor = Color.White; - this.btnChangePort.HoverColor = Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(89)))), ((int)(((byte)(184))))); - this.btnChangePort.Icon = null; - this.btnChangePort.Location = new Point(126, 89); - this.btnChangePort.Name = "btnChangePort"; - this.btnChangePort.Progress = 0; - this.btnChangePort.ProgressColor = Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(46)))), ((int)(((byte)(94))))); - this.btnChangePort.Size = new Size(46, 24); - this.btnChangePort.TabIndex = 12; - this.btnChangePort.Text = "Ok"; - this.btnChangePort.UseMnemonic = false; - this.btnChangePort.UseVisualStyleBackColor = false; - this.btnChangePort.UseWindowsAccentColor = true; - this.btnChangePort.Click += new EventHandler(this.BtnChangePort_Click); + btnChangePort.BorderRadius = 8; + btnChangePort.Cursor = Cursors.Hand; + btnChangePort.FlatAppearance.BorderSize = 0; + btnChangePort.FlatStyle = FlatStyle.Flat; + btnChangePort.Font = new Font("Tahoma", 9.75F, FontStyle.Regular, GraphicsUnit.Point); + btnChangePort.ForeColor = Color.White; + btnChangePort.HoverColor = Color.FromArgb(0, 89, 184); + btnChangePort.Icon = null; + btnChangePort.Location = new Point(126, 89); + btnChangePort.Name = "btnChangePort"; + btnChangePort.Progress = 0; + btnChangePort.ProgressColor = Color.FromArgb(0, 46, 94); + btnChangePort.Size = new Size(46, 24); + btnChangePort.TabIndex = 12; + btnChangePort.Text = "Ok"; + btnChangePort.UseMnemonic = false; + btnChangePort.UseVisualStyleBackColor = false; + btnChangePort.UseWindowsAccentColor = true; + btnChangePort.Click += BtnChangePort_Click; // // groupConnectionInfo // - this.groupConnectionInfo.Anchor = ((AnchorStyles)((((AnchorStyles.Top | AnchorStyles.Bottom) - | AnchorStyles.Left) - | AnchorStyles.Right))); - this.groupConnectionInfo.Controls.Add(this.lblConnectionInfo); - this.groupConnectionInfo.Font = new Font("Tahoma", 14.25F, FontStyle.Regular, GraphicsUnit.Point); - this.groupConnectionInfo.ForeColor = Color.White; - this.groupConnectionInfo.Location = new Point(12, 342); - this.groupConnectionInfo.Name = "groupConnectionInfo"; - this.groupConnectionInfo.Size = new Size(896, 173); - this.groupConnectionInfo.TabIndex = 11; - this.groupConnectionInfo.TabStop = false; - this.groupConnectionInfo.Text = "Info"; + groupConnectionInfo.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; + groupConnectionInfo.Controls.Add(lblConnectionInfo); + groupConnectionInfo.Font = new Font("Tahoma", 14.25F, FontStyle.Regular, GraphicsUnit.Point); + groupConnectionInfo.ForeColor = Color.White; + groupConnectionInfo.Location = new Point(12, 342); + groupConnectionInfo.Name = "groupConnectionInfo"; + groupConnectionInfo.Size = new Size(896, 173); + groupConnectionInfo.TabIndex = 11; + groupConnectionInfo.TabStop = false; + groupConnectionInfo.Text = "Info"; // // lblConnectionInfo // - this.lblConnectionInfo.Dock = DockStyle.Fill; - this.lblConnectionInfo.Font = new Font("Tahoma", 11.25F, FontStyle.Regular, GraphicsUnit.Point); - this.lblConnectionInfo.Location = new Point(3, 26); - this.lblConnectionInfo.Name = "lblConnectionInfo"; - this.lblConnectionInfo.Size = new Size(890, 144); - this.lblConnectionInfo.TabIndex = 0; - this.lblConnectionInfo.Text = resources.GetString("lblConnectionInfo.Text"); - this.lblConnectionInfo.UseMnemonic = false; + lblConnectionInfo.Dock = DockStyle.Fill; + lblConnectionInfo.Font = new Font("Tahoma", 11.25F, FontStyle.Regular, GraphicsUnit.Point); + lblConnectionInfo.Location = new Point(3, 26); + lblConnectionInfo.Name = "lblConnectionInfo"; + lblConnectionInfo.Size = new Size(890, 144); + lblConnectionInfo.TabIndex = 0; + lblConnectionInfo.Text = resources.GetString("lblConnectionInfo.Text"); + lblConnectionInfo.UseMnemonic = false; // // port // - this.port.BackColor = Color.FromArgb(((int)(((byte)(65)))), ((int)(((byte)(65)))), ((int)(((byte)(65))))); - this.port.BorderStyle = BorderStyle.FixedSingle; - this.port.Font = new Font("Tahoma", 11.25F, FontStyle.Regular, GraphicsUnit.Point); - this.port.ForeColor = Color.White; - this.port.Location = new Point(13, 89); - this.port.Maximum = new decimal(new int[] { - 65535, - 0, - 0, - 0}); - this.port.Name = "port"; - this.port.Size = new Size(107, 26); - this.port.TabIndex = 9; - this.port.Value = new decimal(new int[] { - 8191, - 0, - 0, - 0}); + port.BackColor = Color.FromArgb(65, 65, 65); + port.BorderStyle = BorderStyle.FixedSingle; + port.Font = new Font("Tahoma", 11.25F, FontStyle.Regular, GraphicsUnit.Point); + port.ForeColor = Color.White; + port.Location = new Point(13, 89); + port.Maximum = new decimal(new int[] { 65535, 0, 0, 0 }); + port.Name = "port"; + port.Size = new Size(107, 26); + port.TabIndex = 9; + port.Value = new decimal(new int[] { 8191, 0, 0, 0 }); // // lblPort // - this.lblPort.AutoSize = true; - this.lblPort.Font = new Font("Tahoma", 14.25F, FontStyle.Regular, GraphicsUnit.Point); - this.lblPort.ForeColor = Color.Gray; - this.lblPort.Location = new Point(3, 63); - this.lblPort.Name = "lblPort"; - this.lblPort.Size = new Size(43, 23); - this.lblPort.TabIndex = 8; - this.lblPort.Text = "Port"; - this.lblPort.UseMnemonic = false; + lblPort.AutoSize = true; + lblPort.Font = new Font("Tahoma", 14.25F, FontStyle.Regular, GraphicsUnit.Point); + lblPort.ForeColor = Color.Gray; + lblPort.Location = new Point(3, 63); + lblPort.Name = "lblPort"; + lblPort.Size = new Size(43, 23); + lblPort.TabIndex = 8; + lblPort.Text = "Port"; + lblPort.UseMnemonic = false; // // lblIpAddessLabel // - this.lblIpAddessLabel.AutoSize = true; - this.lblIpAddessLabel.Font = new Font("Tahoma", 11.25F, FontStyle.Regular, GraphicsUnit.Point); - this.lblIpAddessLabel.Location = new Point(18, 280); - this.lblIpAddessLabel.Name = "lblIpAddessLabel"; - this.lblIpAddessLabel.Size = new Size(83, 18); - this.lblIpAddessLabel.TabIndex = 7; - this.lblIpAddessLabel.Text = "IP address:"; - this.lblIpAddessLabel.UseMnemonic = false; - this.lblIpAddessLabel.Visible = false; + lblIpAddessLabel.AutoSize = true; + lblIpAddessLabel.Font = new Font("Tahoma", 11.25F, FontStyle.Regular, GraphicsUnit.Point); + lblIpAddessLabel.Location = new Point(18, 280); + lblIpAddessLabel.Name = "lblIpAddessLabel"; + lblIpAddessLabel.Size = new Size(83, 18); + lblIpAddessLabel.TabIndex = 7; + lblIpAddessLabel.Text = "IP address:"; + lblIpAddessLabel.UseMnemonic = false; + lblIpAddessLabel.Visible = false; // // lblIpAddress // - this.lblIpAddress.Font = new Font("Tahoma", 11.25F, FontStyle.Regular, GraphicsUnit.Point); - this.lblIpAddress.Location = new Point(107, 280); - this.lblIpAddress.Name = "lblIpAddress"; - this.lblIpAddress.Size = new Size(187, 17); - this.lblIpAddress.TabIndex = 6; - this.lblIpAddress.Text = "0.0.0.0"; - this.lblIpAddress.UseMnemonic = false; - this.lblIpAddress.Visible = false; + lblIpAddress.Font = new Font("Tahoma", 11.25F, FontStyle.Regular, GraphicsUnit.Point); + lblIpAddress.Location = new Point(107, 280); + lblIpAddress.Name = "lblIpAddress"; + lblIpAddress.Size = new Size(187, 17); + lblIpAddress.TabIndex = 6; + lblIpAddress.Text = "0.0.0.0"; + lblIpAddress.UseMnemonic = false; + lblIpAddress.Visible = false; // // networkAdapter // - this.networkAdapter.BackColor = Color.FromArgb(((int)(((byte)(65)))), ((int)(((byte)(65)))), ((int)(((byte)(65))))); - this.networkAdapter.Cursor = Cursors.Hand; - this.networkAdapter.DropDownStyle = ComboBoxStyle.DropDownList; - this.networkAdapter.Font = new Font("Tahoma", 12F, FontStyle.Regular, GraphicsUnit.Point); - this.networkAdapter.ForeColor = Color.White; - this.networkAdapter.Icon = null; - this.networkAdapter.Location = new Point(18, 245); - this.networkAdapter.Margin = new Padding(4); - this.networkAdapter.Name = "networkAdapter"; - this.networkAdapter.Padding = new Padding(8, 2, 8, 2); - this.networkAdapter.SelectedIndex = -1; - this.networkAdapter.SelectedItem = null; - this.networkAdapter.Size = new Size(276, 31); - this.networkAdapter.TabIndex = 5; - this.networkAdapter.Visible = false; - this.networkAdapter.SelectedIndexChanged += new EventHandler(this.NetworkAdapter_SelectedIndexChanged); + networkAdapter.BackColor = Color.FromArgb(65, 65, 65); + networkAdapter.Cursor = Cursors.Hand; + networkAdapter.DropDownStyle = ComboBoxStyle.DropDownList; + networkAdapter.Font = new Font("Tahoma", 12F, FontStyle.Regular, GraphicsUnit.Point); + networkAdapter.ForeColor = Color.White; + networkAdapter.Icon = null; + networkAdapter.Location = new Point(18, 245); + networkAdapter.Margin = new Padding(4); + networkAdapter.Name = "networkAdapter"; + networkAdapter.Padding = new Padding(8, 2, 8, 2); + networkAdapter.SelectedIndex = -1; + networkAdapter.SelectedItem = null; + networkAdapter.Size = new Size(276, 31); + networkAdapter.TabIndex = 5; + networkAdapter.Visible = false; + networkAdapter.SelectedIndexChanged += NetworkAdapter_SelectedIndexChanged; // // lblNetworkAdapter // - this.lblNetworkAdapter.AutoSize = true; - this.lblNetworkAdapter.Font = new Font("Tahoma", 14.25F, FontStyle.Regular, GraphicsUnit.Point); - this.lblNetworkAdapter.ForeColor = Color.Gray; - this.lblNetworkAdapter.Location = new Point(9, 221); - this.lblNetworkAdapter.Name = "lblNetworkAdapter"; - this.lblNetworkAdapter.Size = new Size(150, 23); - this.lblNetworkAdapter.TabIndex = 2; - this.lblNetworkAdapter.Text = "Network adapter"; - this.lblNetworkAdapter.UseMnemonic = false; - this.lblNetworkAdapter.Visible = false; + lblNetworkAdapter.AutoSize = true; + lblNetworkAdapter.Font = new Font("Tahoma", 14.25F, FontStyle.Regular, GraphicsUnit.Point); + lblNetworkAdapter.ForeColor = Color.Gray; + lblNetworkAdapter.Location = new Point(9, 221); + lblNetworkAdapter.Name = "lblNetworkAdapter"; + lblNetworkAdapter.Size = new Size(150, 23); + lblNetworkAdapter.TabIndex = 2; + lblNetworkAdapter.Text = "Network adapter"; + lblNetworkAdapter.UseMnemonic = false; + lblNetworkAdapter.Visible = false; // // lblConnection // - this.lblConnection.AutoSize = true; - this.lblConnection.Font = new Font("Tahoma", 15.75F, FontStyle.Regular, GraphicsUnit.Point); - this.lblConnection.Location = new Point(3, 0); - this.lblConnection.Name = "lblConnection"; - this.lblConnection.Size = new Size(116, 25); - this.lblConnection.TabIndex = 1; - this.lblConnection.Text = "Connection"; - this.lblConnection.UseMnemonic = false; + lblConnection.AutoSize = true; + lblConnection.Font = new Font("Tahoma", 15.75F, FontStyle.Regular, GraphicsUnit.Point); + lblConnection.Location = new Point(3, 0); + lblConnection.Name = "lblConnection"; + lblConnection.Size = new Size(116, 25); + lblConnection.TabIndex = 1; + lblConnection.Text = "Connection"; + lblConnection.UseMnemonic = false; // // tabUpdater // - this.tabUpdater.BackColor = Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(45))))); - this.tabUpdater.Controls.Add(this.checkAutoUpdate); - this.tabUpdater.Controls.Add(this.checkInstallBetaVersions); - this.tabUpdater.Controls.Add(this.updaterPanel); - this.tabUpdater.Controls.Add(this.btnCheckUpdates); - this.tabUpdater.Controls.Add(this.lblInstalledVersion); - this.tabUpdater.Controls.Add(this.lblInstalledVersionLabel); - this.tabUpdater.Controls.Add(this.lblUpdates); - this.tabUpdater.Font = new Font("Tahoma", 12F, FontStyle.Regular, GraphicsUnit.Point); - this.tabUpdater.ForeColor = Color.White; - this.tabUpdater.Location = new Point(204, 4); - this.tabUpdater.Name = "tabUpdater"; - this.tabUpdater.Size = new Size(923, 526); - this.tabUpdater.TabIndex = 1; - this.tabUpdater.Text = "Updates"; + tabUpdater.BackColor = Color.FromArgb(45, 45, 45); + tabUpdater.Controls.Add(label2); + tabUpdater.Controls.Add(checkAutoUpdate); + tabUpdater.Controls.Add(checkInstallBetaVersions); + tabUpdater.Controls.Add(btnCheckUpdates); + tabUpdater.Controls.Add(lblInstalledVersion); + tabUpdater.Controls.Add(lblInstalledVersionLabel); + tabUpdater.Controls.Add(lblUpdates); + tabUpdater.Font = new Font("Tahoma", 12F, FontStyle.Regular, GraphicsUnit.Point); + tabUpdater.ForeColor = Color.White; + tabUpdater.Location = new Point(204, 4); + tabUpdater.Name = "tabUpdater"; + tabUpdater.Size = new Size(923, 526); + tabUpdater.TabIndex = 1; + tabUpdater.Text = "Updates"; + // + // label2 + // + label2.AutoSize = true; + label2.Font = new Font("Tahoma", 14.25F, FontStyle.Regular, GraphicsUnit.Point); + label2.ForeColor = Color.Gray; + label2.Location = new Point(3, 63); + label2.Name = "label2"; + label2.Size = new Size(82, 23); + label2.TabIndex = 18; + label2.Text = "Behavior"; + label2.UseMnemonic = false; // // checkAutoUpdate // - this.checkAutoUpdate.AutoSize = true; - this.checkAutoUpdate.Location = new Point(13, 28); - this.checkAutoUpdate.Name = "checkAutoUpdate"; - this.checkAutoUpdate.Size = new Size(253, 23); - this.checkAutoUpdate.TabIndex = 17; - this.checkAutoUpdate.Text = "Automatically check for updates"; - this.checkAutoUpdate.UseMnemonic = false; - this.checkAutoUpdate.UseVisualStyleBackColor = true; + checkAutoUpdate.AutoSize = true; + checkAutoUpdate.Location = new Point(13, 89); + checkAutoUpdate.Name = "checkAutoUpdate"; + checkAutoUpdate.Size = new Size(253, 23); + checkAutoUpdate.TabIndex = 17; + checkAutoUpdate.Text = "Automatically check for updates"; + checkAutoUpdate.UseMnemonic = false; + checkAutoUpdate.UseVisualStyleBackColor = true; // // checkInstallBetaVersions // - this.checkInstallBetaVersions.AutoSize = true; - this.checkInstallBetaVersions.Location = new Point(13, 57); - this.checkInstallBetaVersions.Name = "checkInstallBetaVersions"; - this.checkInstallBetaVersions.Size = new Size(169, 23); - this.checkInstallBetaVersions.TabIndex = 16; - this.checkInstallBetaVersions.Text = "Install Beta versions"; - this.checkInstallBetaVersions.UseMnemonic = false; - this.checkInstallBetaVersions.UseVisualStyleBackColor = true; - // - // updaterPanel - // - this.updaterPanel.Anchor = ((AnchorStyles)((((AnchorStyles.Top | AnchorStyles.Bottom) - | AnchorStyles.Left) - | AnchorStyles.Right))); - this.updaterPanel.Location = new Point(3, 103); - this.updaterPanel.Name = "updaterPanel"; - this.updaterPanel.Size = new Size(920, 420); - this.updaterPanel.TabIndex = 14; + checkInstallBetaVersions.AutoSize = true; + checkInstallBetaVersions.Location = new Point(13, 118); + checkInstallBetaVersions.Name = "checkInstallBetaVersions"; + checkInstallBetaVersions.Size = new Size(169, 23); + checkInstallBetaVersions.TabIndex = 16; + checkInstallBetaVersions.Text = "Install Beta versions"; + checkInstallBetaVersions.UseMnemonic = false; + checkInstallBetaVersions.UseVisualStyleBackColor = true; // // btnCheckUpdates // - this.btnCheckUpdates.BorderRadius = 8; - this.btnCheckUpdates.Cursor = Cursors.Hand; - this.btnCheckUpdates.FlatAppearance.BorderSize = 0; - this.btnCheckUpdates.FlatStyle = FlatStyle.Flat; - this.btnCheckUpdates.Font = new Font("Tahoma", 9.75F, FontStyle.Regular, GraphicsUnit.Point); - this.btnCheckUpdates.ForeColor = Color.White; - this.btnCheckUpdates.HoverColor = Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(89)))), ((int)(((byte)(184))))); - this.btnCheckUpdates.Icon = null; - this.btnCheckUpdates.Location = new Point(354, 65); - this.btnCheckUpdates.Name = "btnCheckUpdates"; - this.btnCheckUpdates.Progress = 0; - this.btnCheckUpdates.ProgressColor = Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(46)))), ((int)(((byte)(94))))); - this.btnCheckUpdates.Size = new Size(215, 32); - this.btnCheckUpdates.TabIndex = 9; - this.btnCheckUpdates.Text = "Check for updates now"; - this.btnCheckUpdates.UseMnemonic = false; - this.btnCheckUpdates.UseVisualStyleBackColor = false; - this.btnCheckUpdates.UseWindowsAccentColor = true; - this.btnCheckUpdates.Click += new EventHandler(this.BtnCheckUpdates_Click); + btnCheckUpdates.BorderRadius = 8; + btnCheckUpdates.Cursor = Cursors.Hand; + btnCheckUpdates.FlatAppearance.BorderSize = 0; + btnCheckUpdates.FlatStyle = FlatStyle.Flat; + btnCheckUpdates.Font = new Font("Tahoma", 9.75F, FontStyle.Regular, GraphicsUnit.Point); + btnCheckUpdates.ForeColor = Color.White; + btnCheckUpdates.HoverColor = Color.FromArgb(0, 89, 184); + btnCheckUpdates.Icon = null; + btnCheckUpdates.Location = new Point(354, 265); + btnCheckUpdates.Name = "btnCheckUpdates"; + btnCheckUpdates.Progress = 0; + btnCheckUpdates.ProgressColor = Color.FromArgb(0, 46, 94); + btnCheckUpdates.Size = new Size(215, 32); + btnCheckUpdates.TabIndex = 9; + btnCheckUpdates.Text = "Check for updates now"; + btnCheckUpdates.UseMnemonic = false; + btnCheckUpdates.UseVisualStyleBackColor = false; + btnCheckUpdates.UseWindowsAccentColor = true; + btnCheckUpdates.Click += BtnCheckUpdates_Click; // // lblInstalledVersion // - this.lblInstalledVersion.Location = new Point(769, 29); - this.lblInstalledVersion.Name = "lblInstalledVersion"; - this.lblInstalledVersion.Size = new Size(151, 19); - this.lblInstalledVersion.TabIndex = 8; - this.lblInstalledVersion.Text = "2.0.0"; - this.lblInstalledVersion.TextAlign = ContentAlignment.MiddleRight; - this.lblInstalledVersion.UseMnemonic = false; + lblInstalledVersion.Location = new Point(501, 243); + lblInstalledVersion.Name = "lblInstalledVersion"; + lblInstalledVersion.Size = new Size(229, 19); + lblInstalledVersion.TabIndex = 8; + lblInstalledVersion.Text = "2.0.0"; + lblInstalledVersion.TextAlign = ContentAlignment.MiddleLeft; + lblInstalledVersion.UseMnemonic = false; // // lblInstalledVersionLabel // - this.lblInstalledVersionLabel.Location = new Point(534, 29); - this.lblInstalledVersionLabel.Name = "lblInstalledVersionLabel"; - this.lblInstalledVersionLabel.Size = new Size(229, 19); - this.lblInstalledVersionLabel.TabIndex = 7; - this.lblInstalledVersionLabel.Text = "Installed Version:"; - this.lblInstalledVersionLabel.TextAlign = ContentAlignment.MiddleRight; - this.lblInstalledVersionLabel.UseMnemonic = false; + lblInstalledVersionLabel.Location = new Point(266, 243); + lblInstalledVersionLabel.Name = "lblInstalledVersionLabel"; + lblInstalledVersionLabel.Size = new Size(229, 19); + lblInstalledVersionLabel.TabIndex = 7; + lblInstalledVersionLabel.Text = "Installed Version:"; + lblInstalledVersionLabel.TextAlign = ContentAlignment.MiddleRight; + lblInstalledVersionLabel.UseMnemonic = false; // // lblUpdates // - this.lblUpdates.AutoSize = true; - this.lblUpdates.Font = new Font("Tahoma", 15.75F, FontStyle.Regular, GraphicsUnit.Point); - this.lblUpdates.Location = new Point(3, 0); - this.lblUpdates.Name = "lblUpdates"; - this.lblUpdates.Size = new Size(88, 25); - this.lblUpdates.TabIndex = 2; - this.lblUpdates.Text = "Updates"; - this.lblUpdates.UseMnemonic = false; + lblUpdates.AutoSize = true; + lblUpdates.Font = new Font("Tahoma", 15.75F, FontStyle.Regular, GraphicsUnit.Point); + lblUpdates.Location = new Point(3, 0); + lblUpdates.Name = "lblUpdates"; + lblUpdates.Size = new Size(88, 25); + lblUpdates.TabIndex = 2; + lblUpdates.Text = "Updates"; + lblUpdates.UseMnemonic = false; // // tabBackups // - this.tabBackups.BackColor = Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(45))))); - this.tabBackups.Controls.Add(this.btnCreateBackup); - this.tabBackups.Controls.Add(this.backupsPanel); - this.tabBackups.Controls.Add(this.lblBackups); - this.tabBackups.ForeColor = Color.White; - this.tabBackups.Location = new Point(204, 4); - this.tabBackups.Name = "tabBackups"; - this.tabBackups.Size = new Size(923, 526); - this.tabBackups.TabIndex = 4; - this.tabBackups.Text = "Backups"; + tabBackups.BackColor = Color.FromArgb(45, 45, 45); + tabBackups.Controls.Add(btnCreateBackup); + tabBackups.Controls.Add(backupsPanel); + tabBackups.Controls.Add(lblBackups); + tabBackups.ForeColor = Color.White; + tabBackups.Location = new Point(204, 4); + tabBackups.Name = "tabBackups"; + tabBackups.Size = new Size(923, 526); + tabBackups.TabIndex = 4; + tabBackups.Text = "Backups"; // // btnCreateBackup // - this.btnCreateBackup.BorderRadius = 8; - this.btnCreateBackup.Cursor = Cursors.Hand; - this.btnCreateBackup.FlatAppearance.BorderSize = 0; - this.btnCreateBackup.FlatStyle = FlatStyle.Flat; - this.btnCreateBackup.Font = new Font("Tahoma", 9.75F, FontStyle.Regular, GraphicsUnit.Point); - this.btnCreateBackup.ForeColor = Color.White; - this.btnCreateBackup.HoverColor = Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(89)))), ((int)(((byte)(184))))); - this.btnCreateBackup.Icon = null; - this.btnCreateBackup.Location = new Point(770, 493); - this.btnCreateBackup.Name = "btnCreateBackup"; - this.btnCreateBackup.Progress = 0; - this.btnCreateBackup.ProgressColor = Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(46)))), ((int)(((byte)(94))))); - this.btnCreateBackup.Size = new Size(150, 30); - this.btnCreateBackup.TabIndex = 5; - this.btnCreateBackup.Text = "Create backup"; - this.btnCreateBackup.UseMnemonic = false; - this.btnCreateBackup.UseVisualStyleBackColor = false; - this.btnCreateBackup.UseWindowsAccentColor = true; - this.btnCreateBackup.Click += new EventHandler(this.BtnCreateBackup_Click); + btnCreateBackup.BorderRadius = 8; + btnCreateBackup.Cursor = Cursors.Hand; + btnCreateBackup.FlatAppearance.BorderSize = 0; + btnCreateBackup.FlatStyle = FlatStyle.Flat; + btnCreateBackup.Font = new Font("Tahoma", 9.75F, FontStyle.Regular, GraphicsUnit.Point); + btnCreateBackup.ForeColor = Color.White; + btnCreateBackup.HoverColor = Color.FromArgb(0, 89, 184); + btnCreateBackup.Icon = null; + btnCreateBackup.Location = new Point(770, 493); + btnCreateBackup.Name = "btnCreateBackup"; + btnCreateBackup.Progress = 0; + btnCreateBackup.ProgressColor = Color.FromArgb(0, 46, 94); + btnCreateBackup.Size = new Size(150, 30); + btnCreateBackup.TabIndex = 5; + btnCreateBackup.Text = "Create backup"; + btnCreateBackup.UseMnemonic = false; + btnCreateBackup.UseVisualStyleBackColor = false; + btnCreateBackup.UseWindowsAccentColor = true; + btnCreateBackup.Click += BtnCreateBackup_Click; // // backupsPanel // - this.backupsPanel.AutoScroll = true; - this.backupsPanel.Location = new Point(3, 28); - this.backupsPanel.Name = "backupsPanel"; - this.backupsPanel.Size = new Size(917, 459); - this.backupsPanel.TabIndex = 4; + backupsPanel.AutoScroll = true; + backupsPanel.Location = new Point(3, 28); + backupsPanel.Name = "backupsPanel"; + backupsPanel.Size = new Size(917, 459); + backupsPanel.TabIndex = 4; // // lblBackups // - this.lblBackups.AutoSize = true; - this.lblBackups.Font = new Font("Tahoma", 15.75F, FontStyle.Regular, GraphicsUnit.Point); - this.lblBackups.Location = new Point(3, 0); - this.lblBackups.Name = "lblBackups"; - this.lblBackups.Size = new Size(89, 25); - this.lblBackups.TabIndex = 3; - this.lblBackups.Text = "Backups"; - this.lblBackups.UseMnemonic = false; + lblBackups.AutoSize = true; + lblBackups.Font = new Font("Tahoma", 15.75F, FontStyle.Regular, GraphicsUnit.Point); + lblBackups.Location = new Point(3, 0); + lblBackups.Name = "lblBackups"; + lblBackups.Size = new Size(89, 25); + lblBackups.TabIndex = 3; + lblBackups.Text = "Backups"; + lblBackups.UseMnemonic = false; // // tabAbout // - this.tabAbout.BackColor = Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(45))))); - this.tabAbout.Controls.Add(this.btnGitHub); - this.tabAbout.Controls.Add(this.lblBuild); - this.tabAbout.Controls.Add(this.lblBuildLabel); - this.tabAbout.Controls.Add(this.label1); - this.tabAbout.Controls.Add(this.lblTranslationBy); - this.tabAbout.Controls.Add(this.btnLicenses); - this.tabAbout.Controls.Add(this.lblPluginAPIVersion); - this.tabAbout.Controls.Add(this.lblWebsocketAPIVersion); - this.tabAbout.Controls.Add(this.lblPluginAPILabel); - this.tabAbout.Controls.Add(this.lblWebSocketAPILabel); - this.tabAbout.Controls.Add(this.lblInstalledPlugins); - this.tabAbout.Controls.Add(this.lblInstalledPluginsLabel); - this.tabAbout.Controls.Add(this.lblDeveloped); - this.tabAbout.Controls.Add(this.lblMacroDeck); - this.tabAbout.Controls.Add(this.pictureBox1); - this.tabAbout.Font = new Font("Tahoma", 12F, FontStyle.Regular, GraphicsUnit.Point); - this.tabAbout.ForeColor = Color.White; - this.tabAbout.Location = new Point(204, 4); - this.tabAbout.Name = "tabAbout"; - this.tabAbout.Size = new Size(923, 526); - this.tabAbout.TabIndex = 2; - this.tabAbout.Text = "About"; + tabAbout.BackColor = Color.FromArgb(45, 45, 45); + tabAbout.Controls.Add(btnGitHub); + tabAbout.Controls.Add(label1); + tabAbout.Controls.Add(lblTranslationBy); + tabAbout.Controls.Add(btnLicenses); + tabAbout.Controls.Add(lblPluginAPIVersion); + tabAbout.Controls.Add(lblWebsocketAPIVersion); + tabAbout.Controls.Add(lblPluginAPILabel); + tabAbout.Controls.Add(lblWebSocketAPILabel); + tabAbout.Controls.Add(lblInstalledPlugins); + tabAbout.Controls.Add(lblInstalledPluginsLabel); + tabAbout.Controls.Add(lblDeveloped); + tabAbout.Controls.Add(lblMacroDeck); + tabAbout.Controls.Add(pictureBox1); + tabAbout.Font = new Font("Tahoma", 12F, FontStyle.Regular, GraphicsUnit.Point); + tabAbout.ForeColor = Color.White; + tabAbout.Location = new Point(204, 4); + tabAbout.Name = "tabAbout"; + tabAbout.Size = new Size(923, 526); + tabAbout.TabIndex = 2; + tabAbout.Text = "About"; // // btnGitHub // - this.btnGitHub.BackColor = Color.Transparent; - this.btnGitHub.BackgroundImage = Resources.GitHub_Mark_Light; - this.btnGitHub.BackgroundImageLayout = ImageLayout.Stretch; - this.btnGitHub.Cursor = Cursors.Hand; - this.btnGitHub.HoverImage = null; - this.btnGitHub.Location = new Point(436, 63); - this.btnGitHub.Name = "btnGitHub"; - this.btnGitHub.Size = new Size(50, 50); - this.btnGitHub.TabIndex = 18; - this.btnGitHub.TabStop = false; - this.btnGitHub.Click += new EventHandler(this.BtnGitHub_Click); - // - // lblBuild - // - this.lblBuild.AutoSize = true; - this.lblBuild.Location = new Point(564, 380); - this.lblBuild.Name = "lblBuild"; - this.lblBuild.Size = new Size(27, 19); - this.lblBuild.TabIndex = 17; - this.lblBuild.Text = "13"; - this.lblBuild.UseMnemonic = false; - // - // lblBuildLabel - // - this.lblBuildLabel.AutoSize = true; - this.lblBuildLabel.Location = new Point(332, 380); - this.lblBuildLabel.Name = "lblBuildLabel"; - this.lblBuildLabel.Size = new Size(44, 19); - this.lblBuildLabel.TabIndex = 16; - this.lblBuildLabel.Text = "Build"; - this.lblBuildLabel.UseMnemonic = false; + btnGitHub.BackColor = Color.Transparent; + btnGitHub.BackgroundImage = Resources.GitHub_Mark_Light; + btnGitHub.BackgroundImageLayout = ImageLayout.Stretch; + btnGitHub.Cursor = Cursors.Hand; + btnGitHub.HoverImage = null; + btnGitHub.Location = new Point(436, 63); + btnGitHub.Name = "btnGitHub"; + btnGitHub.Size = new Size(50, 50); + btnGitHub.TabIndex = 18; + btnGitHub.TabStop = false; + btnGitHub.Click += BtnGitHub_Click; // // label1 // - this.label1.Font = new Font("Tahoma", 11.25F, FontStyle.Regular, GraphicsUnit.Point); - this.label1.Location = new Point(219, 226); - this.label1.Name = "label1"; - this.label1.Size = new Size(485, 18); - this.label1.TabIndex = 15; - this.label1.Text = "Licensed under Apache-2.0"; - this.label1.TextAlign = ContentAlignment.MiddleCenter; - this.label1.UseMnemonic = false; + label1.Font = new Font("Tahoma", 11.25F, FontStyle.Regular, GraphicsUnit.Point); + label1.Location = new Point(219, 226); + label1.Name = "label1"; + label1.Size = new Size(485, 18); + label1.TabIndex = 15; + label1.Text = "Licensed under Apache-2.0"; + label1.TextAlign = ContentAlignment.MiddleCenter; + label1.UseMnemonic = false; // // lblTranslationBy // - this.lblTranslationBy.Font = new Font("Tahoma", 11.25F, FontStyle.Regular, GraphicsUnit.Point); - this.lblTranslationBy.Location = new Point(219, 164); - this.lblTranslationBy.Name = "lblTranslationBy"; - this.lblTranslationBy.Size = new Size(485, 18); - this.lblTranslationBy.TabIndex = 14; - this.lblTranslationBy.Text = "English translation by Macro Deck"; - this.lblTranslationBy.TextAlign = ContentAlignment.MiddleCenter; - this.lblTranslationBy.UseMnemonic = false; + lblTranslationBy.Font = new Font("Tahoma", 11.25F, FontStyle.Regular, GraphicsUnit.Point); + lblTranslationBy.Location = new Point(219, 164); + lblTranslationBy.Name = "lblTranslationBy"; + lblTranslationBy.Size = new Size(485, 18); + lblTranslationBy.TabIndex = 14; + lblTranslationBy.Text = "English translation by Macro Deck"; + lblTranslationBy.TextAlign = ContentAlignment.MiddleCenter; + lblTranslationBy.UseMnemonic = false; // // btnLicenses // - this.btnLicenses.BorderRadius = 8; - this.btnLicenses.Cursor = Cursors.Hand; - this.btnLicenses.FlatAppearance.BorderSize = 0; - this.btnLicenses.FlatStyle = FlatStyle.Flat; - this.btnLicenses.Font = new Font("Tahoma", 9.75F, FontStyle.Regular, GraphicsUnit.Point); - this.btnLicenses.ForeColor = Color.White; - this.btnLicenses.HoverColor = Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(89)))), ((int)(((byte)(184))))); - this.btnLicenses.Icon = null; - this.btnLicenses.Location = new Point(361, 297); - this.btnLicenses.Name = "btnLicenses"; - this.btnLicenses.Progress = 0; - this.btnLicenses.ProgressColor = Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(46)))), ((int)(((byte)(94))))); - this.btnLicenses.Size = new Size(200, 27); - this.btnLicenses.TabIndex = 13; - this.btnLicenses.Text = "3rd party licenses"; - this.btnLicenses.UseMnemonic = false; - this.btnLicenses.UseVisualStyleBackColor = false; - this.btnLicenses.UseWindowsAccentColor = true; - this.btnLicenses.Click += new EventHandler(this.BtnLicenses_Click); + btnLicenses.BorderRadius = 8; + btnLicenses.Cursor = Cursors.Hand; + btnLicenses.FlatAppearance.BorderSize = 0; + btnLicenses.FlatStyle = FlatStyle.Flat; + btnLicenses.Font = new Font("Tahoma", 9.75F, FontStyle.Regular, GraphicsUnit.Point); + btnLicenses.ForeColor = Color.White; + btnLicenses.HoverColor = Color.FromArgb(0, 89, 184); + btnLicenses.Icon = null; + btnLicenses.Location = new Point(361, 297); + btnLicenses.Name = "btnLicenses"; + btnLicenses.Progress = 0; + btnLicenses.ProgressColor = Color.FromArgb(0, 46, 94); + btnLicenses.Size = new Size(200, 27); + btnLicenses.TabIndex = 13; + btnLicenses.Text = "3rd party licenses"; + btnLicenses.UseMnemonic = false; + btnLicenses.UseVisualStyleBackColor = false; + btnLicenses.UseWindowsAccentColor = true; + btnLicenses.Click += BtnLicenses_Click; // // lblPluginAPIVersion // - this.lblPluginAPIVersion.AutoSize = true; - this.lblPluginAPIVersion.Location = new Point(564, 434); - this.lblPluginAPIVersion.Name = "lblPluginAPIVersion"; - this.lblPluginAPIVersion.Size = new Size(27, 19); - this.lblPluginAPIVersion.TabIndex = 12; - this.lblPluginAPIVersion.Text = "20"; - this.lblPluginAPIVersion.UseMnemonic = false; + lblPluginAPIVersion.AutoSize = true; + lblPluginAPIVersion.Location = new Point(564, 434); + lblPluginAPIVersion.Name = "lblPluginAPIVersion"; + lblPluginAPIVersion.Size = new Size(27, 19); + lblPluginAPIVersion.TabIndex = 12; + lblPluginAPIVersion.Text = "20"; + lblPluginAPIVersion.UseMnemonic = false; // // lblWebsocketAPIVersion // - this.lblWebsocketAPIVersion.AutoSize = true; - this.lblWebsocketAPIVersion.Location = new Point(564, 407); - this.lblWebsocketAPIVersion.Name = "lblWebsocketAPIVersion"; - this.lblWebsocketAPIVersion.Size = new Size(27, 19); - this.lblWebsocketAPIVersion.TabIndex = 11; - this.lblWebsocketAPIVersion.Text = "20"; - this.lblWebsocketAPIVersion.UseMnemonic = false; + lblWebsocketAPIVersion.AutoSize = true; + lblWebsocketAPIVersion.Location = new Point(564, 407); + lblWebsocketAPIVersion.Name = "lblWebsocketAPIVersion"; + lblWebsocketAPIVersion.Size = new Size(27, 19); + lblWebsocketAPIVersion.TabIndex = 11; + lblWebsocketAPIVersion.Text = "20"; + lblWebsocketAPIVersion.UseMnemonic = false; // // lblPluginAPILabel // - this.lblPluginAPILabel.AutoSize = true; - this.lblPluginAPILabel.Location = new Point(332, 434); - this.lblPluginAPILabel.Name = "lblPluginAPILabel"; - this.lblPluginAPILabel.Size = new Size(146, 19); - this.lblPluginAPILabel.TabIndex = 10; - this.lblPluginAPILabel.Text = "Plugin API version:"; - this.lblPluginAPILabel.UseMnemonic = false; + lblPluginAPILabel.AutoSize = true; + lblPluginAPILabel.Location = new Point(332, 434); + lblPluginAPILabel.Name = "lblPluginAPILabel"; + lblPluginAPILabel.Size = new Size(146, 19); + lblPluginAPILabel.TabIndex = 10; + lblPluginAPILabel.Text = "Plugin API version:"; + lblPluginAPILabel.UseMnemonic = false; // // lblWebSocketAPILabel // - this.lblWebSocketAPILabel.AutoSize = true; - this.lblWebSocketAPILabel.Location = new Point(332, 407); - this.lblWebSocketAPILabel.Name = "lblWebSocketAPILabel"; - this.lblWebSocketAPILabel.Size = new Size(177, 19); - this.lblWebSocketAPILabel.TabIndex = 9; - this.lblWebSocketAPILabel.Text = "Websocket API version:"; - this.lblWebSocketAPILabel.UseMnemonic = false; + lblWebSocketAPILabel.AutoSize = true; + lblWebSocketAPILabel.Location = new Point(332, 407); + lblWebSocketAPILabel.Name = "lblWebSocketAPILabel"; + lblWebSocketAPILabel.Size = new Size(177, 19); + lblWebSocketAPILabel.TabIndex = 9; + lblWebSocketAPILabel.Text = "Websocket API version:"; + lblWebSocketAPILabel.UseMnemonic = false; // // lblInstalledPlugins // - this.lblInstalledPlugins.AutoSize = true; - this.lblInstalledPlugins.Location = new Point(564, 461); - this.lblInstalledPlugins.Name = "lblInstalledPlugins"; - this.lblInstalledPlugins.Size = new Size(18, 19); - this.lblInstalledPlugins.TabIndex = 7; - this.lblInstalledPlugins.Text = "0"; - this.lblInstalledPlugins.UseMnemonic = false; + lblInstalledPlugins.AutoSize = true; + lblInstalledPlugins.Location = new Point(564, 461); + lblInstalledPlugins.Name = "lblInstalledPlugins"; + lblInstalledPlugins.Size = new Size(18, 19); + lblInstalledPlugins.TabIndex = 7; + lblInstalledPlugins.Text = "0"; + lblInstalledPlugins.UseMnemonic = false; // // lblInstalledPluginsLabel // - this.lblInstalledPluginsLabel.AutoSize = true; - this.lblInstalledPluginsLabel.Location = new Point(332, 461); - this.lblInstalledPluginsLabel.Name = "lblInstalledPluginsLabel"; - this.lblInstalledPluginsLabel.Size = new Size(131, 19); - this.lblInstalledPluginsLabel.TabIndex = 4; - this.lblInstalledPluginsLabel.Text = "Installed plugins:"; - this.lblInstalledPluginsLabel.UseMnemonic = false; + lblInstalledPluginsLabel.AutoSize = true; + lblInstalledPluginsLabel.Location = new Point(332, 461); + lblInstalledPluginsLabel.Name = "lblInstalledPluginsLabel"; + lblInstalledPluginsLabel.Size = new Size(131, 19); + lblInstalledPluginsLabel.TabIndex = 4; + lblInstalledPluginsLabel.Text = "Installed plugins:"; + lblInstalledPluginsLabel.UseMnemonic = false; // // lblDeveloped // - this.lblDeveloped.Font = new Font("Tahoma", 11.25F, FontStyle.Regular, GraphicsUnit.Point); - this.lblDeveloped.Location = new Point(219, 206); - this.lblDeveloped.Name = "lblDeveloped"; - this.lblDeveloped.Size = new Size(485, 18); - this.lblDeveloped.TabIndex = 2; - this.lblDeveloped.Text = "Developed by Manuel Mayer (SuchByte) in Germany"; - this.lblDeveloped.TextAlign = ContentAlignment.MiddleCenter; - this.lblDeveloped.UseMnemonic = false; + lblDeveloped.Font = new Font("Tahoma", 11.25F, FontStyle.Regular, GraphicsUnit.Point); + lblDeveloped.Location = new Point(219, 206); + lblDeveloped.Name = "lblDeveloped"; + lblDeveloped.Size = new Size(485, 18); + lblDeveloped.TabIndex = 2; + lblDeveloped.Text = "Developed by Manuel Mayer (SuchByte) in Germany"; + lblDeveloped.TextAlign = ContentAlignment.MiddleCenter; + lblDeveloped.UseMnemonic = false; // // lblMacroDeck // - this.lblMacroDeck.Font = new Font("Tahoma", 21.75F, FontStyle.Regular, GraphicsUnit.Point); - this.lblMacroDeck.ForeColor = Color.LightGray; - this.lblMacroDeck.Location = new Point(3, 3); - this.lblMacroDeck.Name = "lblMacroDeck"; - this.lblMacroDeck.Size = new Size(917, 41); - this.lblMacroDeck.TabIndex = 1; - this.lblMacroDeck.Text = "Macro Deck"; - this.lblMacroDeck.TextAlign = ContentAlignment.MiddleCenter; - this.lblMacroDeck.UseMnemonic = false; + lblMacroDeck.Font = new Font("Tahoma", 21.75F, FontStyle.Regular, GraphicsUnit.Point); + lblMacroDeck.ForeColor = Color.LightGray; + lblMacroDeck.Location = new Point(3, 3); + lblMacroDeck.Name = "lblMacroDeck"; + lblMacroDeck.Size = new Size(917, 41); + lblMacroDeck.TabIndex = 1; + lblMacroDeck.Text = "Macro Deck"; + lblMacroDeck.TextAlign = ContentAlignment.MiddleCenter; + lblMacroDeck.UseMnemonic = false; // // pictureBox1 // - this.pictureBox1.BackgroundImage = Resources.Icon; - this.pictureBox1.BackgroundImageLayout = ImageLayout.Stretch; - this.pictureBox1.Location = new Point(3, 47); - this.pictureBox1.Name = "pictureBox1"; - this.pictureBox1.Size = new Size(200, 187); - this.pictureBox1.TabIndex = 0; - this.pictureBox1.TabStop = false; + pictureBox1.BackgroundImage = Resources.Icon; + pictureBox1.BackgroundImageLayout = ImageLayout.Stretch; + pictureBox1.Location = new Point(3, 47); + pictureBox1.Name = "pictureBox1"; + pictureBox1.Size = new Size(200, 187); + pictureBox1.TabIndex = 0; + pictureBox1.TabStop = false; // // tabIcons // - this.tabIcons.ColorDepth = ColorDepth.Depth4Bit; - this.tabIcons.ImageStream = ((ImageListStreamer)(resources.GetObject("tabIcons.ImageStream"))); - this.tabIcons.TransparentColor = Color.Transparent; - this.tabIcons.Images.SetKeyName(0, "Cog.png"); - this.tabIcons.Images.SetKeyName(1, "Ethernet.png"); - this.tabIcons.Images.SetKeyName(2, "Update.png"); - this.tabIcons.Images.SetKeyName(3, "Backup-Restore.png"); - this.tabIcons.Images.SetKeyName(4, "Informationpng.png"); + tabIcons.ColorDepth = ColorDepth.Depth4Bit; + tabIcons.ImageStream = (ImageListStreamer)resources.GetObject("tabIcons.ImageStream"); + tabIcons.TransparentColor = Color.Transparent; + tabIcons.Images.SetKeyName(0, "Cog.png"); + tabIcons.Images.SetKeyName(1, "Ethernet.png"); + tabIcons.Images.SetKeyName(2, "Update.png"); + tabIcons.Images.SetKeyName(3, "Backup-Restore.png"); + tabIcons.Images.SetKeyName(4, "Informationpng.png"); // // SettingsView // - this.AutoScaleDimensions = new SizeF(96F, 96F); - this.AutoScaleMode = AutoScaleMode.Dpi; - this.BackColor = Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(45))))); - this.Controls.Add(this.verticalTabControl); - this.Font = new Font("Tahoma", 9F, FontStyle.Regular, GraphicsUnit.Point); - this.Name = "SettingsView"; - this.Size = new Size(1137, 540); - this.Load += new EventHandler(this.Settings_Load); - this.verticalTabControl.ResumeLayout(false); - this.tabGeneral.ResumeLayout(false); - this.tabGeneral.PerformLayout(); - this.tabConnection.ResumeLayout(false); - this.tabConnection.PerformLayout(); - this.groupConnectionInfo.ResumeLayout(false); - ((ISupportInitialize)(this.port)).EndInit(); - this.tabUpdater.ResumeLayout(false); - this.tabUpdater.PerformLayout(); - this.tabBackups.ResumeLayout(false); - this.tabBackups.PerformLayout(); - this.tabAbout.ResumeLayout(false); - this.tabAbout.PerformLayout(); - ((ISupportInitialize)(this.btnGitHub)).EndInit(); - ((ISupportInitialize)(this.pictureBox1)).EndInit(); - this.ResumeLayout(false); - + AutoScaleDimensions = new SizeF(96F, 96F); + AutoScaleMode = AutoScaleMode.Dpi; + BackColor = Color.FromArgb(45, 45, 45); + Controls.Add(verticalTabControl); + Font = new Font("Tahoma", 9F, FontStyle.Regular, GraphicsUnit.Point); + Name = "SettingsView"; + Size = new Size(1137, 540); + Load += Settings_Load; + verticalTabControl.ResumeLayout(false); + tabGeneral.ResumeLayout(false); + tabGeneral.PerformLayout(); + tabConnection.ResumeLayout(false); + tabConnection.PerformLayout(); + groupConnectionInfo.ResumeLayout(false); + ((ISupportInitialize)port).EndInit(); + tabUpdater.ResumeLayout(false); + tabUpdater.PerformLayout(); + tabBackups.ResumeLayout(false); + tabBackups.PerformLayout(); + tabAbout.ResumeLayout(false); + tabAbout.PerformLayout(); + ((ISupportInitialize)btnGitHub).EndInit(); + ((ISupportInitialize)pictureBox1).EndInit(); + ResumeLayout(false); } #endregion @@ -812,7 +776,6 @@ private void InitializeComponent() private Label lblWebSocketAPILabel; private ButtonPrimary btnLicenses; private Label lblTranslationBy; - private Panel updaterPanel; private CheckBox checkIconCache; private ImageList tabIcons; private Label label1; @@ -822,8 +785,7 @@ private void InitializeComponent() private Label lblBackups; private FlowLayoutPanel backupsPanel; private ButtonPrimary btnCreateBackup; - private Label lblBuild; - private Label lblBuildLabel; private PictureButton btnGitHub; + private Label label2; } } diff --git a/MacroDeck/GUI/MainWindowViews/SettingsView.cs b/MacroDeck/GUI/MainWindowViews/SettingsView.cs index 5cf2817e..1da2170e 100644 --- a/MacroDeck/GUI/MainWindowViews/SettingsView.cs +++ b/MacroDeck/GUI/MainWindowViews/SettingsView.cs @@ -2,13 +2,17 @@ using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; +using System.Threading; using System.Windows.Forms; using SuchByte.MacroDeck.Backups; +using SuchByte.MacroDeck.DataTypes.Updater; using SuchByte.MacroDeck.GUI.CustomControls.Settings; using SuchByte.MacroDeck.GUI.Dialogs; using SuchByte.MacroDeck.Language; +using SuchByte.MacroDeck.Logging; using SuchByte.MacroDeck.Plugins; using SuchByte.MacroDeck.Server; +using SuchByte.MacroDeck.Services; using SuchByte.MacroDeck.Startup; using MessageBox = SuchByte.MacroDeck.GUI.CustomControls.MessageBox; @@ -26,7 +30,6 @@ public SettingsView(int page = 0) } Dock = DockStyle.Fill; UpdateTranslation(); - Updater.Updater.OnUpdateAvailable += UpdateAvailable; BackupManager.BackupSaved += BackupManager_BackupSaved; BackupManager.BackupFailed += BackupManager_BackupFailed; BackupManager.DeleteSuccess += BackupManager_DeleteSuccess; @@ -34,7 +37,7 @@ public SettingsView(int page = 0) private void UpdateAvailable(object sender, EventArgs e) { - verticalTabControl.SetNotification(2, Updater.Updater.UpdateAvailable); + verticalTabControl.SetNotification(2, UpdateService.Instance().VersionInfo != null); } private void UpdateTranslation() @@ -64,13 +67,10 @@ private void UpdateTranslation() btnCreateBackup.Text = LanguageManager.Strings.CreateBackup; checkInstallBetaVersions.Text = LanguageManager.Strings.InstallBetaVersions; btnCheckUpdates.Text = LanguageManager.Strings.CheckForUpdatesNow; - lblBuildLabel.Text = LanguageManager.Strings.VersionBuild; - lblBuild.Text = MacroDeck.Version.Build.ToString(); lblWebSocketAPILabel.Text = LanguageManager.Strings.WebSocketAPIVersion; lblPluginAPILabel.Text = LanguageManager.Strings.PluginAPIVersion; lblInstalledPluginsLabel.Text = LanguageManager.Strings.InstalledPlugins; lblTranslationBy.Text = string.Format(LanguageManager.Strings.XTranslationByX, LanguageManager.Strings.__Language__, LanguageManager.Strings.__Author__); - Updater.Updater.OnUpdateAvailable += OnUpdateAvailable; } private void Settings_Load(object sender, EventArgs e) @@ -83,19 +83,11 @@ private void Settings_Load(object sender, EventArgs e) LoadIconCache(); LoadBackups(); - lblInstalledVersion.Text = MacroDeck.Version.VersionString; + lblInstalledVersion.Text = MacroDeck.Version.ToString(); lblWebsocketAPIVersion.Text = MacroDeck.ApiVersion.ToString(); lblPluginAPIVersion.Text = MacroDeck.PluginApiVersion.ToString(); - lblMacroDeck.Text = "Macro Deck " + MacroDeck.Version.VersionString; + lblMacroDeck.Text = "Macro Deck " + MacroDeck.Version.ToString(); lblInstalledPlugins.Text = PluginManager.Plugins.Count.ToString(); - - verticalTabControl.SetNotification(2, Updater.Updater.UpdateAvailable); - - if (Updater.Updater.UpdateAvailable) - { - AddUpdateAvailableControl(); - } - } private void LoadLanguage() @@ -156,10 +148,8 @@ private void CheckInstallBetaVersions_CheckedChanged(object sender, EventArgs e) using var msgBox = new MessageBox(); if (msgBox.ShowDialog(LanguageManager.Strings.Warning, LanguageManager.Strings.WarningBetaVersions, MessageBoxButtons.YesNo) == DialogResult.Yes) { - updaterPanel.Controls.Clear(); MacroDeck.Configuration.UpdateBetaVersions = true; MacroDeck.Configuration.Save(ApplicationPaths.MainConfigFilePath); - Updater.Updater.CheckForUpdatesAsync(); } else { @@ -168,10 +158,8 @@ private void CheckInstallBetaVersions_CheckedChanged(object sender, EventArgs e) } else { - updaterPanel.Controls.Clear(); MacroDeck.Configuration.UpdateBetaVersions = false; MacroDeck.Configuration.Save(ApplicationPaths.MainConfigFilePath); - Updater.Updater.CheckForUpdatesAsync(); } } @@ -267,50 +255,47 @@ private void CheckAutoUpdate_CheckedChanged(object sender, EventArgs e) MacroDeck.Configuration.Save(ApplicationPaths.MainConfigFilePath); } - private void BtnCheckUpdates_Click(object sender, EventArgs e) + private async void BtnCheckUpdates_Click(object sender, EventArgs e) { - Invoke(() => { - btnCheckUpdates.Enabled = false; - btnCheckUpdates.Spinner = true; - }); - Updater.Updater.OnLatestVersionInstalled += OnLatestVersion; - Updater.Updater.OnUpdateAvailable += OnUpdateAvailable; - Updater.Updater.CheckForUpdatesAsync(); - } + btnCheckUpdates.Enabled = false; + btnCheckUpdates.Spinner = true; - private void OnLatestVersion(object sender, EventArgs e) - { - Updater.Updater.OnLatestVersionInstalled -= OnLatestVersion; - Invoke(() => + try { - btnCheckUpdates.Enabled = true; - btnCheckUpdates.Spinner = false; - using var msgBox = new MessageBox(); - msgBox.ShowDialog(LanguageManager.Strings.NoUpdatesAvailable, LanguageManager.Strings.LatestVersionInstalled, MessageBoxButtons.OK); - }); + var availableUpdate = await UpdateService.Instance().CheckForUpdatesAsync(CancellationToken.None); + if (availableUpdate == null) + { + using var msgBox = new MessageBox(); + msgBox.ShowDialog( + LanguageManager.Strings.NoUpdatesAvailable, + LanguageManager.Strings.LatestVersionInstalled, + MessageBoxButtons.OK); - - } + return; + } - private void OnUpdateAvailable(object sender, EventArgs e) - { - Updater.Updater.OnUpdateAvailable -= OnUpdateAvailable; - Invoke(() => + using var updateAvailableDialog = new UpdateAvailableDialog(availableUpdate); + updateAvailableDialog.ShowDialog(); + } + catch (Exception ex) { - AddUpdateAvailableControl(); - }); - } + using var msgBox = new MessageBox(); + msgBox.ShowDialog( + "Check for updates failed", + "Make sure you have a internet connection", + MessageBoxButtons.OK); - private void AddUpdateAvailableControl() - { - btnCheckUpdates.Enabled = true; - btnCheckUpdates.Spinner = false; - if (updaterPanel.Controls.Count != 0) + MacroDeckLogger.Error($"Failed to check for updates\n{ex}"); + } + finally { - updaterPanel.Controls.Clear(); + Invoke(() => + { + btnCheckUpdates.Enabled = true; + btnCheckUpdates.Spinner = false; + }); } - updaterPanel.Controls.Add(new UpdateAvailableControl()); } private void BtnLicenses_Click(object sender, EventArgs e) @@ -374,7 +359,7 @@ private void BtnGitHub_Click(object sender, EventArgs e) { var p = new Process { - StartInfo = new ProcessStartInfo("https://github.com/Macro-Deck-org/Macro-Deck") + StartInfo = new ProcessStartInfo("https://github.com/Macro-Deck-App/Macro-Deck") { UseShellExecute = true, } diff --git a/MacroDeck/GUI/MainWindowViews/SettingsView.resx b/MacroDeck/GUI/MainWindowViews/SettingsView.resx index 5925e952..3402277a 100644 --- a/MacroDeck/GUI/MainWindowViews/SettingsView.resx +++ b/MacroDeck/GUI/MainWindowViews/SettingsView.resx @@ -70,7 +70,7 @@ The default port for Macro Deck is 8191. If some other application uses this por AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAmU3lzdGVtLldpbmRvd3MuRm9ybXMu SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAfg4AAAJNU0Z0AUkBTAIBAQUB - AAFQAQABUAEAATABAAEwAQAE/wEFAQAI/wFCAU0BdgcAAXYDAAEoAwABwAMAAWADAAEBAQABBAYAASQY + AAFgAQABYAEAATABAAEwAQAE/wEFAQAI/wFCAU0BdgcAAXYDAAEoAwABwAMAAWADAAEBAQABBAYAASQY AAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8B AAL/AgAD//8A/wD/AA0AAQ8C/10AAQ8D/1wAAQ8D/wHwWwABDwT/AfBaAAEPBf9aAAEPAv8B8AEPAf9a AAEPAv8B8FwAAQ8C/wHwXQAD/10AA/9dAAP/XQAD/10AAQ8C/wHwXAABDwL/AfBcAAEPAv8B8FoAAQ8B diff --git a/MacroDeck/MacroDeck.cs b/MacroDeck/MacroDeck.cs index 70f4db5f..5f70a03b 100644 --- a/MacroDeck/MacroDeck.cs +++ b/MacroDeck/MacroDeck.cs @@ -7,6 +7,7 @@ using Newtonsoft.Json.Linq; using SuchByte.MacroDeck.Backups; using SuchByte.MacroDeck.Configuration; +using SuchByte.MacroDeck.DataTypes.Updater; using SuchByte.MacroDeck.ExtensionStore; using SuchByte.MacroDeck.GUI; using SuchByte.MacroDeck.GUI.CustomControls; @@ -23,14 +24,17 @@ using SuchByte.MacroDeck.Profiles; using SuchByte.MacroDeck.Properties; using SuchByte.MacroDeck.Server; +using SuchByte.MacroDeck.Services; using SuchByte.MacroDeck.Startup; using SuchByte.MacroDeck.Variables; +using Version = SuchByte.MacroDeck.DataTypes.Core.Version; namespace SuchByte.MacroDeck; public class MacroDeck : NativeWindow { - public static VersionModel Version => new(FileVersionInfo.GetVersionInfo(ApplicationPaths.ExecutablePath).ProductVersion); + public static Version Version = + Version.Parse(FileVersionInfo.GetVersionInfo(ApplicationPaths.ExecutablePath).ProductVersion); public static readonly int ApiVersion = 20; public static readonly int PluginApiVersion = 40; @@ -48,7 +52,7 @@ public class MacroDeck : NativeWindow private static readonly NotifyIcon TrayIcon = new() { Icon = Resources.appicon, - Text = @"Macro Deck " + Version.VersionString, + Text = @"Macro Deck " + Version.ToString(), Visible = false, ContextMenuStrip = TrayIconContextMenu }; @@ -71,7 +75,7 @@ internal static void Start(StartParameters startParameters) MacroDeckLogger.StartDebugConsole(); } - MacroDeckLogger.Info($"Macro Deck {Version.VersionString}"); + MacroDeckLogger.Info($"Macro Deck {Version.ToString()}"); MacroDeckLogger.Info($"Path: {ApplicationPaths.ExecutablePath}"); MacroDeckLogger.Info($"Start parameters: {string.Join(" ", StartParameters.ToArray(StartParameters))}"); @@ -126,8 +130,9 @@ internal static void Start(StartParameters startParameters) OnMacroDeckLoaded?.Invoke(null, EventArgs.Empty); - Updater.Updater.OnUpdateAvailable += OnUpdateAvailable; - Updater.Updater.Initialize(StartParameters.ForceUpdate, StartParameters.TestUpdateChannel); + UpdateService.Instance().StartPeriodicalUpdateCheck(); + UpdateService.Instance().UpdateAvailable += OnUpdateAvailable; + ExtensionStoreHelper.SearchUpdatesAsync(); if (StartParameters.ShowMainWindow) @@ -137,6 +142,27 @@ internal static void Start(StartParameters startParameters) Application.Run(); } + + private static void OnUpdateAvailable(object? sender, UpdateApiVersionInfo e) + { + var btnOpenSettings = new ButtonPrimary + { + AutoSize = true, + Text = LanguageManager.Strings.OpenSettings, + }; + btnOpenSettings.Click += (o, args) => + { + MainWindow?.SetView(new SettingsView(2)); + }; + + NotificationManager.SystemNotification( + "Macro Deck Updater", + string.Format(LanguageManager.Strings.VersionXIsNowAvailable, e.Version, e.IsBeta == true ? "Beta" : "Release"), + true, + new List { btnOpenSettings }, Resources.Macro_Deck_2021_update); + + } + private static void PrintNetworkInterfaces() { StringBuilder sb = new(); @@ -188,29 +214,6 @@ private static void MacroDeckPipeServer_PipeMessage(string message) } } - private static void OnUpdateAvailable(object? sender, EventArgs e) - { - Updater.Updater.OnUpdateAvailable -= OnUpdateAvailable; - var versionObject = sender as JObject; - try - { - var btnOpenSettings = new ButtonPrimary - { - AutoSize = true, - Text = LanguageManager.Strings.OpenSettings, - }; - btnOpenSettings.Click += (o, args) => - { - MainWindow?.SetView(new SettingsView(2)); - }; - NotificationManager.SystemNotification("Macro Deck Updater", string.Format(LanguageManager.Strings.VersionXIsNowAvailable, versionObject["version"], versionObject["channel"]), true, new List { btnOpenSettings }, Resources.Macro_Deck_2021_update); - } - catch - { - // ignored - } - } - internal static void ShowBalloonTip(string title, string message) { try diff --git a/MacroDeck/MacroDeck.csproj b/MacroDeck/MacroDeck.csproj index 5fb54914..f5bce3cd 100644 --- a/MacroDeck/MacroDeck.csproj +++ b/MacroDeck/MacroDeck.csproj @@ -7,7 +7,7 @@ true appicon.ico SuchByte.MacroDeck.Program - 2.13.0-b1 + 2.12.0 Macro Deck Manuel Mayer False @@ -175,9 +175,6 @@ UserControl - - UserControl - Component diff --git a/MacroDeck/Services/UpdateService.cs b/MacroDeck/Services/UpdateService.cs new file mode 100644 index 00000000..04a882db --- /dev/null +++ b/MacroDeck/Services/UpdateService.cs @@ -0,0 +1,168 @@ +using System.Diagnostics; +using System.IO; +using System.Net.Http; +using System.Net.Http.Json; +using System.Threading; +using SuchByte.MacroDeck.DataTypes.FileDownloader; +using SuchByte.MacroDeck.DataTypes.Updater; +using SuchByte.MacroDeck.Enums; +using SuchByte.MacroDeck.Extension; +using SuchByte.MacroDeck.Logging; +using SuchByte.MacroDeck.Startup; +using SuchByte.MacroDeck.Utils; + +namespace SuchByte.MacroDeck.Services; + +public class UpdateService : IDisposable +{ + // Make UpdateService singleton + private static UpdateService? _instance; + public static UpdateService Instance() + { + _instance ??= new UpdateService(); + return _instance; + } + + public const PlatformIdentifier PlatformIdentifier = Enums.PlatformIdentifier.WinX64; + private const string UpdateServiceApiUrl = "https://update.api.macro-deck.app/v2"; + + public event EventHandler? UpdateAvailable; + + private readonly CancellationTokenSource _cancellationTokenSource = new(); + private readonly SemaphoreSlim _checkSemaphoreSlim = new(1); + private readonly SemaphoreSlim _downloadSemaphoreSlim = new(1); + + public UpdateApiVersionInfo? VersionInfo { get; set; } + + public void StartPeriodicalUpdateCheck() + { + var cancellationToken = _cancellationTokenSource.Token; + Task.Run(async() => await DoWork(cancellationToken), cancellationToken); + } + + public void Dispose() + { + _cancellationTokenSource.Cancel(); + GC.SuppressFinalize(this); + } + + public async Task CheckForUpdatesAsync(CancellationToken cancellationToken) + { + var checkUrl = $"{UpdateServiceApiUrl}/versions/check/{MacroDeck.Version.ToString()}/{PlatformIdentifier}"; + if (MacroDeck.Configuration.UpdateBetaVersions) + { + checkUrl += "?betaVersions=true"; + } + + await _checkSemaphoreSlim.WaitAsync(cancellationToken); + + using var httpClient = new HttpClient(); + try + { + var result = + await httpClient.GetFromJsonAsync(checkUrl, cancellationToken: cancellationToken); + if (result?.NewerVersionAvailable == null) + { + throw new InvalidOperationException("Result was null"); + } + + if (!result.NewerVersionAvailable.Value && VersionInfo == result.Version) + { + return null; + } + + UpdateAvailable?.Invoke(this, result.Version + ?? throw new InvalidOperationException("Version was null")); + + VersionInfo = result.Version; + return result.Version; + } + finally + { + _checkSemaphoreSlim.Release(); + } + } + + public async ValueTask DownloadAndInstallVersion( + UpdateApiVersionInfo updateApiVersionInfo, + IProgress progress) + { + await _downloadSemaphoreSlim.WaitAsync(); + + try + { + var versionFileInfo = updateApiVersionInfo.Platforms?[PlatformIdentifier]; + var destinationPath = + await DownloadUpdate(versionFileInfo?.DownloadUrl, updateApiVersionInfo.Version, progress); + + await VerifyDownloadedFile(destinationPath, versionFileInfo); + StartInstallation(destinationPath!); + } + finally + { + _downloadSemaphoreSlim.Release(); + } + } + + private static void StartInstallation(string path) + { + new Process + { + StartInfo = new ProcessStartInfo(path) + { + UseShellExecute = true, + Arguments = "/SILENT /SUPPRESSMSGBOXES /CLOSEAPPLICATIONS" + } + }.Start(); + Environment.Exit(0); + } + + private async ValueTask DoWork(CancellationToken cancellationToken) + { + do + { + try + { + await CheckForUpdatesAsync(cancellationToken); + } + catch (Exception ex) + { + MacroDeckLogger.Error($"Failed to automatically check for updates\n{ex}"); + } + + Thread.Sleep(TimeSpan.FromMinutes(30)); + } while (!cancellationToken.IsCancellationRequested); + } + + private static async ValueTask VerifyDownloadedFile(string? path, UpdateApiVersionFileInfo? updateApiVersionFileInfo) + { + if (string.IsNullOrWhiteSpace(path)) + { + throw new InvalidOperationException("The path was empty"); + } + if (!File.Exists(path)) + { + throw new FileNotFoundException("The update file was not found"); + } + + await using var ms = File.OpenRead(path); + var calculatedHash = await ms.CalculateSha256Hash(); + if (!calculatedHash.EqualsCryptographically(updateApiVersionFileInfo?.FileHash)) + { + throw new InvalidOperationException("The hash of the downloaded file does not match the file on the server"); + } + } + + private static async ValueTask DownloadUpdate(string? url, string? version, IProgress progress) + { + if (string.IsNullOrWhiteSpace(url)) + { + throw new InvalidOperationException("Download url was empty"); + } + + var destinationPath = Path.Combine(ApplicationPaths.TempDirectoryPath, $"update-{version}.exe"); + await FileDownloader.DownloadFileAsync(url, destinationPath, progress); + + return destinationPath; + } +} \ No newline at end of file diff --git a/MacroDeck/Updater/Updater.cs b/MacroDeck/Updater/Updater.cs deleted file mode 100644 index 2b7ea0ff..00000000 --- a/MacroDeck/Updater/Updater.cs +++ /dev/null @@ -1,210 +0,0 @@ -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using System.Net; -using System.Security.Cryptography; -using System.Windows.Forms; -using Newtonsoft.Json.Linq; -using SuchByte.MacroDeck.Language; -using SuchByte.MacroDeck.Logging; -using SuchByte.MacroDeck.Startup; -using MessageBox = SuchByte.MacroDeck.GUI.CustomControls.MessageBox; - -namespace SuchByte.MacroDeck.Updater; - -public class ProgressChangedEventArgs -{ - public int ProgressPercentage { get; set; } -} - -public static class Updater -{ - public static bool UpdateAvailable; - - public static event EventHandler OnUpdateAvailable; - public static event EventHandler OnLatestVersionInstalled; - public static event EventHandler OnError; - public static event EventHandler OnProgressChanged; - - private static bool _forceUpdate; - private static bool _testChannel; - - private static JObject _jsonObject; - public static JObject UpdateObject => _jsonObject; - - private static bool _downloading; - public static bool Downloading => _downloading; - - private static int _progressPercentage; - public static int ProgressPercentage => _progressPercentage; - - private static double _updateSizeMb; - public static double UpdateSizeMb => _updateSizeMb; - - public static void Initialize(bool forceUpdate = false, bool testChannel = false) - { - _forceUpdate = forceUpdate; - _testChannel = testChannel; - if (MacroDeck.Configuration.AutoUpdates) - { - CheckForUpdatesAsync(); - } - var updateCheckTimer = new Timer - { - Enabled = true, - Interval = 1000 * 60 * 10 // Check every 10 minutes - }; - } - - private static void UpdateCheckTimerTick(object sender, EventArgs e) - { - if (MacroDeck.Configuration.AutoUpdates) - { - CheckForUpdatesAsync(); - } - } - - public static void CheckForUpdatesAsync() - { - Task.Run(() => - { - CheckForUpdates(); - }); - } - - private static void CheckForUpdates() - { - if (UpdateAvailable) return; - try - { - using var wc = new WebClient(); - var jsonString = ""; - - if (_testChannel) - { - jsonString = wc.DownloadString("https://macrodeck.org/files/versions.php?latest&channel=test"); - } - - jsonString = wc.DownloadString("https://macrodeck.org/files/versions.php?latest" + (MacroDeck.Configuration.UpdateBetaVersions ? "&beta" : "")); - - _jsonObject = JObject.Parse(jsonString); - if (_jsonObject["build"] != null) - { - if (int.TryParse(_jsonObject["build"].ToString(), out var build)) - { - if (build > MacroDeck.Version.Build || _forceUpdate) - { - MacroDeckLogger.Info("Macro Deck version " + _jsonObject["version"] + " available"); - try - { - _updateSizeMb = GetFileSizeMb(new Uri("https://macrodeck.org/files/installer/" + _jsonObject["filename"])); - } - catch { } - if (OnUpdateAvailable != null) - { - UpdateAvailable = true; - OnUpdateAvailable(_jsonObject, EventArgs.Empty); - } - } - else - { - if (OnLatestVersionInstalled != null) - { - UpdateAvailable = false; - OnLatestVersionInstalled(_jsonObject, EventArgs.Empty); - } - } - } - } - } catch (Exception ex) - { - OnError?.Invoke(ex, EventArgs.Empty); - } - } - - private static double GetFileSizeMb(Uri uriPath) - { - var webRequest = HttpWebRequest.Create(uriPath); - webRequest.Method = "HEAD"; - - using var webResponse = webRequest.GetResponse(); - var fileSize = webResponse.Headers.Get("Content-Length"); - var fileSizeInMegaByte = Math.Round(Convert.ToDouble(fileSize) / 1024.0 / 1024.0, 2); - return fileSizeInMegaByte; - } - - public static void DownloadUpdate() - { - if (MacroDeck.StartParameters.PortableMode) - { - return; - } - _downloading = true; - using var webClient = new WebClient(); - webClient.DownloadProgressChanged += WebClient_DownloadProgressChanged; - webClient.DownloadFileCompleted += WebClient_DownloadComplete; - webClient.DownloadFileAsync(new Uri("https://macrodeck.org/files/installer/" + _jsonObject["filename"]), Path.Combine(ApplicationPaths.TempDirectoryPath, _jsonObject["filename"].ToString())); - } - - - private static void WebClient_DownloadComplete(object sender, AsyncCompletedEventArgs e) - { - _downloading = false; - try - { - if (!File.Exists(Path.Combine(ApplicationPaths.TempDirectoryPath, _jsonObject["filename"].ToString()))) - { - using (var msgBox = new MessageBox()) - { - msgBox.ShowDialog(LanguageManager.Strings.Error, LanguageManager.Strings.FileNotFound, MessageBoxButtons.OK); - } - - OnError?.Invoke(null, EventArgs.Empty); - return; - } - - using (var stream = File.OpenRead(Path.Combine(ApplicationPaths.TempDirectoryPath, _jsonObject["filename"].ToString()))) - { - using (var md5 = MD5.Create()) - { - var hash = md5.ComputeHash(stream); - var checksumString = BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); - if (!checksumString.Equals(_jsonObject["md5"].ToString())) - { - using (var msgBox = new MessageBox()) - { - msgBox.ShowDialog(LanguageManager.Strings.Error, LanguageManager.Strings.MD5NotValid, MessageBoxButtons.OK); - } - - OnError?.Invoke(null, EventArgs.Empty); - return; - } - } - } - - var p = new Process - { - StartInfo = new ProcessStartInfo(Path.Combine(ApplicationPaths.TempDirectoryPath, _jsonObject["filename"].ToString())) - { - UseShellExecute = true - } - }; - p.Start(); - Environment.Exit(0); - } - catch - { - OnError?.Invoke(null, EventArgs.Empty); - using var msgBox = new MessageBox(); - msgBox.ShowDialog(LanguageManager.Strings.Error, LanguageManager.Strings.TryAgainOrDownloadManually, MessageBoxButtons.OK); - } - } - - public static void WebClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) - { - _progressPercentage = e.ProgressPercentage; - OnProgressChanged?.Invoke(sender, new ProgressChangedEventArgs { ProgressPercentage = e.ProgressPercentage }); - } - - -} \ No newline at end of file diff --git a/MacroDeck/Utils/FileDownloader.cs b/MacroDeck/Utils/FileDownloader.cs new file mode 100644 index 00000000..c982a5ab --- /dev/null +++ b/MacroDeck/Utils/FileDownloader.cs @@ -0,0 +1,62 @@ +using System.Diagnostics; +using System.IO; +using System.Net.Http; +using System.Threading; +using SuchByte.MacroDeck.DataTypes.FileDownloader; + +namespace SuchByte.MacroDeck.Utils; + +public class FileDownloader +{ + public static async Task DownloadFileAsync(string url, + string destinationFileName, + IProgress? progress = null, + CancellationToken? cancellationToken = null) + { + if (File.Exists(destinationFileName)) + { + File.Delete(destinationFileName); + } + + using var httpClient = new HttpClient(); + using var response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); + response.EnsureSuccessStatusCode(); + + await using Stream contentStream = await response.Content.ReadAsStreamAsync(), + fileStream = new FileStream(destinationFileName, + FileMode.Create, + FileAccess.Write, + FileShare.None, + 8192, + true); + var totalBytes = response.Content.Headers.ContentLength ?? -1L; + var bytesDownloaded = 0L; + var buffer = new byte[8192]; + int bytesRead; + + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + while ((bytesRead = await contentStream.ReadAsync(buffer)) != 0 + && cancellationToken?.IsCancellationRequested != true) + { + await fileStream.WriteAsync(buffer.AsMemory(0, bytesRead)); + bytesDownloaded += bytesRead; + + if (progress == null || totalBytes == -1) + { + continue; + } + + var downloadSpeed = bytesDownloaded / stopwatch.Elapsed.TotalSeconds; + progress.Report(new DownloadProgressInfo + { + TotalBytes = totalBytes, + DownloadedBytes = bytesDownloaded, + DownloadSpeed = downloadSpeed, + Percentage = (int)Math.Round((double)bytesDownloaded / totalBytes * 100) + }); + } + stopwatch.Stop(); + } +} \ No newline at end of file