From fab80b926658c42bc07d9c7fad2181f0c5192fb0 Mon Sep 17 00:00:00 2001 From: blankie Date: Sun, 3 Mar 2024 14:41:04 +1100 Subject: [PATCH] Add Tildes with "Newest reply" --- README.md | 5 ++ Tildes with -Newest reply-.user.js | 90 ++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 Tildes with -Newest reply-.user.js diff --git a/README.md b/README.md index ab3c5bf..2d04d4e 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,11 @@ A userscript that adds a "Close toolbar" and "Open toolbar" button ![A man yelling "I DON'T WANNA", followed by sign up/login boxes](https://gitlab.com/blankX/userscripts/-/raw/master/accounts.jpg) +## Tildes with "Newest reply" + +A userscript that adds a "newest reply" sort option for topics (see also: +https://gitlab.com/tildes/tildes/-/issues/111) + ## Tumblr Unnagger A script that removes several login/account walls on Tumblr diff --git a/Tildes with -Newest reply-.user.js b/Tildes with -Newest reply-.user.js new file mode 100644 index 0000000..856e663 --- /dev/null +++ b/Tildes with -Newest reply-.user.js @@ -0,0 +1,90 @@ +// ==UserScript== +// @name Tildes with "Newest reply" +// @namespace blankie-scripts +// @match https://tildes.net/* +// @version 1.0.0 +// @author blankie +// @description A userscript that adds a "newest reply" to topics on Tildes +// @inject-into content +// @run-at document-end +// ==/UserScript== + +"use strict"; + +function commentSortKey(li) { + // Set `li` to the first reply if possible + li = li.querySelector(".comment-tree-item") || li; + return new Date(li.querySelector(".comment-header .comment-posted-time").dateTime); +} + +function sortCommentsByNewestReply(ol = null) { + ol = ol || document.querySelector("#comments"); + + let comments = []; + for (let li of ol.children) { + sortCommentsByNewestReply(li.querySelector(".comment-tree")); + comments.push(li); + } + + comments.sort(function(lhs, rhs) { + // `rhs - lhs` sorts by reverse chronological order, while `lhs - rhs` + // sorts by chronological order + return commentSortKey(rhs) - commentSortKey(lhs); + }); + + for (let li of comments) { + ol.append(li); + } +} + +function sortFormSubmitHook(event) { + event.preventDefault(); + let searchParams = new URLSearchParams(location.search); + let sortMethod = event.target.querySelector("select").selectedOptions[0].value; + + if (sortMethod === "newest_reply") { + searchParams.delete("comment_order"); + searchParams.set("b_comment_order", "newest_reply"); + history.pushState(null, "", `?${searchParams.toString()}`); + sortCommentsByNewestReply(); + } else { + searchParams.delete("b_comment_order"); + searchParams.set("comment_order", sortMethod); + location.search = searchParams.toString(); + } +} + +function addNewestReply() { + let form = document.querySelector(".topic-comments-header form"); + if (!form) { + return; + } + let searchParams = new URLSearchParams(location.search); + let bCommentOrder = searchParams.get("b_comment_order"); + + let select = form.querySelector("select"); + let newSelect = select.cloneNode(true); + newSelect.removeAttribute("data-js-autosubmit-on-change"); + newSelect.addEventListener("change", function() { + // Auto-submit only if there is no "OK" button + if (!form.querySelector("button[type=submit]")) { + form.requestSubmit(); + } + }); + + let option = document.createElement("option"); + option.value = "newest_reply"; + option.innerText = "newest reply"; + if (bCommentOrder === "newest_reply") { + option.selected = true; + } + newSelect.append(option); + + select.replaceWith(newSelect); + form.addEventListener("submit", sortFormSubmitHook); +} + +addNewestReply(); +if ((new URLSearchParams(location.search)).get("b_comment_order") === "newest_reply") { + sortCommentsByNewestReply(); +}