// ==UserScript==
// @name kbin enhancement script
// @description Few small changes to the kbin UI while they still develop some features
// @namespace com.sirpsychomantis
// @license MIT
// @version 1.5
// @grant none
// @run-at document-end
// @match https://fedia.io/*
// @match https://kbin.social/*
// @downloadURL none
// ==/UserScript==
(function(){
const version = "1.5";
const allSettings = [
{name: "Show domains", value:"show-domains"},
{name: "Show collapse comment", value:"show-collapse"},
{name: "Show collapse replies", value:"show-collapse-replies"},
{name: "Replies start collapsed", value:"start-collapse-replies", default: "false"},
{name: "Move comment box to top", value:"comment-box-top"}
];
allSettings.forEach(setting => {
if (setting.default === "false" && localStorage.getItem("setting-" + setting.value) === null) {
localStorage.setItem("setting-" + setting.value, "false");
}
});
function getSetting(setting) {
let value = localStorage.getItem("setting-" + setting);
if (value === null)
value = "true";
return value === "true";
}
function setSetting(setting, value) {
localStorage.setItem("setting-" + setting, value);
location.reload();
}
function addDomain(link) {
const parts = link.title.split("@");
if (parts[2] !== location.hostname && !link.innerText.includes("@" + parts[2])) {
const linkText = link.childNodes[link.childNodes.length-1];
linkText.nodeValue += "@" + parts[2];
}
}
function addDomains() {
document.querySelectorAll(".magazine-inline, .user-inline").forEach(link => {
addDomain(link);
});
}
function getComments(comment, allComments) {
const id = comment.id.split('-')[2];
allComments.push(comment);
const subComments = comment.parentElement.querySelectorAll('blockquote[data-subject-parent-value="'+id+'"]');
subComments.forEach(blockquote => { getComments(blockquote, allComments); });
}
function getCollapsos(comment, allCollapsos) {
const id = comment.id.split('-')[2];
if (comment.classList.contains('kes-expand'))
allCollapsos.push(comment);
const subComments = comment.parentElement.querySelectorAll('blockquote[data-subject-parent-value="'+id+'"]');
subComments.forEach(blockquote => { getCollapsos(blockquote, allCollapsos); });
}
function removeAllCollapsos(blockquote) {
// Just remove all these for now, don't want to figure out how to do this cleanly right now.
const allCollapsos = [];
getCollapsos(blockquote, allCollapsos);
allCollapsos.forEach(comment => { comment.remove() });
}
function expandComment(blockquote) {
const allComments = [];
getComments(blockquote, allComments);
allComments.forEach(comment => { comment.style.display="" });
removeAllCollapsos(blockquote);
}
function collapseComment(blockquote) {
const id = blockquote.id.split('-')[2];
let commentLevel = "1";
blockquote.classList.forEach(classItem => {
if (classItem.includes("comment-level"))
commentLevel = classItem.split("--")[1];
});
const allComments = [];
getComments(blockquote, allComments);
allComments.forEach(comment => { comment.style.display="none" });
const username = blockquote.querySelector("header a").innerText;
const newBlockquote = document.createElement('blockquote');
newBlockquote.className = 'kes-expand section comment entry-comment comment-level--' + commentLevel;
newBlockquote.style = 'grid-gap: 0; padding-left:20px';
newBlockquote.dataset.subjectParentValue = id;
newBlockquote.innerHTML = '';
newBlockquote.querySelector('a').addEventListener("click", () => {expandComment(blockquote)});
blockquote.parentNode.insertBefore(newBlockquote, blockquote);
}
function getTotalReplyCount(blockquote) {
const allComments = [];
getComments(blockquote, allComments);
return allComments.length - 1;
}
function addCollapseLinks() {
if (location.pathname.startsWith('/m')) {
const comments = document.querySelectorAll("blockquote.comment");
comments.forEach(blockquote => {
const menu = blockquote.querySelector("header");
const newA = document.createElement('a');
newA.href = "javascript:;";
newA.className = "kes-collapse";
newA.innerHTML = '[-]';
menu.appendChild(newA);
});
document.querySelectorAll(".kes-collapse").forEach(link => {link.addEventListener("click", () => {
const blockquote = link.closest("blockquote.comment");
collapseComment(blockquote);
})});
}
}
function getAllReplies(blockquote) {
const allComments = [];
getComments(blockquote, allComments);
allComments.splice(allComments.indexOf(blockquote), 1);
return allComments;
}
function toggleReplies(blockquote, display) {
const id = blockquote.id.split('-')[2];
const allReplies = getAllReplies(blockquote);
let anyHidden = false;
allReplies.forEach(reply => {
if (reply.style.display == 'none')
anyHidden = true;
});
allReplies.forEach(comment => { comment.style.display = anyHidden ? '' : 'none' });
removeAllCollapsos(blockquote);
}
function addCollapseRepliesLinks() {
if (location.pathname.startsWith('/m')) {
const comments = document.querySelectorAll("blockquote.comment-level--1");
comments.forEach(blockquote => {
const id = blockquote.id.split('-')[2];
const subComments = blockquote.parentElement.querySelectorAll('blockquote[data-subject-parent-value="'+id+'"]');
if (subComments.length > 0) {
const menu = blockquote.querySelector("footer menu");
const newLi = document.createElement('li');
newLi.innerHTML = 'toggle replies ('+getTotalReplyCount(blockquote)+')';
menu.appendChild(newLi);
}
});
document.querySelectorAll(".kes-collapse-replies").forEach(link => {link.addEventListener("click", () => {
const blockquote = link.closest("blockquote.comment");
toggleReplies(blockquote);
})});
}
}
function collapseAllReplies() {
const comments = document.querySelectorAll("blockquote.comment-level--2");
comments.forEach(blockquote => {
collapseComment(blockquote);
});
}
function moveCommentBox() {
const commentAdd = document.querySelector('#comment-add');
if (commentAdd)
commentAdd.parentNode.insertBefore(commentAdd, document.querySelector('#comments'));
}
function generateSettingDiv(settingDisplay, setting) {
const settingValue = getSetting(setting);
const newDiv = document.createElement('div');
newDiv.className = "row";
newDiv.innerHTML = `${settingDisplay}:
`;
return newDiv;
}
function addHTMLSettings() {
const settingsList = document.querySelector(".settings-list");
const header = document.createElement('strong');
header.textContent = "kbin enhancement script";
settingsList.appendChild(header);
allSettings.forEach(setting => { settingsList.appendChild(generateSettingDiv(setting.name, setting.value)) });
document.querySelectorAll(".kes-setting-yes").forEach(link => { link.addEventListener("click", () => {setSetting(link.dataset.setting, true) })});
document.querySelectorAll(".kes-setting-no").forEach(link => { link.addEventListener("click", () => {setSetting(link.dataset.setting, false) })});
}
addHTMLSettings();
if (getSetting("show-domains"))
addDomains();
if (getSetting("show-collapse"))
addCollapseLinks();
if (getSetting("show-collapse-replies"))
addCollapseRepliesLinks();
if (getSetting("start-collapse-replies"))
collapseAllReplies();
if (getSetting("comment-box-top"))
moveCommentBox();
if (localStorage.getItem("setting-changelog-version") != version) {
const message = `kbin enhancement script version: ${version}
Thanks for downloading! You can always toggle on and off features in the kbin sidebar settings.
Recent changes:
- Added move comment box to top
- Adjusted collapse functionality
- Added hide all replies
- Added hide all replies by default
- Fixed bugs
`
const versionDiv = document.createElement('div');
versionDiv.id = 'kes-version-dialog';
versionDiv.style = 'position: fixed; width: 100vw; height: 100vh; top: 0; left: 0; display: flex; align-items: center; justify-content: center; background-color: rgba(0,0,0,.3); z-index: 9999999';
versionDiv.innerHTML = ''+message+'
';
document.body.appendChild(versionDiv);
document.querySelector('#kes-version-dialog button').addEventListener("click", () => {
document.querySelector('#kes-version-dialog').remove();
localStorage.setItem("setting-changelog-version", version);
});
}
})();