Reddit - Improve Saved Comments

reveals the save and report buttons and makes links right clickable

目前為 2024-06-14 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Reddit - Improve Saved Comments
// @namespace    https://openuserjs.org/users/zachhardesty7
// @author       Zach Hardesty <[email protected]> (https://github.com/zachhardesty7)
// @description  reveals the save and report buttons and makes links right clickable
// @copyright    2019, Zach Hardesty (https://zachhardesty.com/)
// @license      GPL-3.0-only; http://www.gnu.org/licenses/gpl-3.0.txt
// @version      1.2.3

// @homepageURL  https://github.com/zachhardesty7/tamper-monkey-scripts-collection/raw/master/reddit-improve-saved-comments.user.js
// @homepage     https://github.com/zachhardesty7/tamper-monkey-scripts-collection/raw/master/reddit-improve-saved-comments.user.js
// @homepageURL  https://openuserjs.org/scripts/zachhardesty7/Reddit_-_Improve_Saved_Comments
// @homepage     https://openuserjs.org/scripts/zachhardesty7/Reddit_-_Improve_Saved_Comments
// @supportURL   https://github.com/zachhardesty7/tamper-monkey-scripts-collection/issues


// @include      https://www.reddit.com/user/*/saved/*
// @require      https://greasyfork.org/scripts/419640-onelementready/code/onElementReady.js?version=887637
// ==/UserScript==

/* global onElementReady */

/**
 * sometimes you really need access to react internals to fix somebody
 * else's broken app and add no-brainer features
 *
 * @param {HTMLElement} DOMNode - arbitrary DOM node with a hidden react instance
 * @returns {object} react instance object
 */
const getReactInstance = (DOMNode) => DOMNode[Object.keys(DOMNode)[0]]

/**
 * add features to comments
 *
 * @param {HTMLElement} button - triple dot more button under comments
 */
function improveComments(button) {
  const moreComponent = getReactInstance(button)
  const moreComponentProps = moreComponent.return.return.memoizedProps
  const genericButtonClass = button.parentElement.children[0].className

  const reportButton = document.createElement("button")
  reportButton.textContent = "Report"
  reportButton.className = genericButtonClass
  // navigate react obj
  reportButton.addEventListener(
    "click",
    moreComponentProps.children[0].props.onClick,
  )

  // does not dynamically update text content
  const saveButton = document.createElement("button")
  saveButton.textContent = "Save / Unsave"
  saveButton.className = genericButtonClass
  saveButton.addEventListener(
    "click",
    moreComponentProps.children[1].props.onClick,
  )

  // not defined in a separate function just because this is a quick
  // way to ensure that all of the important parts are loaded
  const comment =
    button.parentElement.parentElement.parentElement.parentElement.parentElement
      .parentElement.parentElement.parentElement

  // wrap the entirety of the comment in link el
  const container = comment.parentElement
  const wrapper = document.createElement("a")
  // link to comment page hidden in react instance
  wrapper.href =
    getReactInstance(comment).return.memoizedProps.comment.permalink
  wrapper.append(comment) // move all original DOM children
  wrapper.addEventListener("click", (e) => e.preventDefault()) // allow original click handler to take over

  container.append(wrapper)

  button.parentElement.append(reportButton)
  button.parentElement.append(saveButton)
  button.remove()
}
// gross, but Reddit uses styled-components / emotion and has almost no
// constant selectors that don't change between renders, detail allows react to hydrate first
window.addEventListener(
  "load",
  () => {
    onElementReady(
      "div.Comment > div > div > div:last-child > div > div:nth-child(2) > div:nth-child(2) > div:last-child > button:last-child[aria-haspopup][aria-expanded][aria-label]",
      { findOnce: false },
      improveComments,
    )
  },
  false,
)