From 6e4db4acea18c65b55ca58e97c617333d118534a Mon Sep 17 00:00:00 2001
From: chylex <contact@chylex.com>
Date: Thu, 26 Jan 2017 15:35:40 +0100
Subject: [PATCH] Rewrite custom CSS injection and automatically inject it
 while typing

---
 Core/Bridge/TweetDeckBridge.cs                   | 12 ------------
 Core/FormBrowser.cs                              |  7 +++++++
 Core/Other/FormSettings.cs                       |  2 +-
 .../Dialogs/DialogSettingsCSS.Designer.cs        | 11 ++++++++++-
 Core/Other/Settings/Dialogs/DialogSettingsCSS.cs | 16 +++++++++++++++-
 Core/Other/Settings/TabSettingsAdvanced.cs       | 16 ++++++----------
 Resources/Scripts/code.js                        | 14 ++++++++------
 7 files changed, 47 insertions(+), 31 deletions(-)

diff --git a/Core/Bridge/TweetDeckBridge.cs b/Core/Bridge/TweetDeckBridge.cs
index e863da5d..b132b5b7 100644
--- a/Core/Bridge/TweetDeckBridge.cs
+++ b/Core/Bridge/TweetDeckBridge.cs
@@ -39,18 +39,6 @@ public bool ExpandLinksOnHover{
             }
         }
 
-        public bool HasCustomBrowserCSS{
-            get{
-                return !string.IsNullOrEmpty(Program.UserConfig.CustomBrowserCSS);
-            }
-        }
-
-        public string CustomBrowserCSS{
-            get{
-                return Program.UserConfig.CustomBrowserCSS;
-            }
-        }
-
         public TweetDeckBridge(FormBrowser form, FormNotification notification){
             this.form = form;
             this.notification = notification;
diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs
index ecc76acf..0dc81856 100644
--- a/Core/FormBrowser.cs
+++ b/Core/FormBrowser.cs
@@ -142,6 +142,7 @@ private void Browser_LoadingStateChanged(object sender, LoadingStateChangedEvent
         private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
             if (e.Frame.IsMain && BrowserUtils.IsTweetDeckWebsite(e.Frame)){
                 ScriptLoader.ExecuteFile(e.Frame, "code.js");
+                ReinjectCustomCSS(Config.CustomBrowserCSS);
 
                 #if DEBUG
                 ScriptLoader.ExecuteFile(e.Frame, "debug.js");
@@ -280,6 +281,12 @@ public void ResumeNotification(){
             notification.ResumeNotification();
         }
 
+        // javascript calls
+
+        public void ReinjectCustomCSS(string css){
+            browser.ExecuteScriptAsync("TDGF_reinjectCustomCSS", css == null ? string.Empty : css.Replace(Environment.NewLine, " "));
+        }
+
         // callback handlers
 
         public void OpenSettings(){
diff --git a/Core/Other/FormSettings.cs b/Core/Other/FormSettings.cs
index e7cb7474..5c3f66ec 100644
--- a/Core/Other/FormSettings.cs
+++ b/Core/Other/FormSettings.cs
@@ -24,7 +24,7 @@ public FormSettings(FormBrowser browser, PluginManager plugins, UpdateHandler up
             this.tabPanel.AddButton("General", SelectTab<TabSettingsGeneral>);
             this.tabPanel.AddButton("Notifications", () => SelectTab(() => new TabSettingsNotifications(browser.CreateNotificationForm(NotificationFlags.DisableContextMenu))));
             this.tabPanel.AddButton("Updates", () => SelectTab(() => new TabSettingsUpdates(updates)));
-            this.tabPanel.AddButton("Advanced", () => SelectTab(() => new TabSettingsAdvanced(browser.ReloadBrowser, plugins)));
+            this.tabPanel.AddButton("Advanced", () => SelectTab(() => new TabSettingsAdvanced(browser.ReinjectCustomCSS, plugins)));
             this.tabPanel.SelectTab(tabPanel.Buttons.First());
         }
 
diff --git a/Core/Other/Settings/Dialogs/DialogSettingsCSS.Designer.cs b/Core/Other/Settings/Dialogs/DialogSettingsCSS.Designer.cs
index bdd2eaf9..fbdba942 100644
--- a/Core/Other/Settings/Dialogs/DialogSettingsCSS.Designer.cs
+++ b/Core/Other/Settings/Dialogs/DialogSettingsCSS.Designer.cs
@@ -23,6 +23,7 @@ protected override void Dispose(bool disposing) {
         /// the contents of this method with the code editor.
         /// </summary>
         private void InitializeComponent() {
+            this.components = new System.ComponentModel.Container();
             this.textBoxBrowserCSS = new System.Windows.Forms.TextBox();
             this.btnCancel = new System.Windows.Forms.Button();
             this.btnApply = new System.Windows.Forms.Button();
@@ -32,6 +33,7 @@ private void InitializeComponent() {
             this.textBoxNotificationCSS = new System.Windows.Forms.TextBox();
             this.labelWarning = new System.Windows.Forms.Label();
             this.btnOpenWiki = new System.Windows.Forms.Button();
+            this.timerTestBrowser = new System.Windows.Forms.Timer(this.components);
             ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
             this.splitContainer.Panel1.SuspendLayout();
             this.splitContainer.Panel2.SuspendLayout();
@@ -52,6 +54,7 @@ private void InitializeComponent() {
             this.textBoxBrowserCSS.Size = new System.Drawing.Size(373, 253);
             this.textBoxBrowserCSS.TabIndex = 0;
             this.textBoxBrowserCSS.WordWrap = false;
+            this.textBoxBrowserCSS.KeyUp += new System.Windows.Forms.KeyEventHandler(this.textBoxBrowserCSS_KeyUp);
             // 
             // btnCancel
             // 
@@ -132,7 +135,7 @@ private void InitializeComponent() {
             this.textBoxNotificationCSS.Multiline = true;
             this.textBoxNotificationCSS.Name = "textBoxNotificationCSS";
             this.textBoxNotificationCSS.ScrollBars = System.Windows.Forms.ScrollBars.Both;
-            this.textBoxNotificationCSS.Size = new System.Drawing.Size(376, 253);
+            this.textBoxNotificationCSS.Size = new System.Drawing.Size(373, 253);
             this.textBoxNotificationCSS.TabIndex = 1;
             this.textBoxNotificationCSS.WordWrap = false;
             // 
@@ -159,6 +162,11 @@ private void InitializeComponent() {
             this.btnOpenWiki.UseVisualStyleBackColor = true;
             this.btnOpenWiki.Click += new System.EventHandler(this.btnOpenWiki_Click);
             // 
+            // timerTestBrowser
+            // 
+            this.timerTestBrowser.Interval = 500;
+            this.timerTestBrowser.Tick += new System.EventHandler(this.timerTestBrowser_Tick);
+            // 
             // DialogSettingsCSS
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -195,5 +203,6 @@ private void InitializeComponent() {
         private System.Windows.Forms.Label labelNotification;
         private System.Windows.Forms.Label labelWarning;
         private System.Windows.Forms.Button btnOpenWiki;
+        private System.Windows.Forms.Timer timerTestBrowser;
     }
 }
\ No newline at end of file
diff --git a/Core/Other/Settings/Dialogs/DialogSettingsCSS.cs b/Core/Other/Settings/Dialogs/DialogSettingsCSS.cs
index ee65187c..8b71e24c 100644
--- a/Core/Other/Settings/Dialogs/DialogSettingsCSS.cs
+++ b/Core/Other/Settings/Dialogs/DialogSettingsCSS.cs
@@ -17,10 +17,14 @@ public string NotificationCSS{
             }
         }
 
-        public DialogSettingsCSS(){
+        private readonly Action<string> reinjectBrowserCSS;
+
+        public DialogSettingsCSS(Action<string> reinjectBrowserCSS){
             InitializeComponent();
             
             Text = Program.BrandName+" Settings - CSS";
+
+            this.reinjectBrowserCSS = reinjectBrowserCSS;
             
             textBoxBrowserCSS.EnableMultilineShortcuts();
             textBoxBrowserCSS.Text = Program.UserConfig.CustomBrowserCSS ?? "";
@@ -29,6 +33,16 @@ public DialogSettingsCSS(){
             textBoxNotificationCSS.Text = Program.UserConfig.CustomNotificationCSS ?? "";
         }
 
+        private void textBoxBrowserCSS_KeyUp(object sender, KeyEventArgs e){
+            timerTestBrowser.Stop();
+            timerTestBrowser.Start();
+        }
+
+        private void timerTestBrowser_Tick(object sender, EventArgs e){
+            reinjectBrowserCSS(textBoxBrowserCSS.Text);
+            timerTestBrowser.Stop();
+        }
+
         private void btnOpenWiki_Click(object sender, EventArgs e){
             BrowserUtils.OpenExternalBrowser("https://github.com/chylex/TweetDuck/wiki");
         }
diff --git a/Core/Other/Settings/TabSettingsAdvanced.cs b/Core/Other/Settings/TabSettingsAdvanced.cs
index 3371ae9c..0bc3f5b2 100644
--- a/Core/Other/Settings/TabSettingsAdvanced.cs
+++ b/Core/Other/Settings/TabSettingsAdvanced.cs
@@ -9,13 +9,13 @@
 
 namespace TweetDck.Core.Other.Settings{
     partial class TabSettingsAdvanced : BaseTabSettings{
-        private readonly Action browserReloadAction;
+        private readonly Action<string> reinjectBrowserCSS;
         private readonly PluginManager plugins;
 
-        public TabSettingsAdvanced(Action browserReloadAction, PluginManager plugins){
+        public TabSettingsAdvanced(Action<string> reinjectBrowserCSS, PluginManager plugins){
             InitializeComponent();
 
-            this.browserReloadAction = browserReloadAction;
+            this.reinjectBrowserCSS = reinjectBrowserCSS;
             this.plugins = plugins;
 
             checkHardwareAcceleration.Checked = HardwareAcceleration.IsEnabled;
@@ -80,17 +80,13 @@ private void btnEditCefArgs_Click(object sender, EventArgs e){
         }
 
         private void btnEditCSS_Click(object sender, EventArgs e){
-            using(DialogSettingsCSS form = new DialogSettingsCSS()){
+            using(DialogSettingsCSS form = new DialogSettingsCSS(reinjectBrowserCSS)){
                 if (form.ShowDialog(ParentForm) == DialogResult.OK){
-                    bool hasChangedBrowser = form.BrowserCSS != Config.CustomBrowserCSS;
-
                     Config.CustomBrowserCSS = form.BrowserCSS;
                     Config.CustomNotificationCSS = form.NotificationCSS;
-
-                    if (hasChangedBrowser && MessageBox.Show("The browser CSS has changed, do you want to reload it?", "Browser CSS Changed", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes){
-                        browserReloadAction();
-                    }
                 }
+
+                reinjectBrowserCSS(Config.CustomBrowserCSS); // reinject on cancel too, because the CSS is updated while typing
             }
         }
 
diff --git a/Resources/Scripts/code.js b/Resources/Scripts/code.js
index ac7be5e1..a76d5ebf 100644
--- a/Resources/Scripts/code.js
+++ b/Resources/Scripts/code.js
@@ -544,12 +544,14 @@
     styleOfficial.sheet.insertRule(".txt-base-smallest .badge-verified:before { height: 13px !important; }", 0); // fix cut off badge icon
     styleOfficial.sheet.insertRule(".keyboard-shortcut-list { vertical-align: top; }", 0); // fix keyboard navigation alignment
     
-    if ($TD.hasCustomBrowserCSS){
-      var styleCustom = document.createElement("style");
-      styleCustom.innerHTML = $TD.customBrowserCSS;
-      document.head.appendChild(styleCustom);
-    }
-    
     TD.services.TwitterActionRetweetedRetweet.prototype.iconClass = "icon-retweet icon-retweet-color txt-base-medium"; // fix retweet icon mismatch
+    
+    window.TDGF_reinjectCustomCSS = function(styles){
+      $("#tweetduck-custom-css").remove();
+      
+      if (styles && styles.length){
+        $(document.head).append("<style type='text/css' id='tweetduck-custom-css'>"+styles+"</style>");
+      }
+    };
   })();
 })($, $TD, TD);