USO - Display additional infos & fixes

Display additional information. Total installs, update date, initial release date. Fix site's navigability.

Από την 24/03/2023. Δείτε την τελευταία έκδοση.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

// ==UserScript==
// @name         USO - Display additional infos & fixes
// @namespace    https://github.com/Procyon-b 
// @version      0.3.1
// @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";

const DEBUG={
  xhr: 0,
  fetch: 0,
  json: 0,
  fJson: 0,
  pushS: 1,
  styles: false,
  mutPop: 1,
  addData: 1,
  jsonIgnoreEmpty: 1,
  hist: 1,
  };

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++;
      }
    });
  if (stylesA.length) {
    if (DEBUG.styles) console.info('%c styles found ','background:green;color:white',{styles, stylesA});
    }
  }

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);
      if (DEBUG.pushS) console.info('changed --> replaceState: '+u);
      }
    }
  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 != arguments[2]) if (DEBUG.pushS) console.info('state fixed', u, '=>', arguments[2]);
    
    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
  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
        let r=newL.querySelector(':scope > .Toastify ~ div[class=""]');
        if (r) console.info('adding mutation obs on', {r});
        if (r) {new MutationObserver(function(muts) {
          for (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() {
          r=newL.querySelector('[class^="styles-grid_gridItems_"]');
          if (r) console.info('adding mutation obs on', {r});
          if (r) {new MutationObserver(function(muts) {
            for (mut of muts) {
              if (mut.addedNodes.length) { 
                addDataTiles();
                break;
                }
              }          
            }).observe(r, { attributes: true, subtree: false, childList: true });
            r.setAttribute('obs', 'grid');
            }
          }

        break;
        }
      
      } 
    }).observe(newL, { attributes: false, subtree: false, childList: true });
    newL.setAttribute('obs', null);

  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) {
      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';
        ttTI.style.left=(totalI.offsetLeft - a.offsetLeft + tt.offsetLeft)+'px';
        if (ttTI._init) return;
        ttTI._init=true;
        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;
}
`;

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); }
}


})();