diff --git a/Resources/Plugins/.debug/browser.js b/Resources/Plugins/.debug/browser.js
index 95ff86a8..0d0b83b3 100644
--- a/Resources/Plugins/.debug/browser.js
+++ b/Resources/Plugins/.debug/browser.js
@@ -1,67 +1,67 @@
 enabled(){
-  this.isDebugging = false;
-  
-  this.onKeyDown = (e) => {
-    
-    // ==========================
-    // F4 key - toggle debug mode
-    // ==========================
-    
-    if (e.keyCode === 115){
-      this.isDebugging = !this.isDebugging;
-      $(".nav-user-info").first().css("background-color", this.isDebugging ? "#5A6B75" : "#292F33");
-    }
-    
-    else if (this.isDebugging){
-      e.preventDefault();
-      
-      // ===================================
-      // N key - simulate popup notification
-      // S key - simulate sound notification
-      // ===================================
-      
-      if (e.keyCode === 78 || e.keyCode === 83){
-        let col = TD.controller.columnManager.getAllOrdered()[0];
-        let model = col.model;
-        
-        let prevPopup = model.getHasNotification();
-        let prevSound = model.getHasSound();
-        
-        model.setHasNotification(e.keyCode === 78);
-        model.setHasSound(e.keyCode === 83);
-        
-        $.publish("/notifications/new", [{
-          column: col,
-          items: [
-            col.updateArray[Math.floor(Math.random()*col.updateArray.length)]
-          ]
-        }]);
-        
-        setTimeout(function(){
-          model.setHasNotification(prevPopup);
-          model.setHasSound(prevSound);
-        }, 1);
-      }
-      
-      // ========================
-      // D key - trigger debugger
-      // ========================
-      
-      else if (e.keyCode === 68){
-        debugger;
-      }
-    }
-  };
+	this.isDebugging = false;
+	
+	this.onKeyDown = (e) => {
+		
+		// ==========================
+		// F4 key - toggle debug mode
+		// ==========================
+		
+		if (e.keyCode === 115) {
+			this.isDebugging = !this.isDebugging;
+			$(".nav-user-info").first().css("background-color", this.isDebugging ? "#5a6b75" : "#292f33");
+		}
+		
+		else if (this.isDebugging) {
+			e.preventDefault();
+			
+			// ===================================
+			// N key - simulate popup notification
+			// S key - simulate sound notification
+			// ===================================
+			
+			if (e.keyCode === 78 || e.keyCode === 83) {
+				let col = TD.controller.columnManager.getAllOrdered()[0];
+				let model = col.model;
+				
+				let prevPopup = model.getHasNotification();
+				let prevSound = model.getHasSound();
+				
+				model.setHasNotification(e.keyCode === 78);
+				model.setHasSound(e.keyCode === 83);
+				
+				$.publish("/notifications/new", [ {
+					column: col,
+					items: [
+						col.updateArray[Math.floor(Math.random() * col.updateArray.length)]
+					]
+				} ]);
+				
+				setTimeout(function() {
+					model.setHasNotification(prevPopup);
+					model.setHasSound(prevSound);
+				}, 1);
+			}
+				
+				// ========================
+				// D key - trigger debugger
+			// ========================
+			
+			else if (e.keyCode === 68) {
+				debugger;
+			}
+		}
+	};
 }
 
 ready(){
-  $(document).on("keydown", this.onKeyDown);
+	$(document).on("keydown", this.onKeyDown);
 }
 
 disabled(){
-  $(document).off("keydown", this.onKeyDown);
+	$(document).off("keydown", this.onKeyDown);
 }
 
 configure(){
-  alert("Configure triggered");
+	alert("Configure triggered");
 }
diff --git a/Resources/Plugins/.debug/notification.js b/Resources/Plugins/.debug/notification.js
index 6ff1c50a..0fc4367a 100644
--- a/Resources/Plugins/.debug/notification.js
+++ b/Resources/Plugins/.debug/notification.js
@@ -1,3 +1,3 @@
 run(){
-  console.info("executed debug plugin in notification");
+	console.info("executed debug plugin in notification");
 }
diff --git a/Resources/Plugins/clear-columns/browser.js b/Resources/Plugins/clear-columns/browser.js
index 7fb3328e..ecf04d70 100644
--- a/Resources/Plugins/clear-columns/browser.js
+++ b/Resources/Plugins/clear-columns/browser.js
@@ -1,173 +1,173 @@
 enabled(){
-  const clearColumn = (columnName) => {
-    TD.controller.columnManager.get(columnName).clear();
-    TD.controller.stats.columnActionClick("clear");
-  };
-  
-  const resetColumn = (columnName) => {
-    let col = TD.controller.columnManager.get(columnName);
-    col.model.setClearedTimestamp(0);
-    col.reloadTweets();
-  };
-  
-  const forEachColumn = (func) => {
-    Object.keys(TD.controller.columnManager.getAll()).forEach(func);
-  };
-  
-  let wasShiftPressed = false;
-  
-  const updateShiftState = (pressed) => {
-    if (pressed != wasShiftPressed){
-      wasShiftPressed = pressed;
-      
-      if (pressed){
-        $(document).on("mousemove", this.eventKeyUp);
-      }
-      else{
-        $(document).off("mousemove", this.eventKeyUp);
-      }
-      
-      $(".clear-columns-btn-all").text(pressed ? "Restore columns" : "Clear columns");
-    }
-  };
-  
-  // event handlers
-  
-  this.eventClickOneCapture = function(e){
-    if (e.target.getAttribute("data-action") === "td-clearcolumns-dosingle"){
-      let name = $(e.target).closest(".js-column").attr("data-column");
-      e.shiftKey ? resetColumn(name) : clearColumn(name);
-      
-      e.preventDefault();
-      e.stopPropagation();
-      e.stopImmediatePropagation();
-    }
-  };
-  
-  this.eventClickAll = function(e){
-    forEachColumn(e.shiftKey ? resetColumn : clearColumn);
-  };
-  
-  this.eventKeyDown = function(e){
-    if (!(document.activeElement === null || document.activeElement === document.body)) {
-      return;
-    }
-    
-    updateShiftState(e.shiftKey);
-    
-    if (e.keyCode === 46){ // 46 = delete
-      if (e.altKey){
-        forEachColumn(e.shiftKey ? resetColumn : clearColumn);
-      }
-      else{
-        let focusedColumn = $(".js-column.is-focused");
-        
-        if (focusedColumn.length){
-          let name = focusedColumn.attr("data-column");
-          e.shiftKey ? resetColumn(name) : clearColumn(name);
-        }
-      }
-    }
-  };
-  
-  this.eventKeyUp = function(e){
-    if (!e.shiftKey){
-      updateShiftState(false);
-    }
-  };
-  
-  this.eventKeyboardShortcuts = function(e){
-    $(".keyboard-shortcut-list").first().append(`
+	const clearColumn = (columnName) => {
+		TD.controller.columnManager.get(columnName).clear();
+		TD.controller.stats.columnActionClick("clear");
+	};
+	
+	const resetColumn = (columnName) => {
+		let col = TD.controller.columnManager.get(columnName);
+		col.model.setClearedTimestamp(0);
+		col.reloadTweets();
+	};
+	
+	const forEachColumn = (func) => {
+		Object.keys(TD.controller.columnManager.getAll()).forEach(func);
+	};
+	
+	let wasShiftPressed = false;
+	
+	const updateShiftState = (pressed) => {
+		if (pressed != wasShiftPressed) {
+			wasShiftPressed = pressed;
+			
+			if (pressed) {
+				$(document).on("mousemove", this.eventKeyUp);
+			}
+			else {
+				$(document).off("mousemove", this.eventKeyUp);
+			}
+			
+			$(".clear-columns-btn-all").text(pressed ? "Restore columns" : "Clear columns");
+		}
+	};
+	
+	// event handlers
+	
+	this.eventClickOneCapture = function(e) {
+		if (e.target.getAttribute("data-action") === "td-clearcolumns-dosingle") {
+			let name = $(e.target).closest(".js-column").attr("data-column");
+			e.shiftKey ? resetColumn(name) : clearColumn(name);
+			
+			e.preventDefault();
+			e.stopPropagation();
+			e.stopImmediatePropagation();
+		}
+	};
+	
+	this.eventClickAll = function(e) {
+		forEachColumn(e.shiftKey ? resetColumn : clearColumn);
+	};
+	
+	this.eventKeyDown = function(e) {
+		if (!(document.activeElement === null || document.activeElement === document.body)) {
+			return;
+		}
+		
+		updateShiftState(e.shiftKey);
+		
+		if (e.keyCode === 46) { // 46 = delete
+			if (e.altKey) {
+				forEachColumn(e.shiftKey ? resetColumn : clearColumn);
+			}
+			else {
+				let focusedColumn = $(".js-column.is-focused");
+				
+				if (focusedColumn.length) {
+					let name = focusedColumn.attr("data-column");
+					e.shiftKey ? resetColumn(name) : clearColumn(name);
+				}
+			}
+		}
+	};
+	
+	this.eventKeyUp = function(e) {
+		if (!e.shiftKey) {
+			updateShiftState(false);
+		}
+	};
+	
+	this.eventKeyboardShortcuts = function(e) {
+		$(".keyboard-shortcut-list").first().append(`
 <dd class="keyboard-shortcut-definition" style="white-space:nowrap">
   <span class="text-like-keyboard-key">1</span> … <span class="text-like-keyboard-key">9</span> + <span class="text-like-keyboard-key">Del</span> Clear column 1-9
 </dd>
 <dd class="keyboard-shortcut-definition">
   <span class="text-like-keyboard-key">Alt</span> + <span class="text-like-keyboard-key">Del</span> Clear all columns
 </dd>`);
-  };
-  
-  // update UI
-  
-  this.btnClearAllHTML = `
+	};
+	
+	// update UI
+	
+	this.btnClearAllHTML = `
 <a class="clear-columns-btn-all-parent js-header-action link-clean cf app-nav-link padding-h--16 padding-v--2" data-title="Clear columns (hold Shift to restore)" data-action="td-clearcolumns-doall">
   <div class="obj-left margin-l--2"><i class="icon icon-medium icon-clear-timeline"></i></div>
   <div class="clear-columns-btn-all nbfc padding-ts hide-condensed txt-size--14 app-nav-link-text">Clear columns</div>
 </a>`;
-  
-  this.btnClearOneHTML = `
+	
+	this.btnClearOneHTML = `
 <a class="js-action-header-button column-header-link" href="#" data-action="td-clearcolumns-dosingle">
   <i class="icon icon-clear-timeline js-show-tip" data-placement="bottom" data-original-title="Clear column (hold Shift to restore)" data-action="td-clearcolumns-dosingle"></i>
 </a>`;
-  
-  this.prevNavMenuMustache = TD.mustaches["menus/column_nav_menu.mustache"];
-  window.TDPF_injectMustache("menus/column_nav_menu.mustache", "replace", "{{_i}}Add column{{/i}}</div> </a> </div>", `{{_i}}Add column{{/i}}</div></a>${this.btnClearAllHTML}</div>`);
-  
-  this.prevColumnHeaderMustache = TD.mustaches["column/column_header.mustache"];
-  window.TDPF_injectMustache("column/column_header.mustache", "prepend", "<a data-testid=\"optionsToggle\"", this.btnClearOneHTML);
-  
-  if (TD.ready){
-    $(".js-header-add-column").after(this.btnClearAllHTML);
-    $("a[data-testid='optionsToggle']", ".js-column-header").before(this.btnClearOneHTML);
-  }
-  
-  // styles
-  
-  if (!document.getElementById("td-clearcolumns-workaround")){
-    // TD started caching mustaches so disabling the plugin doesn't update the column headers properly...
-    let workaround = document.createElement("style");
-    workaround.id = "td-clearcolumns-workaround";
-    workaround.innerText = "#tduck a[data-action='td-clearcolumns-dosingle'] { display: none }";
-    document.head.appendChild(workaround);
-  }
-  
-  this.css = window.TDPF_createCustomStyle(this);
-  
-  this.css.insert(".js-app-add-column.is-hidden + .clear-columns-btn-all-parent { display: none; }");
-  this.css.insert(".column-navigator-overflow .clear-columns-btn-all-parent { display: none !important; }");
-  this.css.insert(".column-navigator-overflow { bottom: 224px !important; }");
-  this.css.insert(".app-navigator .clear-columns-btn-all-parent { font-weight: 700; }");
-  
-  this.css.insert(".column-header-links { min-width: 51px !important; }");
-  this.css.insert(".column[data-td-icon='icon-message'] .column-header-links { min-width: 110px !important; }");
-  this.css.insert(".btn-options-tray[data-action='clear'] { display: none !important; }");
-  
-  this.css.insert("#tduck a[data-action='td-clearcolumns-dosingle'] { display: inline-block; }");
-  this.css.insert("#tduck .column[data-td-icon='icon-schedule'] a[data-action='td-clearcolumns-dosingle'] { display: none; }");
-  this.css.insert("#tduck .column[data-td-icon='icon-custom-timeline'] a[data-action='td-clearcolumns-dosingle'] { display: none; }");
+	
+	this.prevNavMenuMustache = TD.mustaches["menus/column_nav_menu.mustache"];
+	window.TDPF_injectMustache("menus/column_nav_menu.mustache", "replace", "{{_i}}Add column{{/i}}</div> </a> </div>", `{{_i}}Add column{{/i}}</div></a>${this.btnClearAllHTML}</div>`);
+	
+	this.prevColumnHeaderMustache = TD.mustaches["column/column_header.mustache"];
+	window.TDPF_injectMustache("column/column_header.mustache", "prepend", "<a data-testid=\"optionsToggle\"", this.btnClearOneHTML);
+	
+	if (TD.ready) {
+		$(".js-header-add-column").after(this.btnClearAllHTML);
+		$("a[data-testid='optionsToggle']", ".js-column-header").before(this.btnClearOneHTML);
+	}
+	
+	// styles
+	
+	if (!document.getElementById("td-clearcolumns-workaround")) {
+		// TD started caching mustaches so disabling the plugin doesn't update the column headers properly...
+		let workaround = document.createElement("style");
+		workaround.id = "td-clearcolumns-workaround";
+		workaround.innerText = "#tduck a[data-action='td-clearcolumns-dosingle'] { display: none }";
+		document.head.appendChild(workaround);
+	}
+	
+	this.css = window.TDPF_createCustomStyle(this);
+	
+	this.css.insert(".js-app-add-column.is-hidden + .clear-columns-btn-all-parent { display: none; }");
+	this.css.insert(".column-navigator-overflow .clear-columns-btn-all-parent { display: none !important; }");
+	this.css.insert(".column-navigator-overflow { bottom: 224px !important; }");
+	this.css.insert(".app-navigator .clear-columns-btn-all-parent { font-weight: 700; }");
+	
+	this.css.insert(".column-header-links { min-width: 51px !important; }");
+	this.css.insert(".column[data-td-icon='icon-message'] .column-header-links { min-width: 110px !important; }");
+	this.css.insert(".btn-options-tray[data-action='clear'] { display: none !important; }");
+	
+	this.css.insert("#tduck a[data-action='td-clearcolumns-dosingle'] { display: inline-block; }");
+	this.css.insert("#tduck .column[data-td-icon='icon-schedule'] a[data-action='td-clearcolumns-dosingle'] { display: none; }");
+	this.css.insert("#tduck .column[data-td-icon='icon-custom-timeline'] a[data-action='td-clearcolumns-dosingle'] { display: none; }");
 }
 
 ready(){
-  document.addEventListener("click", this.eventClickOneCapture, true);
-  $(document).on("click", "[data-action='td-clearcolumns-doall']", this.eventClickAll);
-  $(document).on("keydown", this.eventKeyDown);
-  $(document).on("keyup", this.eventKeyUp);
-  $(document).on("uiShowKeyboardShortcutList", this.eventKeyboardShortcuts);
-  
-  $(".js-app-add-column").first().after(this.btnClearAllHTML);
-  
-  // fix tooltip
-  
-  let tooltipEvents = $._data($(".js-header-action")[0], "events");
-  
-  if (tooltipEvents.mouseover && tooltipEvents.mouseover.length && tooltipEvents.mouseout && tooltipEvents.mouseout.length){
-    $(".clear-columns-btn-all-parent").on({
-      mouseover: tooltipEvents.mouseover[0].handler,
-      mouseout: tooltipEvents.mouseout[0].handler
-    });
-  }
+	document.addEventListener("click", this.eventClickOneCapture, true);
+	$(document).on("click", "[data-action='td-clearcolumns-doall']", this.eventClickAll);
+	$(document).on("keydown", this.eventKeyDown);
+	$(document).on("keyup", this.eventKeyUp);
+	$(document).on("uiShowKeyboardShortcutList", this.eventKeyboardShortcuts);
+	
+	$(".js-app-add-column").first().after(this.btnClearAllHTML);
+	
+	// fix tooltip
+	
+	let tooltipEvents = $._data($(".js-header-action")[0], "events");
+	
+	if (tooltipEvents.mouseover && tooltipEvents.mouseover.length && tooltipEvents.mouseout && tooltipEvents.mouseout.length) {
+		$(".clear-columns-btn-all-parent").on({
+			mouseover: tooltipEvents.mouseover[0].handler,
+			mouseout: tooltipEvents.mouseout[0].handler
+		});
+	}
 }
 
 disabled(){
-  this.css.remove();
-  
-  document.removeEventListener("click", this.eventClickOneCapture);
-  $(document).off("click", "[data-action='td-clearcolumns-doall']", this.eventClickAll);
-  $(document).off("keydown", this.eventKeyDown);
-  $(document).off("keyup", this.eventKeyUp);
-  $(document).off("uiShowKeyboardShortcutList", this.eventKeyboardShortcuts);
-  
-  TD.mustaches["menus/column_nav_menu.mustache"] = this.prevNavMenuMustache;
-  TD.mustaches["column/column_header.mustache"] = this.prevColumnHeaderMustache;
-  
-  $("[data-action^='td-clearcolumns-']").remove();
+	this.css.remove();
+	
+	document.removeEventListener("click", this.eventClickOneCapture);
+	$(document).off("click", "[data-action='td-clearcolumns-doall']", this.eventClickAll);
+	$(document).off("keydown", this.eventKeyDown);
+	$(document).off("keyup", this.eventKeyUp);
+	$(document).off("uiShowKeyboardShortcutList", this.eventKeyboardShortcuts);
+	
+	TD.mustaches["menus/column_nav_menu.mustache"] = this.prevNavMenuMustache;
+	TD.mustaches["column/column_header.mustache"] = this.prevColumnHeaderMustache;
+	
+	$("[data-action^='td-clearcolumns-']").remove();
 }
diff --git a/Resources/Plugins/edit-design/browser.js b/Resources/Plugins/edit-design/browser.js
index 16ec6136..32febc88 100644
--- a/Resources/Plugins/edit-design/browser.js
+++ b/Resources/Plugins/edit-design/browser.js
@@ -1,550 +1,562 @@
 enabled(){
-  // elements & data
-  this.css = null;
-  this.icons = null;
-  this.config = null;
-  
-  this.defaultConfig = {
-    _theme: "light",
-    themeOverride: false,
-    columnWidth: "310px",
-    composerWidth: "default",
-    fontSize: "12px",
-    hideTweetActions: true,
-    moveTweetActionsToRight: true,
-    themeColorTweaks: true,
-    revertIcons: true,
-    showCharacterCount: true,
-    forceArialFont: true,
-    increaseQuoteTextSize: false,
-    smallComposeTextSize: false,
-    optimizeAnimations: true,
-    avatarRadius: 2
-  };
-  
-  const prepareDefaultConfig = () => {
-    this.defaultConfig._theme = TD.settings.getTheme();
-    
-    switch(TD.settings.getColumnWidth()){
-      case "wide": this.defaultConfig.columnWidth = "350px"; break;
-      case "narrow": this.defaultConfig.columnWidth = "270px"; break;
-    }
-    
-    switch(TD.settings.getFontSize()){
-      case "small": this.defaultConfig.fontSize = "13px"; break;
-      case "medium": this.defaultConfig.fontSize = "14px"; break;
-      case "large": this.defaultConfig.fontSize = "15px"; break;
-      case "largest": this.defaultConfig.fontSize = "16px"; break;
-    }
-  };
-  
-  this.firstTimeLoad = null;
-  
-  const me = this;
-  
-  // configuration
-  const configFile = "config.json";
-  
-  this.tmpConfig = null;
-  this.currentStage = 0;
-  
-  this.onStageReady = () => {
-    if (this.currentStage === 0){
-      this.currentStage = 1;
-    }
-    else if (this.tmpConfig !== null){
-      let needsResave = !("_theme" in this.tmpConfig);
-      
-      prepareDefaultConfig();
-      this.config = $.extend(this.defaultConfig, this.tmpConfig);
-      this.tmpConfig = null;
-      this.reinjectAll();
-      
-      if (this.firstTimeLoad || needsResave){
-        $TDP.writeFile(this.$token, configFile, JSON.stringify(this.config));
-      }
-    }
-  };
-  
-  const loadConfigObject = obj => {
-    this.tmpConfig = obj || {};
-    this.firstTimeLoad = obj === null;
-    
-    this.onStageReady();
-  };
-  
-  if (TD.ready){
-    this.onStageReady();
-  }
-  else{
-    $(document).one("dataSettingsValues", () => this.onStageReady());
-  }
-  
-  $TDP.checkFileExists(this.$token, configFile).then(exists => {
-    if (!exists){
-      loadConfigObject(null);
-    }
-    else{
-      $TDP.readFile(this.$token, configFile, true).then(contents => {
-        try{
-          loadConfigObject(JSON.parse(contents));
-        }catch(err){
-          loadConfigObject(null);
-        }
-      }).catch(err => {
-        loadConfigObject(null);
-        $TD.alert("error", "Problem loading configuration for the design edit plugin: "+err.message);
-      });
-    }
-  });
-  
-  this.saveConfig = () => {
-    $TDP.writeFile(this.$token, configFile, JSON.stringify(this.config)).catch(err => {
-      $TD.alert("error", "Problem saving configuration for the design edit plugin: "+err.message);
-    });
-  };
-  
-  // settings click event
-  this.onSettingsMenuClickedEvent = () => {
-    if (this.config === null) {
-      return;
-    }
-    
-    setTimeout(() => {
-      let menu = $(".js-dropdown-content").children("ul").first();
-      if (menu.length === 0) {
-        return;
-      }
-      
-      let itemTD = menu.children("[data-tweetduck]").first();
-      if (itemTD.length === 0) {
-        return;
-      }
-      
-      if (!itemTD.prev().hasClass("drp-h-divider")){
-        itemTD.before('<li class="drp-h-divider"></li>');
-      }
-      
-      let itemEditDesign = $('<li class="is-selectable"><a href="#" data-action>Edit layout &amp; design</a></li>');
-      itemEditDesign.insertAfter(itemTD);
-      
-      itemEditDesign.on("click", "a", this.configure.bind(this));
-      
-      itemEditDesign.hover(function(){
-        $(this).addClass("is-selected");
-      }, function(){
-        $(this).removeClass("is-selected");
-      });
-    }, 2);
-  };
-  
-  // modal dialog setup
-  const updateKey = function(key, value){
-    me.config[key] = value;
-    
-    setTimeout(function(){
-      me.saveConfig();
-      me.reinjectAll();
-    }, 1); // delays the slight lag caused by saving and reinjection
-  };
-  
-  this.customDesignModal = TD.components.BaseModal.extend(function(){
-    let modal = $("#td-design-plugin-modal");
-    this.setAndShowContainer(modal, false);
-    
-    // RELOAD
-    this.reloadPage = false;
-    modal.find("[data-td-reload]").click(() => this.reloadPage = true);
-    
-    // UI EVENTS
-    let getTextForCustom = function(key){
-      return "Custom ("+me.config[key]+")";
-    };
-    
-    modal.find("[data-td-key]").each(function(){
-      let item = $(this);
-      let tag = item.prop("tagName");
-      let key = item.attr("data-td-key");
-      
-      // INPUTS
-      if (tag === "INPUT"){
-        let type = item.attr("type");
-        
-        if (type === "checkbox"){
-          item.prop("checked", me.config[key]);
-          
-          item.change(function(){
-            updateKey(key, item.prop("checked"));
-          });
-        }
-      }
-      // SELECTS
-      else if (tag === "SELECT"){
-        let optionCustom = item.find("option[value^='custom']");
-        let optionCustomNew = item.find("option[value^='change-custom']");
-        
-        let resetMyValue = () => {
-          if (!item.val(me.config[key]).val() && optionCustom.length === 1){
-            item.val(optionCustom.attr("value"));
-            optionCustom.text(getTextForCustom(key));
-            optionCustomNew.show();
-          }
-          else{
-            optionCustom.text("Custom");
-            optionCustomNew.hide();
-          }
-        };
-        
-        resetMyValue();
-        
-        item.change(function(){
-          let val = item.val();
-          
-          if (val.endsWith("custom-px")){
-            val = (prompt("Enter custom value (px):") || "").trim();
-            
-            if (val){
-              if (val.endsWith("px")){
-                val = val.slice(0, -2).trim();
-              }
-              
-              if (/^[0-9]+$/.test(val)){
-                updateKey(key, val+"px");
-              }
-              else{
-                alert("Invalid value, only px values are supported.");
-              }
-            }
-          }
-          else{
-            updateKey(key, item.val());
-          }
-          
-          resetMyValue();
-        });
-      }
-      // CUSTOM ELEMENTS
-      else{
-        let value = item.attr("data-td-value");
-        
-        if (value == me.config[key]){
-          item.addClass("selected");
-        }
-        
-        item.click(function(){
-          modal.find("[data-td-key='"+key+"']").removeClass("selected");
-          item.addClass("selected");
-          updateKey(key, value);
-        });
-      }
-    });
-    
-    // THEMES
-    let selectedTheme = TD.settings.getTheme();
-    
-    if (selectedTheme === "dark" && me.config.themeOverride === "black"){
-      selectedTheme = me.config.themeOverride;
-    }
-    
-    modal.find("[data-td-theme='"+selectedTheme+"']").prop("checked", true);
-    
-    modal.find("[data-td-theme]").change(function(){
-      let theme = $(this).attr("data-td-theme");
-      me.config._theme = theme;
-      
-      if (theme === "black"){
-        me.config.themeOverride = theme;
-        theme = "dark";
-      }
-      else{
-        me.config.themeOverride = false;
-      }
-      
-      setTimeout(function(){
-        if (theme != TD.settings.getTheme()){
-          TD.settings.setTheme(theme);
-        }
-        
-        me.saveConfig();
-        me.reinjectAll();
-      }, 1);
-    });
-  }).methods({
-    _render: function(){
-      return $(me.htmlModal);
-    },
-    destroy: function(){
-      if (this.reloadPage){
-        window.TDPF_requestReload();
-        return;
-      }
-      
-      delete me.htmlModal;
-      
-      $("#td-design-plugin-modal").hide();
-      this.supr();
-    }
-  });
-  
-  // animation optimization
-  this.optimizations = null;
-  this.optimizationTimer = null;
-  
-  let clearOptimizationTimer = () => {
-    if (this.optimizationTimer){
-      window.clearTimeout(this.optimizationTimer);
-      this.optimizationTimer = null;
-    }
-  };
-  
-  let runOptimizationTimer = timeout => {
-    if (!this.optimizationTimer){
-      this.optimizationTimer = window.setTimeout(optimizationTimerFunc, timeout);
-    }
-  };
-  
-  let optimizationTimerFunc = () => {
-    this.optimizationTimer = null;
-    
-    if (this.config.optimizeAnimations){
-      $TD.getIdleSeconds().then(s => {
-        if (s >= 16){
-          disableOptimizations();
-          runOptimizationTimer(2500);
-        }
-        else{
-          injectOptimizations();
-        }
-      });
-    }
-  };
-  
-  let injectOptimizations = force => {
-    if (!this.optimizations && (force || document.hasFocus())){
-      this.optimizations = window.TDPF_createCustomStyle(this);
-      this.optimizations.insert(".app-content { will-change: transform }");
-      this.optimizations.insert(".column-holder { will-change: transform }");
-    }
-    
-    clearOptimizationTimer();
-    runOptimizationTimer(10000);
-  };
-  
-  let disableOptimizations = () => {
-    if (this.optimizations){
-      this.optimizations.remove();
-      this.optimizations = null;
-    }
-  };
-  
-  this.onWindowFocusEvent = () => {
-    if (this.config && this.config.optimizeAnimations){
-      injectOptimizations(true);
-    }
-  };
-  
-  this.onWindowBlurEvent = () => {
-    if (this.config && this.config.optimizeAnimations){
-      disableOptimizations();
-      clearOptimizationTimer();
-    }
-  };
-  
-  // css and layout injection
-  this.resetDesign = () => {
-    if (this.css){
-      this.css.remove();
-    }
-    
-    this.css = window.TDPF_createCustomStyle(this);
-    
-    if (this.theme){
-      this.theme.remove();
-    }
-    
-    if (this.config.themeOverride){
-      this.theme = window.TDPF_createCustomStyle(this);
-    }
-    
-    if (this.icons){
-      document.head.removeChild(this.icons);
-      this.icons = null;
-    }
-  };
-  
-  this.reinjectAll = () => {
-    this.resetDesign();
-    
-    clearOptimizationTimer();
-    
-    if (this.config.optimizeAnimations){
-      injectOptimizations();
-    }
-    else{
-      disableOptimizations();
-    }
-    
-    this.css.insert("#general_settings .cf { display: none !important }");
-    this.css.insert("#settings-modal .js-setting-list li:nth-child(3) { border-bottom: 1px solid #ccd6dd }");
-    
-    this.css.insert(`html[data-td-font] { font-size: ${this.config.fontSize} !important }`);
-    this.css.insert(`.avatar { border-radius: ${this.config.avatarRadius}% !important }`);
-    
-    if (this.config.composerWidth !== "default"){
-      const width = this.config.composerWidth;
-      this.css.insert(`.js-app-content.is-open { margin-right: ${width} !important; transform: translateX(${width}) !important }`);
-      this.css.insert(`#tduck .js-app-content.tduck-is-opening { margin-right: 0 !important }`);
-      this.css.insert(`.js-drawer { width: ${width} !important; left: -${width} !important }`);
-    }
-    
-    let currentTheme = TD.settings.getTheme();
-    
-    if (currentTheme === "dark" && this.config.themeOverride){
-      currentTheme = this.config.themeOverride;
-    }
-    
-    let notificationScrollbarColor = null;
-    
-    if (this.config.themeColorTweaks){
-      switch(currentTheme){
-        case "black":
-          this.css.insert(".app-content, .app-columns-container { background-color: #444448 !important }");
-          this.css.insert(".column-header-temp { background-color: transparent !important }");
-          this.css.insert(".column-drag-handle { opacity: 0.5 !important }");
-          this.css.insert(".column-drag-handle:hover { opacity: 1 !important }");
-          this.css.insert(".column-message.is-actionable span:hover > .icon-small-valigned { filter: saturate(20) }");
-          this.css.insert(".scroll-styled-v:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover), .scroll-styled-h:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover) { background-color: #666 !important }");
-          notificationScrollbarColor = "666";
-          break;
-          
-        case "dark":
-          this.css.insert(".scroll-styled-v:not(.scroll-alt)::-webkit-scrollbar-track, .scroll-styled-h:not(.scroll-alt)::-webkit-scrollbar-track { border-left-color: #14171A !important }");
-          break;
-          
-        case "light":
-          this.css.insert(".scroll-styled-v:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover), .scroll-styled-h:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover) { background-color: #d2d6da !important }");
-          this.css.insert(".app-columns-container.scroll-styled-h::-webkit-scrollbar-thumb:not(:hover) { background-color: #a5aeb5 !important }");
-          notificationScrollbarColor = "a5aeb5";
-          break;
-      }
-    }
-    
-    if (this.config.showCharacterCount){
-      this.css.insert("#tduck .js-character-count.is-hidden { display: inline !important }");
-    }
-    
-    if (this.config.hideTweetActions){
-      this.css.insert(".tweet-action { opacity: 0; }");
-      this.css.insert(".tweet-actions.is-visible .tweet-action { opacity: 0.5 }");
-      this.css.insert(".is-favorite .tweet-action, .is-retweet .tweet-action { opacity: 0.5; visibility: visible !important }");
-      this.css.insert(".tweet:hover .tweet-action, .tweet-action.is-selected, .is-favorite .tweet-action[rel='favorite'], .is-retweet .tweet-action[rel='retweet'] { opacity: 1 !important; visibility: visible !important }");
-    }
-    
-    if (this.config.moveTweetActionsToRight){
-      this.css.insert("#tduck .tweet-actions { float: right !important; width: auto !important }");
-      this.css.insert("#tduck .tweet-actions > li:nth-child(4) { margin-right: 2px !important }");
-    }
-    
-    if (this.config.forceArialFont){
-      this.css.insert("#tduck { font-family: Arial, sans-serif; font-weight: 400 }");
-      this.css.insert("#tduck input, #tduck label, #tduck select, #tduck textarea { font-family: Arial }")
-    }
-    
-    if (this.config.increaseQuoteTextSize){
-      this.css.insert(".quoted-tweet { font-size: 1em !important }");
-    }
-    
-    if (this.config.smallComposeTextSize){
-      this.css.insert("#tduck .compose-text { font-size: 12px !important; height: 120px !important }");
-    }
-    
-    if (this.config.revertIcons){
-      let iconData = [
-        [ "twitter-bird", "00" ],
-        [ "mention", "01" ],
-        [ "following", "02" ],
-        [ "message", "03" ],
-        [ "home", "04" ],
-        [ "hashtag", "05" ],
-        [ "reply", "06" ],
-        [ "favorite", "55" ],
-        [ "retweet", "08" ],
-        [ "drafts", "09" ],
-        [ "search", "0a" ],
-        [ "trash", "0c" ],
-        [ "close", "0d" ],
-        [ "arrow-r:before,.Icon--caretRight", "0e" ],
-        [ "arrow-l:before,.Icon--caretLeft", "0f" ],
-        [ "protected", "13" ],
-        [ "list", "14" ],
-        [ "camera", "15" ],
-        [ "more", "16" ],
-        [ "settings", "18" ],
-        [ "notifications", "19" ],
-        [ "user-dd", "1a" ],
-        [ "activity", "1c" ],
-        [ "trending", "1d" ],
-        [ "minus", "1e" ],
-        [ "plus", "1f" ],
-        [ "geo", "20" ],
-        [ "check", "21" ],
-        [ "schedule", "22" ],
-        [ "dot", "23" ],
-        [ "user", "24" ],
-        [ "content", "25" ],
-        [ "arrow-d:before,.Icon--caretDown", "26" ],
-        [ "arrow-u", "27" ],
-        [ "share", "28" ],
-        [ "info", "29" ],
-        [ "verified", "2a" ],
-        [ "translator", "2b" ],
-        [ "blocked", "2c" ],
-        [ "constrain", "2d" ],
-        [ "play-video", "2e" ],
-        [ "empty", "2f" ],
-        [ "clear-input", "30" ],
-        [ "compose", "31" ],
-        [ "mark-read", "32" ],
-        [ "arrow-r-double", "33" ],
-        [ "arrow-l-double", "34" ],
-        [ "follow", "35" ],
-        [ "image", "36" ],
-        [ "popout", "37" ],
-        [ "move", "39" ],
-        [ "compose-grid", "3a" ],
-        [ "compose-minigrid", "3b" ],
-        [ "compose-list", "3c" ],
-        [ "edit", "40" ],
-        [ "clear-timeline", "41" ],
-        [ "sliders", "42" ],
-        [ "custom-timeline", "43" ],
-        [ "compose-dm", "44" ],
-        [ "bg-dot", "45" ],
-        [ "user-team-mgr", "46" ],
-        [ "user-switch", "47" ],
-        [ "conversation", "48" ],
-        [ "dataminr", "49" ],
-        [ "link", "4a", ],
-        [ "flash", "50" ],
-        [ "pointer-u", "51" ],
-        [ "analytics", "54" ],
-        [ "heart", "55" ],
-        [ "calendar", "56" ],
-        [ "attachment", "57" ],
-        [ "play", "58" ],
-        [ "bookmark", "59" ],
-        [ "play-badge", "60" ],
-        [ "gif-badge", "61" ],
-        [ "poll", "62" ],
-        
-        [ "heart-filled", "55" ],
-        [ "retweet-filled", "08" ],
-        [ "list-filled", "14" ],
-        [ "user-filled", "35" ],
-      ];
-      
-      this.icons = document.createElement("style");
-      this.icons.innerHTML = `
+	// elements & data
+	this.css = null;
+	this.icons = null;
+	this.config = null;
+	
+	this.defaultConfig = {
+		_theme: "light",
+		themeOverride: false,
+		columnWidth: "310px",
+		composerWidth: "default",
+		fontSize: "12px",
+		hideTweetActions: true,
+		moveTweetActionsToRight: true,
+		themeColorTweaks: true,
+		revertIcons: true,
+		showCharacterCount: true,
+		forceArialFont: true,
+		increaseQuoteTextSize: false,
+		smallComposeTextSize: false,
+		optimizeAnimations: true,
+		avatarRadius: 2
+	};
+	
+	const prepareDefaultConfig = () => {
+		this.defaultConfig._theme = TD.settings.getTheme();
+		
+		switch (TD.settings.getColumnWidth()) {
+			case "wide":
+				this.defaultConfig.columnWidth = "350px";
+				break;
+			case "narrow":
+				this.defaultConfig.columnWidth = "270px";
+				break;
+		}
+		
+		switch (TD.settings.getFontSize()) {
+			case "small":
+				this.defaultConfig.fontSize = "13px";
+				break;
+			case "medium":
+				this.defaultConfig.fontSize = "14px";
+				break;
+			case "large":
+				this.defaultConfig.fontSize = "15px";
+				break;
+			case "largest":
+				this.defaultConfig.fontSize = "16px";
+				break;
+		}
+	};
+	
+	this.firstTimeLoad = null;
+	
+	const me = this;
+	
+	// configuration
+	const configFile = "config.json";
+	
+	this.tmpConfig = null;
+	this.currentStage = 0;
+	
+	this.onStageReady = () => {
+		if (this.currentStage === 0) {
+			this.currentStage = 1;
+		}
+		else if (this.tmpConfig !== null) {
+			let needsResave = !("_theme" in this.tmpConfig);
+			
+			prepareDefaultConfig();
+			this.config = $.extend(this.defaultConfig, this.tmpConfig);
+			this.tmpConfig = null;
+			this.reinjectAll();
+			
+			if (this.firstTimeLoad || needsResave) {
+				$TDP.writeFile(this.$token, configFile, JSON.stringify(this.config));
+			}
+		}
+	};
+	
+	const loadConfigObject = obj => {
+		this.tmpConfig = obj || {};
+		this.firstTimeLoad = obj === null;
+		
+		this.onStageReady();
+	};
+	
+	if (TD.ready) {
+		this.onStageReady();
+	}
+	else {
+		$(document).one("dataSettingsValues", () => this.onStageReady());
+	}
+	
+	$TDP.checkFileExists(this.$token, configFile).then(exists => {
+		if (!exists) {
+			loadConfigObject(null);
+		}
+		else {
+			$TDP.readFile(this.$token, configFile, true).then(contents => {
+				try {
+					loadConfigObject(JSON.parse(contents));
+				} catch (err) {
+					loadConfigObject(null);
+				}
+			}).catch(err => {
+				loadConfigObject(null);
+				$TD.alert("error", "Problem loading configuration for the design edit plugin: " + err.message);
+			});
+		}
+	});
+	
+	this.saveConfig = () => {
+		$TDP.writeFile(this.$token, configFile, JSON.stringify(this.config)).catch(err => {
+			$TD.alert("error", "Problem saving configuration for the design edit plugin: " + err.message);
+		});
+	};
+	
+	// settings click event
+	this.onSettingsMenuClickedEvent = () => {
+		if (this.config === null) {
+			return;
+		}
+		
+		setTimeout(() => {
+			let menu = $(".js-dropdown-content").children("ul").first();
+			if (menu.length === 0) {
+				return;
+			}
+			
+			let itemTD = menu.children("[data-tweetduck]").first();
+			if (itemTD.length === 0) {
+				return;
+			}
+			
+			if (!itemTD.prev().hasClass("drp-h-divider")) {
+				itemTD.before("<li class=\"drp-h-divider\"></li>");
+			}
+			
+			let itemEditDesign = $("<li class=\"is-selectable\"><a href=\"#\" data-action>Edit layout &amp; design</a></li>");
+			itemEditDesign.insertAfter(itemTD);
+			
+			itemEditDesign.on("click", "a", this.configure.bind(this));
+			
+			itemEditDesign.hover(function() {
+				$(this).addClass("is-selected");
+			}, function() {
+				$(this).removeClass("is-selected");
+			});
+		}, 2);
+	};
+	
+	// modal dialog setup
+	const updateKey = function(key, value) {
+		me.config[key] = value;
+		
+		setTimeout(function() {
+			me.saveConfig();
+			me.reinjectAll();
+		}, 1); // delays the slight lag caused by saving and reinjection
+	};
+	
+	this.customDesignModal = TD.components.BaseModal.extend(function() {
+		let modal = $("#td-design-plugin-modal");
+		this.setAndShowContainer(modal, false);
+		
+		// RELOAD
+		this.reloadPage = false;
+		modal.find("[data-td-reload]").click(() => this.reloadPage = true);
+		
+		// UI EVENTS
+		let getTextForCustom = function(key) {
+			return "Custom (" + me.config[key] + ")";
+		};
+		
+		modal.find("[data-td-key]").each(function() {
+			let item = $(this);
+			let tag = item.prop("tagName");
+			let key = item.attr("data-td-key");
+			
+			// INPUTS
+			if (tag === "INPUT") {
+				let type = item.attr("type");
+				
+				if (type === "checkbox") {
+					item.prop("checked", me.config[key]);
+					
+					item.change(function() {
+						updateKey(key, item.prop("checked"));
+					});
+				}
+			}
+			// SELECTS
+			else if (tag === "SELECT") {
+				let optionCustom = item.find("option[value^='custom']");
+				let optionCustomNew = item.find("option[value^='change-custom']");
+				
+				let resetMyValue = () => {
+					if (!item.val(me.config[key]).val() && optionCustom.length === 1) {
+						item.val(optionCustom.attr("value"));
+						optionCustom.text(getTextForCustom(key));
+						optionCustomNew.show();
+					}
+					else {
+						optionCustom.text("Custom");
+						optionCustomNew.hide();
+					}
+				};
+				
+				resetMyValue();
+				
+				item.change(function() {
+					let val = item.val();
+					
+					if (val.endsWith("custom-px")) {
+						val = (prompt("Enter custom value (px):") || "").trim();
+						
+						if (val) {
+							if (val.endsWith("px")) {
+								val = val.slice(0, -2).trim();
+							}
+							
+							if (/^[0-9]+$/.test(val)) {
+								updateKey(key, val + "px");
+							}
+							else {
+								alert("Invalid value, only px values are supported.");
+							}
+						}
+					}
+					else {
+						updateKey(key, item.val());
+					}
+					
+					resetMyValue();
+				});
+			}
+			// CUSTOM ELEMENTS
+			else {
+				let value = item.attr("data-td-value");
+				
+				if (value == me.config[key]) {
+					item.addClass("selected");
+				}
+				
+				item.click(function() {
+					modal.find("[data-td-key='" + key + "']").removeClass("selected");
+					item.addClass("selected");
+					updateKey(key, value);
+				});
+			}
+		});
+		
+		// THEMES
+		let selectedTheme = TD.settings.getTheme();
+		
+		if (selectedTheme === "dark" && me.config.themeOverride === "black") {
+			selectedTheme = me.config.themeOverride;
+		}
+		
+		modal.find("[data-td-theme='" + selectedTheme + "']").prop("checked", true);
+		
+		modal.find("[data-td-theme]").change(function() {
+			let theme = $(this).attr("data-td-theme");
+			me.config._theme = theme;
+			
+			if (theme === "black") {
+				me.config.themeOverride = theme;
+				theme = "dark";
+			}
+			else {
+				me.config.themeOverride = false;
+			}
+			
+			setTimeout(function() {
+				if (theme != TD.settings.getTheme()) {
+					TD.settings.setTheme(theme);
+				}
+				
+				me.saveConfig();
+				me.reinjectAll();
+			}, 1);
+		});
+	}).methods({
+		_render: function() {
+			return $(me.htmlModal);
+		},
+		destroy: function() {
+			if (this.reloadPage) {
+				window.TDPF_requestReload();
+				return;
+			}
+			
+			delete me.htmlModal;
+			
+			$("#td-design-plugin-modal").hide();
+			this.supr();
+		}
+	});
+	
+	// animation optimization
+	this.optimizations = null;
+	this.optimizationTimer = null;
+	
+	let clearOptimizationTimer = () => {
+		if (this.optimizationTimer) {
+			window.clearTimeout(this.optimizationTimer);
+			this.optimizationTimer = null;
+		}
+	};
+	
+	let runOptimizationTimer = timeout => {
+		if (!this.optimizationTimer) {
+			this.optimizationTimer = window.setTimeout(optimizationTimerFunc, timeout);
+		}
+	};
+	
+	let optimizationTimerFunc = () => {
+		this.optimizationTimer = null;
+		
+		if (this.config.optimizeAnimations) {
+			$TD.getIdleSeconds().then(s => {
+				if (s >= 16) {
+					disableOptimizations();
+					runOptimizationTimer(2500);
+				}
+				else {
+					injectOptimizations();
+				}
+			});
+		}
+	};
+	
+	let injectOptimizations = force => {
+		if (!this.optimizations && (force || document.hasFocus())) {
+			this.optimizations = window.TDPF_createCustomStyle(this);
+			this.optimizations.insert(".app-content { will-change: transform }");
+			this.optimizations.insert(".column-holder { will-change: transform }");
+		}
+		
+		clearOptimizationTimer();
+		runOptimizationTimer(10000);
+	};
+	
+	let disableOptimizations = () => {
+		if (this.optimizations) {
+			this.optimizations.remove();
+			this.optimizations = null;
+		}
+	};
+	
+	this.onWindowFocusEvent = () => {
+		if (this.config && this.config.optimizeAnimations) {
+			injectOptimizations(true);
+		}
+	};
+	
+	this.onWindowBlurEvent = () => {
+		if (this.config && this.config.optimizeAnimations) {
+			disableOptimizations();
+			clearOptimizationTimer();
+		}
+	};
+	
+	// css and layout injection
+	this.resetDesign = () => {
+		if (this.css) {
+			this.css.remove();
+		}
+		
+		this.css = window.TDPF_createCustomStyle(this);
+		
+		if (this.theme) {
+			this.theme.remove();
+		}
+		
+		if (this.config.themeOverride) {
+			this.theme = window.TDPF_createCustomStyle(this);
+		}
+		
+		if (this.icons) {
+			document.head.removeChild(this.icons);
+			this.icons = null;
+		}
+	};
+	
+	this.reinjectAll = () => {
+		this.resetDesign();
+		
+		clearOptimizationTimer();
+		
+		if (this.config.optimizeAnimations) {
+			injectOptimizations();
+		}
+		else {
+			disableOptimizations();
+		}
+		
+		this.css.insert("#general_settings .cf { display: none !important }");
+		this.css.insert("#settings-modal .js-setting-list li:nth-child(3) { border-bottom: 1px solid #ccd6dd }");
+		
+		this.css.insert(`html[data-td-font] { font-size: ${this.config.fontSize} !important }`);
+		this.css.insert(`.avatar { border-radius: ${this.config.avatarRadius}% !important }`);
+		
+		if (this.config.composerWidth !== "default") {
+			const width = this.config.composerWidth;
+			this.css.insert(`.js-app-content.is-open { margin-right: ${width} !important; transform: translateX(${width}) !important }`);
+			this.css.insert(`#tduck .js-app-content.tduck-is-opening { margin-right: 0 !important }`);
+			this.css.insert(`.js-drawer { width: ${width} !important; left: -${width} !important }`);
+		}
+		
+		let currentTheme = TD.settings.getTheme();
+		
+		if (currentTheme === "dark" && this.config.themeOverride) {
+			currentTheme = this.config.themeOverride;
+		}
+		
+		let notificationScrollbarColor = null;
+		
+		if (this.config.themeColorTweaks) {
+			switch (currentTheme) {
+				case "black":
+					this.css.insert(".app-content, .app-columns-container { background-color: #444448 !important }");
+					this.css.insert(".column-header-temp { background-color: transparent !important }");
+					this.css.insert(".column-drag-handle { opacity: 0.5 !important }");
+					this.css.insert(".column-drag-handle:hover { opacity: 1 !important }");
+					this.css.insert(".column-message.is-actionable span:hover > .icon-small-valigned { filter: saturate(20) }");
+					this.css.insert(".scroll-styled-v:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover), .scroll-styled-h:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover) { background-color: #666 !important }");
+					notificationScrollbarColor = "666";
+					break;
+				
+				case "dark":
+					this.css.insert(".scroll-styled-v:not(.scroll-alt)::-webkit-scrollbar-track, .scroll-styled-h:not(.scroll-alt)::-webkit-scrollbar-track { border-left-color: #14171A !important }");
+					break;
+				
+				case "light":
+					this.css.insert(".scroll-styled-v:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover), .scroll-styled-h:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover) { background-color: #d2d6da !important }");
+					this.css.insert(".app-columns-container.scroll-styled-h::-webkit-scrollbar-thumb:not(:hover) { background-color: #a5aeb5 !important }");
+					notificationScrollbarColor = "a5aeb5";
+					break;
+			}
+		}
+		
+		if (this.config.showCharacterCount) {
+			this.css.insert("#tduck .js-character-count.is-hidden { display: inline !important }");
+		}
+		
+		if (this.config.hideTweetActions) {
+			this.css.insert(".tweet-action { opacity: 0; }");
+			this.css.insert(".tweet-actions.is-visible .tweet-action { opacity: 0.5 }");
+			this.css.insert(".is-favorite .tweet-action, .is-retweet .tweet-action { opacity: 0.5; visibility: visible !important }");
+			this.css.insert(".tweet:hover .tweet-action, .tweet-action.is-selected, .is-favorite .tweet-action[rel='favorite'], .is-retweet .tweet-action[rel='retweet'] { opacity: 1 !important; visibility: visible !important }");
+		}
+		
+		if (this.config.moveTweetActionsToRight) {
+			this.css.insert("#tduck .tweet-actions { float: right !important; width: auto !important }");
+			this.css.insert("#tduck .tweet-actions > li:nth-child(4) { margin-right: 2px !important }");
+		}
+		
+		if (this.config.forceArialFont) {
+			this.css.insert("#tduck { font-family: Arial, sans-serif; font-weight: 400 }");
+			this.css.insert("#tduck input, #tduck label, #tduck select, #tduck textarea { font-family: Arial }");
+		}
+		
+		if (this.config.increaseQuoteTextSize) {
+			this.css.insert(".quoted-tweet { font-size: 1em !important }");
+		}
+		
+		if (this.config.smallComposeTextSize) {
+			this.css.insert("#tduck .compose-text { font-size: 12px !important; height: 120px !important }");
+		}
+		
+		if (this.config.revertIcons) {
+			let iconData = [
+				[ "twitter-bird", "00" ],
+				[ "mention", "01" ],
+				[ "following", "02" ],
+				[ "message", "03" ],
+				[ "home", "04" ],
+				[ "hashtag", "05" ],
+				[ "reply", "06" ],
+				[ "favorite", "55" ],
+				[ "retweet", "08" ],
+				[ "drafts", "09" ],
+				[ "search", "0a" ],
+				[ "trash", "0c" ],
+				[ "close", "0d" ],
+				[ "arrow-r:before,.Icon--caretRight", "0e" ],
+				[ "arrow-l:before,.Icon--caretLeft", "0f" ],
+				[ "protected", "13" ],
+				[ "list", "14" ],
+				[ "camera", "15" ],
+				[ "more", "16" ],
+				[ "settings", "18" ],
+				[ "notifications", "19" ],
+				[ "user-dd", "1a" ],
+				[ "activity", "1c" ],
+				[ "trending", "1d" ],
+				[ "minus", "1e" ],
+				[ "plus", "1f" ],
+				[ "geo", "20" ],
+				[ "check", "21" ],
+				[ "schedule", "22" ],
+				[ "dot", "23" ],
+				[ "user", "24" ],
+				[ "content", "25" ],
+				[ "arrow-d:before,.Icon--caretDown", "26" ],
+				[ "arrow-u", "27" ],
+				[ "share", "28" ],
+				[ "info", "29" ],
+				[ "verified", "2a" ],
+				[ "translator", "2b" ],
+				[ "blocked", "2c" ],
+				[ "constrain", "2d" ],
+				[ "play-video", "2e" ],
+				[ "empty", "2f" ],
+				[ "clear-input", "30" ],
+				[ "compose", "31" ],
+				[ "mark-read", "32" ],
+				[ "arrow-r-double", "33" ],
+				[ "arrow-l-double", "34" ],
+				[ "follow", "35" ],
+				[ "image", "36" ],
+				[ "popout", "37" ],
+				[ "move", "39" ],
+				[ "compose-grid", "3a" ],
+				[ "compose-minigrid", "3b" ],
+				[ "compose-list", "3c" ],
+				[ "edit", "40" ],
+				[ "clear-timeline", "41" ],
+				[ "sliders", "42" ],
+				[ "custom-timeline", "43" ],
+				[ "compose-dm", "44" ],
+				[ "bg-dot", "45" ],
+				[ "user-team-mgr", "46" ],
+				[ "user-switch", "47" ],
+				[ "conversation", "48" ],
+				[ "dataminr", "49" ],
+				[ "link", "4a", ],
+				[ "flash", "50" ],
+				[ "pointer-u", "51" ],
+				[ "analytics", "54" ],
+				[ "heart", "55" ],
+				[ "calendar", "56" ],
+				[ "attachment", "57" ],
+				[ "play", "58" ],
+				[ "bookmark", "59" ],
+				[ "play-badge", "60" ],
+				[ "gif-badge", "61" ],
+				[ "poll", "62" ],
+				
+				[ "heart-filled", "55" ],
+				[ "retweet-filled", "08" ],
+				[ "list-filled", "14" ],
+				[ "user-filled", "35" ],
+			];
+			
+			this.icons = document.createElement("style");
+			this.icons.innerHTML = `
 @font-face {
   font-family: '_of';
   src: url("https://ton.twimg.com/tweetdeck-web/web/assets/fonts/tweetdeck-regular-webfont.5f4ea87976.woff") format("woff");
@@ -567,52 +579,60 @@ ${iconData.map(entry => `#tduck .icon-${entry[0]}:before{content:\"\\f0${entry[1
 .tweet-action-item .icon-favorite-toggle { font-size: 16px !important; }
 .tweet-action-item .heartsprite { top: -260% !important; left: -260% !important; transform: scale(0.4, 0.39) translateY(0.5px) !important; }
 .tweet-footer { margin-top: 6px !important }`;
-      
-      document.head.appendChild(this.icons);
-    }
-    
-    if (currentTheme === "black"){
-      $TDP.readFileRoot(this.$token, "theme.black.css").then(contents => {
-        if (this.theme){
-          this.theme.element.innerHTML = contents;
-          TD.settings.setTheme("dark"); // forces refresh of notification head tag
-        }
-      });
-    }
-    
-    if (this.config.columnWidth[0] === '/'){
-      let cols = this.config.columnWidth.slice(1);
-      
-      this.css.insert(".column { width: calc((100vw - 205px) / "+cols+" - 6px) !important; min-width: 160px }");
-      this.css.insert(".is-condensed .column { width: calc((100vw - 65px) / "+cols+" - 6px) !important }");
-    }
-    else{
-      this.css.insert(".column { width: "+this.config.columnWidth+" !important }");
-    }
-    
-    switch(this.config.columnWidth){
-      case "/6":
-        TD.settings.setColumnWidth("narrow");
-        break;
-        
-      case "310px":
-      case "/5":
-        TD.settings.setColumnWidth("medium");
-        break;
-        
-      default:
-        TD.settings.setColumnWidth(parseInt(this.config.columnWidth, 10) < 310 ? "narrow" : "wide"); // NaN will give "wide"
-        break;
-    }
-    
-    switch(this.config.fontSize){
-      case "13px": TD.settings.setFontSize("small"); break;
-      case "14px": TD.settings.setFontSize("medium"); break;
-      case "15px": TD.settings.setFontSize("large"); break;
-      default: TD.settings.setFontSize(parseInt(this.config.fontSize, 10) >= 16 ? "largest" : "smallest"); break;
-    }
-    
-    $TDP.injectIntoNotificationsBefore(this.$token, "css", "</head>", `
+			
+			document.head.appendChild(this.icons);
+		}
+		
+		if (currentTheme === "black") {
+			$TDP.readFileRoot(this.$token, "theme.black.css").then(contents => {
+				if (this.theme) {
+					this.theme.element.innerHTML = contents;
+					TD.settings.setTheme("dark"); // forces refresh of notification head tag
+				}
+			});
+		}
+		
+		if (this.config.columnWidth[0] === "/") {
+			let cols = this.config.columnWidth.slice(1);
+			
+			this.css.insert(".column { width: calc((100vw - 205px) / " + cols + " - 6px) !important; min-width: 160px }");
+			this.css.insert(".is-condensed .column { width: calc((100vw - 65px) / " + cols + " - 6px) !important }");
+		}
+		else {
+			this.css.insert(".column { width: " + this.config.columnWidth + " !important }");
+		}
+		
+		switch (this.config.columnWidth) {
+			case "/6":
+				TD.settings.setColumnWidth("narrow");
+				break;
+			
+			case "310px":
+			case "/5":
+				TD.settings.setColumnWidth("medium");
+				break;
+			
+			default:
+				TD.settings.setColumnWidth(parseInt(this.config.columnWidth, 10) < 310 ? "narrow" : "wide"); // NaN will give "wide"
+				break;
+		}
+		
+		switch (this.config.fontSize) {
+			case "13px":
+				TD.settings.setFontSize("small");
+				break;
+			case "14px":
+				TD.settings.setFontSize("medium");
+				break;
+			case "15px":
+				TD.settings.setFontSize("large");
+				break;
+			default:
+				TD.settings.setFontSize(parseInt(this.config.fontSize, 10) >= 16 ? "largest" : "smallest");
+				break;
+		}
+		
+		$TDP.injectIntoNotificationsBefore(this.$token, "css", "</head>", `
 <style type='text/css'>
 html[data-td-font] { font-size: ${this.config.fontSize} !important }
 .avatar { border-radius: ${this.config.avatarRadius}% !important }
@@ -645,103 +665,102 @@ ${notificationScrollbarColor ? `
 .scroll-styled-v::-webkit-scrollbar-thumb:not(:hover), .scroll-styled-h::-webkit-scrollbar-thumb:not(:hover) { background-color: #${notificationScrollbarColor} !important }
 ` : ``}
 </style>`);
-  };
-  
-  this.uiShowActionsMenuEvent = () => {
-    if (this.config.moveTweetActionsToRight){
-      $(".js-dropdown.pos-r").toggleClass("pos-r pos-l");
-    }
-  };
-  
-  this.uiDrawerActiveEvent = (e, data) => {
-    if (data.activeDrawer === null || this.config.composerWidth === "default") {
-      return;
-    }
-    
-    const ele = $(".js-app-content").addClass("tduck-is-opening");
-    setTimeout(() => ele.removeClass("tduck-is-opening"), 250);
-  };
+	};
+	
+	this.uiShowActionsMenuEvent = () => {
+		if (this.config.moveTweetActionsToRight) {
+			$(".js-dropdown.pos-r").toggleClass("pos-r pos-l");
+		}
+	};
+	
+	this.uiDrawerActiveEvent = (e, data) => {
+		if (data.activeDrawer === null || this.config.composerWidth === "default") {
+			return;
+		}
+		
+		const ele = $(".js-app-content").addClass("tduck-is-opening");
+		setTimeout(() => ele.removeClass("tduck-is-opening"), 250);
+	};
 }
 
 ready(){
-  // optimization events
-  $(window).on("focus", this.onWindowFocusEvent);
-  $(window).on("blur", this.onWindowBlurEvent);
-  
-  // layout events
-  $(document).on("uiShowActionsMenu", this.uiShowActionsMenuEvent);
-  $(document).on("uiDrawerActive", this.uiDrawerActiveEvent);
-  
-  // modal
-  $("[data-action='settings-menu']").on("click", this.onSettingsMenuClickedEvent);
-  $(".js-app").append('<div id="td-design-plugin-modal" class="js-modal settings-modal ovl scroll-v scroll-styled-v"></div>');
-  
-  // global settings override
-  const me = this;
-  
-  this.prevFuncSettingsGetInfo = TD.components.GlobalSettings.prototype.getInfo;
-  this.prevFuncSettingsSwitchTab = TD.components.GlobalSettings.prototype.switchTab;
-  
-  TD.components.GlobalSettings.prototype.getInfo = function(){
-    let data = me.prevFuncSettingsGetInfo.apply(this, arguments);
-    
-    data.tabs.push({
-      title: "Layout & Design",
-      action: "tdp-edit-design"
-    });
-    
-    return data;
-  };
-  
-  TD.components.GlobalSettings.prototype.switchTab = function(tab){
-    if (tab === "tdp-edit-design"){
-      me.configure();
-    }
-    else{
-      return me.prevFuncSettingsSwitchTab.apply(this, arguments);
-    }
-  };
+	// optimization events
+	$(window).on("focus", this.onWindowFocusEvent);
+	$(window).on("blur", this.onWindowBlurEvent);
+	
+	// layout events
+	$(document).on("uiShowActionsMenu", this.uiShowActionsMenuEvent);
+	$(document).on("uiDrawerActive", this.uiDrawerActiveEvent);
+	
+	// modal
+	$("[data-action='settings-menu']").on("click", this.onSettingsMenuClickedEvent);
+	$(".js-app").append("<div id=\"td-design-plugin-modal\" class=\"js-modal settings-modal ovl scroll-v scroll-styled-v\"></div>");
+	
+	// global settings override
+	const me = this;
+	
+	this.prevFuncSettingsGetInfo = TD.components.GlobalSettings.prototype.getInfo;
+	this.prevFuncSettingsSwitchTab = TD.components.GlobalSettings.prototype.switchTab;
+	
+	TD.components.GlobalSettings.prototype.getInfo = function() {
+		let data = me.prevFuncSettingsGetInfo.apply(this, arguments);
+		
+		data.tabs.push({
+			title: "Layout & Design", action: "tdp-edit-design"
+		});
+		
+		return data;
+	};
+	
+	TD.components.GlobalSettings.prototype.switchTab = function(tab) {
+		if (tab === "tdp-edit-design") {
+			me.configure();
+		}
+		else {
+			return me.prevFuncSettingsSwitchTab.apply(this, arguments);
+		}
+	};
 }
 
 configure(){
-  $TDP.readFileRoot(this.$token, "modal.html").then(contents => {
-    this.htmlModal = contents;
-    new this.customDesignModal();
-  }).catch(err => {
-    $TD.alert("error", "Error loading the configuration dialog: "+err.message);
-  });
+	$TDP.readFileRoot(this.$token, "modal.html").then(contents => {
+		this.htmlModal = contents;
+		new this.customDesignModal();
+	}).catch(err => {
+		$TD.alert("error", "Error loading the configuration dialog: " + err.message);
+	});
 }
 
 disabled(){
-  if (this.css){
-    this.css.remove();
-  }
-  
-  if (this.theme){
-    this.theme.remove();
-  }
-  
-  if (this.icons){
-    document.head.removeChild(this.icons);
-  }
-  
-  if (this.optimizations){
-    this.optimizations.remove();
-  }
-  
-  if (this.optimizationTimer){
-    window.clearTimeout(this.optimizationTimer);
-  }
-  
-  $(window).off("focus", this.onWindowFocusEvent);
-  $(window).off("blur", this.onWindowBlurEvent);
-  
-  $(document).off("uiShowActionsMenu", this.uiShowActionsMenuEvent);
-  $(document).off("uiDrawerActive", this.uiDrawerActiveEvent);
-  
-  TD.components.GlobalSettings.prototype.getInfo = this.prevFuncSettingsGetInfo;
-  TD.components.GlobalSettings.prototype.switchTab = this.prevFuncSettingsSwitchTab;
-  
-  $("[data-action='settings-menu']").off("click", this.onSettingsMenuClickedEvent);
-  $("#td-design-plugin-modal").remove();
+	if (this.css) {
+		this.css.remove();
+	}
+	
+	if (this.theme) {
+		this.theme.remove();
+	}
+	
+	if (this.icons) {
+		document.head.removeChild(this.icons);
+	}
+	
+	if (this.optimizations) {
+		this.optimizations.remove();
+	}
+	
+	if (this.optimizationTimer) {
+		window.clearTimeout(this.optimizationTimer);
+	}
+	
+	$(window).off("focus", this.onWindowFocusEvent);
+	$(window).off("blur", this.onWindowBlurEvent);
+	
+	$(document).off("uiShowActionsMenu", this.uiShowActionsMenuEvent);
+	$(document).off("uiDrawerActive", this.uiDrawerActiveEvent);
+	
+	TD.components.GlobalSettings.prototype.getInfo = this.prevFuncSettingsGetInfo;
+	TD.components.GlobalSettings.prototype.switchTab = this.prevFuncSettingsSwitchTab;
+	
+	$("[data-action='settings-menu']").off("click", this.onSettingsMenuClickedEvent);
+	$("#td-design-plugin-modal").remove();
 }
diff --git a/Resources/Plugins/edit-design/modal.html b/Resources/Plugins/edit-design/modal.html
index 3924c9ed..b0c572c1 100644
--- a/Resources/Plugins/edit-design/modal.html
+++ b/Resources/Plugins/edit-design/modal.html
@@ -143,9 +143,9 @@
         </div>
         
         <div class="l-column mdl-column">
-      
+          
           <!-- AVATAR SHAPE -->
-        
+          
           <label class="txt-uppercase touch-larger-label">
             <b>Avatar shape</b>
           </label>
@@ -187,12 +187,12 @@
   #edit-design-panel {
     width: 693px;
     height: 424px;
-    background-color: #FFF;
+    background-color: #fff;
     box-shadow: 0 0 10px rgba(17, 17, 17, 0.5);
   }
   
   #edit-design-panel .mdl-header {
-    color: #8899A6;
+    color: #8899a6;
   }
   
   #edit-design-panel .mdl-inner {
@@ -200,8 +200,8 @@
   }
   
   #edit-design-panel .mdl-content {
-    border: 1px solid #CCD6DD;
-    background: #EAEAEA;
+    border: 1px solid #ccd6dd;
+    background: #eaeaea;
   }
   
   #edit-design-panel-inner-cols {
@@ -260,8 +260,8 @@
     padding: 16px 14px 8px;
     box-sizing: border-box;
     box-shadow: 0 0 4px rgba(0, 0, 0, 0.1);
-    border: 2px solid #F5F8FA;
-    background-color: #F5F8FA;
+    border: 2px solid #f5f8fa;
+    background-color: #f5f8fa;
   }
   
   .td-avatar-shape-item-outer:hover {
@@ -279,6 +279,6 @@
   .td-avatar-shape {
     width: 48px;
     height: 48px;
-    background-color: #71BAF2;
+    background-color: #71baf2;
   }
 </style>
diff --git a/Resources/Plugins/emoji-keyboard/browser.js b/Resources/Plugins/emoji-keyboard/browser.js
index 79470660..07add591 100644
--- a/Resources/Plugins/emoji-keyboard/browser.js
+++ b/Resources/Plugins/emoji-keyboard/browser.js
@@ -1,565 +1,571 @@
 enabled(){
-  this.ENABLE_CUSTOM_KEYBOARD = false;
-  
-  this.selectedSkinTone = "";
-  this.currentKeywords = [];
-  
-  this.skinToneList = [
-    "", "1F3FB", "1F3FC", "1F3FD", "1F3FE", "1F3FF"
-  ];
-  
-  this.skinToneNonDefaultList = [
-    "1F3FB", "1F3FC", "1F3FD", "1F3FE", "1F3FF"
-  ];
-  
-  this.skinToneData = [
-    [ "", "#FFDD67" ],
-    [ "1F3FB", "#FFE1BD" ],
-    [ "1F3FC", "#FED0AC" ],
-    [ "1F3FD", "#D6A57C" ],
-    [ "1F3FE", "#B47D56" ],
-    [ "1F3FF", "#8A6859" ],
-  ];
-  
-  this.emojiData1 = []; // no skin tones, prepended
-  this.emojiData2 = {}; // contains emojis with skin tones
-  this.emojiData3 = []; // no skin tones, appended
-  this.emojiNames = [];
-  
-  const me = this;
-  
-  // styles
-  
-  this.css = window.TDPF_createCustomStyle(this);
-  this.css.insert(".emoji-keyboard { position: absolute; width: 15.35em; background-color: white; border-radius: 1px; font-size: 24px; z-index: 9999 }");
-  this.css.insert(".emoji-keyboard-popup-btn { height: 36px !important }");
-  this.css.insert(".emoji-keyboard-popup-btn .icon { vertical-align: -4px !important }");
-  
-  this.css.insert(".emoji-keyboard-list { height: 10.14em; padding: 0.1em; box-sizing: border-box; overflow-y: auto }");
-  this.css.insert(".emoji-keyboard-list .separator { height: 26px }");
-  this.css.insert(".emoji-keyboard-list img { padding: 0.1em !important; width: 1em; height: 1em; vertical-align: -0.1em; cursor: pointer }");
-  
-  this.css.insert(".emoji-keyboard-search { height: auto; padding: 4px 10px 8px; background-color: #292f33; border-radius: 1px 1px 0 0 }");
-  this.css.insert(".emoji-keyboard-search input { width: 100%; border-radius: 1px; }");
-  
-  this.css.insert(".emoji-keyboard-skintones { height: 1.3em; text-align: center; background-color: #292f33; border-radius: 0 0 1px 1px }");
-  this.css.insert(".emoji-keyboard-skintones div { width: 0.8em; height: 0.8em; margin: 0.25em 0.1em; border-radius: 50%; display: inline-block; box-sizing: border-box; cursor: pointer }");
-  this.css.insert(".emoji-keyboard-skintones .sel { border: 2px solid rgba(0, 0, 0, 0.35); box-shadow: 0 0 2px 0 rgba(255, 255, 255, 0.65), 0 0 1px 0 rgba(255, 255, 255, 0.4) inset }");
-  this.css.insert(".emoji-keyboard-skintones :hover { border: 2px solid rgba(0, 0, 0, 0.25); box-shadow: 0 0 1px 0 rgba(255, 255, 255, 0.65), 0 0 1px 0 rgba(255, 255, 255, 0.25) inset }");
-  
-  this.css.insert(".js-compose-text { font-family: \"Twitter Color Emoji\", Helvetica, Arial, Verdana, sans-serif; }");
-  
-  // layout
-  
-  let buttonHTML = '<button class="needsclick btn btn-on-blue txt-left padding-v--6 padding-h--8 emoji-keyboard-popup-btn"><i class="icon icon-heart"></i></button>';
-  
-  this.prevComposeMustache = TD.mustaches["compose/docked_compose.mustache"];
-  window.TDPF_injectMustache("compose/docked_compose.mustache", "append", '<div class="cf margin-t--12 margin-b--30">', buttonHTML);
-  
-  this.getDrawerInput = () => {
-    return $(".js-compose-text", me.composeDrawer);
-  };
-  
-  this.getDrawerScroller = () => {
-    return $(".js-compose-scroller > .scroll-v", me.composeDrawer);
-  };
-  
-  // keyboard generation
-  
-  this.currentKeyboard = null;
-  this.currentSpanner = null;
-  
-  let wasSearchFocused = false;
-  let lastEmojiKeyword, lastEmojiPosition, lastEmojiLength;
-  
-  const hideKeyboard = (refocus) => {
-    $(this.currentKeyboard).remove();
-    this.currentKeyboard = null;
-    
-    $(this.currentSpanner).remove();
-    this.currentSpanner = null;
-    
-    this.currentKeywords = [];
-    
-    this.getDrawerScroller().trigger("scroll");
-    
-    $(".emoji-keyboard-popup-btn").removeClass("is-selected");
-    
-    if (refocus){
-      this.getDrawerInput().focus();
-      
-      if (lastEmojiKeyword && lastEmojiPosition === 0){
-        document.execCommand("insertText", false, lastEmojiKeyword);
-      }
-    }
-    
-    lastEmojiKeyword = null;
-  };
-  
-  const generateEmojiHTML = skinTone => {
-    let index = 0;
-    let html = [ "<p style='font-size:13px;color:#444;margin:4px;text-align:center'>Please, note that some emoji may not show up correctly in the text box above, but they will display in the tweet.</p>" ];
-    
-    for(let array of [ this.emojiData1, this.emojiData2[skinTone], this.emojiData3 ]){
-      for(let emoji of array){
-        if (emoji === "___"){
-          html.push("<div class='separator'></div>");
-        }
-        else{
-          html.push(TD.util.cleanWithEmoji(emoji).replace(' class="emoji" draggable="false"', ''));
-          index++;
-        }
-      }
-    }
-    
-    return html.join("");
-  };
-  
-  const updateFilters = () => {
-    let keywords = this.currentKeywords;
-    let container = $(this.currentKeyboard.children[1]);
-    
-    let emoji = container.children("img");
-    let info = container.children("p:first");
-    let separators = container.children("div");
-    
-    if (keywords.length === 0){
-      info.css("display", "block");
-      separators.css("display", "block");
-      emoji.css("display", "inline");
-    }
-    else{
-      info.css("display", "none");
-      separators.css("display", "none");
-      
-      emoji.css("display", "none");
-      emoji.filter(index => keywords.every(kw => me.emojiNames[index].includes(kw))).css("display", "inline");
-    }
-  };
-  
-  const selectSkinTone = skinTone => {
-    let selectedEle = this.currentKeyboard.children[2].querySelector("[data-tone='"+this.selectedSkinTone+"']");
-    selectedEle && selectedEle.classList.remove("sel");
-    
-    this.selectedSkinTone = skinTone;
-    this.currentKeyboard.children[1].innerHTML = generateEmojiHTML(skinTone);
-    this.currentKeyboard.children[2].querySelector("[data-tone='"+this.selectedSkinTone+"']").classList.add("sel");
-    updateFilters();
-  };
-  
-  this.generateKeyboard = (left, top) => {
-    let outer = document.createElement("div");
-    outer.classList.add("emoji-keyboard");
-    outer.style.left = left+"px";
-    outer.style.top = top+"px";
-    
-    let keyboard = document.createElement("div");
-    keyboard.classList.add("emoji-keyboard-list");
-    
-    keyboard.addEventListener("click", function(e){
-      let ele = e.target;
-      
-      if (ele.tagName === "IMG"){
-        insertEmoji(ele.getAttribute("src"), ele.getAttribute("alt"));
-      }
-      
-      e.stopPropagation();
-    });
-    
-    let search = document.createElement("div");
-    search.innerHTML = "<input type='text' placeholder='Search...'>";
-    search.classList.add("emoji-keyboard-search");
-    
-    let skintones = document.createElement("div");
-    skintones.innerHTML = me.skinToneData.map(entry => "<div data-tone='"+entry[0]+"' style='background-color:"+entry[1]+"'></div>").join("");
-    skintones.classList.add("emoji-keyboard-skintones");
-    
-    outer.appendChild(search);
-    outer.appendChild(keyboard);
-    outer.appendChild(skintones);
-    $(".js-app").append(outer);
-    
-    skintones.addEventListener("click", function(e){
-      if (e.target.hasAttribute("data-tone")){
-        selectSkinTone(e.target.getAttribute("data-tone") || "");
-      }
-      
-      e.stopPropagation();
-    });
-    
-    search.addEventListener("click", function(e){
-      e.stopPropagation();
-    });
-    
-    let searchInput = search.children[0];
-    searchInput.focus();
-    
-    wasSearchFocused = false;
-    
-    searchInput.addEventListener("input", function(e){
-      me.currentKeywords = e.target.value.split(" ").filter(kw => kw.length > 0).map(kw => kw.toLowerCase());
-      updateFilters();
-      
-      wasSearchFocused = $(this).val().length > 0;
-      e.stopPropagation();
-    });
-    
-    searchInput.addEventListener("keydown", function(e){
-      if (e.keyCode === 13 && $(this).val().length){ // enter
-        let ele = $(".emoji-keyboard-list").children("img").filter(":visible").first();
-        
-        if (ele.length > 0){
-          insertEmoji(ele[0].getAttribute("src"), ele[0].getAttribute("alt"));
-        }
-        
-        e.preventDefault();
-      }
-    });
-    
-    searchInput.addEventListener("click", function(){
-      $(this).select();
-    });
-    
-    searchInput.addEventListener("focus", function(){
-      wasSearchFocused = true;
-    });
-    
-    this.currentKeyboard = outer;
-    selectSkinTone(this.selectedSkinTone);
-    
-    this.currentSpanner = document.createElement("div");
-    this.currentSpanner.style.height = ($(this.currentKeyboard).height()-10)+"px";
-    $(".emoji-keyboard-popup-btn").parent().after(this.currentSpanner);
-    
-    this.getDrawerScroller().trigger("scroll");
-  };
-  
-  const getKeyboardTop = () => {
-    let button = $(".emoji-keyboard-popup-btn");
-    return button.offset().top + button.outerHeight() + me.getDrawerScroller().scrollTop() + 8;
-  };
-  
-  const insertEmoji = (src, alt) => {
-    let input = this.getDrawerInput();
-    
-    let val = input.val();
-    let posStart = input[0].selectionStart;
-    let posEnd = input[0].selectionEnd;
-    
-    input.val(val.slice(0, posStart)+alt+val.slice(posEnd));
-    input.trigger("change");
-    
-    input[0].selectionStart = posStart+alt.length;
-    input[0].selectionEnd = posStart+alt.length;
-    
-    lastEmojiKeyword = null;
-    
-    if (wasSearchFocused){
-      $(".emoji-keyboard-search").children("input").focus();
-    }
-    else{
-      input.focus();
-    }
-  };
-  
-  // general event handlers
-  
-  this.emojiKeyboardButtonClickEvent = function(e){
-    if (me.currentKeyboard){
-      $(this).blur();
-      hideKeyboard(true);
-    }
-    else{
-      me.generateKeyboard($(this).offset().left, getKeyboardTop());
-      $(this).addClass("is-selected");
-    }
-    
-    e.stopPropagation();
-  };
-  
-  this.composerScrollEvent = function(e){
-    if (me.currentKeyboard){
-      me.currentKeyboard.style.marginTop = (-$(this).scrollTop())+"px";
-    }
-  };
-  
-  this.composeInputKeyDownEvent = function(e){
-    if (lastEmojiKeyword && (e.keyCode === 8 || e.keyCode === 27)){ // backspace, escape
-      let ele = $(this)[0];
-      
-      if (ele.selectionStart === lastEmojiPosition){
-        ele.selectionStart -= lastEmojiLength; // selects the emoji
-        document.execCommand("insertText", false, lastEmojiKeyword);
-        
-        e.preventDefault();
-        e.stopPropagation();
-      }
-      
-      lastEmojiKeyword = null;
-    }
-  };
-  
-  this.composeInputKeyPressEvent = function(e){
-    if (String.fromCharCode(e.which) === ':'){
-      let ele = $(this);
-      let val = ele.val();
-      
-      let firstColon = val.lastIndexOf(':', ele[0].selectionStart);
-      if (firstColon === -1) {
-        return;
-      }
-      
-      let search = val.substring(firstColon+1, ele[0].selectionStart).toLowerCase();
-      if (!/^[a-z_]+$/.test(search)) {
-        return;
-      }
-      
-      let keywords = search.split("_").filter(kw => kw.length > 0).map(kw => kw.toLowerCase());
-      if (keywords.length === 0) {
-        return;
-      }
-      
-      let foundNames = me.emojiNames.filter(name => keywords.every(kw => name.includes(kw)));
-      
-      if (foundNames.length === 0){
-        return;
-      }
-      else if (foundNames.length > 1 && foundNames.includes(search)){
-        foundNames = [ search ];
-      }
-      
-      lastEmojiKeyword = `:${search}:`;
-      lastEmojiPosition = lastEmojiLength = 0;
-      
-      if (foundNames.length === 1){
-        let foundIndex = me.emojiNames.indexOf(foundNames[0]);
-        let foundEmoji;
-        
-        for(let array of [ me.emojiData1, me.emojiData2[me.selectedSkinTone], me.emojiData3 ]){
-          let realArray = array.filter(ele => ele !== "___");
-          
-          if (foundIndex >= realArray.length){
-            foundIndex -= realArray.length;
-          }
-          else{
-            foundEmoji = realArray[foundIndex];
-            break;
-          }
-        }
-        
-        if (foundEmoji){
-          e.preventDefault();
-          
-          ele.val(val.substring(0, firstColon)+foundEmoji+val.substring(ele[0].selectionStart));
-          ele[0].selectionEnd = ele[0].selectionStart = firstColon+foundEmoji.length;
-          ele.trigger("change");
-          ele.focus();
-          
-          lastEmojiPosition = firstColon+foundEmoji.length;
-          lastEmojiLength = foundEmoji.length;
-        }
-      }
-      else if (foundNames.length > 1 && $(".js-app-content").is(".is-open")){
-        e.preventDefault();
-        ele.val(val.substring(0, firstColon)+val.substring(ele[0].selectionStart));
-        ele[0].selectionEnd = ele[0].selectionStart = firstColon;
-        ele.trigger("change");
-        
-        if (!me.currentKeyboard){
-          $(".emoji-keyboard-popup-btn").click();
-        }
-        
-        $(".emoji-keyboard-search").children("input").focus().val("");
-        document.execCommand("insertText", false, keywords.join(" "));
-      }
-    }
-    else{
-      lastEmojiKeyword = null;
-    }
-  };
-  
-  this.composeInputFocusEvent = function(e){
-    wasSearchFocused = false;
-  };
-  
-  this.composerSendingEvent = function(e){
-    hideKeyboard();
-  };
-  
-  this.composerActiveEvent = function(e){
-    $(".emoji-keyboard-popup-btn", me.composeDrawer).on("click", me.emojiKeyboardButtonClickEvent);
-    $(".js-docked-compose .js-compose-scroller > .scroll-v", me.composeDrawer).on("scroll", me.composerScrollEvent);
-  };
-  
-  this.documentClickEvent = function(e){
-    if (me.currentKeyboard && $(e.target).closest(".compose-text-container").length === 0){
-      hideKeyboard();
-    }
-  };
-  
-  this.documentKeyEvent = function(e){
-    if (me.currentKeyboard && e.keyCode === 27){ // escape
-      hideKeyboard(true);
-      e.stopPropagation();
-    }
-  };
-  
-  this.uploadFilesEvent = function(e){
-    if (me.currentKeyboard){
-      me.currentKeyboard.style.top = getKeyboardTop()+"px";
-    }
-  };
-  
-  // re-enabling
-  
-  let maybeDockedComposePanel = $(".js-docked-compose");
-  
-  if (maybeDockedComposePanel.length){
-    maybeDockedComposePanel.find(".cf.margin-t--12.margin-b--30").first().append(buttonHTML);
-    this.composerActiveEvent();
-  }
+	this.ENABLE_CUSTOM_KEYBOARD = false;
+	
+	this.selectedSkinTone = "";
+	this.currentKeywords = [];
+	
+	this.skinToneList = [
+		"", "1F3FB", "1F3FC", "1F3FD", "1F3FE", "1F3FF"
+	];
+	
+	this.skinToneNonDefaultList = [
+		"1F3FB", "1F3FC", "1F3FD", "1F3FE", "1F3FF"
+	];
+	
+	this.skinToneData = [
+		[ "", "#ffdd67" ],
+		[ "1F3FB", "#ffe1bd" ],
+		[ "1F3FC", "#fed0ac" ],
+		[ "1F3FD", "#d6a57c" ],
+		[ "1F3FE", "#b47d56" ],
+		[ "1F3FF", "#8a6859" ],
+	];
+	
+	this.emojiData1 = []; // no skin tones, prepended
+	this.emojiData2 = {}; // contains emojis with skin tones
+	this.emojiData3 = []; // no skin tones, appended
+	this.emojiNames = [];
+	
+	const me = this;
+	
+	// styles
+	
+	this.css = window.TDPF_createCustomStyle(this);
+	this.css.insert(".emoji-keyboard { position: absolute; width: 15.35em; background-color: white; border-radius: 1px; font-size: 24px; z-index: 9999 }");
+	this.css.insert(".emoji-keyboard-popup-btn { height: 36px !important }");
+	this.css.insert(".emoji-keyboard-popup-btn .icon { vertical-align: -4px !important }");
+	
+	this.css.insert(".emoji-keyboard-list { height: 10.14em; padding: 0.1em; box-sizing: border-box; overflow-y: auto }");
+	this.css.insert(".emoji-keyboard-list .separator { height: 26px }");
+	this.css.insert(".emoji-keyboard-list img { padding: 0.1em !important; width: 1em; height: 1em; vertical-align: -0.1em; cursor: pointer }");
+	
+	this.css.insert(".emoji-keyboard-search { height: auto; padding: 4px 10px 8px; background-color: #292f33; border-radius: 1px 1px 0 0 }");
+	this.css.insert(".emoji-keyboard-search input { width: 100%; border-radius: 1px; }");
+	
+	this.css.insert(".emoji-keyboard-skintones { height: 1.3em; text-align: center; background-color: #292f33; border-radius: 0 0 1px 1px }");
+	this.css.insert(".emoji-keyboard-skintones div { width: 0.8em; height: 0.8em; margin: 0.25em 0.1em; border-radius: 50%; display: inline-block; box-sizing: border-box; cursor: pointer }");
+	this.css.insert(".emoji-keyboard-skintones .sel { border: 2px solid rgba(0, 0, 0, 0.35); box-shadow: 0 0 2px 0 rgba(255, 255, 255, 0.65), 0 0 1px 0 rgba(255, 255, 255, 0.4) inset }");
+	this.css.insert(".emoji-keyboard-skintones :hover { border: 2px solid rgba(0, 0, 0, 0.25); box-shadow: 0 0 1px 0 rgba(255, 255, 255, 0.65), 0 0 1px 0 rgba(255, 255, 255, 0.25) inset }");
+	
+	this.css.insert(".js-compose-text { font-family: \"Twitter Color Emoji\", Helvetica, Arial, Verdana, sans-serif; }");
+	
+	// layout
+	
+	let buttonHTML = "<button class=\"needsclick btn btn-on-blue txt-left padding-v--6 padding-h--8 emoji-keyboard-popup-btn\"><i class=\"icon icon-heart\"></i></button>";
+	
+	this.prevComposeMustache = TD.mustaches["compose/docked_compose.mustache"];
+	window.TDPF_injectMustache("compose/docked_compose.mustache", "append", "<div class=\"cf margin-t--12 margin-b--30\">", buttonHTML);
+	
+	this.getDrawerInput = () => {
+		return $(".js-compose-text", me.composeDrawer);
+	};
+	
+	this.getDrawerScroller = () => {
+		return $(".js-compose-scroller > .scroll-v", me.composeDrawer);
+	};
+	
+	// keyboard generation
+	
+	this.currentKeyboard = null;
+	this.currentSpanner = null;
+	
+	let wasSearchFocused = false;
+	let lastEmojiKeyword, lastEmojiPosition, lastEmojiLength;
+	
+	const hideKeyboard = (refocus) => {
+		$(this.currentKeyboard).remove();
+		this.currentKeyboard = null;
+		
+		$(this.currentSpanner).remove();
+		this.currentSpanner = null;
+		
+		this.currentKeywords = [];
+		
+		this.getDrawerScroller().trigger("scroll");
+		
+		$(".emoji-keyboard-popup-btn").removeClass("is-selected");
+		
+		if (refocus) {
+			this.getDrawerInput().focus();
+			
+			if (lastEmojiKeyword && lastEmojiPosition === 0) {
+				document.execCommand("insertText", false, lastEmojiKeyword);
+			}
+		}
+		
+		lastEmojiKeyword = null;
+	};
+	
+	const generateEmojiHTML = skinTone => {
+		let index = 0;
+		let html = [ "<p style='font-size:13px;color:#444;margin:4px;text-align:center'>Please, note that some emoji may not show up correctly in the text box above, but they will display in the tweet.</p>" ];
+		
+		for (let array of [ this.emojiData1, this.emojiData2[skinTone], this.emojiData3 ]) {
+			for (let emoji of array) {
+				if (emoji === "___") {
+					html.push("<div class='separator'></div>");
+				}
+				else {
+					html.push(TD.util.cleanWithEmoji(emoji).replace(" class=\"emoji\" draggable=\"false\"", ""));
+					index++;
+				}
+			}
+		}
+		
+		return html.join("");
+	};
+	
+	const updateFilters = () => {
+		let keywords = this.currentKeywords;
+		let container = $(this.currentKeyboard.children[1]);
+		
+		let emoji = container.children("img");
+		let info = container.children("p:first");
+		let separators = container.children("div");
+		
+		if (keywords.length === 0) {
+			info.css("display", "block");
+			separators.css("display", "block");
+			emoji.css("display", "inline");
+		}
+		else {
+			info.css("display", "none");
+			separators.css("display", "none");
+			
+			emoji.css("display", "none");
+			emoji.filter(index => keywords.every(kw => me.emojiNames[index].includes(kw))).css("display", "inline");
+		}
+	};
+	
+	const selectSkinTone = skinTone => {
+		let selectedEle = this.currentKeyboard.children[2].querySelector("[data-tone='" + this.selectedSkinTone + "']");
+		selectedEle && selectedEle.classList.remove("sel");
+		
+		this.selectedSkinTone = skinTone;
+		this.currentKeyboard.children[1].innerHTML = generateEmojiHTML(skinTone);
+		this.currentKeyboard.children[2].querySelector("[data-tone='" + this.selectedSkinTone + "']").classList.add("sel");
+		updateFilters();
+	};
+	
+	this.generateKeyboard = (left, top) => {
+		let outer = document.createElement("div");
+		outer.classList.add("emoji-keyboard");
+		outer.style.left = left + "px";
+		outer.style.top = top + "px";
+		
+		let keyboard = document.createElement("div");
+		keyboard.classList.add("emoji-keyboard-list");
+		
+		keyboard.addEventListener("click", function(e) {
+			let ele = e.target;
+			
+			if (ele.tagName === "IMG") {
+				insertEmoji(ele.getAttribute("src"), ele.getAttribute("alt"));
+			}
+			
+			e.stopPropagation();
+		});
+		
+		let search = document.createElement("div");
+		search.innerHTML = "<input type='text' placeholder='Search...'>";
+		search.classList.add("emoji-keyboard-search");
+		
+		let skintones = document.createElement("div");
+		skintones.innerHTML = me.skinToneData.map(entry => "<div data-tone='" + entry[0] + "' style='background-color:" + entry[1] + "'></div>").join("");
+		skintones.classList.add("emoji-keyboard-skintones");
+		
+		outer.appendChild(search);
+		outer.appendChild(keyboard);
+		outer.appendChild(skintones);
+		$(".js-app").append(outer);
+		
+		skintones.addEventListener("click", function(e) {
+			if (e.target.hasAttribute("data-tone")) {
+				selectSkinTone(e.target.getAttribute("data-tone") || "");
+			}
+			
+			e.stopPropagation();
+		});
+		
+		search.addEventListener("click", function(e) {
+			e.stopPropagation();
+		});
+		
+		let searchInput = search.children[0];
+		searchInput.focus();
+		
+		wasSearchFocused = false;
+		
+		searchInput.addEventListener("input", function(e) {
+			me.currentKeywords = e.target.value.split(" ").filter(kw => kw.length > 0).map(kw => kw.toLowerCase());
+			updateFilters();
+			
+			wasSearchFocused = $(this).val().length > 0;
+			e.stopPropagation();
+		});
+		
+		searchInput.addEventListener("keydown", function(e) {
+			if (e.keyCode === 13 && $(this).val().length) { // enter
+				let ele = $(".emoji-keyboard-list").children("img").filter(":visible").first();
+				
+				if (ele.length > 0) {
+					insertEmoji(ele[0].getAttribute("src"), ele[0].getAttribute("alt"));
+				}
+				
+				e.preventDefault();
+			}
+		});
+		
+		searchInput.addEventListener("click", function() {
+			$(this).select();
+		});
+		
+		searchInput.addEventListener("focus", function() {
+			wasSearchFocused = true;
+		});
+		
+		this.currentKeyboard = outer;
+		selectSkinTone(this.selectedSkinTone);
+		
+		this.currentSpanner = document.createElement("div");
+		this.currentSpanner.style.height = ($(this.currentKeyboard).height() - 10) + "px";
+		$(".emoji-keyboard-popup-btn").parent().after(this.currentSpanner);
+		
+		this.getDrawerScroller().trigger("scroll");
+	};
+	
+	const getKeyboardTop = () => {
+		let button = $(".emoji-keyboard-popup-btn");
+		return button.offset().top + button.outerHeight() + me.getDrawerScroller().scrollTop() + 8;
+	};
+	
+	const insertEmoji = (src, alt) => {
+		let input = this.getDrawerInput();
+		
+		let val = input.val();
+		let posStart = input[0].selectionStart;
+		let posEnd = input[0].selectionEnd;
+		
+		input.val(val.slice(0, posStart) + alt + val.slice(posEnd));
+		input.trigger("change");
+		
+		input[0].selectionStart = posStart + alt.length;
+		input[0].selectionEnd = posStart + alt.length;
+		
+		lastEmojiKeyword = null;
+		
+		if (wasSearchFocused) {
+			$(".emoji-keyboard-search").children("input").focus();
+		}
+		else {
+			input.focus();
+		}
+	};
+	
+	// general event handlers
+	
+	this.emojiKeyboardButtonClickEvent = function(e) {
+		if (me.currentKeyboard) {
+			$(this).blur();
+			hideKeyboard(true);
+		}
+		else {
+			me.generateKeyboard($(this).offset().left, getKeyboardTop());
+			$(this).addClass("is-selected");
+		}
+		
+		e.stopPropagation();
+	};
+	
+	this.composerScrollEvent = function(e) {
+		if (me.currentKeyboard) {
+			me.currentKeyboard.style.marginTop = (-$(this).scrollTop()) + "px";
+		}
+	};
+	
+	this.composeInputKeyDownEvent = function(e) {
+		if (lastEmojiKeyword && (e.keyCode === 8 || e.keyCode === 27)) { // backspace, escape
+			let ele = $(this)[0];
+			
+			if (ele.selectionStart === lastEmojiPosition) {
+				ele.selectionStart -= lastEmojiLength; // selects the emoji
+				document.execCommand("insertText", false, lastEmojiKeyword);
+				
+				e.preventDefault();
+				e.stopPropagation();
+			}
+			
+			lastEmojiKeyword = null;
+		}
+	};
+	
+	this.composeInputKeyPressEvent = function(e) {
+		if (String.fromCharCode(e.which) === ":") {
+			let ele = $(this);
+			let val = ele.val();
+			
+			let firstColon = val.lastIndexOf(":", ele[0].selectionStart);
+			if (firstColon === -1) {
+				return;
+			}
+			
+			let search = val.substring(firstColon + 1, ele[0].selectionStart).toLowerCase();
+			if (!/^[a-z_]+$/.test(search)) {
+				return;
+			}
+			
+			let keywords = search.split("_").filter(kw => kw.length > 0).map(kw => kw.toLowerCase());
+			if (keywords.length === 0) {
+				return;
+			}
+			
+			let foundNames = me.emojiNames.filter(name => keywords.every(kw => name.includes(kw)));
+			
+			if (foundNames.length === 0) {
+				return;
+			}
+			else if (foundNames.length > 1 && foundNames.includes(search)) {
+				foundNames = [ search ];
+			}
+			
+			lastEmojiKeyword = `:${search}:`;
+			lastEmojiPosition = lastEmojiLength = 0;
+			
+			if (foundNames.length === 1) {
+				let foundIndex = me.emojiNames.indexOf(foundNames[0]);
+				let foundEmoji;
+				
+				for (let array of [ me.emojiData1, me.emojiData2[me.selectedSkinTone], me.emojiData3 ]) {
+					let realArray = array.filter(ele => ele !== "___");
+					
+					if (foundIndex >= realArray.length) {
+						foundIndex -= realArray.length;
+					}
+					else {
+						foundEmoji = realArray[foundIndex];
+						break;
+					}
+				}
+				
+				if (foundEmoji) {
+					e.preventDefault();
+					
+					ele.val(val.substring(0, firstColon) + foundEmoji + val.substring(ele[0].selectionStart));
+					ele[0].selectionEnd = ele[0].selectionStart = firstColon + foundEmoji.length;
+					ele.trigger("change");
+					ele.focus();
+					
+					lastEmojiPosition = firstColon + foundEmoji.length;
+					lastEmojiLength = foundEmoji.length;
+				}
+			}
+			else if (foundNames.length > 1 && $(".js-app-content").is(".is-open")) {
+				e.preventDefault();
+				ele.val(val.substring(0, firstColon) + val.substring(ele[0].selectionStart));
+				ele[0].selectionEnd = ele[0].selectionStart = firstColon;
+				ele.trigger("change");
+				
+				if (!me.currentKeyboard) {
+					$(".emoji-keyboard-popup-btn").click();
+				}
+				
+				$(".emoji-keyboard-search").children("input").focus().val("");
+				document.execCommand("insertText", false, keywords.join(" "));
+			}
+		}
+		else {
+			lastEmojiKeyword = null;
+		}
+	};
+	
+	this.composeInputFocusEvent = function(e) {
+		wasSearchFocused = false;
+	};
+	
+	this.composerSendingEvent = function(e) {
+		hideKeyboard();
+	};
+	
+	this.composerActiveEvent = function(e) {
+		$(".emoji-keyboard-popup-btn", me.composeDrawer).on("click", me.emojiKeyboardButtonClickEvent);
+		$(".js-docked-compose .js-compose-scroller > .scroll-v", me.composeDrawer).on("scroll", me.composerScrollEvent);
+	};
+	
+	this.documentClickEvent = function(e) {
+		if (me.currentKeyboard && $(e.target).closest(".compose-text-container").length === 0) {
+			hideKeyboard();
+		}
+	};
+	
+	this.documentKeyEvent = function(e) {
+		if (me.currentKeyboard && e.keyCode === 27) { // escape
+			hideKeyboard(true);
+			e.stopPropagation();
+		}
+	};
+	
+	this.uploadFilesEvent = function(e) {
+		if (me.currentKeyboard) {
+			me.currentKeyboard.style.top = getKeyboardTop() + "px";
+		}
+	};
+	
+	// re-enabling
+	
+	let maybeDockedComposePanel = $(".js-docked-compose");
+	
+	if (maybeDockedComposePanel.length) {
+		maybeDockedComposePanel.find(".cf.margin-t--12.margin-b--30").first().append(buttonHTML);
+		this.composerActiveEvent();
+	}
 }
 
 ready(){
-  this.composeDrawer = $(".js-drawer[data-drawer='compose']");
-  this.composeSelector = ".js-compose-text,.js-reply-tweetbox";
-  
-  $(document).on("click", this.documentClickEvent);
-  $(document).on("keydown", this.documentKeyEvent);
-  $(document).on("tduckOldComposerActive", this.composerActiveEvent);
-  $(document).on("uiComposeImageAdded", this.uploadFilesEvent);
-  
-  this.composeDrawer.on("uiComposeTweetSending", this.composerSendingEvent);
-  
-  $(document).on("keydown", this.composeSelector, this.composeInputKeyDownEvent);
-  $(document).on("keypress", this.composeSelector, this.composeInputKeyPressEvent);
-  $(document).on("focus", this.composeSelector, this.composeInputFocusEvent);
-  
-  // HTML generation
-  
-  const convUnicode = function(codePt){
-    if (codePt > 0xFFFF){
-      codePt -= 0x10000;
-      return String.fromCharCode(0xD800+(codePt>>10), 0xDC00+(codePt&0x3FF));
-    }
-    else{
-      return String.fromCharCode(codePt);
-    }
-  };
-  
-  $TDP.readFileRoot(this.$token, "emoji-ordering.txt").then(contents => {
-    for(let skinTone of this.skinToneList){
-      this.emojiData2[skinTone] = [];
-    }
-    
-    // declaration inserters
-    
-    let mapUnicode = pt => convUnicode(parseInt(pt, 16));
-    
-    let addDeclaration1 = decl => {
-      this.emojiData1.push(decl.split(" ").map(mapUnicode).join(""));
-    };
-    
-    let addDeclaration2 = (tone, decl) => {
-      let gen = decl.split(" ").map(mapUnicode).join("");
-      
-      if (tone === null){
-        for(let skinTone of this.skinToneList){
-          this.emojiData2[skinTone].push(gen);
-        }
-      }
-      else{
-        this.emojiData2[tone].push(gen);
-      }
-    };
-    
-    let addDeclaration3 = decl => {
-      this.emojiData3.push(decl.split(" ").map(mapUnicode).join(""));
-    };
-    
-    // line reading
-    
-    let skinToneState = 0;
-    
-    for(let line of contents.split("\n")){
-      if (line[0] === '@'){
-        switch(skinToneState){
-          case 0: this.emojiData1.push("___"); break;
-          case 1: this.skinToneList.forEach(skinTone => this.emojiData2[skinTone].push("___")); break;
-          case 2: this.emojiData3.push("___"); break;
-        }
-        
-        continue;
-      }
-      else if (line[0] === '#'){
-        if (line[1] === '1'){
-          skinToneState = 1;
-        }
-        else if (line[1] === '2'){
-          skinToneState = 2;
-        }
-        
-        continue;
-      }
-      
-      let semicolon = line.indexOf(';');
-      let decl = line.slice(0, semicolon);
-      let desc = line.slice(semicolon+1).toLowerCase();
-      
-      if (skinToneState === 1){
-        let skinIndex = decl.indexOf('$');
-        
-        if (skinIndex !== -1){
-          let declPre = decl.slice(0, skinIndex);
-          let declPost = decl.slice(skinIndex+1);
-          
-          for(let skinTone of this.skinToneNonDefaultList){
-            this.emojiData2[skinTone].pop();
-            addDeclaration2(skinTone, declPre+skinTone+declPost);
-          }
-        }
-        else{
-          addDeclaration2(null, decl);
-          this.emojiNames.push(desc);
-        }
-      }
-      else if (skinToneState === 2){
-        addDeclaration3(decl);
-        this.emojiNames.push(desc);
-      }
-      else if (skinToneState === 0){
-        addDeclaration1(decl);
-        this.emojiNames.push(desc);
-      }
-    }
-  }).catch(err => {
-    $TD.alert("error", "Problem loading emoji keyboard: "+err.message);
-  });
+	this.composeDrawer = $(".js-drawer[data-drawer='compose']");
+	this.composeSelector = ".js-compose-text,.js-reply-tweetbox";
+	
+	$(document).on("click", this.documentClickEvent);
+	$(document).on("keydown", this.documentKeyEvent);
+	$(document).on("tduckOldComposerActive", this.composerActiveEvent);
+	$(document).on("uiComposeImageAdded", this.uploadFilesEvent);
+	
+	this.composeDrawer.on("uiComposeTweetSending", this.composerSendingEvent);
+	
+	$(document).on("keydown", this.composeSelector, this.composeInputKeyDownEvent);
+	$(document).on("keypress", this.composeSelector, this.composeInputKeyPressEvent);
+	$(document).on("focus", this.composeSelector, this.composeInputFocusEvent);
+	
+	// HTML generation
+	
+	const convUnicode = function(codePt) {
+		if (codePt > 0xFFFF) {
+			codePt -= 0x10000;
+			return String.fromCharCode(0xD800 + (codePt >> 10), 0xDC00 + (codePt & 0x3FF));
+		}
+		else {
+			return String.fromCharCode(codePt);
+		}
+	};
+	
+	$TDP.readFileRoot(this.$token, "emoji-ordering.txt").then(contents => {
+		for (let skinTone of this.skinToneList) {
+			this.emojiData2[skinTone] = [];
+		}
+		
+		// declaration inserters
+		
+		let mapUnicode = pt => convUnicode(parseInt(pt, 16));
+		
+		let addDeclaration1 = decl => {
+			this.emojiData1.push(decl.split(" ").map(mapUnicode).join(""));
+		};
+		
+		let addDeclaration2 = (tone, decl) => {
+			let gen = decl.split(" ").map(mapUnicode).join("");
+			
+			if (tone === null) {
+				for (let skinTone of this.skinToneList) {
+					this.emojiData2[skinTone].push(gen);
+				}
+			}
+			else {
+				this.emojiData2[tone].push(gen);
+			}
+		};
+		
+		let addDeclaration3 = decl => {
+			this.emojiData3.push(decl.split(" ").map(mapUnicode).join(""));
+		};
+		
+		// line reading
+		
+		let skinToneState = 0;
+		
+		for (let line of contents.split("\n")) {
+			if (line[0] === "@") {
+				switch (skinToneState) {
+					case 0:
+						this.emojiData1.push("___");
+						break;
+					case 1:
+						this.skinToneList.forEach(skinTone => this.emojiData2[skinTone].push("___"));
+						break;
+					case 2:
+						this.emojiData3.push("___");
+						break;
+				}
+				
+				continue;
+			}
+			else if (line[0] === "#") {
+				if (line[1] === "1") {
+					skinToneState = 1;
+				}
+				else if (line[1] === "2") {
+					skinToneState = 2;
+				}
+				
+				continue;
+			}
+			
+			let semicolon = line.indexOf(";");
+			let decl = line.slice(0, semicolon);
+			let desc = line.slice(semicolon + 1).toLowerCase();
+			
+			if (skinToneState === 1) {
+				let skinIndex = decl.indexOf("$");
+				
+				if (skinIndex !== -1) {
+					let declPre = decl.slice(0, skinIndex);
+					let declPost = decl.slice(skinIndex + 1);
+					
+					for (let skinTone of this.skinToneNonDefaultList) {
+						this.emojiData2[skinTone].pop();
+						addDeclaration2(skinTone, declPre + skinTone + declPost);
+					}
+				}
+				else {
+					addDeclaration2(null, decl);
+					this.emojiNames.push(desc);
+				}
+			}
+			else if (skinToneState === 2) {
+				addDeclaration3(decl);
+				this.emojiNames.push(desc);
+			}
+			else if (skinToneState === 0) {
+				addDeclaration1(decl);
+				this.emojiNames.push(desc);
+			}
+		}
+	}).catch(err => {
+		$TD.alert("error", "Problem loading emoji keyboard: " + err.message);
+	});
 }
 
 disabled(){
-  this.css.remove();
-  
-  if (this.currentKeyboard){
-    $(this.currentKeyboard).remove();
-  }
-  
-  if (this.currentSpanner){
-    $(this.currentSpanner).remove();
-  }
-  
-  $(".emoji-keyboard-popup-btn").remove();
-  
-  $(document).off("click", this.documentClickEvent);
-  $(document).off("keydown", this.documentKeyEvent);
-  $(document).off("tduckOldComposerActive", this.composerActiveEvent);
-  $(document).off("uiComposeImageAdded", this.uploadFilesEvent);
-  
-  this.composeDrawer.off("uiComposeTweetSending", this.composerSendingEvent);
-  
-  $(document).off("keydown", this.composeSelector, this.composeInputKeyDownEvent);
-  $(document).off("keypress", this.composeSelector, this.composeInputKeyPressEvent);
-  $(document).off("focus", this.composeSelector, this.composeInputFocusEvent);
-  
-  TD.mustaches["compose/docked_compose.mustache"] = this.prevComposeMustache;
+	this.css.remove();
+	
+	if (this.currentKeyboard) {
+		$(this.currentKeyboard).remove();
+	}
+	
+	if (this.currentSpanner) {
+		$(this.currentSpanner).remove();
+	}
+	
+	$(".emoji-keyboard-popup-btn").remove();
+	
+	$(document).off("click", this.documentClickEvent);
+	$(document).off("keydown", this.documentKeyEvent);
+	$(document).off("tduckOldComposerActive", this.composerActiveEvent);
+	$(document).off("uiComposeImageAdded", this.uploadFilesEvent);
+	
+	this.composeDrawer.off("uiComposeTweetSending", this.composerSendingEvent);
+	
+	$(document).off("keydown", this.composeSelector, this.composeInputKeyDownEvent);
+	$(document).off("keypress", this.composeSelector, this.composeInputKeyPressEvent);
+	$(document).off("focus", this.composeSelector, this.composeInputFocusEvent);
+	
+	TD.mustaches["compose/docked_compose.mustache"] = this.prevComposeMustache;
 }
diff --git a/Resources/Plugins/reply-account/browser.js b/Resources/Plugins/reply-account/browser.js
index e33853f8..9bce7335 100644
--- a/Resources/Plugins/reply-account/browser.js
+++ b/Resources/Plugins/reply-account/browser.js
@@ -1,151 +1,151 @@
 enabled(){
-  let configuration = { defaultAccount: "#preferred" };
-  
-  window.TDPF_loadConfigurationFile(this, "configuration.js", "configuration.default.js", obj => configuration = obj);
-  
-  this.lastSelectedAccount = null;
-  
-  this.uiComposeTweetEvent = (e, data) => {
-    if (!(data.type === "reply" || (data.type === "tweet" && "quotedTweet" in data)) || data.popFromInline || !("element" in data)) {
-      return;
-    }
-    
-    let query;
-    
-    if (configuration.useAdvancedSelector){
-      if (configuration.customSelector){
-        let customSelectorDef = configuration.customSelector.toString();
-        
-        if (customSelectorDef.startsWith("function (column){")){
-          $TD.alert("warning", "Plugin reply-account has invalid configuration: customSelector needs to be updated due to TweetDeck changes, please read the default configuration file for the updated guide");
-          return;
-        }
-        else if (customSelectorDef.startsWith("function (type,")){
-          $TD.alert("warning", "Plugin reply-account has invalid configuration: the type parameter is no longer present due to TweetDeck changes, please read the default configuration file for the updated guide");
-          return;
-        }
-        
-        let section = data.element.closest("section.js-column");
-        let column = TD.controller.columnManager.get(section.attr("data-column"));
-        
-        let feeds = column.getFeeds();
-        let accountText = "";
-        
-        if (feeds.length === 1){
-          let metadata = feeds[0].getMetadata();
-          let id = metadata.ownerId || metadata.id;
-          
-          if (id){
-            accountText = TD.cache.names.getScreenName(id);
-          }
-          else{
-            let account = TD.storage.accountController.get(feeds[0].getAccountKey());
-            
-            if (account){
-              accountText = "@"+account.getUsername();
-            }
-          }
-        }
-        
-        let header = $(".column-header-title", section);
-        let title = header.children(".column-heading");
-        let titleText = title.length ? title.text() : header.children(".column-title-edit-box").val();
-        
-        try{
-          query = configuration.customSelector(titleText, accountText, column, section.hasClass("column-temp"));
-        }catch(e){
-          $TD.alert("warning", "Plugin reply-account has invalid configuration: customSelector threw an error: "+e.message);
-          return;
-        }
-      }
-      else{
-        $TD.alert("warning", "Plugin reply-account has invalid configuration: useAdvancedSelector is true, but customSelector function is missing");
-        return;
-      }
-    }
-    else{
-      query = configuration.defaultAccount;
-      
-      if (query === ""){
-        query = "#preferred";
-      }
-      else if (typeof query !== "string"){
-        query = "#default";
-      }
-    }
-    
-    if (typeof query === "undefined"){
-      query = "#preferred";
-    }
-    
-    if (typeof query !== "string"){
-      return;
-    }
-    else if (query.length === 0){
-      $TD.alert("warning", "Plugin reply-account has invalid configuration: the requested account is empty");
-      return;
-    }
-    else if (query[0] !== '@' && query[0] !== '#'){
-      $TD.alert("warning", "Plugin reply-account has invalid configuration: the requested account does not begin with @ or #: "+query);
-      return;
-    }
-    
-    let identifier = null;
-    
-    switch(query){
-      case "#preferred":
-        identifier = TD.storage.clientController.client.getDefaultAccount();
-        break;
-      
-      case "#last":
-        if (this.lastSelectedAccount === null) {
-          return;
-        }
-        
-        identifier = this.lastSelectedAccount;
-        break;
-      
-      case "#default":
-        return;
-      
-      default:
-        if (query[0] === '@'){
-          let obj = TD.storage.accountController.getAccountFromUsername(query.substring(1));
-          
-          if (obj.length === 0){
-            $TD.alert("warning", "Plugin reply-account has invalid configuration: requested account not found: "+query);
-            return;
-          }
-          else{
-            identifier = obj[0].privateState.key;
-          }
-        }
-        else{
-          $TD.alert("warning", "Plugin reply-account has invalid configuration: unknown requested account query: "+query);
-          return;
-        }
-    }
-    
-    data.singleFrom = data.from = [ identifier ];
-  };
-  
-  this.onSelectedAccountChanged = () => {
-    let selected = $(".js-account-item.is-selected", ".js-account-list");
-    this.lastSelectedAccount = selected.length === 1 ? selected.attr("data-account-key") : null;
-  };
+	let configuration = { defaultAccount: "#preferred" };
+	
+	window.TDPF_loadConfigurationFile(this, "configuration.js", "configuration.default.js", obj => configuration = obj);
+	
+	this.lastSelectedAccount = null;
+	
+	this.uiComposeTweetEvent = (e, data) => {
+		if (!(data.type === "reply" || (data.type === "tweet" && "quotedTweet" in data)) || data.popFromInline || !("element" in data)) {
+			return;
+		}
+		
+		let query;
+		
+		if (configuration.useAdvancedSelector) {
+			if (configuration.customSelector) {
+				let customSelectorDef = configuration.customSelector.toString();
+				
+				if (customSelectorDef.startsWith("function (column){")) {
+					$TD.alert("warning", "Plugin reply-account has invalid configuration: customSelector needs to be updated due to TweetDeck changes, please read the default configuration file for the updated guide");
+					return;
+				}
+				else if (customSelectorDef.startsWith("function (type,")) {
+					$TD.alert("warning", "Plugin reply-account has invalid configuration: the type parameter is no longer present due to TweetDeck changes, please read the default configuration file for the updated guide");
+					return;
+				}
+				
+				let section = data.element.closest("section.js-column");
+				let column = TD.controller.columnManager.get(section.attr("data-column"));
+				
+				let feeds = column.getFeeds();
+				let accountText = "";
+				
+				if (feeds.length === 1) {
+					let metadata = feeds[0].getMetadata();
+					let id = metadata.ownerId || metadata.id;
+					
+					if (id) {
+						accountText = TD.cache.names.getScreenName(id);
+					}
+					else {
+						let account = TD.storage.accountController.get(feeds[0].getAccountKey());
+						
+						if (account) {
+							accountText = "@" + account.getUsername();
+						}
+					}
+				}
+				
+				let header = $(".column-header-title", section);
+				let title = header.children(".column-heading");
+				let titleText = title.length ? title.text() : header.children(".column-title-edit-box").val();
+				
+				try {
+					query = configuration.customSelector(titleText, accountText, column, section.hasClass("column-temp"));
+				} catch (e) {
+					$TD.alert("warning", "Plugin reply-account has invalid configuration: customSelector threw an error: " + e.message);
+					return;
+				}
+			}
+			else {
+				$TD.alert("warning", "Plugin reply-account has invalid configuration: useAdvancedSelector is true, but customSelector function is missing");
+				return;
+			}
+		}
+		else {
+			query = configuration.defaultAccount;
+			
+			if (query === "") {
+				query = "#preferred";
+			}
+			else if (typeof query !== "string") {
+				query = "#default";
+			}
+		}
+		
+		if (typeof query === "undefined") {
+			query = "#preferred";
+		}
+		
+		if (typeof query !== "string") {
+			return;
+		}
+		else if (query.length === 0) {
+			$TD.alert("warning", "Plugin reply-account has invalid configuration: the requested account is empty");
+			return;
+		}
+		else if (query[0] !== "@" && query[0] !== "#") {
+			$TD.alert("warning", "Plugin reply-account has invalid configuration: the requested account does not begin with @ or #: " + query);
+			return;
+		}
+		
+		let identifier = null;
+		
+		switch (query) {
+			case "#preferred":
+				identifier = TD.storage.clientController.client.getDefaultAccount();
+				break;
+			
+			case "#last":
+				if (this.lastSelectedAccount === null) {
+					return;
+				}
+				
+				identifier = this.lastSelectedAccount;
+				break;
+			
+			case "#default":
+				return;
+			
+			default:
+				if (query[0] === "@") {
+					let obj = TD.storage.accountController.getAccountFromUsername(query.substring(1));
+					
+					if (obj.length === 0) {
+						$TD.alert("warning", "Plugin reply-account has invalid configuration: requested account not found: " + query);
+						return;
+					}
+					else {
+						identifier = obj[0].privateState.key;
+					}
+				}
+				else {
+					$TD.alert("warning", "Plugin reply-account has invalid configuration: unknown requested account query: " + query);
+					return;
+				}
+		}
+		
+		data.singleFrom = data.from = [ identifier ];
+	};
+	
+	this.onSelectedAccountChanged = () => {
+		let selected = $(".js-account-item.is-selected", ".js-account-list");
+		this.lastSelectedAccount = selected.length === 1 ? selected.attr("data-account-key") : null;
+	};
 }
 
 ready(){
-  for(let event of [ "uiInlineComposeTweet", "uiDockedComposeTweet" ]){
-    $(document).on(event, this.uiComposeTweetEvent);
-    window.TDPF_prioritizeNewestEvent(document, event);
-  }
-  
-  $(document).on("click", ".js-account-list .js-account-item", this.onSelectedAccountChanged);
+	for (let event of [ "uiInlineComposeTweet", "uiDockedComposeTweet" ]) {
+		$(document).on(event, this.uiComposeTweetEvent);
+		window.TDPF_prioritizeNewestEvent(document, event);
+	}
+	
+	$(document).on("click", ".js-account-list .js-account-item", this.onSelectedAccountChanged);
 }
 
 disabled(){
-  $(document).off("uiInlineComposeTweet", this.uiComposeTweetEvent);
-  $(document).off("uiDockedComposeTweet", this.uiComposeTweetEvent);
-  $(document).off("click", ".js-account-list .js-account-item", this.onSelectedAccountChanged);
+	$(document).off("uiInlineComposeTweet", this.uiComposeTweetEvent);
+	$(document).off("uiDockedComposeTweet", this.uiComposeTweetEvent);
+	$(document).off("click", ".js-account-list .js-account-item", this.onSelectedAccountChanged);
 }
diff --git a/Resources/Plugins/templates/browser.js b/Resources/Plugins/templates/browser.js
index 5affe0f5..c050cace 100644
--- a/Resources/Plugins/templates/browser.js
+++ b/Resources/Plugins/templates/browser.js
@@ -1,403 +1,403 @@
 enabled(){
-  let me = this;
-  
-  // configuration
-  
-  this.config = {
-    templates: {} // identifier: { name, contents }
-  };
-  
-  const configFile = "config.json";
-  
-  $TDP.checkFileExists(this.$token, configFile).then(exists => {
-    if (!exists){
-      $TDP.writeFile(this.$token, configFile, JSON.stringify(this.config));
-    }
-    else{
-      $TDP.readFile(this.$token, configFile, true).then(contents => {
-        try{
-          $.extend(true, this.config, JSON.parse(contents));
-        }catch(err){
-          // why :(
-        }
-      }).catch(err => {
-        $TD.alert("error", "Problem loading configuration for the template plugin: "+err.message);
-      });
-    }
-  });
-  
-  this.saveConfig = () => {
-    $TDP.writeFile(this.$token, configFile, JSON.stringify(this.config)).catch(err => {
-      $TD.alert("error", "Problem saving configuration for the template plugin: "+err.message);
-    });
-  };
-  
-  // setup
-  
-  this.htmlModal = null;
-  
-  $TDP.readFileRoot(this.$token, "modal.html").then(contents => {
-    this.htmlModal = contents;
-  }).catch(err => {
-    $TD.alert("error", "Problem loading data for the template plugin: "+err.message);
-  });
-  
-  // button
-  
-  let buttonHTML = '<button class="manage-templates-btn needsclick btn btn-on-blue full-width txt-left margin-b--12 padding-v--6 padding-h--12"><i class="icon icon-bookmark"></i><span class="label padding-ls">Manage templates</span></button>';
-  
-  this.prevComposeMustache = TD.mustaches["compose/docked_compose.mustache"];
-  window.TDPF_injectMustache("compose/docked_compose.mustache", "prepend", '<div class="js-tweet-type-button">', buttonHTML);
-  
-  let dockedComposePanel = $(".js-docked-compose");
-  
-  if (dockedComposePanel.length){
-    dockedComposePanel.find(".js-tweet-type-button").first().before(buttonHTML);
-  }
-  
-  // template implementation
-  
-  const readTemplateTokens = (contents, tokenData) => {
-    let startIndex = -1;
-    let endIndex = -1;
-    
-    let data = [];
-    let tokenNames = Object.keys(tokenData);
-    
-    for(let currentIndex = 0; currentIndex < contents.length; currentIndex++){
-      if (contents[currentIndex] === '\\'){
-        contents = contents.substring(0, currentIndex)+contents.substring(currentIndex+1);
-        continue;
-      }
-      else if (contents[currentIndex] !== '{'){
-        continue;
-      }
-      
-      startIndex = currentIndex+1;
-      
-      for(; startIndex < contents.length; startIndex++){
-        if (!tokenNames.some(name => contents[startIndex] === name[startIndex-currentIndex-1])){
-          break;
-        }
-      }
-      
-      endIndex = startIndex;
-      
-      let token = contents.substring(currentIndex+1, startIndex);
-      let replacement = tokenData[token] || "";
-      
-      let entry = [ token, currentIndex ];
-      
-      if (contents[endIndex] === '#'){
-        ++endIndex;
-        
-        let bracketCount = 1;
-        
-        for(; endIndex < contents.length; endIndex++){
-          if (contents[endIndex] === '{'){
-            ++bracketCount;
-          }
-          else if (contents[endIndex] === '}'){
-            if (--bracketCount === 0){
-              entry.push(contents.substring(startIndex+1, endIndex));
-              break;
-            }
-          }
-          else if (contents[endIndex] === '#'){
-            entry.push(contents.substring(startIndex+1, endIndex));
-            startIndex = endIndex;
-          }
-          else if (contents[endIndex] === '\\'){
-            contents = contents.substring(0, endIndex)+contents.substring(endIndex+1);
-          }
-        }
-      }
-      else if (contents[endIndex] !== '}'){
-        continue;
-      }
-      
-      data.push(entry);
-      
-      contents = contents.substring(0, currentIndex)+replacement+contents.substring(endIndex+1);
-      currentIndex += replacement.length;
-    }
-    
-    return [ contents, data ];
-  };
-  
-  const doAjaxRequest = (index, url, evaluator) => {
-    return new Promise((resolve, reject) => {
-      if (!url){
-        resolve([ index, "{ajax}" ]);
-        return;
-      }
-      
-      $TD.makeGetRequest(url, function(data){
-        if (evaluator){
-          resolve([ index, eval(evaluator.replace(/\$/g, "'"+data.replace(/(["'\\\n\r\u2028\u2029])/g, "\\$1")+"'"))]);
-        }
-        else{
-          resolve([ index, data ]);
-        }
-      }, function(err){
-        resolve([ index, "" ]);
-        $TD.alert("error", "Error executing AJAX request: "+err);
-      });
-    });
-  };
-  
-  const useTemplate = (contents, append) => {
-    let ele = $(".js-compose-text");
-    if (ele.length === 0) {
-      return;
-    }
-    
-    let value = append ? ele.val()+contents : contents;
-    let prevLength = value.length;
-    
-    let tokens = null;
-    
-    [value, tokens] = readTemplateTokens(value, {
-      "cursor": "",
-      "ajax": "(...)"
-    });
-    
-    ele.val(value);
-    ele.trigger("change");
-    ele.focus();
-    
-    ele[0].selectionStart = ele[0].selectionEnd = value.length;
-    
-    let promises = [];
-    let indexOffset = 0;
-    
-    for(let token of tokens){
-      switch(token[0]){
-        case "cursor":
-          let [, index1, length ] = token;
-          ele[0].selectionStart = index1;
-          ele[0].selectionEnd = index1+(length | 0 || 0);
-          break;
-          
-        case "ajax":
-          let [, index2, evaluator, url ] = token;
-          
-          if (!url){
-            url = evaluator;
-            evaluator = null;
-          }
-          
-          promises.push(doAjaxRequest(index2, url, evaluator));
-          break;
-      }
-    }
-    
-    if (promises.length > 0){
-      let selStart = ele[0].selectionStart;
-      let selEnd = ele[0].selectionEnd;
-      
-      ele.prop("disabled", true);
-      
-      Promise.all(promises).then(values => {
-        const placeholderLen = 5; // "(...)".length
-        let indexOffset = 0;
-        
-        for(let value of values){
-          let diff = value[1].length-placeholderLen;
-          let realIndex = indexOffset+value[0];
-          
-          let val = ele.val();
-          ele.val(val.substring(0, realIndex)+value[1]+val.substring(realIndex+placeholderLen));
-          
-          indexOffset += diff;
-        }
-        
-        ele.prop("disabled", false);
-        ele.trigger("change");
-        ele.focus();
-        
-        ele[0].selectionStart = selStart+indexOffset;
-        ele[0].selectionEnd = selEnd+indexOffset;
-      });
-    }
-    
-    if (!append){
-      hideTemplateModal();
-    }
-  };
-  
-  // modal dialog
-  
-  this.editingTemplate = null;
-  
-  const showTemplateModal = () => {
-    $(".js-app-content").prepend(this.htmlModal);
-    
-    /* TODO possibly implement this later
-    
-    <li>{paste}</li>
-    <li>Paste text or an image from clipboard</li>
-    <li>{paste#text}</li>
-    <li>Paste only if clipboard has text</li>
-    <li>{paste#image}</li>
-    <li>Paste only if clipboard has an image</li>
-    
-    */
-    
-    let ele = $("#templates-modal-wrap").first();
-    
-    ele.on("click", "li[data-template]", function(e){
-      let template = me.config.templates[$(this).attr("data-template")];
-      useTemplate(template.contents, e.shiftKey);
-    });
-    
-    ele.on("click", "li[data-template] i[data-action]", function(e){
-      let identifier = $(this).closest("li").attr("data-template");
-      
-      switch($(this).attr("data-action")){
-        case "edit-template":
-          let editor = $("#template-editor");
-          
-          if (editor.hasClass("invisible")){
-            toggleEditor();
-          }
-          
-          let template = me.config.templates[identifier];
-          $("[name='template-name']", editor).val(template.name);
-          $("[name='template-contents']", editor).val(template.contents);
-          
-          me.editingTemplate = identifier;
-          break;
-          
-        case "delete-template":
-          delete me.config.templates[identifier];
-          onTemplatesUpdated(true);
-          
-          if (me.editingTemplate === identifier){
-            me.editingTemplate = null;
-          }
-          
-          break;
-      }
-      
-      e.stopPropagation();
-    });
-    
-    ele.on("click", ".template-editor-tips-button", function(e){
-      $(this).children(".icon").toggleClass("icon-arrow-d icon-arrow-u");
-      ele.find(".template-editor-tips").toggle();
-    });
-    
-    ele.on("click", "button", function(e){
-      switch($(this).attr("data-action")){
-        case "new-template":
-        case "editor-cancel":
-          toggleEditor();
-          break;
-          
-        case "editor-confirm":
-          let editor = $("#template-editor");
-          
-          if (me.editingTemplate !== null){
-            delete me.config.templates[me.editingTemplate];
-          }
-          
-          let name = $("[name='template-name']", editor).val();
-          let identifier = name.toLowerCase().replace(/[^a-z0-9]/g, "")+"-"+(Math.random().toString(36).substring(2, 7));
-          
-          if (name.trim().length === 0){
-            alert("Please, include a name for your template.");
-            $("[name='template-name']", editor).focus();
-            return;
-          }
-          
-          me.config.templates[identifier] = {
-            name: name,
-            contents: $("[name='template-contents']", editor).val()
-          };
-          
-          toggleEditor();
-          onTemplatesUpdated(true);
-          break;
-        
-        case "close":
-          hideTemplateModal();
-          break;
-      }
-      
-      $(this).blur();
-    });
-    
-    onTemplatesUpdated(false);
-  };
-  
-  const hideTemplateModal = () => {
-    $("#templates-modal-wrap").remove();
-  };
-  
-  const toggleEditor = () => {
-    let editor = $("#template-editor");
-    $("[name]", editor).val("");
-    
-    if ($("button[data-action='new-template']", "#template-list").add(editor).toggleClass("invisible").hasClass("invisible")){
-      me.editingTemplate = null;
-    }
-  };
-  
-  const onTemplatesUpdated = (save) => {
-    let eles = [];
-    
-    for(let identifier of Object.keys(this.config.templates)){
-      eles.push(`<li data-template="${identifier}">
+	let me = this;
+	
+	// configuration
+	
+	this.config = {
+		templates: {} // identifier: { name, contents }
+	};
+	
+	const configFile = "config.json";
+	
+	$TDP.checkFileExists(this.$token, configFile).then(exists => {
+		if (!exists) {
+			$TDP.writeFile(this.$token, configFile, JSON.stringify(this.config));
+		}
+		else {
+			$TDP.readFile(this.$token, configFile, true).then(contents => {
+				try {
+					$.extend(true, this.config, JSON.parse(contents));
+				} catch (err) {
+					// why :(
+				}
+			}).catch(err => {
+				$TD.alert("error", "Problem loading configuration for the template plugin: " + err.message);
+			});
+		}
+	});
+	
+	this.saveConfig = () => {
+		$TDP.writeFile(this.$token, configFile, JSON.stringify(this.config)).catch(err => {
+			$TD.alert("error", "Problem saving configuration for the template plugin: " + err.message);
+		});
+	};
+	
+	// setup
+	
+	this.htmlModal = null;
+	
+	$TDP.readFileRoot(this.$token, "modal.html").then(contents => {
+		this.htmlModal = contents;
+	}).catch(err => {
+		$TD.alert("error", "Problem loading data for the template plugin: " + err.message);
+	});
+	
+	// button
+	
+	let buttonHTML = "<button class=\"manage-templates-btn needsclick btn btn-on-blue full-width txt-left margin-b--12 padding-v--6 padding-h--12\"><i class=\"icon icon-bookmark\"></i><span class=\"label padding-ls\">Manage templates</span></button>";
+	
+	this.prevComposeMustache = TD.mustaches["compose/docked_compose.mustache"];
+	window.TDPF_injectMustache("compose/docked_compose.mustache", "prepend", "<div class=\"js-tweet-type-button\">", buttonHTML);
+	
+	let dockedComposePanel = $(".js-docked-compose");
+	
+	if (dockedComposePanel.length) {
+		dockedComposePanel.find(".js-tweet-type-button").first().before(buttonHTML);
+	}
+	
+	// template implementation
+	
+	const readTemplateTokens = (contents, tokenData) => {
+		let startIndex = -1;
+		let endIndex = -1;
+		
+		let data = [];
+		let tokenNames = Object.keys(tokenData);
+		
+		for (let currentIndex = 0; currentIndex < contents.length; currentIndex++) {
+			if (contents[currentIndex] === "\\") {
+				contents = contents.substring(0, currentIndex) + contents.substring(currentIndex + 1);
+				continue;
+			}
+			else if (contents[currentIndex] !== "{") {
+				continue;
+			}
+			
+			startIndex = currentIndex + 1;
+			
+			for (; startIndex < contents.length; startIndex++) {
+				if (!tokenNames.some(name => contents[startIndex] === name[startIndex - currentIndex - 1])) {
+					break;
+				}
+			}
+			
+			endIndex = startIndex;
+			
+			let token = contents.substring(currentIndex + 1, startIndex);
+			let replacement = tokenData[token] || "";
+			
+			let entry = [ token, currentIndex ];
+			
+			if (contents[endIndex] === "#") {
+				++endIndex;
+				
+				let bracketCount = 1;
+				
+				for (; endIndex < contents.length; endIndex++) {
+					if (contents[endIndex] === "{") {
+						++bracketCount;
+					}
+					else if (contents[endIndex] === "}") {
+						if (--bracketCount === 0) {
+							entry.push(contents.substring(startIndex + 1, endIndex));
+							break;
+						}
+					}
+					else if (contents[endIndex] === "#") {
+						entry.push(contents.substring(startIndex + 1, endIndex));
+						startIndex = endIndex;
+					}
+					else if (contents[endIndex] === "\\") {
+						contents = contents.substring(0, endIndex) + contents.substring(endIndex + 1);
+					}
+				}
+			}
+			else if (contents[endIndex] !== "}") {
+				continue;
+			}
+			
+			data.push(entry);
+			
+			contents = contents.substring(0, currentIndex) + replacement + contents.substring(endIndex + 1);
+			currentIndex += replacement.length;
+		}
+		
+		return [ contents, data ];
+	};
+	
+	const doAjaxRequest = (index, url, evaluator) => {
+		return new Promise((resolve, reject) => {
+			if (!url) {
+				resolve([ index, "{ajax}" ]);
+				return;
+			}
+			
+			$TD.makeGetRequest(url, function(data) {
+				if (evaluator) {
+					resolve([ index, eval(evaluator.replace(/\$/g, "'" + data.replace(/(["'\\\n\r\u2028\u2029])/g, "\\$1") + "'")) ]);
+				}
+				else {
+					resolve([ index, data ]);
+				}
+			}, function(err) {
+				resolve([ index, "" ]);
+				$TD.alert("error", "Error executing AJAX request: " + err);
+			});
+		});
+	};
+	
+	const useTemplate = (contents, append) => {
+		let ele = $(".js-compose-text");
+		if (ele.length === 0) {
+			return;
+		}
+		
+		let value = append ? ele.val() + contents : contents;
+		let prevLength = value.length;
+		
+		let tokens = null;
+		
+		[ value, tokens ] = readTemplateTokens(value, {
+			"cursor": "",
+			"ajax": "(...)"
+		});
+		
+		ele.val(value);
+		ele.trigger("change");
+		ele.focus();
+		
+		ele[0].selectionStart = ele[0].selectionEnd = value.length;
+		
+		let promises = [];
+		let indexOffset = 0;
+		
+		for (let token of tokens) {
+			switch (token[0]) {
+				case "cursor":
+					let [ , index1, length ] = token;
+					ele[0].selectionStart = index1;
+					ele[0].selectionEnd = index1 + (length | 0 || 0);
+					break;
+				
+				case "ajax":
+					let [ , index2, evaluator, url ] = token;
+					
+					if (!url) {
+						url = evaluator;
+						evaluator = null;
+					}
+					
+					promises.push(doAjaxRequest(index2, url, evaluator));
+					break;
+			}
+		}
+		
+		if (promises.length > 0) {
+			let selStart = ele[0].selectionStart;
+			let selEnd = ele[0].selectionEnd;
+			
+			ele.prop("disabled", true);
+			
+			Promise.all(promises).then(values => {
+				const placeholderLen = 5; // "(...)".length
+				let indexOffset = 0;
+				
+				for (let value of values) {
+					let diff = value[1].length - placeholderLen;
+					let realIndex = indexOffset + value[0];
+					
+					let val = ele.val();
+					ele.val(val.substring(0, realIndex) + value[1] + val.substring(realIndex + placeholderLen));
+					
+					indexOffset += diff;
+				}
+				
+				ele.prop("disabled", false);
+				ele.trigger("change");
+				ele.focus();
+				
+				ele[0].selectionStart = selStart + indexOffset;
+				ele[0].selectionEnd = selEnd + indexOffset;
+			});
+		}
+		
+		if (!append) {
+			hideTemplateModal();
+		}
+	};
+	
+	// modal dialog
+	
+	this.editingTemplate = null;
+	
+	const showTemplateModal = () => {
+		$(".js-app-content").prepend(this.htmlModal);
+		
+		/* TODO possibly implement this later
+		
+		<li>{paste}</li>
+		<li>Paste text or an image from clipboard</li>
+		<li>{paste#text}</li>
+		<li>Paste only if clipboard has text</li>
+		<li>{paste#image}</li>
+		<li>Paste only if clipboard has an image</li>
+		
+		*/
+		
+		let ele = $("#templates-modal-wrap").first();
+		
+		ele.on("click", "li[data-template]", function(e) {
+			let template = me.config.templates[$(this).attr("data-template")];
+			useTemplate(template.contents, e.shiftKey);
+		});
+		
+		ele.on("click", "li[data-template] i[data-action]", function(e) {
+			let identifier = $(this).closest("li").attr("data-template");
+			
+			switch ($(this).attr("data-action")) {
+				case "edit-template":
+					let editor = $("#template-editor");
+					
+					if (editor.hasClass("invisible")) {
+						toggleEditor();
+					}
+					
+					let template = me.config.templates[identifier];
+					$("[name='template-name']", editor).val(template.name);
+					$("[name='template-contents']", editor).val(template.contents);
+					
+					me.editingTemplate = identifier;
+					break;
+				
+				case "delete-template":
+					delete me.config.templates[identifier];
+					onTemplatesUpdated(true);
+					
+					if (me.editingTemplate === identifier) {
+						me.editingTemplate = null;
+					}
+					
+					break;
+			}
+			
+			e.stopPropagation();
+		});
+		
+		ele.on("click", ".template-editor-tips-button", function(e) {
+			$(this).children(".icon").toggleClass("icon-arrow-d icon-arrow-u");
+			ele.find(".template-editor-tips").toggle();
+		});
+		
+		ele.on("click", "button", function(e) {
+			switch ($(this).attr("data-action")) {
+				case "new-template":
+				case "editor-cancel":
+					toggleEditor();
+					break;
+				
+				case "editor-confirm":
+					let editor = $("#template-editor");
+					
+					if (me.editingTemplate !== null) {
+						delete me.config.templates[me.editingTemplate];
+					}
+					
+					let name = $("[name='template-name']", editor).val();
+					let identifier = name.toLowerCase().replace(/[^a-z0-9]/g, "") + "-" + (Math.random().toString(36).substring(2, 7));
+					
+					if (name.trim().length === 0) {
+						alert("Please, include a name for your template.");
+						$("[name='template-name']", editor).focus();
+						return;
+					}
+					
+					me.config.templates[identifier] = {
+						name: name,
+						contents: $("[name='template-contents']", editor).val()
+					};
+					
+					toggleEditor();
+					onTemplatesUpdated(true);
+					break;
+				
+				case "close":
+					hideTemplateModal();
+					break;
+			}
+			
+			$(this).blur();
+		});
+		
+		onTemplatesUpdated(false);
+	};
+	
+	const hideTemplateModal = () => {
+		$("#templates-modal-wrap").remove();
+	};
+	
+	const toggleEditor = () => {
+		let editor = $("#template-editor");
+		$("[name]", editor).val("");
+		
+		if ($("button[data-action='new-template']", "#template-list").add(editor).toggleClass("invisible").hasClass("invisible")) {
+			me.editingTemplate = null;
+		}
+	};
+	
+	const onTemplatesUpdated = (save) => {
+		let eles = [];
+		
+		for (let identifier of Object.keys(this.config.templates)) {
+			eles.push(`<li data-template="${identifier}">
 <span class="template-name">${this.config.templates[identifier].name}</span>
 <span class="template-actions"><i class="icon icon-edit" data-action="edit-template"></i><i class="icon icon-close" data-action="delete-template"></i></span>
 </li>`);
-    }
-    
-    if (eles.length === 0){
-      eles.push("<li>No templates available</li>");
-    }
-    
-    $("#template-list").children("ul").html(eles.join(""));
-    
-    if (save){
-      this.saveConfig();
-    }
-  };
-  
-  // event handlers
-  
-  this.manageTemplatesButtonClickEvent = function(e){
-    if ($("#templates-modal-wrap").length){
-      hideTemplateModal();
-    }
-    else{
-      showTemplateModal();
-    }
-    
-    $(this).blur();
-  };
-  
-  this.drawerToggleEvent = function(e, data){
-    if (typeof data === "undefined" || data.activeDrawer !== "compose"){
-      hideTemplateModal();
-    }
-  };
+		}
+		
+		if (eles.length === 0) {
+			eles.push("<li>No templates available</li>");
+		}
+		
+		$("#template-list").children("ul").html(eles.join(""));
+		
+		if (save) {
+			this.saveConfig();
+		}
+	};
+	
+	// event handlers
+	
+	this.manageTemplatesButtonClickEvent = function(e) {
+		if ($("#templates-modal-wrap").length) {
+			hideTemplateModal();
+		}
+		else {
+			showTemplateModal();
+		}
+		
+		$(this).blur();
+	};
+	
+	this.drawerToggleEvent = function(e, data) {
+		if (typeof data === "undefined" || data.activeDrawer !== "compose") {
+			hideTemplateModal();
+		}
+	};
 }
 
 ready(){
-  $(".js-drawer[data-drawer='compose']").on("click", ".manage-templates-btn", this.manageTemplatesButtonClickEvent);
-  $(document).on("uiDrawerActive", this.drawerToggleEvent);
-  $(document).on("click", ".js-new-composer-opt-in", this.drawerToggleEvent);
+	$(".js-drawer[data-drawer='compose']").on("click", ".manage-templates-btn", this.manageTemplatesButtonClickEvent);
+	$(document).on("uiDrawerActive", this.drawerToggleEvent);
+	$(document).on("click", ".js-new-composer-opt-in", this.drawerToggleEvent);
 }
 
 disabled(){
-  $(".manage-templates-btn").remove();
-  $("#templates-modal-wrap").remove();
-  
-  $(".js-drawer[data-drawer='compose']").off("click", ".manage-templates-btn", this.manageTemplatesButtonClickEvent);
-  $(document).off("uiDrawerActive", this.drawerToggleEvent);
-  $(document).off("click", ".js-new-composer-opt-in", this.drawerToggleEvent);
-  
-  TD.mustaches["compose/docked_compose.mustache"] = this.prevComposeMustache;
+	$(".manage-templates-btn").remove();
+	$("#templates-modal-wrap").remove();
+	
+	$(".js-drawer[data-drawer='compose']").off("click", ".manage-templates-btn", this.manageTemplatesButtonClickEvent);
+	$(document).off("uiDrawerActive", this.drawerToggleEvent);
+	$(document).off("click", ".js-new-composer-opt-in", this.drawerToggleEvent);
+	
+	TD.mustaches["compose/docked_compose.mustache"] = this.prevComposeMustache;
 }
diff --git a/Resources/Plugins/timeline-polls/browser.js b/Resources/Plugins/timeline-polls/browser.js
index 1b854f80..4802836c 100644
--- a/Resources/Plugins/timeline-polls/browser.js
+++ b/Resources/Plugins/timeline-polls/browser.js
@@ -1,76 +1,76 @@
 enabled(){
-  // styles
-  
-  this.css = window.TDPF_createCustomStyle(this);
-  this.css.insert("html[data-td-theme='dark'] .quoted-tweet .td-timeline-poll { color: #e1e8ed; }");
-  
-  // utility functions
-  
-  const hasPoll = function(tweet){
-    return tweet.hasPoll && tweet.hasPoll();
-  };
-  
-  const renderTweetPoll = function(tweet){
-    return `<div class='td-timeline-poll'>${TD.ui.template.render("status/poll", $.extend({}, tweet, {
-      chirp: tweet
-    }))}</div>`;
-  };
-  
-  const renderPollHook = function(tweet, html){
-    let ele = null;
-    
-    if (hasPoll(tweet)){
-      (ele || (ele = $(html))).find(".js-tweet-body").first().children("div").last().after(renderTweetPoll(tweet));
-    }
-    
-    if (tweet.quotedTweet && hasPoll(tweet.quotedTweet)){
-      (ele || (ele = $(html))).find(".js-quoted-tweet-text").first().after(renderTweetPoll(tweet.quotedTweet));
-    }
-    
-    if (ele){
-      ele.find(".js-card-container").css("display", "none");
-      return ele.prop("outerHTML");
-    }
-    else{
-      return html;
-    }
-  };
-  
-  // hooks
-  
-  const funcs = {
-    TwitterStatus: TD.services.TwitterStatus.prototype.render,
-    TwitterActionOnTweet: TD.services.TwitterActionOnTweet.prototype.render,
-    TweetDetailView: TD.components.TweetDetailView.prototype._renderChirp
-  };
-  
-  TD.services.TwitterStatus.prototype.render = function(e){
-    return renderPollHook(this, funcs.TwitterStatus.apply(this, arguments));
-  };
-  
-  TD.services.TwitterActionOnTweet.prototype.render = function(e){
-    return renderPollHook(this.targetTweet, funcs.TwitterActionOnTweet.apply(this, arguments));
-  };
-  
-  TD.components.TweetDetailView.prototype._renderChirp = function(){
-    let result = funcs.TweetDetailView.apply(this, arguments);
-    
-    if (this.mainChirp.quotedTweet && hasPoll(this.mainChirp.quotedTweet)){
-      $(this.$tweetDetail).find(".js-quoted-tweet-text").first().after(renderTweetPoll(this.mainChirp.quotedTweet));
-    }
-    
-    return result;
-  };
-  
-  this.prevRenderFuncs = funcs;
-  window.TDPF_reloadColumns();
+	// styles
+	
+	this.css = window.TDPF_createCustomStyle(this);
+	this.css.insert("html[data-td-theme='dark'] .quoted-tweet .td-timeline-poll { color: #e1e8ed; }");
+	
+	// utility functions
+	
+	const hasPoll = function(tweet) {
+		return tweet.hasPoll && tweet.hasPoll();
+	};
+	
+	const renderTweetPoll = function(tweet) {
+		return `<div class='td-timeline-poll'>${TD.ui.template.render("status/poll", $.extend({}, tweet, {
+			chirp: tweet
+		}))}</div>`;
+	};
+	
+	const renderPollHook = function(tweet, html) {
+		let ele = null;
+		
+		if (hasPoll(tweet)) {
+			(ele || (ele = $(html))).find(".js-tweet-body").first().children("div").last().after(renderTweetPoll(tweet));
+		}
+		
+		if (tweet.quotedTweet && hasPoll(tweet.quotedTweet)) {
+			(ele || (ele = $(html))).find(".js-quoted-tweet-text").first().after(renderTweetPoll(tweet.quotedTweet));
+		}
+		
+		if (ele) {
+			ele.find(".js-card-container").css("display", "none");
+			return ele.prop("outerHTML");
+		}
+		else {
+			return html;
+		}
+	};
+	
+	// hooks
+	
+	const funcs = {
+		TwitterStatus: TD.services.TwitterStatus.prototype.render,
+		TwitterActionOnTweet: TD.services.TwitterActionOnTweet.prototype.render,
+		TweetDetailView: TD.components.TweetDetailView.prototype._renderChirp
+	};
+	
+	TD.services.TwitterStatus.prototype.render = function(e) {
+		return renderPollHook(this, funcs.TwitterStatus.apply(this, arguments));
+	};
+	
+	TD.services.TwitterActionOnTweet.prototype.render = function(e) {
+		return renderPollHook(this.targetTweet, funcs.TwitterActionOnTweet.apply(this, arguments));
+	};
+	
+	TD.components.TweetDetailView.prototype._renderChirp = function() {
+		let result = funcs.TweetDetailView.apply(this, arguments);
+		
+		if (this.mainChirp.quotedTweet && hasPoll(this.mainChirp.quotedTweet)) {
+			$(this.$tweetDetail).find(".js-quoted-tweet-text").first().after(renderTweetPoll(this.mainChirp.quotedTweet));
+		}
+		
+		return result;
+	};
+	
+	this.prevRenderFuncs = funcs;
+	window.TDPF_reloadColumns();
 }
 
 disabled(){
-  TD.services.TwitterStatus.prototype.render = this.prevRenderFuncs.TwitterStatus;
-  TD.services.TwitterActionOnTweet.prototype.render = this.prevRenderFuncs.TwitterActionOnTweet;
-  TD.components.TweetDetailView.prototype._renderChirp = this.prevRenderFuncs.TweetDetailView;
-  
-  this.css.remove();
-  window.TDPF_reloadColumns();
+	TD.services.TwitterStatus.prototype.render = this.prevRenderFuncs.TwitterStatus;
+	TD.services.TwitterActionOnTweet.prototype.render = this.prevRenderFuncs.TwitterActionOnTweet;
+	TD.components.TweetDetailView.prototype._renderChirp = this.prevRenderFuncs.TweetDetailView;
+	
+	this.css.remove();
+	window.TDPF_reloadColumns();
 }