Twitter profile replies hider

Hide replies on Twitter profiles

  1. // ==UserScript==
  2. // @name Twitter profile replies hider
  3. // @namespace https://github.com/jerone/UserScripts
  4. // @description Hide replies on Twitter profiles
  5. // @author jerone
  6. // @copyright 2014+, jerone (https://github.com/jerone)
  7. // @license CC-BY-NC-SA-4.0; https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
  8. // @license GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt
  9. // @homepage https://github.com/jerone/UserScripts/tree/master/Hide_replies_on_Twitter_user_account
  10. // @homepageURL https://github.com/jerone/UserScripts/tree/master/Hide_replies_on_Twitter_user_account
  11. // @supportURL https://github.com/jerone/UserScripts/issues
  12. // @contributionURL https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VCYMHWQ7ZMBKW
  13. // @include *://twitter.com/*
  14. // @exclude *://twitter.com/
  15. // @exclude *://twitter.com
  16. // @version 5
  17. // @grant none
  18. // ==/UserScript==
  19.  
  20. (function () {
  21. var settingsKey = "userscript_hide_replies",
  22. selector = ".js-stream-tweet[data-is-reply-to]",
  23. textOn = "Show Replies",
  24. textOff = "Hide Replies";
  25.  
  26. function addMenuItem() {
  27. // ignore own account;
  28. //if(document.body.classList.contains("logged-in") && location.href === document.querySelector(".profile a").href) return;
  29.  
  30. // tweets timeline;
  31. var timeline =
  32. document.getElementById("stream-items-id") ||
  33. document.getElementsByClassName("GridTimeline")[0];
  34. if (!timeline) return;
  35.  
  36. // user menu;
  37. var menuDivider = document.getElementsByClassName(
  38. "dropdown-divider is-following",
  39. )[0];
  40. if (!menuDivider) return;
  41.  
  42. // setting;
  43. var settingSaved = !!~~localStorage.getItem(settingsKey, +true);
  44.  
  45. // work-around to get new tweets;
  46. var loadTweets = function () {
  47. var y = 0;
  48. function scroll() {
  49. y++;
  50. window.scrollTo(
  51. document.documentElement.scrollLeft,
  52. document.documentElement.scrollTop + 1,
  53. );
  54. if (y < 10) {
  55. window.setTimeout(scroll, 13);
  56. } else {
  57. window.scrollTo(
  58. document.documentElement.scrollLeft,
  59. document.documentElement.scrollTop - y,
  60. );
  61. }
  62. }
  63. window.setTimeout(scroll, 13);
  64. };
  65.  
  66. // toggle visibility;
  67. var toggle = function (hide, init) {
  68. window.setTimeout(function () {
  69. Array.forEach(
  70. document.querySelectorAll(selector),
  71. function (tweet) {
  72. tweet.style.display = !hide ? "block" : "none";
  73. },
  74. );
  75.  
  76. if (hide && init) {
  77. loadTweets();
  78. }
  79. });
  80. };
  81.  
  82. // menu item;
  83. var liShow = document.createElement("li");
  84. liShow.appendChild(document.createTextNode(textOn));
  85. liShow.classList.add("dropdown-link");
  86. liShow.style.display = settingSaved ? "block" : "none";
  87. menuDivider.parentNode.insertBefore(liShow, menuDivider.nextSibling);
  88.  
  89. var liHide = document.createElement("li");
  90. liHide.appendChild(document.createTextNode(textOff));
  91. liHide.classList.add("dropdown-link");
  92. liHide.style.display = !settingSaved ? "block" : "none";
  93. menuDivider.parentNode.insertBefore(liHide, menuDivider.nextSibling);
  94.  
  95. liShow.addEventListener("click", function (e) {
  96. e.preventDefault();
  97. localStorage.setItem(settingsKey, +false);
  98. toggle(false);
  99. liShow.style.display = "none";
  100. liHide.style.display = "block";
  101. return false;
  102. });
  103.  
  104. liHide.addEventListener("click", function (e) {
  105. e.preventDefault();
  106. localStorage.setItem(settingsKey, +true);
  107. toggle(true);
  108. liShow.style.display = "block";
  109. liHide.style.display = "none";
  110. return false;
  111. });
  112.  
  113. // new tweets are loaded, handle accordingly;
  114. new MutationObserver(function (mutations) {
  115. mutations.forEach(function () {
  116. toggle(!!~~localStorage.getItem(settingsKey, +true));
  117. });
  118. }).observe(timeline, { childList: true });
  119.  
  120. // load previous state;
  121. toggle(settingSaved, true);
  122. }
  123.  
  124. window.setTimeout(function () {
  125. addMenuItem();
  126.  
  127. unsafeWindow.$(document).on("uiPageChanged", function () {
  128. addMenuItem();
  129. });
  130. }, 1);
  131.  
  132. /* useful for the user popup;
  133. function MutationObserverStyle(elem, property, fn) {
  134. var that = this;
  135. that.propertyChanged = false;
  136. new MutationObserver(function(mutations) {
  137. mutations.forEach(function(mutation) {
  138. if (that.propertyChanged !== (mutation.target.style[property] != "none")) {
  139. that.propertyChanged = !that.propertyChanged;
  140. fn();
  141. }
  142. });
  143. }).observe(elem, { attributes: true, attributeFilter: ["style"] });
  144. }
  145.  
  146. MutationObserverStyle(document.getElementById("profile_popup"), "display", function() {
  147. console.log("MutationObserverStyle propertyChanged");
  148. });
  149. */
  150.  
  151. /* alternative page load;
  152. var window_History_prototype_pushState = window.History.prototype.pushState;
  153. window.History.prototype.pushState = function() {
  154. window_History_prototype_pushState.apply(window.history, arguments);
  155. window.setTimeout(function() {
  156. //init();
  157. document.title = "3" + document.title;
  158. });
  159. };
  160. */
  161. })();