userscripts/Tildes with -Newest reply-....

103 lines
3.2 KiB
JavaScript

// ==UserScript==
// @name Tildes with "Newest reply"
// @namespace blankie-scripts
// @match https://tildes.net/*
// @version 1.0.2
// @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 most nested reply
while (true) {
let reply = li.querySelector(".comment-tree-item");
if (!reply) {
break;
}
li = reply;
}
return new Date(li.querySelector(".comment-header .comment-posted-time").dateTime);
}
function sortCommentsByNewestReply(ol = null, sortedCommentTrees = null) {
ol = ol || document.querySelector("#comments");
sortedCommentTrees = sortedCommentTrees || new WeakSet();
let comments = [];
for (let li of ol.children) {
let commentTree = li.querySelector(".comment-tree");
if (!commentTree || sortedCommentTrees.has(commentTree)) {
continue;
}
sortedCommentTrees.add(commentTree);
sortCommentsByNewestReply(commentTree, sortedCommentTrees);
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();
}