Responsive Dumb Browser Viewport

Responsive max-500px grayscale viewport with scale, fake slow links, page delay, and video delay.

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

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

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

Advertisement:

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

Advertisement:

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         Responsive Dumb Browser Viewport
// @namespace    https://greasyfork.org/users/your-name
// @version      1.2
// @description  Responsive max-500px grayscale viewport with scale, fake slow links, page delay, and video delay.
// @author       You
// @match        *://*/*
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function () {
  "use strict";

  /*
    Main settings
  */
  const MAX_BOX_WIDTH = "500px";
  const MAX_BOX_HEIGHT = "500px";

  /*
    Mobile fit settings

    Width and height are capped at 500px, but shrink on small screens.
    Lower these if the box still feels too large on mobile.
  */
  const MOBILE_BOX_WIDTH = "92vw";
  const MOBILE_BOX_HEIGHT = "78vh";

  /*
    Scale setting

    1.0 = normal size
    0.9 = slightly smaller
    0.8 = much smaller
    1.1 = larger, not recommended on mobile
  */
  const PAGE_SCALE = 1;

  /*
    Delay settings

    PAGE_REVEAL_DELAY_MS hides the page after load, like slow loading.
    LINK_CLICK_DELAY_MS delays link navigation, like slow internet.
    VIDEO_START_DELAY_MS delays video playback after pressing play.
  */
  const PAGE_REVEAL_DELAY_MS = 700;
  const LINK_CLICK_DELAY_MS = 1200;
  const VIDEO_START_DELAY_MS = 1800;

  /*
    Visual degradation
  */
  const ENABLE_GRAYSCALE = true;
  const ENABLE_MONOSPACE_FONT = false;
  const ENABLE_NO_ROUNDED_CORNERS = false;
  const ENABLE_NO_ANIMATIONS = false;

  /*
    Internal state
  */
  let dumbBrowserAllowNavigation = false;

  function injectStyle() {
    if (document.getElementById("dumb-browser-viewport-style")) return;

    const grayscaleFilter = ENABLE_GRAYSCALE
      ? "grayscale(100%)"
      : "none";

    const monospaceRule = ENABLE_MONOSPACE_FONT
      ? "font-family: monospace !important;"
      : "";

    const noRoundedCornersRule = ENABLE_NO_ROUNDED_CORNERS
      ? "border-radius: 0 !important;"
      : "";

    const noAnimationsRule = ENABLE_NO_ANIMATIONS
      ? `
        animation: none !important;
        transition: none !important;
        scroll-behavior: auto !important;
      `
      : "";

    const style = document.createElement("style");
    style.id = "dumb-browser-viewport-style";

    style.textContent = `
      :root {
        --dumb-box-width: min(${MAX_BOX_WIDTH}, ${MOBILE_BOX_WIDTH});
        --dumb-box-height: min(${MAX_BOX_HEIGHT}, ${MOBILE_BOX_HEIGHT});
        --dumb-page-scale: ${PAGE_SCALE};
      }

      html {
        width: 100vw !important;
        height: 100vh !important;
        min-width: 100vw !important;
        min-height: 100vh !important;
        margin: 0 !important;
        padding: 0 !important;
        overflow: hidden !important;
        background: #111 !important;
        filter: ${grayscaleFilter} !important;
      }

      body {
        width: var(--dumb-box-width) !important;
        height: var(--dumb-box-height) !important;
        max-width: var(--dumb-box-width) !important;
        max-height: var(--dumb-box-height) !important;

        position: fixed !important;
        left: 50% !important;
        top: 50% !important;

        transform:
          translate(-50%, -50%)
          scale(var(--dumb-page-scale)) !important;

        transform-origin: center center !important;

        margin: 0 !important;
        padding: 0 !important;

        overflow-x: auto !important;
        overflow-y: auto !important;
        overscroll-behavior: contain !important;

        background: #fff !important;
        color: #000 !important;

        box-sizing: border-box !important;
        box-shadow: 0 0 0 9999px #111 !important;

        filter: ${grayscaleFilter} !important;
        opacity: 0 !important;

        ${monospaceRule}
      }

      body.dumb-browser-visible {
        opacity: 1 !important;
      }

      body,
      body * {
        box-sizing: border-box !important;
        filter: ${grayscaleFilter} !important;
        ${noRoundedCornersRule}
        ${noAnimationsRule}
      }

      img,
      video,
      canvas,
      iframe,
      svg,
      picture {
        filter: ${grayscaleFilter} !important;
      }
    `;

    document.documentElement.appendChild(style);
  }

  function revealPageAfterDelay() {
    const reveal = () => {
      if (!document.body) return;

      setTimeout(() => {
        document.body.classList.add("dumb-browser-visible");
      }, PAGE_REVEAL_DELAY_MS);
    };

    if (document.readyState === "loading") {
      document.addEventListener("DOMContentLoaded", reveal, { once: true });
    } else {
      reveal();
    }
  }

  function addSlowLinkClicks() {
    document.addEventListener(
      "click",
      function (event) {
        const link = event.target.closest && event.target.closest("a[href]");

        if (!link) return;
        if (dumbBrowserAllowNavigation) return;

        const href = link.href;

        if (!href) return;
        if (href.startsWith("javascript:")) return;
        if (href.startsWith("#")) return;

        event.preventDefault();
        event.stopPropagation();

        setTimeout(() => {
          dumbBrowserAllowNavigation = true;
          window.location.href = href;
        }, LINK_CLICK_DELAY_MS);
      },
      true
    );
  }

  function addVideoStartDelay() {
    const delayedVideos = new WeakSet();

    function patchVideo(video) {
      if (!video || delayedVideos.has(video)) return;

      video.addEventListener(
        "play",
        function () {
          if (video.dataset.dumbBrowserVideoAllowed === "true") {
            video.dataset.dumbBrowserVideoAllowed = "false";
            return;
          }

          video.pause();

          setTimeout(() => {
            video.dataset.dumbBrowserVideoAllowed = "true";
            video.play().catch(() => {
              /*
                Some browsers block programmatic play.
                If that happens, the user has to press play again.
              */
            });
          }, VIDEO_START_DELAY_MS);
        },
        true
      );

      delayedVideos.add(video);
    }

    function patchAllVideos() {
      document.querySelectorAll("video").forEach(patchVideo);
    }

    if (document.readyState === "loading") {
      document.addEventListener("DOMContentLoaded", patchAllVideos);
    } else {
      patchAllVideos();
    }

    const observer = new MutationObserver(() => {
      patchAllVideos();
    });

    observer.observe(document.documentElement, {
      childList: true,
      subtree: true,
    });
  }

  injectStyle();
  revealPageAfterDelay();
  addSlowLinkClicks();
  addVideoStartDelay();
})();