RPS Hide Read Posts

Hides posts on the RPS homepage when they're clicked & adds a "Mark all as read" button

  1. // ==UserScript==
  2. // @name RPS Hide Read Posts
  3. // @description Hides posts on the RPS homepage when they're clicked & adds a "Mark all as read" button
  4. // @version 5
  5. // @namespace https://github.com/insin/greasemonkey
  6. // @grant none
  7. // @match https://www.rockpapershotgun.com/
  8. // ==/UserScript==
  9.  
  10. // @ts-ignore
  11. let debug = false
  12.  
  13. /**
  14. * @param {HTMLElement} section
  15. * @returns {boolean}
  16. */
  17. function areAllPostsHidden(section) {
  18. return Array.from(section.querySelectorAll('article.summary')).every(
  19. (article) => article.parentElement.style.display === 'none'
  20. )
  21. }
  22.  
  23. /**
  24. * @param {HTMLElement} target
  25. * @returns {string}
  26. */
  27. function getPostClickHref(target) {
  28. if (target.tagName === 'A' && target.closest('article.summary')) {
  29. return /** @type {HTMLAnchorElement} */ (target).pathname
  30. }
  31. return ''
  32. }
  33.  
  34. function postsPage() {
  35. let $style = document.createElement('style')
  36. $style.innerText = `
  37. /* Prevent the top section taking up space when posts are removed */
  38. #content_above {
  39. min-height: unset !important;
  40. }
  41. `
  42. document.head.appendChild($style)
  43.  
  44. /** @type {string[]} */
  45. let clickedPosts = JSON.parse(localStorage.getItem('clickedPosts') || '[]')
  46.  
  47. function hideEmptySections() {
  48. for (let section of /** @type {NodeListOf<HTMLElement>} */ (document.querySelectorAll(
  49. '#content_above, section.featured_tag_shelf, section.latest_shelf, section.shelf, section.supporters_shelf'
  50. ))) {
  51. if (section.style.display === 'none') continue
  52. if (areAllPostsHidden(section)) {
  53. section.style.display = 'none'
  54. }
  55. }
  56. }
  57.  
  58. function hideClickedPosts() {
  59. for (let link of /** @type {NodeListOf<HTMLAnchorElement>} */ (document.querySelectorAll(
  60. 'a.link_overlay'
  61. ))) {
  62. if (clickedPosts.includes(link.pathname)) {
  63. let nodeToHide = link.closest('li')
  64. if (nodeToHide && nodeToHide.style.display !== 'none') {
  65. nodeToHide.style.display = 'none'
  66. }
  67. }
  68. }
  69. hideEmptySections()
  70. }
  71.  
  72. function markAllAsRead(e) {
  73. e.preventDefault()
  74. for (let link of /** @type {NodeListOf<HTMLAnchorElement>} */ (document.querySelectorAll(
  75. 'a.link_overlay'
  76. ))) {
  77. if (!clickedPosts.includes(link.pathname)) {
  78. clickedPosts.unshift(link.pathname)
  79. }
  80. }
  81. localStorage.setItem('clickedPosts', JSON.stringify(clickedPosts))
  82. hideClickedPosts()
  83. }
  84.  
  85. document.addEventListener('click', (e) => {
  86. let target = /** @type {HTMLElement} */ (e.target)
  87. if (e.button === 0 && getPostClickHref(target)) {
  88. // Hold ctrl + shift when clicking a post to hide it without opening it
  89. if (debug || (e.shiftKey && e.ctrlKey)) e.preventDefault()
  90. clickedPosts.unshift(getPostClickHref(target))
  91. localStorage.setItem('clickedPosts', JSON.stringify(clickedPosts))
  92. hideClickedPosts()
  93. }
  94. })
  95.  
  96. document.addEventListener('auxclick', (e) => {
  97. let target = /** @type {HTMLElement} */ (e.target)
  98. if (e.button === 1 && getPostClickHref(target)) {
  99. // Hold ctrl when middle-clicking a post to hide it without opening it
  100. if (debug || e.ctrlKey) e.preventDefault()
  101. clickedPosts.unshift(getPostClickHref(target))
  102. localStorage.setItem('clickedPosts', JSON.stringify(clickedPosts))
  103. hideClickedPosts()
  104. }
  105. })
  106.  
  107. let topButtons = document.querySelector('div.commercial.button_group')
  108. if (topButtons != null) {
  109. let button = document.createElement('a')
  110. button.className = 'button supporter'
  111. button.innerText = 'Mark all as read'
  112. button.href = '#'
  113. button.addEventListener('click', markAllAsRead)
  114. button.id = 'mark-all-as-read'
  115. topButtons.appendChild(button)
  116. }
  117.  
  118. hideClickedPosts()
  119. }
  120.  
  121. if (location.pathname === '/' && !document.querySelector('#mark-all-as-read')) {
  122. postsPage()
  123. }