// ==UserScript== // @name Improved Channel Select Menu for Kbin // @namespace http://tampermonkey.net/ // @version 0.3.0 // @description Adds subscribed magazines and liked collections to the channel select menu. // @author NeighborlyFedora // @match *://kbin.social/* // @match *://kbin.earth/* // @icon https://www.google.com/s2/favicons?sz=64&domain=kbin.social // @require https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js // @license GPL-3.0-or-later // @downloadURL https://update.greasyfork.icu/scripts/484196/Improved%20Channel%20Select%20Menu%20for%20Kbin.user.js // @updateURL https://update.greasyfork.icu/scripts/484196/Improved%20Channel%20Select%20Menu%20for%20Kbin.meta.js // ==/UserScript== //Code partially based on Floating Subs List by raltsm4k (https://greasyfork.org/en/scripts/469121-floating-subs-list) let user; let cacheId; let subs = []; let clls = []; let subsHtml = []; let cllsHtml = []; let settings = { cllsFirst: true, cacheEnabled: true, defaultIcons: true, fillOnChange: true }; const SETTINGS_TEXT = { cllsFirst: "List liked collections before subscribed magazines.", cacheEnabled: "Cache menu items for faster loading.", defaultIcons: "Add placeholder icons to collections and iconless magazines.", fillOnChange: "Immediately reload menu when a magazine is subscribed to." } let settingsOpen = false; let isFilling = false; let fetchTries = 3; main(); const observer = new MutationObserver( function(records){ for(const record of records){ if( Array.from(record.addedNodes).filter(node => node.nodeName == "BODY").length ){ main(); } if(settings["fillOnChange"]){ const subButtons = Array.from(record.addedNodes).filter( node => node.classList !== undefined && node.classList.contains("magazine__subscribe") ); if(subButtons.length){ fill(); }; } } }); observer.observe(document,{subtree: true, childList: true}); function main() { "use strict"; user = document.querySelector("#header a.login").getAttribute("href"); cacheId = "icsm_" + user; if(user === "/login") return; const channelList = document.querySelector("#header li:has(a[title='Select a channel']) .dropdown__menu"); Object.assign(channelList, { id: "channel-list" }); let clRefresh = document.querySelector("#cl-refresh") if(clRefresh === null){ clRefresh = Object.assign(document.createElement("button"), { id: "cl-refresh", title: "Refresh list", }); clRefresh.appendChild(Object.assign(document.createElement("i"), { className: "fa-solid fa-rotate" })); } channelList.prepend(clRefresh); clRefresh.addEventListener("click", fill); let clSettings = document.querySelector("#cl-settings") if(clSettings === null){ clSettings = Object.assign(document.createElement("button"), { id: "cl-settings", title: "Settings", }); clSettings.appendChild(Object.assign(document.createElement("i"), { className: "fa-solid fa-gear" })); } channelList.prepend(clSettings); clSettings.addEventListener("click", function(){ if(settingsOpen){ closeSettings(); }else{ openSettings(); } settingsOpen = !settingsOpen; }); $(document).on("keydown", function(event) { if(event.key == "Escape"){ closeSettings(); } }); const icsmSettings = Object.assign(document.createElement("ul"), { id: "icsm-settings" }); $(icsmSettings).hide(); channelList.append(icsmSettings); icsmSettings.append(Object.assign(document.createElement("h3"), { textContent: "Settings" })); $("