steam-janitor/steam-janitor.user.js
Jetsparrow 3625ea3bda v0.0.2-alpha
- Renamed (planning to do guides too)
- Added filter toggle to switch between filtering and displaying hidden content
- General tidying up
2022-02-11 22:07:24 +03:00

193 lines
6.5 KiB
JavaScript

// ==UserScript==
// @name Steam Janitor
// @description Hide unwanted user content in browse view, endless scrolling
// @match *://*.steamcommunity.com/workshop/browse/*
// @run-at document-end
// @version 0.0.2
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_listValues
// @updateURL https://raw.githubusercontent.com/Jetsparrow/steam-janitor/main/steam-janitor.js
// @downloadURL https://raw.githubusercontent.com/Jetsparrow/steam-janitor/main/steam-janitor.js
// ==/UserScript==
const addGlobalStyle = (doc, css) => {
let head = doc.getElementsByTagName('head')[0];
if (!head) return null;
let style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
return style;
}
const htmlToElement = (doc, html) => {
var template = doc.createElement('template');
template.innerHTML = html.trim();
return template.content.firstChild;
}
const onVisible = (element, callback) => {
const observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
callback();
observer.unobserve(entry.target);
}
});
},
{ rootMargin: "0px 0px 200px 0px" }
);
observer.observe(element);
};
const selectors = {
PAGING_INFO: ".workshopBrowsePagingWithBG",
ITEM_CONTAINER: ".workshopBrowseItems .workshopItemPreviewHolder",
ITEMS_CONTAINER: ".workshopBrowseItems",
ITEMS_HOVERS: ".workshopBrowseItems script",
NEXT_BUTTON: ".workshopBrowsePagingControls .pagebtn:last-child",
PAGINATOR: ".workshopBrowsePagingControls",
FOOTER: ".workshopBrowsePaging"
};
const unhiddenClass = "janitorItem";
const hiddenFilteredClass = "janitorItemHidden";
const hiddenUnfilteredClass = "janitorItemHiddenUnfiltered";
const hideButtonClass = "janitorHideButton";
const showButtonClass = "janitorShowButton";
const janitorCss = `
.${hiddenFilteredClass} { display:none !important; }
.${hiddenUnfilteredClass} {opacity: 0.25;}
.${hiddenUnfilteredClass} .${showButtonClass} { display:inline !important; }
.${hiddenUnfilteredClass} .${hideButtonClass} { display:none !important; }
.${unhiddenClass} .${showButtonClass} { display:none !important; }
.${unhiddenClass} .${hideButtonClass} { display:inline !important; }
`;
const defaultModData = () => {
let d = new Object();
d.hide = false;
return d;
}
const loadModData = (modId) => {
var j = GM_getValue("modid:" + modId, "");
return j == "" ? defaultModData() : JSON.parse(j);
}
const saveModData = (modId, data) => GM_setValue("modid:" + modId, JSON.stringify(data));
const updateHiddenClass = (doc, modId) => {
var container = doc.getElementById(modId)?.parentElement?.parentElement;
if (!container) return;
const d = loadModData(modId);
container.classList.remove(unhiddenClass);
container.classList.remove(hiddenFilteredClass);
container.classList.remove(hiddenUnfilteredClass);
if (!d.hide) container.classList.add(unhiddenClass);
else if (window.janitorFilterEnabled) container.classList.add(hiddenFilteredClass);
else container.classList.add(hiddenUnfilteredClass);
}
const setHidden = (doc, modId, isHidden) => {
var d = loadModData(modId);
d.hide = isHidden;
saveModData(modId, d);
updateHiddenClass(doc, modId);
}
const addHideButtons = (doc, container, id) => {
const hide = htmlToElement(doc, `<a class="${hideButtonClass}">hide</a>`)
hide.onclick = () => {setHidden(document, id, true);};
container.prepend(hide);
const show = htmlToElement(doc, `<a class="${showButtonClass}">show</a>`)
show.onclick = () => {setHidden(document, id, false);};
container.prepend(show);
}
const processContainers = (doc) => {
for (var el of doc.querySelectorAll(selectors.ITEM_CONTAINER)){
const container = el.parentElement.parentElement;
const id = el.id;
updateHiddenClass(doc, id);
if (container.janitorButtonsAdded) continue;
container.janitorButtonsAdded = true;
addHideButtons(doc, container, id);
}
}
const loadNextPage = (url) => {
fetch(url, { credentials: "same-origin" })
.then(response => response.text())
.then(html => {
const parser = new DOMParser();
const newDoc = parser.parseFromString(html, "text/html");
processContainers(newDoc);
const newMods = newDoc.querySelectorAll(selectors.ITEM_CONTAINER);
const modContainer = document.querySelector(selectors.ITEMS_CONTAINER);
for (const mod of newMods) {
const container = mod.parentElement.parentElement;
modContainer.appendChild(container);
}
const scripts = newDoc.querySelectorAll(selectors.ITEMS_HOVERS);
for (const newScript of scripts){
const matches = newScript.innerHTML.match(/(sharedfile_\d+)/);
if (matches.length < 1) continue;
const data = loadModData(matches[0]);
if (data.hide) continue;
eval("try{ "+ newScript.innerHTML + " } catch {} ");
}
const nextUrl = newDoc.querySelector(selectors.NEXT_BUTTON)?.getAttribute("href");
const footer = document.getElementById("footer");
if (nextUrl) onVisible(footer, loadNextPage.bind(null, nextUrl));
window.history.pushState("", "", url);
});
};
function toggleFilter(checkbox) {
window.janitorFilterEnabled = checkbox.checked;
GM_setValue("janitorFilterEnabled", checkbox.checked);
const doc = checkbox.ownerDocument;
processContainers(doc);
}
(() => {
const load = () => {
console.log(GM_listValues());
addGlobalStyle(document, janitorCss);
const filterToggleRoot = document.querySelector(selectors.PAGING_INFO);
const toggle = htmlToElement(document, `
<div>
<input type="checkbox" id="janitorFilterToggle">
<label for="janitorFilterToggle">Filter</label>
</div>
`);
const checkbox = toggle.children[0];
checkbox.checked = window.janitorFilterEnabled = GM_getValue("janitorFilterEnabled", true);
checkbox.onclick = () => toggleFilter(checkbox);
filterToggleRoot.prepend(toggle);
processContainers(document);
const nextUrl = document.querySelector(selectors.NEXT_BUTTON)?.getAttribute("href");
if (!nextUrl) {
console.error(`Could not find nextUrl through "${selectors.NEXT_BUTTON}"`);
return;
}
loadNextPage(nextUrl);
document.querySelector(selectors.PAGINATOR)?.remove();
};
load();
})();