TBD: TorrentBD GitHub Dark (Minimal)

Minimal GitHub Dark theme for TorrentBD.

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         TBD: TorrentBD GitHub Dark (Minimal)
// @namespace    https://torrentbd.tools/
// @version      1.0.0
// @description  Minimal GitHub Dark theme for TorrentBD.
// @author       s4db1n
// @license      GPL-3.0-or-later
// @match        https://*.torrentbd.com/*
// @match        https://*.torrentbd.net/*
// @match        https://*.torrentbd.org/*
// @match        https://*.torrentbd.me/*
// @grant        none
// ==/UserScript==

(function () {
  "use strict";

  const THEME = {
    bodybg: "#000000",
    cardbg: "#000000",
    bodycolor: "#e6e6e6",
    bodystark: "#ffffff",
    btncolor: "#000000",
    btnhover: "#000000",
    accent1: "#58a6ff",
    accent2: "#ff7b72",
    accent3: "#3fb950",
    navbg: "#000000",
    titlecolor: "#ffffff",
    logo: "#ffffff",
    catfilter: "hue-rotate(60deg) saturate(5)"
  };

  function setJSON(key, data) {
    localStorage.setItem(key, JSON.stringify(data));
  }

  function getRGB(hexColor) {
    const color = hexColor.replace("#", "");
    const r = parseInt(color.slice(0, 2), 16);
    const g = parseInt(color.slice(2, 4), 16);
    const b = parseInt(color.slice(4, 6), 16);
    return { r, g, b };
  }

  // Same behavior the original engine used for quick tint/shade generation.
  function applyShade(hexColor, amount) {
    const { r, g, b } = getRGB(hexColor);
    const clamp = (v) => Math.max(0, Math.min(255, v));
    const rr = clamp(Math.round(r + (255 * amount) / 100));
    const gg = clamp(Math.round(g + (255 * amount) / 100));
    const bb = clamp(Math.round(b + (255 * amount) / 100));
    return `#${rr.toString(16).padStart(2, "0")}${gg
      .toString(16)
      .padStart(2, "0")}${bb.toString(16).padStart(2, "0")}`;
  }

  function persistTheme() {
    setJSON("themeDark", THEME);
    setJSON("themeLight", THEME);
    localStorage.setItem("theme", "dark");

    if (!localStorage.getItem("fontlink")) {
      localStorage.setItem(
        "fontlink",
        "https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,400;0,700;1,400;1,700&display=swap"
      );
    }
    if (!localStorage.getItem("fontname")) {
      localStorage.setItem("fontname", "IBM Plex Sans");
    }
  }

  const css = `:root {
--engine-body-bg: ${THEME.bodybg};
--engine-card-bg: ${THEME.cardbg};
--engine-nav-bg: ${THEME.navbg};
--engine-body-color: ${THEME.bodycolor};
--engine-body-color-stark: ${THEME.bodystark};
--engine-button-color: ${THEME.btncolor};
--engine-button-color-hover: ${THEME.btnhover};
--engine-accent-color-1: ${THEME.accent1};
--engine-accent-color-2: ${THEME.accent2};
--engine-accent-color-3: ${THEME.accent3};
--engine-content-title: ${THEME.titlecolor};
--engine-logo-color: ${THEME.logo};
--engine-cat-filter: ${THEME.catfilter};

--engine-body-color-light: ${THEME.bodycolor}cc;
--engine-table-odd-bg: ${applyShade(THEME.cardbg, -4)};
--engine-accent-color-1a: ${applyShade(THEME.accent1, 20)};
--engine-accent-color-1b: ${applyShade(THEME.accent1, -70)};
--engine-accent-color-1c: ${THEME.accent1}22;
--engine-accent-color-1d: ${applyShade(THEME.accent1, -30)};
--engine-accent-color-2a: ${applyShade(THEME.accent2, 20)};
--engine-accent-color-3a: ${applyShade(THEME.accent3, 20)};
--engine-media-hover-bg: ${applyShade(THEME.cardbg, 15)}cc;
--engine-account-buttons: ${THEME.bodycolor};
--engine-account-buttons-hover: ${THEME.bodystark};
--engine-account-buttons-background: ${THEME.bodystark}15;

--engine-seeders: #4caf50;
--engine-leechers: #f44336;
--engine-completed: #ffa726;
--engine-shortlink-color: #ffffff;

--engine-search-color: var(--engine-content-title);
--engine-search-background: var(--engine-nav-bg);
--engine-menu-item: var(--engine-content-title);
--engine-menu-item-hover: var(--engine-accent-color-1);
--engine-like-button: var(--engine-content-title);
--engine-border-color: #2f3b47;
--engine-theme-toggle: var(--engine-account-buttons);
--engine-theme-toggle-hover: var(--engine-account-buttons-hover);
--engine-theme-toggle-background: var(--engine-account-buttons-background);

--engine-backdrop-bg: transparent;
--body-bg: var(--engine-body-bg);
--body-color: var(--engine-body-color);
--body-color-light: var(--engine-body-color-light);
--border-color: var(--engine-border-color);
--border-sp-color: rgba(120, 138, 160, 0.9);
--border-sp-light-color: rgba(120, 138, 160, 0.65);
--btn-1-color: var(--engine-accent-color-1);
--cm-bg: var(--engine-body-bg);
--cmodal-dark-bg: var(--engine-body-bg);
--light-color-3: #b5bbbc;
--link-cm1-color: var(--engine-accent-color-1a);
--link-color: var(--engine-accent-color-1);
--link-hover-color: var(--engine-accent-color-1a);
--link-sp1-color: var(--engine-body-color);
--link-sp1-hover-color: var(--engine-accent-color-1);
--link-sp2-color: var(--engine-accent-color-2);
--link-sp3-color: var(--engine-accent-color-3);
--main-bg: var(--engine-card-bg);
--modal-color: #c1cdd2;
--nav-alt-bg: #006064;
--nav-bg: var(--engine-nav-bg);
--placeholder-color: rgba(181, 199, 207, 0.7);
--readable-bg: rgba(69, 74, 89, 0.9);
--engine-font-family: '${localStorage.getItem("fontname") || "IBM Plex Sans"}', 'IBM Plex Sans', 'Noto Sans Bengali', 'Siyam Rupali', Verdana, sans-serif;
}

.engine-dawn { display: none !important; }
.engine-dusk { display: inherit !important; }

/* Keep form/control outlines visible on full-black backgrounds. */
input[type="text"],
input[type="search"],
input[type="number"],
input[type="password"],
select,
textarea {
  border: 1px solid var(--engine-border-color) !important;
}

input[type="checkbox"],
input[type="radio"] {
  border: 1px solid var(--engine-border-color) !important;
}
`;

  function injectStyle() {
    if (document.getElementById("tbd-github-dark-min")) {
      return;
    }
    const style = document.createElement("style");
    style.id = "tbd-github-dark-min";
    style.textContent = css;

    if (document.head) {
      document.head.appendChild(style);
    } else {
      document.documentElement.appendChild(style);
    }
  }

  persistTheme();
  injectStyle();

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

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