// ==UserScript==
// @name USO - Display additional infos & fixes
// @namespace https://github.com/Procyon-b
// @version 0.3.4
// @description Display additional information. Total installs, update date, initial release date. Fix site's navigability.
// @author Achernar
// @match https://userstyles.org/*
// @run-at document-start
// @grant none
// ==/UserScript==
(function() {
"use strict";
var initial=true, firstPage=true;
// catch site errors
if (location.pathname.startsWith('/styles/[styleId]/')) {
let u=location.pathname.substr(17);
history.replaceState({}, null, u);
location.pathname=u;
return;
}
// XHR -- XML
self.XMLHttpRequest = class extends self.XMLHttpRequest {
open(...args) {
let t=this;
// intercept and source code
if ( arguments[1].startsWith('https://gateway.userstyles.org/styles/getStyleCss/') ) {
styleLoaded=styleID || -1;
loadCSS=1;
this.addEventListener('load', function(){
var id=t.responseURL.split('/').pop();
if (styles[id] && !styles[id].sourceCode) styles[id].sourceCode=JP(t.response).result;
});
}
return super.open(...args);
}
}
// JSON.parse
var JP=JSON.parse;
JSON.parse=function(){
var r=JP(...arguments);
getStyles(r);
return r;
}
// stop svg js animation
window.requestAnimationFrame=function(){}
// handle data
var stylesA=[], styles={};
var total=0, styleLoaded;
var closeBut;
function getStyles(o) {
stylesA=parseObj(o, [], ['styles', 'stylesList', 'style']);
stylesA.forEach((e) => {
if (e.id && !styles[e.id]) {
styles[e.id]=Object.assign({}, e);
total++;
}
});
}
function parseObj(o, A, n=[]) {
var k, v;
if ( (typeof o != 'object') || !Array.isArray(A)) return;
for (k in o) {
v=o[k];
if ((typeof v == 'object') && n.includes(k)) A=A.concat(v);
if (typeof v == 'object') A=parseObj(v, A, n);
}
return A;
}
var done, newL, Tit, title, title0='Website Themes & Skins by Stylish | Userstyles.org',
userID, cancelNextRS=0, dontCancel='', site='',
bgPage='/', blockTitle;
if (document.readyState != 'loading') init('"already done"', 1);
else {
document.addEventListener('DOMContentLoaded', (ev) => { init('DOM');} );
window.addEventListener('load', (ev) => { init('wLoad', 1);} );
}
function chkState(a) {
var u=a[2];
if (u == '/styles/browse') {
if (bgPage.startsWith(u)) u=bgPage;
}
else if (u.startsWith('/styles/[styleId]/')) {
title='';
document.title=title0;
u=bgPage;
}
else if (u.startsWith('/user-profile/[...userId]')) {
if (userID || __NEXT_DATA__) {
u='/user-profile/'+(userID || __NEXT_DATA__.query.userId);
}
}
a[2]=u;
}
// hide logo when scrolled. (saves cpu on old hardware)
var Logo, LHidden=false;
function hideLogo() {
function toggle(set) {
if ( Logo=(Logo && Logo.parentNode && Logo) || document.querySelector('[class^="welcome-banner_top_"] svg') )
LHidden=Logo.classList.toggle('hideMe',set);
else LHidden=set;
}
window.addEventListener('scroll', function() {
if (window.scrollY > 200) {
if (LHidden) return;
toggle(true);
}
else if (LHidden) toggle(false);
});
}
var reactID;
function init(v, old) {
if (done) return;
newL=document.querySelector('#__next');
if (!newL) {
if (old && ST) ST.remove();
return;
}
addSt();
hideLogo();
let t;
done=true;
reactID= (t=Object.keys(newL).find( (v) => v.startsWith('__react') )) && t.split('$')[1];
if (__NEXT_DATA__.page == '/styles/[styleId]/[[...styleParams]]') bgPage='/';
else if ( (__NEXT_DATA__.page == '/styles/browse/[[...categoryParams]]') || (__NEXT_DATA__.page == '/user-profile/[...userId]') )
bgPage='/'+__NEXT_DATA__.props.metaTagsData.og.url.split('/').slice(3).join('/');
let pushState=history.pushState;
history.pushState=function(){
let u=arguments[2];
// ignore if same state
if (cancelNextRS && (dontCancel == u) ) {
dontCancel='';
}
else if (cancelNextRS || (u == location.pathname) ) {
//cancelNextRS=false;
cancelNextRS && cancelNextRS--;
dontCancel='';
selfTitle=blockTitle=true;
return;
}
initial=false;
firstPage=false;
chkState(arguments);
if (u.startsWith('/user-profile/') && (u[13] != '[') ) userID=u.split('/')[2];
if ( (u == '/') || u.startsWith('/user-profile/') || u.startsWith('/styles/browse/') ) bgPage=u;
pushState.apply(history, arguments);
if (location.pathname.startsWith('/styles/')) {
addData('from pushState (path)');
}
}
var hback=history.back,
hforward=history.forward,
hgo=history.go,
hreplaceState=history.replaceState;
history.replaceState=function() {
if (cancelNextRS && (dontCancel == arguments[2]) ) {
dontCancel='';
}
else if (cancelNextRS || (arguments[2] == location.pathname) ) {
cancelNextRS && cancelNextRS--;
dontCancel='';
selfTitle=blockTitle=true;
return;
}
initial=false;
firstPage=false;
return hreplaceState.apply(history, arguments);
}
window.addEventListener('popstate', (ev) => {
if (location.pathname.startsWith('/user-profile/')) {
if (newL.querySelector(':scope > [class^="style_mainWrapper_"]')) {
let e=newL.querySelector(':scope > [class^="style_mainWrapper_"] a[data-stylish="close-style-page-button"]');
if (e) {
e.click();
}
}
}
else if (location.pathname.startsWith('/styles/')) {
let i, r, e=document.querySelector('a[href^="'+location.pathname+'"]');
if (!e) {
r=newL.querySelectorAll('[class^="styles-list_styleRow_"]');
let st, ost;
let ID=location.pathname.split('/')[2]
for (i=0; i < r.length; i++) {
if (r[i]['__reactFiber$'+reactID] && (ID == r[i]['__reactFiber$'+reactID].key.split('-').pop()) ) {
e=r[i];
break;
}
}
}
if (!e) {
let A=document.querySelector('a[href^="/styles/"][href*="1"]');
if (A) {
let react=Object.keys(A).find( (v) => v.startsWith('__reactFiber') );
e=document.createElement('a');
e.href=location.pathname;
e.style='display: none !important;';
let r=newL.querySelector(':scope > div > [class^="Home_homepageWrapper_"]')
if (r) r.appendChild(e);
}
}
if (e) e.click();
}
else if (location.pathname == '/') {
let e=newL.querySelector(':scope > [class^="style_mainWrapper_"] a[data-stylish="close-style-page-button"]');
if (e) {
cancelNextRS=1;
e.click();
}
}
});
// check Title
var Tit = document.querySelector('title'), selfTitle=false;
new MutationObserver(function(mutations) {
if (selfTitle) { selfTitle=false; return; }
if (title && !Tit.textContent.startsWith(title) ) {
document.title=title;
selfTitle=true;
}
}).observe(Tit, { attributes: false, subtree: false, childList: true });
site=document.title.split('|')[1] || '';
if (site) site=' |'+site;
// detect (no) popup
new MutationObserver(function(mutations) {
if (!newL.querySelector(':scope > [class^="style_mainWrapper_"]')) {
title='';
document.title=title0;
if (location.pathname.startsWith('/styles/')) {
if (firstPage && !initial) {
}
}
}
else {
addData('from is popup');
}
}).observe(newL, { attributes: false, subtree: false, childList: true });
// mutation add-er
// sub Mut
function mutToast() {
let r=newL.querySelector(':scope > .Toastify ~ div[class=""], :scope > .Toastify ~ div[class^="MainLayout_mainLayout__"]');
if (r && r.attributes.obs) {
return;
}
if (r) {
new MutationObserver(function(muts) {
for (let mut of muts) {
if (mut.addedNodes.length && mut.previousSibling && (mut.previousSibling.localName == 'header') ) {
addDataTiles();
watchGrid();
break;
}
}
}).observe(r, { attributes: true, subtree: false, childList: true });
r.setAttribute('obs', 'tiles');
}
// added cards ?
watchGrid();
}
function watchGrid() {
var r=newL.querySelector('[class^="styles-grid_gridItems_"]') ||
newL.querySelector('[class^="styles-gallery_scrollWrapper_"] > div:not([class])');
if (r.attributes.obs) {
return;
}
if (r) {new MutationObserver(function(muts) {
for (let mut of muts) {
if (mut.addedNodes.length) {
addDataTiles();
break;
}
}
}).observe(r, { attributes: true, subtree: false, childList: true });
r.setAttribute('obs', 'grid');
}
}
new MutationObserver(function(muts) {
let mut;
for (mut of muts) {
// new body
if (mut.addedNodes.length && mut.previousSibling && (mut.previousSibling.className == 'Toastify') ) {
addDataTiles();
// new list
mutToast();
break;
}
}
}).observe(newL, { attributes: false, subtree: false, childList: true });
newL.setAttribute('obs', null);
mutToast();
addDataTiles();
if (location.pathname.startsWith('/styles/')) {
setTimeout((e) => {addData('from ini '+v)}, 0);
}
}
var totalI, styleID, showCSS, loadCSS;
function getCSS(id, callback) {
if (id && (typeof callback == 'function') ) {
fetch('https://gateway.userstyles.org/styles/getStyleCss/'+id)
.then((response) => response.json())
.then((data) => callback(data));
}
}
function addData() {
var id=styleID=location.pathname.split('/')[2],
s=styles[id];
if (initial) {
// this is the only case when this has to be done.
var t=newL.querySelector('[class^="style-header_close_"]')
if (!closeBut || (closeBut !== t) ) {
closeBut=t;
if (closeBut) {
closeBut.addEventListener('click', function() {
cancelNextRS=1;
dontCancel='/';
title='';
document.title=title0;
history.pushState({}, null, '/');
});
}
}
}
if (!s) return;
var a=document.querySelector('#weekly-installs');
if (!a) return;
if (!totalI || !totalI._root.parentNode) {
totalI=a.cloneNode(true);
totalI.id='totalInstalls';
totalI.dataset.tooltipContent='';
totalI._v=totalI.querySelector(':scope div span');
totalI._v.textContent='';
var tt=a.nextElementSibling, ttTI;
if ( tt.attributes.role && (tt.attributes.role.value == 'tooltip') ) ttTI=tt.cloneNode(true);
if (!ttTI) {
ttTI=document.createElement('div');
ttTI.innerHTML='<div role="tooltip" _model class="react-tooltip styles-module_tooltip__mnnfp styles-module_dark__xNqje react-tooltip__place-top styles-module_show__2NboJ" style="visibility: hidden;">test<div class="react-tooltip-arrow styles-module_arrow__K0L3T" style="left: 40px; bottom: -4px;"></div></div>';
ttTI=ttTI.firstElementChild;
tt=totalI;
}
if (ttTI) {
a.parentNode.insertBefore(ttTI, tt.nextSibling);
if (ttTI.childNodes.length == 1) {
let T=document.createTextNode('Total installs');
ttTI.insertBefore(T, ttTI.firstChild);
}
else ttTI.childNodes[0].textContent='Total installs';
totalI.onmouseenter=function(){
ttTI.style.opacity='0.9';
ttTI.style.visibility='visible';
if (ttTI._init) return;
ttTI._init=true;
if (ttTI.attributes._model) {
ttTI.style.top=(totalI.offsetTop - 47) +'px';
ttTI.style.left=(totalI.offsetLeft -10) +'px';
}
else {
ttTI.style.left=(totalI.offsetLeft - a.offsetLeft + tt.offsetLeft)+'px';
ttTI.style.top=tt.style.top;
ttTI.firstElementChild.setAttribute('style', tt.firstElementChild.attributes.style.value);
}
};
totalI.onmouseleave=function(){ttTI.style.opacity='0'; ttTI.style.visibility='hidden';};
}
var i=totalI.querySelector(':scope > svg'), i2;
if (i) {
i2=i.cloneNode(true);
totalI.insertBefore(i2, i.nextSibling);
i2.style='margin-left: -17px';
}
a.parentNode.insertBefore(totalI, (tt || a).nextSibling);
totalI._root=totalI.closest('[class^="style_mainWrapper_"]');
showCSS=totalI._root.querySelector('[class*="style-info_showCss_"]');
if (showCSS) {
new MutationObserver(function(mutations) {
let e;
if (e=showCSS.parentNode.querySelector('[class^="Popup_modalWrapper_"] textarea')) {
if (loadCSS) {loadCSS=0; return;}
if (styles[styleID].sourceCode) e.value=styles[styleID].sourceCode;
else {
e.value='';
getCSS(styleID, function(v){e.value=styles[styleID].sourceCode=v.result;} );
}
}
}).observe(showCSS.parentNode, { attributes: false, subtree: false, childList: true });
}
}
else {
let e=totalI._root.querySelector('[class^="Popup_modalWrapper_"] textarea');
if (e) {
if (styles[styleID].sourceCode) e.value=styles[styleID].sourceCode;
else {
e.value='';
getCSS(styleID, function(v){e.value=styles[styleID].sourceCode=v.result;} );
}
}
}
let v=parseInt(s.totalInstallsCount);
let vd=a.querySelector('span'), vdv=vd.innerText;
if (vdv.endsWith('k')) vdv=Math.floor(parseFloat(vdv) * 1000);
else vdv=parseInt(vdv);
if (vdv > v) {vd.style='text-decoration: line-through; text-decoration-color: red;';}
else vd.style='';
if (v > 1000) v=(v/1000).toFixed(1)+'k';
totalI._v.textContent=v;
document.title=title=s.name+site;
setTimeout(function(){
if (!totalI._root.parentNode) addData('after');
},10);
}
function addDataTiles() {
var a=document.querySelectorAll('[data-stylish^="strip-cube-styles"]:not(._done), [data-stylish^="grid-cube-styles"]:not(._done)');
a.forEach((e) => e.classList.add('_done'));
var i=0;
add2Tiles();
function add2Tiles() {
var max=Date.now() + 100;
for (; i < a.length; i++) {
if (Date.now() > max) {
setTimeout(add2Tiles, 0);
return;
}
let e=a[i].querySelector('[class*="style-cube_activeUsers_"]');
if (!e) continue;
let h=a[i].querySelector('a[href^="/styles/"]');
if (!h) continue;
let s=styles[h.pathname.split('/')[2]];
if (!s) continue;
let r=a[i].querySelector('[class^="style-cube_styleDetails_"]');
let tot=e.cloneNode(true);
e.title='Weekly installs';
tot.classList.add('_totalInstalls');
tot.title='Total installs';
let _v=tot.querySelector(':scope div span');
_v.textContent='';
let I=tot.querySelector(':scope > svg'), i2;
if (I) {
i2=I.cloneNode(true);
tot.insertBefore(i2, I.nextSibling);
i2.style='margin-left: -9px';
}
// insert total
e.parentNode.insertBefore(tot, e);
let v=parseInt(s.totalInstallsCount);
if (v > 1000) v=(v/1000).toFixed(1)+'k';
_v.textContent=v;
// add dates
e=document.createElement('div');
e.className='_dates_';
let C=s.created.split('T')[0], U=s.updated.split('T')[0];
e.innerHTML=(C == U ? '':'<span title="Last updated">'+U+'</span>')+'<span title="Date created">'+C+'</span>';
r.appendChild(e);
// add user name
e=a[i].querySelector('[class^="style-cube_authorAvatar_"]');
if (e) e.title=s.user.name;
}
}
}
var iST=`
.hideMe {
display: none;
}
div[class^="style_mainWrapper__"] {
padding-top: 0;
}
[data-stylish^="strip-cube-styles"] [class^="style-cube_topWrapper_"],
[data-stylish^="grid-cube-styles"] [class^="style-cube_topWrapper_"] {
margin-bottom: 0;
}
[data-stylish^="strip-cube-styles"] [class^="style-cube_styleDetails_"],
[data-stylish^="grid-cube-styles"] [class^="style-cube_styleDetails_"] {
flex-direction: row wrap;
background: var(--bg, gray);
margin-top: 2px;
transition: unset !important;
transition-delay: unset !important;
padding-top: 2px;
color: white;
}
[data-stylish^="strip-cube-styles"] [class^="style-cube_styleDetails_"] > *,
[data-stylish^="grid-cube-styles"] [class^="style-cube_styleDetails_"] > * {
text-overflow: ellipsis;
overflow: hidden;
word-break: break-all;
}
[data-stylish^="strip-cube-styles"] [class^="style-cube_styleDetails_"] [class^="style-cube_activeUsers_"],
[data-stylish^="grid-cube-styles"] [class^="style-cube_styleDetails_"] [class^="style-cube_activeUsers_"] {
width: auto !important;
margin-left: auto;
}
[data-stylish^="strip-cube-styles"] [class^="style-cube_styleDetails_"] [class^="style-cube_activeUsers_"] + [class^="style-cube_activeUsers_"],
[data-stylish^="grid-cube-styles"] [class^="style-cube_styleDetails_"] [class^="style-cube_activeUsers_"] + [class^="style-cube_activeUsers_"] {
margin-left: 1em;
}
[data-stylish^="strip-cube-styles"] [class^="style-cube_styleDetails_"] [class^="style-cube_activeUsers_"] svg,
[data-stylish^="grid-cube-styles"] [class^="style-cube_styleDetails_"] [class^="style-cube_activeUsers_"] svg {
fill: white;
display: block;
}
[data-stylish^="strip-cube-styles"] [class^="style-cube_styleDetails_"] [class^="style-cube_name_"] *,
[data-stylish^="grid-cube-styles"] [class^="style-cube_styleDetails_"] [class^="style-cube_name_"] * {
text-overflow: ellipsis;
overflow: hidden;
}
[data-stylish^="strip-cube-styles"] [class^="style-cube_styleDetails_"] > [class^="style-cube_styleName_"],
[data-stylish^="grid-cube-styles"] [class^="style-cube_styleDetails_"] > [class^="style-cube_styleName_"] {
oline-height: normal;
flex-basis: calc(100% - 40px);
}
[data-stylish^="strip-cube-styles"] [class^="style-cube_styleDetails_"] > [class^="style-cube_details_"],
[data-stylish^="grid-cube-styles"] [class^="style-cube_styleDetails_"] > [class^="style-cube_details_"] {
width: auto !important;
margin-left: auto;
ooutline: 2px solid red !important;
}
[data-stylish^="strip-cube-styles"] [class*="style-cube_withHover_"]:hover,
[data-stylish^="grid-cube-styles"] [class*="style-cube_withHover_"]:hover {
transform: unset !important;
transition: unset !important;
transition-delay: unset !important;
background-color: unset !important;
--bg: DarkSlateGrey;
}
._dates_._dates_ {
flex-basis: 100%;
margin-top: 2px;
text-align: right;
}
._dates_ span {
color: lightgray;
font-size: 11px;
}
._dates_ span + span {
margin-left: 1em;
}
[class^="styles-strip_stripItemsWrapper_"] > button {
display: none !important;
}
[class^="styles-strip_stripItemsWrapper_"] {
overflow-x: scroll;
padding-bottom: 4px;
}
[class^="styles-strip_stripItemsWrapper_"]::-webkit-scrollbar {
height: 8px !important;
}
[class^="styles-strip_items_"] {
transform: unset !important;
}
:not(g):not(button):not([class^="style_mainWrapper_"])) {
transform: unset !important;
transition: unset !important;
transition-delay: unset !important;
}
svg[transform*="rotate(-180)"] {
transform: rotate(-180deg) !important;
}
[class^="category-filter_borderRadios_"] {
display: none;
}
[class^="styles-list_styleName_"] {
word-break: break-word;
}
[role="tooltip"] .react-tooltip-arrow {
bottom: -7px !important;
border-color: var(--rt-color-dark) transparent;
border-style: solid;
border-width: 7px 7px 0 7px;
display: block;
background: transparent;
transform: none;
}
#totalInstalls {
order: -1;
}
/* fix prothemes sliding right-left - 20230613*/
[class^="styles-strip_sliderWrapper_"][class*="styles-strip_lastPage_"] {
left: -40px !important;
right: auto !important;
}
`;
addSt();
var ST;
function addSt() {
if (!iST) {
document.documentElement.appendChild(ST);
return;
}
try {
ST=document.createElement('style');
document.documentElement.appendChild(ST);
ST.textContent=iST;
iST='';
}catch(e){
setTimeout(addSt,0); }
}
})();