diff --git a/Configuration/UserConfig.cs b/Configuration/UserConfig.cs index f1394bb9..14f34893 100644 --- a/Configuration/UserConfig.cs +++ b/Configuration/UserConfig.cs @@ -32,6 +32,9 @@ sealed class UserConfig{ public int NotificationEdgeDistance { get; set; } public int NotificationDisplay { get; set; } + public bool EnableUpdateCheck { get; set; } + public string DismissedUpdate { get; set; } + public bool IsCustomWindowLocationSet{ get{ return WindowLocation.X != -32000 && WindowLocation.X != 32000; @@ -61,6 +64,7 @@ private UserConfig(string file){ NotificationPosition = TweetNotification.Position.TopRight; CustomNotificationPosition = new Point(-32000,-32000); NotificationEdgeDistance = 8; + EnableUpdateCheck = true; } private void UpgradeFile(){ @@ -71,6 +75,7 @@ private void UpgradeFile(){ // if outdated, cycle through all versions if (fileVersion == 0){ DisplayNotificationTimer = true; + EnableUpdateCheck = true; ++fileVersion; } diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs index 7b7e8905..d0fa35df 100644 --- a/Core/FormBrowser.cs +++ b/Core/FormBrowser.cs @@ -145,8 +145,21 @@ public void OpenSettings(){ currentFormSettings.BringToFront(); } else{ + bool prevEnableUpdateCheck = Config.EnableUpdateCheck; + currentFormSettings = new FormSettings(this); - currentFormSettings.FormClosed += (sender, args) => currentFormSettings = null; + + currentFormSettings.FormClosed += (sender, args) => { + currentFormSettings = null; + + if (!prevEnableUpdateCheck && Config.EnableUpdateCheck){ + Config.DismissedUpdate = string.Empty; + Config.Save(); + + browser.ExecuteScriptAsync("TDGF_runUpdateCheck",new object[0]); + } + }; + ShowChildForm(currentFormSettings); } } diff --git a/Core/Handling/TweetDeckBridge.cs b/Core/Handling/TweetDeckBridge.cs index 2d3b80d0..df2d9bc2 100644 --- a/Core/Handling/TweetDeckBridge.cs +++ b/Core/Handling/TweetDeckBridge.cs @@ -10,6 +10,24 @@ public string BrandName{ } } + public string VersionTag{ + get{ + return Program.VersionTag; + } + } + + public bool UpdateCheckEnabled{ + get{ + return Program.UserConfig.EnableUpdateCheck; + } + } + + public string DismissedVersionTag{ + get{ + return Program.UserConfig.DismissedUpdate ?? string.Empty; + } + } + public TweetDeckBridge(FormBrowser form){ this.form = form; } @@ -38,6 +56,18 @@ public void OnTweetPopup(string tweetHtml, int tweetCharacters){ }); } + public void OnUpdateAccepted(string versionTag, string downloadUrl){ + form.InvokeSafe(() => { + }); + } + + public void OnUpdateDismissed(string versionTag){ + form.InvokeSafe(() => { + Program.UserConfig.DismissedUpdate = versionTag; + Program.UserConfig.Save(); + }); + } + public void OpenBrowser(string url){ BrowserUtils.OpenExternalBrowser(url); } diff --git a/Core/Other/FormSettings.Designer.cs b/Core/Other/FormSettings.Designer.cs index 66579134..71cc1f24 100644 --- a/Core/Other/FormSettings.Designer.cs +++ b/Core/Other/FormSettings.Designer.cs @@ -36,13 +36,14 @@ private void InitializeComponent() { this.tableLayout = new System.Windows.Forms.TableLayoutPanel(); this.tableColumn2Panel = new System.Windows.Forms.Panel(); this.groupUserInterface = new System.Windows.Forms.GroupBox(); + this.checkNotificationTimer = new System.Windows.Forms.CheckBox(); this.checkMinimizeTray = new System.Windows.Forms.CheckBox(); this.groupNotificationDuration = new System.Windows.Forms.GroupBox(); - this.checkNotificationTimer = new System.Windows.Forms.CheckBox(); this.radioDurVeryLong = new System.Windows.Forms.RadioButton(); this.radioDurLong = new System.Windows.Forms.RadioButton(); this.radioDurMedium = new System.Windows.Forms.RadioButton(); this.radioDurShort = new System.Windows.Forms.RadioButton(); + this.checkUpdateNotifications = new System.Windows.Forms.CheckBox(); this.groupNotificationLocation.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.trackBarEdgeDistance)).BeginInit(); this.tableLayout.SuspendLayout(); @@ -218,6 +219,7 @@ private void InitializeComponent() { // this.groupUserInterface.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); + this.groupUserInterface.Controls.Add(this.checkUpdateNotifications); this.groupUserInterface.Controls.Add(this.checkNotificationTimer); this.groupUserInterface.Controls.Add(this.checkMinimizeTray); this.groupUserInterface.Location = new System.Drawing.Point(3, 128); @@ -227,6 +229,17 @@ private void InitializeComponent() { this.groupUserInterface.TabStop = false; this.groupUserInterface.Text = "User Interface"; // + // checkNotificationTimer + // + this.checkNotificationTimer.AutoSize = true; + this.checkNotificationTimer.Location = new System.Drawing.Point(6, 43); + this.checkNotificationTimer.Name = "checkNotificationTimer"; + this.checkNotificationTimer.Size = new System.Drawing.Size(145, 17); + this.checkNotificationTimer.TabIndex = 4; + this.checkNotificationTimer.Text = "Display Notification Timer"; + this.checkNotificationTimer.UseVisualStyleBackColor = true; + this.checkNotificationTimer.CheckedChanged += new System.EventHandler(this.checkNotificationTimer_CheckedChanged); + // // checkMinimizeTray // this.checkMinimizeTray.AutoSize = true; @@ -253,17 +266,6 @@ private void InitializeComponent() { this.groupNotificationDuration.TabStop = false; this.groupNotificationDuration.Text = "Notification Duration"; // - // checkNotificationTimer - // - this.checkNotificationTimer.AutoSize = true; - this.checkNotificationTimer.Location = new System.Drawing.Point(6, 43); - this.checkNotificationTimer.Name = "checkNotificationTimer"; - this.checkNotificationTimer.Size = new System.Drawing.Size(145, 17); - this.checkNotificationTimer.TabIndex = 4; - this.checkNotificationTimer.Text = "Display Notification Timer"; - this.checkNotificationTimer.UseVisualStyleBackColor = true; - this.checkNotificationTimer.CheckedChanged += new System.EventHandler(this.checkNotificationTimer_CheckedChanged); - // // radioDurVeryLong // this.radioDurVeryLong.AutoSize = true; @@ -316,6 +318,17 @@ private void InitializeComponent() { this.radioDurShort.CheckedChanged += new System.EventHandler(this.radioDur_CheckedChanged); this.radioDurShort.Click += new System.EventHandler(this.radioDur_Click); // + // checkUpdateNotifications + // + this.checkUpdateNotifications.AutoSize = true; + this.checkUpdateNotifications.Location = new System.Drawing.Point(6, 67); + this.checkUpdateNotifications.Name = "checkUpdateNotifications"; + this.checkUpdateNotifications.Size = new System.Drawing.Size(122, 17); + this.checkUpdateNotifications.TabIndex = 5; + this.checkUpdateNotifications.Text = "Update Notifications"; + this.checkUpdateNotifications.UseVisualStyleBackColor = true; + this.checkUpdateNotifications.CheckedChanged += new System.EventHandler(this.checkUpdateNotifications_CheckedChanged); + // // FormSettings // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -364,5 +377,6 @@ private void InitializeComponent() { private System.Windows.Forms.RadioButton radioDurShort; private System.Windows.Forms.CheckBox checkMinimizeTray; private System.Windows.Forms.CheckBox checkNotificationTimer; + private System.Windows.Forms.CheckBox checkUpdateNotifications; } } \ No newline at end of file diff --git a/Core/Other/FormSettings.cs b/Core/Other/FormSettings.cs index 6b638fad..de31362d 100644 --- a/Core/Other/FormSettings.cs +++ b/Core/Other/FormSettings.cs @@ -56,6 +56,7 @@ public FormSettings(FormBrowser browserForm){ trackBarEdgeDistance.Value = Config.NotificationEdgeDistance; checkMinimizeTray.Checked = Config.MinimizeToTray; checkNotificationTimer.Checked = Config.DisplayNotificationTimer; + checkUpdateNotifications.Checked = Config.EnableUpdateCheck; } private void FormSettings_FormClosing(object sender, FormClosingEventArgs e){ @@ -130,5 +131,11 @@ private void checkNotificationTimer_CheckedChanged(object sender, EventArgs e){ Config.DisplayNotificationTimer = checkNotificationTimer.Checked; notification.ShowNotificationForSettings(true); } + + private void checkUpdateNotifications_CheckedChanged(object sender, EventArgs e){ + if (!isLoaded)return; + + Config.EnableUpdateCheck = checkUpdateNotifications.Checked; + } } } diff --git a/Program.cs b/Program.cs index 284bbd2e..66904f40 100644 --- a/Program.cs +++ b/Program.cs @@ -22,6 +22,8 @@ static class Program{ public const string Website = "http://tweetdick.chylex.com"; #endif + public const string VersionTag = "1.1"; + public static readonly string StoragePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),BrandName); private static readonly LockManager LockManager = new LockManager(Path.Combine(StoragePath,".lock")); diff --git a/Resources/code.js b/Resources/code.js index 48232ebb..6583dad6 100644 --- a/Resources/code.js +++ b/Resources/code.js @@ -14,6 +14,11 @@ // var prevFontSizeClass; + // + // Variable: Current timeout ID for update checking. + // + var updateCheckTimeoutID; + // // Function: Initializes TweetD*ck events. Called after the website app is loaded. // @@ -66,6 +71,9 @@ return true; }; + // Run update check + runUpdateCheck(); + // Finish init isInitialized = true; }; @@ -157,6 +165,115 @@ return tags.join(""); }; + // + // Function: Creates the update notification element. Removes the old one if already exists. + // + var createUpdateNotificationElement = function(version, download){ + var ele = $("#tweetdck-update"); + var existed = ele.length > 0; + + if (existed > 0){ + ele.remove(); + } + + var html = [ + "<div id='tweetdck-update'>", + "<p class='tdu-title'>"+$TD.brandName+" Update</p>", + "<p class='tdu-info'>Version "+version+" is now available.</p>", + "<div class='tdu-buttons'>", + "<button class='btn btn-positive tdu-btn-download'><span class='label'>Download</button>", + "<button class='btn btn-negative tdu-btn-dismiss'><span class='label'>Dismiss</button>", + "</div>", + "</div>" + ]; + + $("h1.app-title").after(html.join("")); + + ele = $("#tweetdck-update"); + + var buttonDiv = ele.children("div.tdu-buttons").first(); + + ele.css({ + color: "#fff", + backgroundColor: "rgb(32,94,138)", + position: "absolute", + left: "4px", + bottom: "4px", + width: "192px", + height: "86px", + display: existed ? "block" : "none", + borderRadius: "2px" + }); + + ele.children("p.tdu-title").first().css({ + fontSize: "17px", + fontWeight: "bold", + textAlign: "center", + letterSpacing: "0.2px", + margin: "4px auto 2px" + }); + + ele.children("p.tdu-info").first().css({ + fontSize: "12px", + textAlign: "center", + margin: "2px auto 6px" + }); + + buttonDiv.css({ + textAlign: "center" + }); + + buttonDiv.children().css({ + margin: "0 4px", + minHeight: "25px", + boxShadow: "1px 1px 1px rgba(17,17,17,0.5)" + }); + + buttonDiv.find("span").css({ + verticalAlign: "baseline" + }); + + ele.find("span.tdu-data-tag").first().css({ + cursor: "pointer", + textDecoration: "underline" + }); + + buttonDiv.children(".tdu-btn-download").click(function(){ + $TD.onUpdateAccepted(version,download); + ele.slideUp(function(){ ele.remove(); }); + }); + + buttonDiv.children(".tdu-btn-dismiss").click(function(){ + $TD.onUpdateDismissed(version); + ele.slideUp(function(){ ele.remove(); }); + }); + + if (!existed){ + ele.slideDown(); + } + + return ele; + }; + + // + // Function: Runs an update check and updates all DOM elements appropriately + // + var runUpdateCheck = function(){ + clearTimeout(updateCheckTimeoutID); + updateCheckTimeoutID = setTimeout(runUpdateCheck,1000*60*60); // 1 hour + + if (!$TD.updateCheckEnabled)return; + + $.getJSON("https://api.github.com/repos/chylex/"+$TD.brandName+"/releases/latest",function(response){ + var tagName = response.tag_name; + + if (tagName != $TD.versionTag && tagName != $TD.dismissedVersionTag){ + var dlLink = "https://github.com/chylex/"+$TD.brandName+"/releases/download/"+tagName+"/"+response.assets[0].name; + createUpdateNotificationElement(tagName,dlLink); + } + }); + }; + // // Block: Observe the app <div> element and initialize TweetD*ck whenever possible. // @@ -245,4 +362,9 @@ e.preventDefault(); } }); + + // + // Block: Setup global functions. + // + window.TDGF_runUpdateCheck = runUpdateCheck; })($,$TD);