// ==UserScript== // @name Kbin Subscriptions Panel // @namespace https://perry.dev // @license MIT // @version 2.9 // @description Adds a side panel with all magazine subscriptions. // @author Daniel Pervan // @match https://kbin.social/* // @match https://lab2.kbin.pub/* // @match https://lab3.kbin.pub/* // @icon https://www.google.com/s2/favicons?sz=64&domain=kbin.social // @downloadURL https://update.greasyfork.icu/scripts/469139/Kbin%20Subscriptions%20Panel.user.js // @updateURL https://update.greasyfork.icu/scripts/469139/Kbin%20Subscriptions%20Panel.meta.js // ==/UserScript== (function () { 'use strict'; (() => { var __getOwnPropNames = Object.getOwnPropertyNames; var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; // style-helper:index.js function inject_style(text) { if (typeof document !== "undefined") { var style = document.createElement("style"); var node = document.createTextNode(text); style.appendChild(node); document.head.appendChild(style); } } var init_index = __esm({ "style-helper:index.js"() { } }); // src/style.scss var init_style = __esm({ "src/style.scss"() { init_index(); inject_style('body.subscription-panel-injected.extend-width:not(.subscription-panel-force-mobile,.subscription-panel-open) .kbin-container{max-width:1620px}body.subscription-panel-injected .subscription-panel-modal{position:fixed;top:0;left:0;width:100%;height:100%;z-index:99;background-color:#00000080;display:flex;align-items:center;justify-content:center;backdrop-filter:blur(2px)}body.subscription-panel-injected .subscription-panel-modal-content{background-color:var(--kbin-section-bg);border:var(--kbin-options-border);color:var(--kbin-section-text-color);padding:2rem 1rem;height:fit-content;font-size:.8em;position:relative;max-width:600px;min-width:400px;width:100%;animation:modalopen .2s ease-in-out}body.subscription-panel-injected .subscription-panel-modal-content h1,body.subscription-panel-injected .subscription-panel-modal-content h2,body.subscription-panel-injected .subscription-panel-modal-content h3{margin-top:0;text-align:center;margin-bottom:0}body.subscription-panel-injected .subscription-panel-modal-content h3{opacity:.5;font-size:2em}body.subscription-panel-injected .subscription-panel-modal-content .close{color:#aaa;font-size:28px;cursor:pointer;position:absolute;top:.5rem;right:1rem}body.subscription-panel-injected .subscription-panel-modal-content .close:hover{color:var(--kbin-sidebar-header-text-color)}body.subscription-panel-injected.rounded-edges .subscription-panel-modal-content{border-radius:.5rem}body.subscription-panel-injected.rounded-edges #subscription-panel-content{border-radius:0 0 .5rem .5rem}body.subscription-panel-injected.rounded-edges .subscription-panel-modal .danger{border-radius:.5rem}body.subscription-panel-injected.subscription-panel-sticky:not(.subscription-panel-open).fixed-navbar.topbar #subscription-panel-content{top:calc(50.5px + 1.1rem);max-height:calc(100vh - 50px - 1.1rem - 1em)}body.subscription-panel-injected.subscription-panel-sticky:not(.subscription-panel-open).fixed-navbar #subscription-panel-content{top:50px;max-height:calc(100vh - 50px - 1em)}body.subscription-panel-injected.subscription-panel-sticky:not(.subscription-panel-open).topbar #subscription-panel-content{top:1.1rem;max-height:calc(100vh - 1.1rem - 1em)}body.subscription-panel-injected.subscription-panel-sticky:not(.subscription-panel-open) #subscription-panel-content{position:sticky;overflow:auto;max-height:calc(100vh - 1em);top:0}body.subscription-panel-injected.subscription-panel-sticky:not(.subscription-panel-open) #subscription-panel-content>h3{position:sticky;top:-2.5em;background:var(--kbin-section-bg);z-index:3;margin-bottom:0}body.subscription-panel-injected.subscription-panel-sticky:not(.subscription-panel-open) #subscription-panel-content .search-box-container{position:sticky;top:1.25em;z-index:3;padding:1em 0;background:var(--kbin-section-bg)}body.subscription-panel-injected.subscription-panel-sticky:not(.subscription-panel-open) #subscription-panel-content .search-box-container .search-box-clear{top:1.2em}body.subscription-panel-injected.subscription-panel-sticky:not(.subscription-panel-open) #subscription-panel-content .last-clicked-container h3{position:sticky;top:7em;margin-top:0;z-index:2;background:var(--kbin-section-bg)}body.subscription-panel-injected.subscription-panel-sticky:not(.subscription-panel-open).subscription-panel-collapsed #subscription-panel-content .last-clicked-container h3{top:-1em;padding-top:1em}body.subscription-panel-injected.subscription-panel-sticky:not(.subscription-panel-open) #subscription-panel.edit-mode #subscription-panel-content{padding-top:0}body.subscription-panel-injected.subscription-panel-sticky:not(.subscription-panel-open) #subscription-panel.edit-mode .search-box-container{top:3.5em;margin-top:1em;padding:0 0 1em}body.subscription-panel-injected.subscription-panel-sticky:not(.subscription-panel-open) #subscription-panel.edit-mode #subscription-panel-edit-button{position:sticky;top:-.5em;margin:0;padding-top:1em;z-index:5;background:var(--kbin-section-bg)}body.subscription-panel-injected #subscription-panel .search-box-container{position:relative}body.subscription-panel-injected #subscription-panel .search-box-clear{position:absolute;top:.6em;right:1em;font-size:1.5em;display:none;cursor:pointer;transition:color .2s ease-in-out;animation:searchBoxClearShow .25s ease-in-out}@keyframes searchBoxClearShow{0%{opacity:0;transform:scale(.9)}to{opacity:1;transform:scale(1)}}body.subscription-panel-injected #subscription-panel .search-box-clear:hover{color:var(--kbin-sidebar-header-text-color)}body.subscription-panel-injected #subscription-panel .search-box-clear.active{display:block}body.subscription-panel-injected #subscription-panel-edit-button{position:absolute;top:0;left:0;margin:.5rem;padding:.5rem;z-index:5;color:var(--kbin-section-text-color);font-size:.8em;cursor:pointer;transition:font-size .2s ease-in-out}body.subscription-panel-injected #subscription-panel-edit-button i{transition:transform .2s ease-in-out}body.subscription-panel-injected #subscription-panel-edit-button:not(.active):hover i{color:var(--kbin-sidebar-header-text-color);transform:rotate(-25deg)}body.subscription-panel-injected #subscription-panel-edit-button.active{font-size:1.5em}body.subscription-panel-injected #subscription-panel-edit-button.active:hover{color:var(--kbin-link-hover-color)}body.subscription-panel-injected #subscription-panel-edit-button.active:hover i{transform:scale(1.2)}body.subscription-panel-injected #subscription-panel-settings-button{position:absolute;top:0;right:0;margin:.5rem;padding:.5rem;color:var(--kbin-section-text-color);font-size:.8em;cursor:pointer;transition:transform .2s ease-in-out;z-index:3}body.subscription-panel-injected #subscription-panel-settings-button:hover{color:var(--kbin-sidebar-header-text-color);transform:rotate(25deg)}body.subscription-panel-injected #subscription-panel-settings-button:active{animation:settingsbuttonclick .5s ease-in-out}@keyframes settingsbuttonclick{0%{transform:rotate(0)}to{transform:rotate(360deg)}}body.subscription-panel-injected .subscription-panel-settings-modal-content{max-width:600px;min-width:400px}body.subscription-panel-injected .subscription-panel-settings-modal-content ul{list-style:none;padding-inline:0}body.subscription-panel-injected .subscription-panel-settings-modal-content ul li{margin-bottom:1rem}body.subscription-panel-injected .subscription-panel-settings-modal-content ul li label{display:block;margin-bottom:.5rem}body.subscription-panel-injected .subscription-panel-settings-modal-content ul li label.danger{background-color:RGBA(255,0,0,.1);border:1px solid RGBA(255,0,0,.5);padding:.5rem;color:var(--kbin-section-text-color);margin:2em 0}body.subscription-panel-injected .subscription-panel-settings-modal-content ul li .description{font-size:.8em;font-weight:100;font-style:italic;opacity:.8}body.subscription-panel-injected .subscription-panel-settings-modal-content ul li input[type=checkbox]{margin-right:.5rem}body.subscription-panel-injected .subscription-panel-settings-modal-content ul li input[type=button]{margin-right:.5rem;padding:.5rem}body.subscription-panel-injected .subscription-panel-settings-modal-content ul li input[type=button]:active{opacity:.8}body.subscription-panel-injected .subscription-panel-settings-modal-content h2{margin-top:0}@keyframes modalopen{0%{opacity:0;transform:scale(.9)}to{opacity:1;transform:scale(1)}}body.subscription-panel-injected #subscription-panel-collapse-button{position:relative;display:inline-block;right:0;margin:.5rem;padding:.5rem;color:var(--kbin-section-text-color);font-size:.8em;cursor:pointer;transition:transform .2s ease-in-out}body.subscription-panel-injected.subscription-panel-collapsed #subscription-panel h3:hover #subscription-panel-collapse-button{transform:translate(2px)}body.subscription-panel-injected #subscription-panel h3:hover #subscription-panel-collapse-button{color:var(--kbin-sidebar-header-text-color);transform:translate(-2px)}body.subscription-panel-injected:not(.subscription-panel-force-mobile,.subscription-panel-open,.sidebar-left) #middle>.kbin-container{grid-template-areas:"subscription-panel main sidebar";grid-template-columns:minmax(200px,1fr) 3fr 1fr}body.subscription-panel-injected.sidebar-left:not(.subscription-panel-force-mobile,.subscription-panel-open) #middle>.kbin-container{grid-template-areas:"sidebar main subscription-panel";grid-template-columns:1fr 3fr minmax(200px,1fr)}body.subscription-panel-injected.subscription-panel-collapsed:not(.subscription-panel-force-mobile,.subscription-panel-open) #middle>.kbin-container{grid-template-columns:minmax(100px,120px) 3fr 1fr}body.subscription-panel-injected.subscription-panel-collapsed.sidebar-left:not(.subscription-panel-force-mobile,.subscription-panel-open) #middle>.kbin-container{grid-template-columns:1fr 3fr minmax(100px,120px)}body.subscription-panel-injected.subscription-panel-collapsed #middle>.kbin-container #subscription-panel #subscription-panel-edit-button{display:none}body.subscription-panel-injected.subscription-panel-collapsed #middle>.kbin-container #subscription-panel #subscription-panel-collapse-button{margin:0;padding:0 .5em}body.subscription-panel-injected.subscription-panel-collapsed #middle>.kbin-container #subscription-panel li{font-size:.8em}body.subscription-panel-injected.subscription-panel-collapsed #middle>.kbin-container #subscription-panel .search-box-container{display:none}body.subscription-panel-injected.subscription-panel-collapsed.subscription-panel-hide-on-collapse #middle>.kbin-container #subscription-panel ul{display:none}body.subscription-panel-injected.subscription-panel-collapsed.subscription-panel-hide-on-collapse #middle>.kbin-container .last-clicked-container{display:none}body.subscription-panel-injected:not(.subscription-panel-force-mobile,.subscription-panel-open) .sidebar-left #middle>.kbin-container{grid-template-areas:"sidebar main subscription-panel";grid-template-columns:1fr 3fr minmax(200px,1fr)}body.subscription-panel-injected.subscription-panel-collapsed:not(.subscription-panel-force-mobile,.subscription-panel-open) .sidebar-left #middle>.kbin-container{grid-template-columns:1fr 3fr minmax(100px,120px)}body.subscription-panel-injected #subscription-panel-content{background-color:var(--kbin-section-bg);border:var(--kbin-options-border);color:var(--kbin-section-text-color);margin-bottom:.5rem;padding:2rem 1rem;height:fit-content;font-size:.8em;margin-right:.5rem;position:relative}body.subscription-panel-injected #subscription-panel.edit-mode h3,body.subscription-panel-injected #subscription-panel.edit-mode .last-clicked-container,body.subscription-panel-injected #subscription-panel.edit-mode #subscription-panel-settings-button{display:none}body.subscription-panel-injected #subscription-panel.edit-mode .search-box-container{margin-top:2em}body.subscription-panel-injected #subscription-panel.edit-mode .group.open>ul{width:auto}body.subscription-panel-injected #subscription-panel h3{border-bottom:var(--kbin-sidebar-header-border);color:var(--kbin-sidebar-header-text-color);font-size:.8rem;margin:0 0 1em;text-transform:uppercase;width:100%}body.subscription-panel-injected #subscription-panel .last-clicked-container{border-bottom:var(--kbin-sidebar-header-border)}body.subscription-panel-injected #subscription-panel .last-clicked-container.hideItem{display:none}body.subscription-panel-injected #subscription-panel .last-clicked-container h3{margin-top:1em}body.subscription-panel-injected #subscription-panel ul{list-style:none;line-height:2.5em;padding-inline:0}body.subscription-panel-injected #subscription-panel ul.fade-in,body.subscription-panel-injected #subscription-panel ul li.fade-in{animation:showItem .5s ease-in-out}body.subscription-panel-injected #subscription-panel ul li{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}body.subscription-panel-injected #subscription-panel ul li.ignore:not(.edit-mode){display:none}body.subscription-panel-injected #subscription-panel ul li.hideItem{animation:hideItem .25s ease-in-out;animation-fill-mode:forwards}body.subscription-panel-injected #subscription-panel ul li .magazine{transition:transform .2s ease-in-out;display:inline-block}body.subscription-panel-injected #subscription-panel ul li .tools .toolItem{display:inline-block;margin-right:.5rem;cursor:pointer;color:var(--kbin-link-color)}body.subscription-panel-injected #subscription-panel ul li .tools .toolItem:hover{color:var(--kbin-link-hover-color)}body.subscription-panel-injected #subscription-panel ul li.starred .toolItem.star{color:RGBA(255,215,0,1)}body.subscription-panel-injected #subscription-panel ul li.starred .toolItem.star:hover{color:RGBA(255,215,0,.8)}body.subscription-panel-injected #subscription-panel ul li.ignore .toolItem.ignore{color:var(--kbin-link-hover-color)}body.subscription-panel-injected #subscription-panel ul li.ignore .toolItem.ignore:hover{opacity:.8}body.subscription-panel-injected #subscription-panel ul li.edit-mode .magazine{transform:translate(3.5em)}body.subscription-panel-injected #subscription-panel ul li.edit-mode.group .count{display:none}body.subscription-panel-injected #subscription-panel ul li.edit-mode .tools{display:inline-block;animation:showTools .5s ease-in-out;position:absolute}@keyframes showTools{0%{opacity:0;transform:scale(.9)}to{opacity:1;transform:scale(1)}}body.subscription-panel-injected #subscription-panel ul li .tools{display:none}body.subscription-panel-injected #subscription-panel ul li a img{height:1.4em;margin-right:.5em;border-radius:50%;vertical-align:middle}body.subscription-panel-injected #subscription-panel ul li.no-image a.magazine{padding-left:1.9em}body.subscription-panel-injected #subscription-panel ul li.group{font-weight:700}body.subscription-panel-injected #subscription-panel ul li.group a.group-name .name{margin-left:.5em}body.subscription-panel-injected #subscription-panel ul li.group a.group-name .count{margin-left:.25em;font-weight:400;opacity:.8}body.subscription-panel-injected #subscription-panel ul li.group a.group-name .image{font-size:1.2em;vertical-align:middle;width:1.2em}body.subscription-panel-injected #subscription-panel ul li.group ul{margin-left:.75em;padding-left:.75em;padding-right:.75em;border-left:var(--kbin-sidebar-header-border);border-bottom:var(--kbin-sidebar-header-border);width:fit-content;border-bottom-left-radius:.5rem;display:none}body.subscription-panel-injected #subscription-panel ul li.group ul li{font-weight:400}body.subscription-panel-injected #subscription-panel ul li.group.open ul{animation:openGroup .25s ease-in-out;display:block}body.subscription-panel-injected #subscription-panel .instance-name{opacity:.8;font-weight:100}@keyframes openGroup{0%{transform:translateY(-.5em);opacity:0}to{transform:translateY(0);opacity:1}}body.subscription-panel-injected #subscription-panel-spinner{text-align:center;font-size:2em}@keyframes showItem{0%{opacity:0}to{opacity:1}}@keyframes hideItem{0%{opacity:1;max-height:2.5em}to{opacity:0;max-height:0}}body.subscription-panel-injected #header menu li a.subscription-panel-mobile-button{display:none}@keyframes showMobileSubscriptionPanelUL{0%{transform:translateY(-2em)}to{transform:translateY(0)}}@keyframes showMobileSubscriptionPanel{0%{opacity:0}to{opacity:1}}body.subscription-panel-injected.subscription-panel-open{overflow:hidden}body.subscription-panel-injected.subscription-panel-open #scroll-top{display:none!important}body.subscription-panel-injected.subscription-panel-open #subscription-panel{z-index:5;top:0;height:100%;width:100%;left:0;position:fixed;margin:0}body.subscription-panel-injected.subscription-panel-open.subscription-panel-force-mobile #middle>.kbin-container #subscription-panel,body.subscription-panel-injected.subscription-panel-open.subscription-panel-open #middle>.kbin-container #subscription-panel{overflow:hidden;border-radius:0!important;border:none;background:RGBA(0,0,0,.5);backdrop-filter:blur(2px);display:flex;align-items:center;justify-content:center}body.subscription-panel-injected.subscription-panel-open.subscription-panel-force-mobile #middle>.kbin-container #subscription-panel #subscription-panel-content,body.subscription-panel-injected.subscription-panel-open.subscription-panel-open #middle>.kbin-container #subscription-panel #subscription-panel-content{height:100%;overflow:auto;padding:1em 10em;padding-bottom:100px!important;position:fixed;top:49px;width:fit-content;margin:2em 0 0;animation:showMobileSubscriptionPanel .2s ease-out}body.subscription-panel-injected.subscription-panel-open.subscription-panel-force-mobile #middle>.kbin-container #subscription-panel ul,body.subscription-panel-injected.subscription-panel-open.subscription-panel-open #middle>.kbin-container #subscription-panel ul{animation:showMobileSubscriptionPanelUL .2s ease-out}body.subscription-panel-injected.subscription-panel-open.rounded-edges #middle>.kbin-container #subscription-panel-content{border-radius:.5rem}body.subscription-panel-injected.subscription-panel-open #header menu li a.subscription-panel-mobile-button{border-bottom:var(--kbin-header-hover-border)}body.subscription-panel-injected.subscription-panel-force-mobile:not(.subscription-panel-open) #middle>.kbin-container #subscription-panel{display:none}body.subscription-panel-injected #header menu li a.subscription-panel-mobile-button{font-size:0;cursor:pointer;transition:border-bottom .2s ease-in-out}body.subscription-panel-injected.subscription-panel-alternative-menu:not(.subscription-panel-force-mobile) a.subscription-panel-mobile-button{display:none!important}body.subscription-panel-injected.subscription-panel-force-mobile #header menu li a.subscription-panel-mobile-button,body.subscription-panel-injected.subscription-panel-open #header menu li a.subscription-panel-mobile-button{display:flex}body.subscription-panel-injected.subscription-panel-force-mobile #subscription-panel-collapse-button,body.subscription-panel-injected.subscription-panel-open #subscription-panel-collapse-button{display:none}body.subscription-panel-injected a.subscription-panel-mobile-button i{font-size:.85rem}body.subscription-panel-injected .subscription-panel-mobile-close-button-alt{position:relative;top:-.5em;font-size:2em;display:none}body.subscription-panel-injected.subscription-panel-alternative-menu.subscription-panel-open .subscription-panel-mobile-close-button-alt{display:block}@media (min-width: 991.98px){body.subscription-panel-injected .mobile-subscriptions-panel-button-alt{display:none!important}}@media (max-width: 991.98px){body.subscription-panel-injected.subscription-panel-alternative-menu .mobile-subscriptions-panel-button-alt,body.subscription-panel-injected #header menu li a.subscription-panel-mobile-button{display:flex}body.subscription-panel-injected #middle>.kbin-container,body.subscription-panel-injected body.subscription-panel-collapsed #middle>.kbin-container{grid-template-areas:"main main" "subscription-panel subscription-panel" "sidebar sidebar"!important;grid-template-columns:1fr!important}body.subscription-panel-injected.subscription-panel-sticky #middle>.kbin-container #subscription-panel{display:none}body.subscription-panel-injected.subscription-panel-open #middle>.kbin-container #subscription-panel{animation:showMobileSubscriptionPanel .2s ease-out}body.subscription-panel-injected.subscription-panel-open #middle>.kbin-container #subscription-panel #subscription-panel-content{height:100%;left:0;padding:2em 2em 100px!important;width:100%!important;border-radius:0!important;border:none;top:49px!important;margin:0!important;overflow:auto}body.subscription-panel-injected.subscription-panel-open #middle>.kbin-container #subscription-panel ul{animation:showMobileSubscriptionPanelUL .2s ease-out}body.subscription-panel-injected #subscription-panel-collapse-button{display:none}body.subscription-panel-injected #subscription-panel-settings-button{right:1em}body.subscription-panel-injected #subscription-panel-edit-button{right:4em;left:unset}body.subscription-panel-injected #subscription-panel.edit-mode #subscription-panel-edit-button{right:1em}}@media (hover: none){body.subscription-panel-injected #header menu li a.subscription-panel-mobile-button:hover{border-bottom:3px solid transparent}body.subscription-panel-injected #subscription-panel-settings-button:hover i,body.subscription-panel-injected #subscription-panel-edit-button:hover i{transform:none!important}}@media (pointer: coarse){body.subscription-panel-injected #subscription-panel-settings-button,body.subscription-panel-injected #subscription-panel-edit-button{font-size:1.2em}}body.subscription-panel-injected .subscription-panel-onboarding .subscription-panel-onboarding-content{max-width:800px}body.subscription-panel-injected .subscription-panel-onboarding-next{margin-top:1em;font-size:2em;text-align:center;display:block}'); } }); // src/utils.js function getSettings() { const settings = localStorage.getItem("subscription-panel-settings"); let settingsObj = {}; if (settings) { settingsObj = JSON.parse(settings); } if (settingsObj.useCache === void 0) { settingsObj.useCache = true; } if (settingsObj.useGroups === void 0) { settingsObj.useGroups = true; } if (settingsObj.showLastClicked === void 0) { settingsObj.showLastClicked = true; } return settingsObj; } function saveSettings(settings) { localStorage.setItem("subscription-panel-settings", JSON.stringify(settings)); } function resetSettings() { localStorage.removeItem("subscription-panel-settings"); localStorage.removeItem("subscription-panel-magazine-data"); } var init_utils = __esm({ "src/utils.js"() { } }); // src/Classes/Item.js var Item, Item_default; var init_Item = __esm({ "src/Classes/Item.js"() { Item = class _Item { #icon; type; fullName; editMode; hidden = false; element; static get TYPE() { return { MAGAZINE: "magazine", GROUP: "group" }; } constructor(fullName, type) { this.fullName = fullName; this.name = fullName; this.type = type; this.#icon = null; this.editMode = false; } get icon() { return this.#icon; } getElement() { let li = document.createElement("li"); li.classList.add("item"); li.setAttribute("data-type", this.type); li.setAttribute("data-name", this.fullName); return li; } enableEditMode() { this.editMode = true; } disableEditMode() { this.editMode = false; } toggleEditMode() { if (this.editMode) { this.disableEditMode(); } else { this.enableEditMode(); } } isStarred() { return false; } isHidden() { return this.hidden; } hide(fadeOut = false) { this.hidden = true; if (!this.element) { return; } this.element.classList.add("hideItem"); } show(fadeIn = false) { if (!this.hidden) { return; } this.hidden = false; if (!this.element) { return; } if (fadeIn && this.element.classList.contains("hideItem")) { this.element.addEventListener("animationend", () => { this.element.classList.remove("fade-in"); }); this.element.classList.add("fade-in"); } this.element.classList.remove("hideItem"); } toggleHidden() { if (this.isHidden()) { this.hide(); } else { this.show(); } } isIgnored() { return false; } search(query, includeIgnored = false) { if (!includeIgnored && this.isIgnored()) { return false; } return this.fullName.toLowerCase().includes(query.toLowerCase()); } copy() { return new _Item(this.fullName, this.type); } }; Item_default = Item; } }); // src/Classes/Magazine.js var Magazine, Magazine_default; var init_Magazine = __esm({ "src/Classes/Magazine.js"() { init_Item(); Magazine = class _Magazine extends Item_default { icon; element; starred; constructor(fullName, url, icon = null) { super(fullName, Item_default.TYPE.MAGAZINE); this.icon = icon; this.url = url; this.name = fullName.replace(/@.*/, ""); const instanceName = fullName.match(/@(.*)/); this.instanceName = instanceName ? instanceName[1] : null; } registerClickTime() { this.appendMagazineData({ clickTime: Date.now() }); } getMagazineData() { let magData = localStorage.getItem("subscription-panel-magazine-data"); if (magData) { magData = JSON.parse(magData); magData = magData[this.fullName] || {}; } else { magData = {}; } return magData; } getClickTime() { return this.getMagazineData().clickTime || 0; } appendMagazineData(data) { let magData = localStorage.getItem("subscription-panel-magazine-data"); if (magData) { magData = JSON.parse(magData); } else { magData = {}; } if (!magData[this.fullName]) { magData[this.fullName] = data; } else { magData[this.fullName] = { ...magData[this.fullName], ...data }; } localStorage.setItem("subscription-panel-magazine-data", JSON.stringify(magData)); } static fromElement(element) { let magA = element.querySelector("a"); return new _Magazine(magA.innerText, magA.href, element.querySelector("figure img")?.src); } enableEditMode() { super.enableEditMode(); if (!this.element) { return; } this.element.classList.add("edit-mode"); } disableEditMode() { super.disableEditMode(); if (!this.element) { return; } this.element.classList.remove("edit-mode"); } toggleStar() { let data = this.getMagazineData(); if (data?.starred) { this.unstar(); } else { this.star(); } } star() { this.appendMagazineData({ starred: true }); this.element.classList.add("starred"); this.starred = true; } unstar() { this.appendMagazineData({ starred: false }); this.element.classList.remove("starred"); this.starred = false; } isStarred() { if (this.starred === void 0) { this.starred = this.getMagazineData()?.starred === true; } return this.starred; } ignore() { this.element.classList.add("ignore"); this.ignored = true; this.appendMagazineData({ ignored: true }); this.element.querySelector(".toolItem.ignore").innerHTML = ''; } unignore() { this.element.classList.remove("ignore"); this.ignored = false; this.appendMagazineData({ ignored: false }); this.element.querySelector(".toolItem.ignore").innerHTML = ''; } toggleIgnored() { if (this.isIgnored()) { this.unignore(); } else { this.ignore(); } } isIgnored() { if (this.ignored === void 0) { this.ignored = this.getMagazineData()?.ignored === true; } return this.ignored; } getElement() { if (this.element) { return this.element; } let magData = this.getMagazineData(); let li = document.createElement("li"); if (magData?.starred) { li.classList.add("starred"); } if (this.isIgnored()) { li.classList.add("ignore"); } const tools = Object.assign(document.createElement("span"), { className: "tools" }); const star = Object.assign(document.createElement("span"), { className: "star toolItem", title: "Star", innerHTML: '', onclick: () => { this.toggleStar(); } }); const ignore = Object.assign(document.createElement("span"), { className: "ignore toolItem", title: "Ignore", innerHTML: this.isIgnored() ? '' : '', onclick: () => { this.toggleIgnored(); } }); tools.appendChild(star); tools.appendChild(ignore); li.appendChild(tools); this.element = li; let a = document.createElement("a"); a.href = this.url; a.className = "magazine"; a.addEventListener("click", () => { this.registerClickTime(); }); a.title = this.fullName; if (this.icon) { let icon = document.createElement("img"); icon.src = this.icon; a.appendChild(icon); } else { li.classList.add("no-image"); } const span = document.createElement("span"); span.className = "name"; span.appendChild(document.createTextNode(this.name)); a.appendChild(span); if (this.instanceName) { const span2 = document.createElement("span"); span2.className = "instance-name"; span2.appendChild(document.createTextNode("@" + this.instanceName)); a.appendChild(span2); } li.appendChild(a); return li; } static fromJSON(json) { return new _Magazine(json.fullName, json.url, json.icon); } toJSON() { return { fullName: this.fullName, icon: this.icon, url: this.url, type: this.type }; } copy() { return new _Magazine(this.fullName, this.url, this.icon); } }; Magazine_default = Magazine; } }); // src/Classes/Group.js var Group, Group_default; var init_Group = __esm({ "src/Classes/Group.js"() { init_Item(); init_Magazine(); Group = class _Group extends Item_default { #isOpen = false; element; magazines = []; countElement; constructor(fullName, subMagazines) { super(fullName, Item_default.TYPE.GROUP); this.magazines = subMagazines; this.name = fullName; } set isOpen(isOpen) { this.#isOpen = !!isOpen; } get isOpen() { return !!this.#isOpen; } get icon() { if (this.isOpen) { return ''; } else { return ''; } } getClickTime() { let latest = 0; this.magazines.forEach((mag) => { if (mag.getClickTime() > latest) { latest = mag.getClickTime(); } }); return latest || 0; } static fromElement(element) { let groupA = element.querySelector("a"); return new _Group(groupA.innerText, element.querySelector("figure img")?.src, groupA.href); } toggle() { this.isOpen ? this.close() : this.open(); } open() { this.isOpen = true; this.element.classList.add("open"); const a = this.element.querySelector("a"); const icon = a.querySelector("i"); a.setAttribute("aria-expanded", "true"); icon.classList.remove("fa-box"); icon.classList.add("fa-box-open"); } close() { this.isOpen = false; this.element.classList.remove("open"); const a = this.element.querySelector("a"); const icon = a.querySelector("i"); a.setAttribute("aria-expanded", "false"); icon.classList.remove("fa-box-open"); icon.classList.add("fa-box"); } getElement() { if (this.element) { return this.element; } const magazineCount = this.magazineCount(); let li = document.createElement("li"); this.element = li; li.classList.add("group"); if (this.isIgnored() || magazineCount === 0) { li.classList.add("ignore"); } let a = document.createElement("a"); a.className = "group-name"; a.href = "#"; a.title = this.fullName; a.ariaLabel = this.fullName; a.addEventListener("click", (e) => { e.preventDefault(); e.stopPropagation(); this.toggle(); }); const count = Object.assign(document.createElement("span"), { className: "count", innerHTML: "(" + magazineCount + ")" }); this.countElement = count; a.innerHTML = this.icon + '' + this.fullName + ""; a.appendChild(count); li.appendChild(a); let ul = document.createElement("ul"); this.magazines.forEach((subMag) => { const el = subMag.getElement(); ul.appendChild(el); }); li.appendChild(ul); return li; } static fromJSON(json) { return new _Group(json.fullName, json.magazines.map((mag) => Magazine_default.fromJSON(mag))); } toJSON() { return { fullName: this.fullName, magazines: this.magazines.map((mag) => mag.toJSON()), type: this.type }; } copy() { return new _Group(this.fullName, this.magazines.map((mag) => mag.copy())); } enableEditMode() { super.enableEditMode(); if (!this.element) { return; } this.magazines.forEach((mag) => { mag.enableEditMode(); }); this.open(); this.element.classList.add("edit-mode"); } disableEditMode() { super.disableEditMode(); if (!this.element) { return; } this.magazines.forEach((mag) => { mag.disableEditMode(); }); this.close(); this.element.classList.remove("edit-mode"); if (this.isIgnored()) { this.element.classList.add("ignore"); } else { this.element.classList.remove("ignore"); } this.countElement.innerHTML = "(" + this.magazineCount() + ")"; } isStarred() { return this.magazines.some((mag) => mag.isStarred()); } isIgnored() { return this.magazineCount() === 0; } hide(fadeOut = false) { super.hide(); if (!this.element) { return; } this.magazines.forEach((mag) => { mag.hide(fadeOut); }); this.element.classList.add("hideItem"); } show(fadeIn = false) { super.show(fadeIn); } showAll(fadeIn = false) { super.show(fadeIn); if (!this.element) { return; } this.magazines.forEach((mag) => { mag.show(); }); } magazineCount() { let count = 0; this.magazines.forEach((mag) => { if (!mag.isIgnored()) { count++; } }); return count; } search(query, includeIgnored = false) { let found = super.search(query, includeIgnored); if (!found && !includeIgnored && this.isIgnored()) { return false; } this.magazines.forEach((mag) => { if (mag.search(query, includeIgnored)) { found = true; } }); return found; } }; Group_default = Group; } }); // src/Classes/Cache.js var Cache, Cache_default; var init_Cache = __esm({ "src/Classes/Cache.js"() { init_utils(); init_Group(); init_Magazine(); init_Item(); Cache = class { constructor() { localStorage.removeItem("subscription-panel-cache"); } save(cache) { const settings = getSettings(); let cacheWrapper = { cache, timestamp: Date.now(), version: 1 }; if (settings?.useCache) { localStorage.setItem("subscription-panel-item-cache", JSON.stringify(cacheWrapper)); } } remove() { localStorage.removeItem("subscription-panel-item-cache"); } parseItem(item) { if (item.type === Item_default.TYPE.MAGAZINE) { return new Magazine_default(item.fullName, item.url, item.icon); } else if (item.type === Item_default.TYPE.GROUP) { let magazines = []; item.magazines.forEach((mag) => { magazines.push(this.parseItem(mag)); }); return new Group_default(item.fullName, magazines); } } get() { const settings = getSettings(); if (settings?.useCache) { const cache = localStorage.getItem("subscription-panel-item-cache"); if (cache) { let cacheWrapper = JSON.parse(cache); if (cacheWrapper.version === 1) { let output = []; cacheWrapper.cache.forEach((item) => { output.push(this.parseItem(item)); }); return output; } else { this.remove(); return []; } } } return []; } }; Cache_default = Cache; } }); // src/Classes/SettingsModal.js var SettingsModal, SettingsModal_default; var init_SettingsModal = __esm({ "src/Classes/SettingsModal.js"() { init_utils(); init_Cache(); SettingsModal = class { subscriptionsPanel; modalElement; constructor(subscriptionsPanel) { this.subscriptionsPanel = subscriptionsPanel; } getSettingsButtonElement() { const settingsButton = document.createElement("div"); settingsButton.id = "subscription-panel-settings-button"; settingsButton.title = "Settings"; settingsButton.ariaLabel = "Settings"; settingsButton.innerHTML = ''; settingsButton.addEventListener("click", () => { this.show(); }); return settingsButton; } init() { const settingsButton = this.getSettingsButtonElement(); this.subscriptionsPanel.contentElement.appendChild(settingsButton); this.applySettings(); window.addEventListener("open-subscriptions-panel-settings", () => { this.show(); }); setTimeout(() => { const KUP = document.KUP; const settingsPanel = KUP?.settingsPanel; const SettingsPanelBooleanRow = KUP?.components?.SettingsPanelButtonRow; const SettingsPanelSection = KUP?.components?.SettingsPanelSection; if (settingsPanel && SettingsPanelBooleanRow && SettingsPanelSection) { const section = new SettingsPanelSection("Subscriptions Panel"); section.addSettingsRows([new SettingsPanelBooleanRow("Open settings", { label: "Open", onClick: () => { window.dispatchEvent(new CustomEvent("open-subscriptions-panel-settings")); } })]); settingsPanel.addSection(section); } }, 100); } close() { if (this.modalElement) { this.modalElement.remove(); this.modalElement = null; } } /** Apply settings to the subscriptions panel * @param id {string} The id of the element * @param setting {string} The setting to apply * @param invert {boolean} Invert checked state from settings * @param callback {function} Callback to run when checkbox is changed */ registerCheckbox(id, setting, invert = false, callback = null) { const element = document.getElementById(id); const settings = getSettings(); if (settings?.[setting] === true) { element.checked = !invert; } element.addEventListener("change", (e) => { const settings2 = getSettings(); settings2[setting] = !!e.target.checked; saveSettings(settings2); if (callback) { callback(element.checked); } }); } show() { const settings = getSettings(); const modal = document.createElement("div"); this.modalElement = modal; const version = GM_info.script.version || "Unknown"; modal.className = "subscription-panel-settings-modal subscription-panel-modal"; modal.innerHTML = `

Subscriptions Panel Settings

Version ${version}

`; document.body.appendChild(modal); const extendWidthEl = modal.querySelector("#subscription-panel-extend-width"); if (settings?.extendWidth) { extendWidthEl.checked = true; } const hideOnCollapseEl = modal.querySelector("#subscription-panel-hide-on-collapse"); if (settings?.hideOnCollapse) { hideOnCollapseEl.checked = true; } const useCacheEl = modal.querySelector("#subscription-panel-use-cache"); if (settings?.useCache) { useCacheEl.checked = true; } const skipOnboardingEl = modal.querySelector("#subscription-panel-show-onboarding"); if (settings?.onboardingDone) { skipOnboardingEl.checked = false; } const forceMobileEl = modal.querySelector("#subscription-panel-force-mobile"); if (settings?.forceMobile) { forceMobileEl.checked = true; } const useGroupsEl = modal.querySelector("#subscription-panel-use-groups"); if (settings?.useGroups) { useGroupsEl.checked = true; } const lastClickedEl = modal.querySelector("#subscription-panel-show-last-clicked"); if (settings?.showLastClicked) { lastClickedEl.checked = true; } this.registerCheckbox("subscription-panel-sticky", "sticky", false, () => { this.applySettings(); }); this.registerCheckbox("subscription-panel-alternative-menu", "alternativeMenu", false, () => { this.applySettings(); }); const resetEl = modal.querySelector("#subscription-panel-reset"); resetEl.addEventListener("click", () => { const cache = new Cache_default(); cache.remove(); resetSettings(); window.location.reload(); }); modal.querySelector(".subscription-panel-settings-modal .close").addEventListener("click", () => { this.close(); }); modal.addEventListener("click", (e) => { if (e.target === modal) { this.close(); } }); modal.querySelector("#subscription-panel-extend-width").addEventListener("change", (e) => { const settings2 = getSettings(); settings2.extendWidth = !!e.target.checked; saveSettings(settings2); this.applySettings(); }); modal.querySelector("#subscription-panel-use-cache").addEventListener("change", (e) => { const settings2 = getSettings(); if (e.target.checked) { settings2.useCache = true; } else { settings2.useCache = false; const cache = new Cache_default(); cache.remove(); } saveSettings(settings2); this.applySettings(); }); modal.querySelector("#subscription-panel-hide-on-collapse").addEventListener("change", (e) => { const settings2 = getSettings(); settings2.hideOnCollapse = !!e.target.checked; saveSettings(settings2); this.applySettings(); }); modal.querySelector("#subscription-panel-show-onboarding").addEventListener("change", (e) => { const settings2 = getSettings(); settings2.onboardingDone = !e.target.checked; saveSettings(settings2); }); modal.querySelector("#subscription-panel-use-groups").addEventListener("change", (e) => { const settings2 = getSettings(); settings2.useGroups = !!e.target.checked; const subscriptionsHandler = this.subscriptionsPanel.subscriptionsHandler; subscriptionsHandler.reload().then(() => { this.subscriptionsPanel.addMagazinesToDOM(subscriptionsHandler.subscriptions, true); }); saveSettings(settings2); this.applySettings(); }); modal.querySelector("#subscription-panel-force-mobile").addEventListener("change", (e) => { const settings2 = getSettings(); settings2.forceMobile = !!e.target.checked; saveSettings(settings2); this.applySettings(); }); modal.querySelector("#subscription-panel-show-last-clicked").addEventListener("change", (e) => { const settings2 = getSettings(); settings2.showLastClicked = !!e.target.checked; const subscriptionsHandler = this.subscriptionsPanel.subscriptionsHandler; subscriptionsHandler.reload().then(() => { this.subscriptionsPanel.addMagazinesToDOM(subscriptionsHandler.subscriptions, true); }); saveSettings(settings2); this.applySettings(); }); } applySettings() { const settings = getSettings(); if (settings?.extendWidth) { document.body.classList.add("extend-width"); } else { document.body.classList.remove("extend-width"); } if (settings?.collapsed) { this.subscriptionsPanel.collapsePanel(); } else { this.subscriptionsPanel.expandPanel(); } if (settings?.hideOnCollapse) { document.body.classList.add("subscription-panel-hide-on-collapse"); } else { document.body.classList.remove("subscription-panel-hide-on-collapse"); } if (settings?.forceMobile) { document.body.classList.add("subscription-panel-force-mobile"); } else { document.body.classList.remove("subscription-panel-force-mobile"); this.subscriptionsPanel.closeMobilePanel(); } if (settings?.sticky) { document.body.classList.add("subscription-panel-sticky"); } else { document.body.classList.remove("subscription-panel-sticky"); } if (settings?.alternativeMenu) { document.body.classList.add("subscription-panel-alternative-menu"); } else { document.body.classList.remove("subscription-panel-alternative-menu"); } } }; SettingsModal_default = SettingsModal; } }); // src/Classes/SubscriptionsHandler.js var SubscriptionsHandler, SubscriptionsHandler_default; var init_SubscriptionsHandler = __esm({ "src/Classes/SubscriptionsHandler.js"() { init_utils(); init_Cache(); init_Magazine(); init_Item(); init_Group(); SubscriptionsHandler = class { subscriptions; constructor() { this.subscriptions = []; } reload() { this.subscriptions = []; return this.load(1); } sort() { const sortFunction = (a, b) => { if (a.isStarred() && !b.isStarred()) { return -1; } else if (!a.isStarred() && b.isStarred()) { return 1; } else { return a.fullName.localeCompare(b.fullName); } }; this.subscriptions.sort((a, b) => { return sortFunction(a, b); }); this.subscriptions.forEach((sub) => { if (sub.type === Item_default.TYPE.GROUP) { sub.magazines.sort((a, b) => { return sortFunction(a, b); }); } }); } append(magazines) { const settings = getSettings(); const useGroups = settings?.useGroups; magazines.forEach( (mag) => { let found = false; this.subscriptions.some((sub, index) => { if (sub.type === Item_default.TYPE.MAGAZINE && mag.type === Item_default.TYPE.MAGAZINE && sub.url === mag.url) { found = true; } else if (useGroups && sub.name.toLowerCase() === mag.name.toLowerCase()) { if (sub.type === Item_default.TYPE.GROUP) { sub.magazines.push(mag); } else { this.subscriptions[index] = new Group_default(sub.name, [sub, mag]); } found = true; } return found; }); if (!found) { this.subscriptions.push(mag); } } ); this.sort(); const cache = new Cache_default(); cache.save(this.subscriptions); } load(page) { page = page || 1; const fetchURL = window.location.origin + "/settings/subscriptions/magazines?p=" + page; const fetchPromise = fetch(fetchURL); return fetchPromise.then((response) => { const spinner = document.querySelector("#subscription-panel-spinner"); if (spinner) { spinner.remove(); } return response.text(); }).then((pageContent) => { let dom = new DOMParser().parseFromString(pageContent, "text/html"); let magazinesElements = dom.querySelectorAll(".section.magazines.magazines-columns ul>li"); let magazines = []; if (magazinesElements.length === 0) { document.querySelector("#subscription-panel-content").appendChild(document.createTextNode("No subscriptions found")); return Promise.resolve(); } magazinesElements.forEach((el) => { const mag = Magazine_default.fromElement(el); magazines.push(mag); const currentMagazine = window.location.pathname.match(/\/m\/(.+?)(\/|$)/); if (currentMagazine && currentMagazine[1] === mag.fullName) { mag.registerClickTime(); } }); this.append(magazines); let nextPage = dom.querySelector("a.pagination__item.pagination__item--next-page")?.href; nextPage = nextPage ? nextPage.match(/p=(\d+)/)[1] : void 0; nextPage = nextPage ? parseInt(nextPage) : 1; if (page < nextPage && page < 100) { return this.load(page + 1); } else { return Promise.resolve(); } }).catch((error) => { console.error(error); document.querySelector("#subscription-panel-content").appendChild(document.createTextNode("Failed to load subscriptions")); return Promise.reject(error); }); } loadSubscriptions(page, callback) { page = page || 1; const xhr = new XMLHttpRequest(); xhr.onreadystatechange = () => { if (xhr.readyState === 4) { const spinner = document.querySelector("#subscription-panel-spinner"); if (spinner) { spinner.remove(); } if (xhr.status === 200) { let dom = new DOMParser().parseFromString(xhr.responseText, "text/html"); let magazinesElements = dom.querySelectorAll(".section.magazines.magazines-columns ul>li"); let magazines = []; magazinesElements.forEach((el) => { const mag = Magazine_default.fromElement(el); magazines.push(mag); if (window.location && window.location.pathname === mag.url) { mag.registerClickTime(); } }); this.append(magazines); let nextPage = dom.querySelector("a.pagination__item.pagination__item--next-page")?.href; nextPage = nextPage ? nextPage.match(/p=(\d+)/)[1] : void 0; nextPage = nextPage ? parseInt(nextPage) : 1; if (page < nextPage && page < 100) { this.loadSubscriptions(page + 1, callback); } else if (callback) { callback(this.subscriptions); } } else { document.querySelector("#subscription-panel-content").appendChild(document.createTextNode("Failed to load subscriptions")); } } }; xhr.open("GET", "/settings/subscriptions/magazines?p=" + page, true); xhr.send(); } }; SubscriptionsHandler_default = SubscriptionsHandler; } }); // src/Classes/SearchBox.js var SearchBox, SearchBox_default; var init_SearchBox = __esm({ "src/Classes/SearchBox.js"() { init_Magazine(); SearchBox = class { #element; #containerElement; panelElement; searchQuery = ""; #editMode = false; constructor(subscriptionsHandler, panelElement) { this.subscriptionsHandler = subscriptionsHandler; this.panelElement = panelElement; } clear() { this.doSearch(""); } set editMode(editMode) { this.#editMode = !!editMode; this.doSearch(this.searchQuery); } get editMode() { return this.#editMode; } doSearch(filter) { filter = filter.trim(); this.searchQuery = filter; this.#element.value = filter; let lastClickedContainer = this.panelElement.querySelector(".last-clicked-container"); if (filter.length > 0) { this.#containerElement.querySelector(".search-box-clear")?.classList.add("active"); } else { this.#containerElement.querySelector(".search-box-clear")?.classList.remove("active"); lastClickedContainer.classList.remove("hideItem"); this.subscriptionsHandler.subscriptions.forEach((mag) => { if (mag.type === Magazine_default.TYPE.GROUP) { mag.showAll(); if (!this.editMode) { mag.close(); } else { mag.open(); } } else { mag.show(); } }); return; } filter = filter.toLowerCase(); lastClickedContainer.classList.add("hideItem"); this.subscriptionsHandler.subscriptions.forEach((mag) => { if (mag.type === Magazine_default.TYPE.GROUP) { mag.open(); let subMagFound = false; mag.magazines.forEach((subMag) => { if (subMag.search(filter, this.editMode)) { subMagFound = true; subMag.show(true); } else { subMag.hide(true); } }); if (subMagFound) { mag.show(true); } else { mag.hide(true); } } else if (mag.type === Magazine_default.TYPE.MAGAZINE) { if (mag.search(filter, this.editMode)) { mag.show(true); } else { mag.hide(true); } } }); } getElement() { if (this.#element) { return this.#element; } const searchBox = document.createElement("input"); this.#element = searchBox; searchBox.type = "text"; searchBox.id = "subscription-panel-search"; searchBox.placeholder = "Filter"; searchBox.addEventListener("input", (e) => { this.doSearch(e.target.value); }); const searchBoxClear = document.createElement("span"); searchBoxClear.className = "search-box-clear"; searchBoxClear.innerHTML = ''; searchBoxClear.addEventListener("click", () => { this.clear(); }); searchBox.addEventListener("keydown", (e) => { if (e.key === "Escape") { this.clear(); searchBox.blur(); } }); const searchBoxContainer = document.createElement("div"); this.#containerElement = searchBoxContainer; searchBoxContainer.className = "search-box-container"; searchBoxContainer.appendChild(searchBox); searchBoxContainer.appendChild(searchBoxClear); return searchBoxContainer; } }; SearchBox_default = SearchBox; } }); // src/Classes/SubscriptionsPanel.js var SubscriptionsPanel, SubscriptionsPanel_default; var init_SubscriptionsPanel = __esm({ "src/Classes/SubscriptionsPanel.js"() { init_Cache(); init_utils(); init_SubscriptionsHandler(); init_SearchBox(); init_Magazine(); SubscriptionsPanel = class { subscriptionsHandler; containerElement; contentElement; editMode = false; constructor() { this.subscriptionsHandler = new SubscriptionsHandler_default(); } init() { const settings = getSettings(); document.body.classList.add("subscription-panel-injected"); const kbinContainer = document.querySelector("#middle > .kbin-container"); const magazinePanelContainer = document.createElement("div"); this.containerElement = magazinePanelContainer; magazinePanelContainer.id = "subscription-panel"; const magazinePanel = document.createElement("aside"); this.contentElement = magazinePanel; const magazinePanelUl = document.createElement("ul"); magazinePanelUl.className = "fade-in subscription-list"; magazinePanelUl.addEventListener("animationend", () => { magazinePanelUl.classList.remove("fade-in"); }); const title = document.createElement("h3"); magazinePanel.id = "subscription-panel-content"; title.innerHTML = 'Subscriptions'; magazinePanel.appendChild(title); const editButton = Object.assign(document.createElement("div"), { id: "subscription-panel-edit-button", title: "Edit subscriptions", ariaLabel: "Edit subscriptions", innerHTML: '' }); editButton.addEventListener("click", () => { this.toggleEditMode(); }); magazinePanel.appendChild(editButton); magazinePanelContainer.appendChild(magazinePanel); kbinContainer.appendChild(magazinePanelContainer); const searchBox = new SearchBox_default(this.subscriptionsHandler, magazinePanelContainer); this.searchBox = searchBox; magazinePanel.appendChild(searchBox.getElement()); const collapseButton = document.createElement("span"); collapseButton.id = "subscription-panel-collapse-button"; collapseButton.title = "Hide Subscriptions"; collapseButton.ariaLabel = "Hide Subscriptions"; collapseButton.innerHTML = ''; title.addEventListener("click", () => { this.toggleCollapsePanel(); }); title.appendChild(collapseButton); if (settings?.forceMobile || !settings?.alternativeMenu) { const menu = document.querySelector(".kbin-container > menu"); const mobileButtonLi = document.createElement("li"); const mobileButton = document.createElement("a"); mobileButton.className = "subscription-panel-mobile-button"; mobileButton.title = "Subscriptions"; mobileButton.ariaLabel = "Subscriptions"; mobileButton.href = "#"; mobileButton.innerHTML = ''; mobileButton.addEventListener("click", (e) => { this.toggleOpenMobilePanel(); e.preventDefault(); }); mobileButtonLi.appendChild(mobileButton); menu.insertBefore(mobileButtonLi, menu.firstChild); magazinePanelContainer.addEventListener("click", (e) => { if (e.target === magazinePanelContainer) { if (document.body.classList.contains("subscription-panel-open")) { this.closeMobilePanel(); } } }); } const altMobileButton = Object.assign(document.createElement("a"), { title: "Subscriptions", ariaLabel: "Subscriptions", href: "#", innerHTML: '' }); altMobileButton.addEventListener("click", (e) => { this.toggleOpenMobilePanel(); e.preventDefault(); }); const mobileMenu = document.querySelector(".top-options menu ul"); const mobileMenuLi = Object.assign(document.createElement("li"), { className: "mobile-subscriptions-panel-button-alt" }); mobileMenuLi.appendChild(altMobileButton); mobileMenu.insertBefore(mobileMenuLi, mobileMenu.lastChild.previousSibling); const altCloseButton = Object.assign(document.createElement("a"), { className: "subscription-panel-mobile-close-button-alt", title: "Close", ariaLabel: "Close", innerHTML: '', href: "#" }); altCloseButton.addEventListener("click", (e) => { this.closeMobilePanel(); e.preventDefault(); }); magazinePanel.insertBefore(altCloseButton, magazinePanel.firstChild); const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.attributeName === "class") { const attributeValue = mutation.target.getAttribute(mutation.attributeName); if (attributeValue.includes("open")) { this.closeMobilePanel(); } } }); }); observer.observe(document.getElementById("sidebar"), { attributes: true }); const lastClickedContainer = document.createElement("div"); lastClickedContainer.className = "last-clicked-container"; lastClickedContainer.appendChild(Object.assign(document.createElement("h3"), { innerText: "Recently viewed" })); const magazinePanelLastClickedUl = document.createElement("ul"); magazinePanelLastClickedUl.className = "fade-in last-clicked-list"; if (settings?.showLastClicked !== true) { lastClickedContainer.classList.add("hideItem"); } lastClickedContainer.appendChild(magazinePanelLastClickedUl); magazinePanel.appendChild(lastClickedContainer); magazinePanel.appendChild(magazinePanelUl); const cache = new Cache_default(); let cacheData = cache.get(); if (cacheData.length > 0) { this.addMagazinesToDOM(cacheData, false); } else { let spinner = document.createElement("div"); spinner.id = "subscription-panel-spinner"; spinner.innerHTML = ''; magazinePanel.appendChild(spinner); } this.subscriptionsHandler.load().then(() => { this.addMagazinesToDOM(this.subscriptionsHandler.subscriptions, true); }); window.addEventListener("hide-all-modals", () => { this.closeMobilePanel(); }); } enableEditMode() { this.editMode = true; this.containerElement.classList.add("edit-mode"); this.expandPanel(); this.subscriptionsHandler.subscriptions.forEach((mag) => { mag.enableEditMode(); }); this.searchBox.editMode = true; const editButton = document.getElementById("subscription-panel-edit-button"); editButton.innerHTML = ' Done'; editButton.classList.add("active"); } disableEditMode() { this.editMode = false; this.containerElement.classList.remove("edit-mode"); this.subscriptionsHandler.subscriptions.forEach((mag) => { mag.disableEditMode(); }); this.subscriptionsHandler.sort(); this.addMagazinesToDOM(this.subscriptionsHandler.subscriptions); const editButton = document.getElementById("subscription-panel-edit-button"); editButton.innerHTML = ''; editButton.classList.remove("active"); this.searchBox.editMode = false; this.searchBox.clear(); } toggleEditMode() { if (this.editMode) { this.disableEditMode(); } else { this.enableEditMode(); } } toggleCollapsePanel() { const settings = getSettings(); if (document.body.classList.contains("subscription-panel-collapsed")) { this.expandPanel(); settings.collapsed = false; } else { if (this.collapsePanel()) { settings.collapsed = true; } } saveSettings(settings); } collapsePanel() { if (window.innerWidth <= 991.98 || document.body.classList.contains("subscription-panel-force-mobile") || this.editMode) { return false; } const lastClickedH3 = document.querySelector(".last-clicked-container h3"); if (lastClickedH3) { lastClickedH3.innerHTML = ' Recent'; } if (document.body.classList.contains("sidebar-left")) { document.querySelector("#subscription-panel-collapse-button i").className = "fa-solid fa-chevron-left"; } else { document.querySelector("#subscription-panel-collapse-button i").className = "fa-solid fa-chevron-right"; } const button = document.querySelector("#subscription-panel-collapse-button"); button.title = "Show subscriptions"; button.ariaLabel = "Show subscriptions"; document.querySelector(".subscription-panel-header").innerHTML = ' Subs'; document.body.classList.add("subscription-panel-collapsed"); return true; } expandPanel() { if (document.body.classList.contains("sidebar-left")) { document.querySelector("#subscription-panel-collapse-button i").className = "fa-solid fa-chevron-right"; } else { document.querySelector("#subscription-panel-collapse-button i").className = "fa-solid fa-chevron-left"; } const lastClickedH3 = document.querySelector(".last-clicked-container h3"); if (lastClickedH3) { lastClickedH3.innerText = "Recently viewed"; } const button = document.querySelector("#subscription-panel-collapse-button"); button.title = "Hide subscriptions"; button.ariaLabel = "Hide subscriptions"; document.querySelector(".subscription-panel-header").innerText = "Subscriptions"; document.body.classList.remove("subscription-panel-collapsed"); return true; } toggleOpenMobilePanel() { if (document.body.classList.contains("subscription-panel-open")) { this.closeMobilePanel(); } else { this.openMobilePanel(); } } openMobilePanel() { window.dispatchEvent(new Event("hide-all-modals")); document.body.classList.add("subscription-panel-open"); if (!document.body.classList.contains("fixed-navbar")) { window.scrollTo(0, 0); } document.getElementById("sidebar")?.classList.remove("open"); } closeMobilePanel() { document.body.classList.remove("subscription-panel-open"); } addMagazinesToDOM(magazines) { const magazinePanelUl = document.querySelector("#subscription-panel ul.subscription-list"); const lastClickedContainer = document.querySelector("#subscription-panel .last-clicked-container"); const magazinePanelLastClickedUl = document.querySelector("#subscription-panel ul.last-clicked-list"); magazinePanelUl.innerHTML = ""; magazinePanelLastClickedUl.innerHTML = ""; const settings = getSettings(); if (settings?.showLastClicked === true) { lastClickedContainer.classList.remove("hideItem"); let lastMagazines = [...magazines].sort((a, b) => { return b.getClickTime() - a.getClickTime(); }).slice(0, 4); lastMagazines = lastMagazines.filter((mag) => mag.getClickTime() > 0); if (lastMagazines.length === 0) { lastClickedContainer.classList.add("hideItem"); } else { lastMagazines.forEach((mag) => { const newMag = mag.copy(); if (newMag.type === Magazine_default.TYPE.GROUP) { newMag.magazines.sort((a, b) => { return b.getClickTime() - a.getClickTime(); }); } let el = newMag.getElement(); el.classList.add("last-clicked"); magazinePanelLastClickedUl.appendChild(el); }); } } else { lastClickedContainer.classList.add("hideItem"); } magazines.forEach((mag) => { let el = mag.getElement(); magazinePanelUl.appendChild(el); }); } }; SubscriptionsPanel_default = SubscriptionsPanel; } }); // src/Classes/OnboardingModal.js var OnboardingModal, OnboardingModal_default; var init_OnboardingModal = __esm({ "src/Classes/OnboardingModal.js"() { init_utils(); OnboardingModal = class { modalElement; constructor() { } init() { const settings = getSettings(); if (!settings?.onboardingDone) { settings.onboardingDone = true; saveSettings(settings); this.show(); } } close() { if (this.modalElement) { this.modalElement.remove(); this.modalElement = null; } } show() { const onboarding = document.createElement("div"); this.modalElement = onboarding; onboarding.className = "subscription-panel-onboarding subscription-panel-modal"; onboarding.innerHTML = `

Thanks for using Subscriptions Panel!

Click on the icon to collapse the panel.

Click on the icon to open the settings.

Click on the icon to open the panel on mobile.

Magazines that share the same name are grouped together. A group is indicated by a icon.

Please take a few seconds to review the settings in the next step. You can always do this later if you want.

Show settings
`; onboarding.querySelector(".subscription-panel-onboarding-close").addEventListener("click", (e) => { this.close(); e.preventDefault(); }); onboarding.querySelector(".subscription-panel-onboarding-next").addEventListener("click", (e) => { this.close(); window.dispatchEvent(new Event("open-subscriptions-panel-settings")); e.preventDefault(); }); onboarding.addEventListener("click", (e) => { if (e.target === onboarding) { this.close(); window.dispatchEvent(new Event("open-subscriptions-panel-settings")); e.preventDefault(); } }); document.body.appendChild(onboarding); } }; OnboardingModal_default = OnboardingModal; } }); // src/index.js var require_src = __commonJS({ "src/index.js"() { init_style(); init_SettingsModal(); init_SubscriptionsPanel(); init_OnboardingModal(); var loginElement = document.querySelector(".login"); if (!loginElement.href.endsWith("/login")) { const subscriptionsPanel = new SubscriptionsPanel_default(); const settingsModal = new SettingsModal_default(subscriptionsPanel); const onboardingModal = new OnboardingModal_default(settingsModal); subscriptionsPanel.init(); settingsModal.init(); onboardingModal.init(); } } }); require_src(); })(); })();