youtube-playlist-randomizer improvements

Improve your youtube-playlist-randomizer experience with these cosmetic changes.

As of 2025-05-26. See the latest version.

// ==UserScript==
// @name         youtube-playlist-randomizer improvements
// @namespace    https://r5ne.carrd.co/
// @version      1.0
// @include      https://youtube-playlist-randomizer.bitbucket.io*
// @include      https://ytplr.bitbucket.io*
// @description  Improve your youtube-playlist-randomizer experience with these cosmetic changes.
// @author       r5ne
// @grant        none
// @license      GPL-3.0-only
// ==/UserScript==


;(function() {
  const html = document.documentElement;
  const body = document.body;
  const CENTER_CSS = `
    html, body {
      margin: 0; padding: 0; height: 100%; width: 100%;
      display: flex; flex-direction: column;
      align-items: center; text-align: center;
    }
    body { margin: 0; }
    body > div { max-width: 100%; width: auto; }
    iframe {
      display: block; margin: 1em 0;
      flex: 0 0 auto; /* respect its own width/height */
    }
  `;
  const centerStyle = document.createElement('style');
  centerStyle.textContent = CENTER_CSS;
  document.head.appendChild(centerStyle);
  const contentOverlayCSS = document.createElement('style');
  contentOverlayCSS.textContent = `
    /* Box all top‑level DIVs except the placeholder */
    body > div:not(#video-placeholder) {
      background: rgba(0,0,0,0.25);
      padding: 1rem;
      border-radius: 0.5rem;
      max-width: 90vw;
      box-sizing: border-box;
    }
  `;
  document.head.appendChild(contentOverlayCSS);

  const dynamicStyle = document.createElement('style');
  dynamicStyle.id = 'dynamic-theme';
  document.head.appendChild(dynamicStyle);

  const LUMINANCE_THRESHOLD  = `120`;  // Increase to have the dark theme (e.g. white font) used for lighter images.
  const DARK_TEXT_COLOR      = '#000';
  const LIGHT_TEXT_COLOR     = '#fff';
  const DARK_LINK_COLOR      = '#0066cc';
  const DARK_LINK_VISITED    = '#551A8B';
  const LIGHT_LINK_COLOR     = '#66CCFF';
  const LIGHT_LINK_VISITED   = '#AA99FF';
  const HEAVY_TEXT_SHADOW    = `
    1px 1px 2px rgba(0,0,0,0.8),
    -1px -1px 2px rgba(0,0,0,0.8),
    1px -1px 2px rgba(0,0,0,0.8),
    -1px 1px 2px rgba(0,0,0,0.8)
  `;
  const UNSPLASH_ACCESS_KEY = 'bla bla bla ble ble ble blu blu blu blu';  // Replace with your own unsplash access key. See script description for more info.
  const queries = ["landscape", "abandoned", "cosmos", "waterfall", "mountain", "desert landscape", "stars", "sky", "day", "night", "night sky", "nature"];  // Replace with whatever themes you want your images to be.

  const sampleCanvas = document.createElement('canvas');
  sampleCanvas.width = sampleCanvas.height = 10;
  const sampleCtx = sampleCanvas.getContext('2d');

  function pickTextColorFromImage(url) {
    return new Promise(resolve => {
      const img = new Image();
      img.crossOrigin = 'anonymous';
      img.onload = () => {
        sampleCtx.drawImage(img, 0, 0, 10, 10);
        const data = sampleCtx.getImageData(0, 0, 10, 10).data;
        let total = 0, count = 0;
        for (let i = 0; i < data.length; i += 4) {
          const [r,g,b] = [data[i], data[i+1], data[i+2]];
          total += 0.2126*r + 0.7152*g + 0.0722*b;
          count++;
        }
        console.log('average Luminance = ', (total/count));
        resolve((total/count) < LUMINANCE_THRESHOLD);
      };
      img.onerror = () => resolve(false);
      img.src = url;
    });
  }

  function showAttribution({ href, label }) {
    let el = document.getElementById('bg-attribution');
    if (!el) {
      el = document.createElement('div');
      el.id = 'bg-attribution';
      Object.assign(el.style, {
        position:       'fixed',
        bottom:         '8px',
        right:          '8px',
        padding:        '4px 8px',
        background:     'rgba(0,0,0,0.4)',
        color:          'white',
        fontSize:       '12px',
        borderRadius:   '4px',
        zIndex:         9999,
        pointerEvents:  'auto',
        lineHeight:     '1.2'
      });
      body.appendChild(el);
    }
    el.innerHTML = `
      <div>
        <a href="https://greasyfork.org/en/scripts/537152-youtube-playlist-randomizer-improvements"
           target="_blank" style="color:inherit;text-decoration:underline">
          Script by r5ne
        </a>
      </div>
      <div>
        <a href="${href}" target="_blank" style="color:inherit;text-decoration:underline">
          ${label}
        </a>
      </div>
    `;
  }

  async function BG_change() {
    const selectedQuery = queries[Math.floor(Math.random() * queries.length)];
    const apiUrl = `https://api.unsplash.com/photos/random?client_id=${UNSPLASH_ACCESS_KEY}&query=${selectedQuery}&orientation=landscape`;
    try {
      const res   = await fetch(apiUrl);
      if (!res.ok) throw new Error(res.status);
      const photo = await res.json();

      const finalUrl = `${photo.urls.raw}&w=2560&h=1440&fit=crop&crop=entropy`;
      const isDark   = await pickTextColorFromImage(finalUrl);

      const linkColor   = isDark ? LIGHT_LINK_COLOR  : DARK_LINK_COLOR;
      const linkVisited = isDark ? LIGHT_LINK_VISITED: DARK_LINK_VISITED;
      const textColor   = isDark ? LIGHT_TEXT_COLOR : DARK_TEXT_COLOR;
      const textShadow  = isDark ? HEAVY_TEXT_SHADOW : 'none';

      dynamicStyle.textContent = `
        html { color: ${textColor}; }
        body { text-shadow: ${textShadow}; }
        a, a:visited { color: ${linkColor} !important; }
        a:visited { color: ${linkVisited} !important; }
      `;

      body.style.backgroundImage    = `url("${finalUrl}")`;
      body.style.backgroundSize     = 'cover';
      body.style.backgroundRepeat   = 'no-repeat';
      body.style.backgroundPosition = 'center';
      html.style.minHeight          = '100vh';
      body.style.minHeight          = '100vh';
      body.style.margin             = '0';

      showAttribution({
        href:  photo.links.html,
        label: `Unsplash: Photo by ${photo.user.name}`
      });
    }
    catch (err) {
      console.error('BG_change error:', err);
      body.style.backgroundImage = 'url("https://picsum.photos/1920/1080")';
      showAttribution({
        href:  'https://picsum.photos/',
        label: 'Lorem Picsum © Image'
      });
    }
  }

  window.addEventListener('load', BG_change);
})();