wnacg 優化

電腦版頁面支持切換自動翻頁或手動按鍵翻頁,並可自定背景顏色及圖像大小。電腦開啟的手機頁面 (移動端不適用),則可自定背景顏色及圖像大小。

// ==UserScript==
// @name            wnacg 優化
// @name:zh-TW      wnacg 優化
// @name:zh-CN      wnacg 优化
// @name:ja         wnacg 最適化
// @name:en         wnacg Optimization
// @version         0.0.15
// @author          Canaan HS
// @description         電腦版頁面支持切換自動翻頁或手動按鍵翻頁,並可自定背景顏色及圖像大小。電腦開啟的手機頁面 (移動端不適用),則可自定背景顏色及圖像大小。
// @description:zh-TW   電腦版頁面支持切換自動翻頁或手動按鍵翻頁,並可自定背景顏色及圖像大小。電腦開啟的手機頁面 (移動端不適用),則可自定背景顏色及圖像大小。
// @description:zh-CN   电脑版页面支持切换自动翻页或手动按键翻页,并可自定背景颜色及图像大小。电脑开启的手机页面(移动端不适用),则可自定背景颜色及图像大小。
// @description:ja      デスクトップ版ページでは、自動ページ送りと手動キー操作によるページ送りの切り替えができ、背景色と画像サイズをカスタマイズできます。デスクトップで開いたモバイルページ(モバイル端末では適用されません)では、背景色と画像サイズをカスタマイズできます。
// @description:en      The desktop version supports switching between automatic page turning and manual key press page turning, with customizable background color and image size. The mobile version opened on a desktop (not applicable on mobile devices) allows for customizing the background color and image size.

// @match       *://*.wnacg.com/photos-view-id-*.html
// @match       *://*.wnacg01.ru/photos-view-id-*.html
// @match       *://*.wnacg02.ru/photos-view-id-*.html
// @match       *://*.wnacg03.ru/photos-view-id-*.html

// @match       *://*.wnacg.com/photos-slist-aid-*.html
// @match       *://*.wnacg01.ru/photos-slist-aid-*.html
// @match       *://*.wnacg02.ru/photos-slist-aid-*.html
// @match       *://*.wnacg03.ru/photos-slist-aid-*.html

// @icon        https://www.wnacg.com/favicon.ico

// @license     MIT
// @namespace   https://greasyfork.org/users/989635

// @run-at      document-start
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_deleteValue
// @grant       GM_registerMenuCommand

// @require     https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js
// @require     https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.14.0/jquery-ui.min.js
// @require     https://update.greasyfork.org/scripts/495339/1456526/ObjectSyntax_min.js
// @require     https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js
// @require     https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js
// ==/UserScript==

(async () => {
  async function x(a, e) {
      document.title = document.title.split(" - ")[1];
      const f = Syn.$$("a", { root: a }).href,
          r = Syn.$$("img", { root: a }).src;
      if (h.SwitchStatus) {
          let q = Syn.$$("select option", { all: !0 }).length - e;
          const p = new IntersectionObserver(
              (c) => {
                  c.forEach((b) => {
                      b.isIntersecting &&
                          (history.pushState(null, null, b.target.alt),
                              p.unobserve(b.target));
                  });
              },
              { threshold: 0.3 }
          );
          function m({ OLink: c, src: b }) {
              return React.createElement("img", {
                  src: b,
                  alt: c,
                  loading: "lazy",
                  className: "ImageOptimization",
                  ref: function (g) {
                      g && p.observe(g);
                  },
              });
          }
          async function n(c) {
              0 < q &&
                  fetch(c)
                      .then((b) => b.text())
                      .then((b) => {
                          b = Syn.$$("#photo_body", { root: Syn.DomParse(b) });
                          const g = Syn.$$("a", { root: b }).href;
                          b = Syn.$$("img", { root: b }).src;
                          ReactDOM.render(
                              React.createElement(m, { OLink: c, src: b }),
                              a.appendChild(document.createElement("div"))
                          );
                          setTimeout(() => {
                              q--;
                              n(g);
                          }, 500);
                      })
                      .catch((b) => {
                          n(c);
                      });
          }
          ReactDOM.render(
              React.createElement(m, { OLink: Syn.Device.Url, src: r }),
              a
          );
          Syn.$$("#header").scrollIntoView();
          n(f);
      } else {
          function q({ number: c, src: b }) {
              return React.createElement("img", {
                  src: b,
                  "data-number": c,
                  className: "ImageOptimization",
              });
          }
          async function p(c) {
              fetch(c)
                  .then((b) => b.text())
                  .then((b) => {
                      b = Syn.DomParse(b);
                      var g = Syn.$$("#photo_body", { root: b });
                      g = Syn.$$("img", { root: g }).src;
                      ReactDOM.render(React.createElement(q, { number: m, src: g }), a);
                      b = Syn.$$(".newpage .btntuzao", { all: !0, root: b });
                      n.set(m, { PrevLink: b[0].href, NextLink: b[1].href });
                      history.pushState(null, null, c);
                      window.scrollTo(0, 0);
                  });
          }
          let m = e;
          const n = new Map();
          e = Syn.$$(".newpage .btntuzao", { all: !0 });
          n.set(m, { PrevLink: e[0].href, NextLink: e[1].href });
          ReactDOM.render(
              React.createElement(q, { number: m, NLink: f, src: r }),
              a
          );
          document.onkeydown = void 0;
          u(window, "keydown", (c) => {
              var b = c.key;
              if ("ArrowLeft" == b || "4" == b)
                  c.stopImmediatePropagation(),
                      --m,
                      (c = +Syn.$$("img", { root: a }).getAttribute("data-number")),
                      (b = n.get(c - 1)) ? p(b.PrevLink) : p(n.get(c).PrevLink);
              else if ("ArrowRight" == b || "6" == b)
                  c.stopImmediatePropagation(),
                      ++m,
                      (c = +Syn.$$("img", { root: a }).getAttribute("data-number")),
                      (c = n.get(c).NextLink),
                      p(c);
          });
      }
  }
  async function u(a, e, f) {
      $(a).on(e, f);
  }
  async function w(a = !1) {
      if (Syn.$$(".modal-background")) a && Syn.$$(".modal-background").remove();
      else {
          var {
              SwitchStatus: e,
              ImageBasicWidth: f,
              ImageMaxWidth: r,
              ImageBasicHight: q,
              ImageMaxHight: p,
              ImageSpacing: m,
              BackgroundColor: n,
          } = h.LoadingConfig();
          a = [];
          for (var c of [m, f, r, q, p, n]) a.push(h.ConfigAnalyze(c));
          c = h.IsMobile
              ? ""
              : `
          <div class="DMS">
              <input type="checkbox" class="DMS-checkbox" id="SwitchMode" ${e ? "checked" : ""
              }>
              <label class="DMS-label" for="SwitchMode">
                  <span class="DMS-inner"></span>
                  <span class="DMS-switch"></span>
              </label>
          </div>
      `;
          a = `
          <div class="modal-background">
              <div class="modal-interface">
                  <div style="display: flex; justify-content: space-between;">
                      <h1 style="margin-bottom: 1rem; font-size: 1.3rem;">${h.Transl(
              "\u5716\u50cf\u8a2d\u7f6e"
          )}</h1>${c}
                  </div>
                  <p>
                      <Cins>${h.Transl(
              "\u5716\u50cf\u9593\u8ddd"
          )}</Cins><input type="range" id="ImageSpacing" class="slider" min="0" max="100" step="1" value="${a[0].RangeValue
              }">
                      <span class="Cshow">${a[0].DisplayText}</span>
                  </p>
                  <br>
                  <p>
                      <Cins>${h.Transl(
                  "\u57fa\u672c\u5bec\u5ea6"
              )}</Cins><input type="range" id="ImageBasicWidth" class="slider" min="9" max="100" step="1" value="${a[1].RangeValue
              }">
                      <span class="Cshow">${a[1].DisplayText}</span>
                  </p>
                  <br>
                  <p>
                      <Cins>${h.Transl(
                  "\u6700\u5927\u5bec\u5ea6"
              )}</Cins><input type="range" id="ImageMaxWidth" class="slider" min="9" max="100" step="1" value="${a[2].RangeValue
              }">
                      <span class="Cshow">${a[2].DisplayText}</span>
                  </p>
                  <br>
                  <p>
                      <Cins>${h.Transl(
                  "\u57fa\u672c\u9ad8\u5ea6"
              )}</Cins><input type="range" id="ImageBasicHight" class="slider" min="9" max="100" step="1" value="${a[3].RangeValue
              }">
                      <span class="Cshow">${a[3].DisplayText}</span>
                  </p>
                  <br>
                  <p>
                      <Cins>${h.Transl(
                  "\u6700\u5927\u9ad8\u5ea6"
              )}</Cins><input type="range" id="ImageMaxHight" class="slider" min="9" max="100" step="1" value="${a[4].RangeValue
              }">
                      <span class="Cshow">${a[4].DisplayText}</span>
                  </p>
                  <br>
                  <p>
                      <Cins>${h.Transl(
                  "\u80cc\u666f\u984f\u8272"
              )}</Cins><input type="color" id="BackgroundColor" class="color" value="${a[5].RangeValue
              }">
                      <span style="margin-right: 17.9rem;"></span><button id="SaveConfig" class="button-sty">${h.Transl(
                  "\u4fdd\u5b58\u8a2d\u7f6e"
              )}</button>
                  </p>
              </div>
          </div>
      `;
          var b = document.body;
          $(b).append(a);
          $(".modal-interface").draggable({
              scroll: !0,
              opacity: 0.8,
              cursor: "grabbing",
          });
          var g, k, t;
          u("#BackgroundColor", "input", (l) => {
              g = l.target.id;
              k = $(l.target).val();
              h.StylePointer[g](b, k);
          });
          u("#ImageSpacing", "input", (l) => {
              t = $(l.target).next(".Cshow");
              g = l.target.id;
              k = $(l.target).val();
              h.StylePointer[g](`${k}rem`);
              t.text(`${k}rem`);
          });
          u("#ImageBasicWidth, #ImageMaxWidth", "input", (l) => {
              t = $(l.target).next(".Cshow");
              g = l.target.id;
              k = $(l.target).val();
              "9" === k
                  ? (h.StylePointer[g]("auto"), t.text("auto"))
                  : (h.StylePointer[g](`${k}%`), t.text(`${k}%`));
          });
          u("#ImageBasicHight, #ImageMaxHight", "input", (l) => {
              t = $(l.target).next(".Cshow");
              g = l.target.id;
              k = $(l.target).val();
              "9" === k
                  ? (h.StylePointer[g]("auto"), t.text("auto"))
                  : (h.StylePointer[g](`${k}rem`), t.text(`${k}rem`));
          });
          u("#SaveConfig", "click", function () {
              const l = {};
              l.SwitchStatus = $("#SwitchMode").prop("checked") ? !0 : !1;
              var d = $(".modal-interface");
              const v = d.css("top");
              d = d.css("left");
              l.MenuTop = v;
              l.MenuLeft = d;
              h.StylePointer.MenuTop(v);
              h.StylePointer.MenuLeft(d);
              $(".modal-interface")
                  .find("input")
                  .not("#SwitchMode")
                  .each(function () {
                      g = $(this).attr("id");
                      k = $(this).val();
                      l[g] =
                          "ImageSpacing" === g
                              ? `${k}rem`
                              : "ImageBasicWidth" === g || "ImageMaxWidth" === g
                                  ? "9" === k
                                      ? "auto"
                                      : `${k}%`
                                  : "ImageBasicHight" === g || "ImageMaxHight" === g
                                      ? "9" === k
                                          ? "auto"
                                          : `${k}rem`
                                      : k;
                  });
              Syn.Store("s", "Config", l);
              $(".modal-background").remove();
          });
      }
  }
  (async () => {
      Syn.Store("g", "Mode_V2", !1) && Syn.Store("d", "Mode_V2");
      const a = Syn.Store("g", "Settings");
      if (a) {
          Syn.Store("d", "Settings");
          const { ULS: e, BW: f, MW: r, BH: q, MH: p, BC: m, MT: n, ML: c } = a[0];
          Syn.Store("s", "Config", {
              SwitchStatus: !0,
              MenuTop: n,
              MenuLeft: c,
              ImageBasicWidth: f,
              ImageMaxWidth: r,
              ImageBasicHight: q,
              ImageMaxHight: p,
              ImageSpacing: e,
              BackgroundColor: m,
          });
      }
  })();
  const h = (() => {
      const a = () =>
          Syn.Store("g", "Config", null) ?? {
              SwitchStatus: !0,
              MenuTop: "auto",
              MenuLeft: "auto",
              ImageSpacing: "0rem",
              ImageBasicWidth: "100%",
              ImageMaxWidth: "60%",
              ImageBasicHight: "auto",
              ImageMaxHight: "auto",
              BackgroundColor: "#000",
          };
      let e;
      var f = {},
          r = {
              "\u5716\u50cf\u8a2d\u7f6e": "\u56fe\u50cf\u8bbe\u7f6e",
              "\u5716\u50cf\u9593\u8ddd": "\u56fe\u50cf\u95f4\u8ddd",
              "\u57fa\u672c\u5bec\u5ea6": "\u57fa\u672c\u5bbd\u5ea6",
              "\u6700\u5927\u5bec\u5ea6": "\u6700\u5927\u5bbd\u5ea6",
              "\u57fa\u672c\u9ad8\u5ea6": "\u57fa\u672c\u9ad8\u5ea6",
              "\u6700\u5927\u9ad8\u5ea6": "\u6700\u5927\u9ad8\u5ea6",
              "\u80cc\u666f\u984f\u8272": "\u80cc\u666f\u989c\u8272",
              "\u4fdd\u5b58\u8a2d\u7f6e": "\u4fdd\u5b58\u8bbe\u7f6e",
              "\u6efe\u52d5\u95b1\u8b80": "\u6eda\u52a8\u9605\u8bfb",
              "\u7ffb\u9801\u95b1\u8b80": "\u7ffb\u9875\u9605\u8bfb",
              "\ud83d\udd32 \u958b\u95dc\u83dc\u55ae": "\u5f00\u5173\u83dc\u5355",
          };
      f = {
          "zh-TW": f,
          "zh-HK": f,
          "zh-MO": f,
          "zh-CN": r,
          "zh-SG": r,
          "en-US": {
              "\u5716\u50cf\u8a2d\u7f6e": "Image Settings",
              "\u5716\u50cf\u9593\u8ddd": "Image ImageSpacing",
              "\u57fa\u672c\u5bec\u5ea6": "Base Width",
              "\u6700\u5927\u5bec\u5ea6": "Max Width",
              "\u57fa\u672c\u9ad8\u5ea6": "Base Height",
              "\u6700\u5927\u9ad8\u5ea6": "Max Height",
              "\u80cc\u666f\u984f\u8272": "BackgroundColor Color",
              "\u4fdd\u5b58\u8a2d\u7f6e": "Save Settings",
              "\u6efe\u52d5\u95b1\u8b80": "Scroll Read",
              "\u7ffb\u9801\u95b1\u8b80": "TurnPage Read",
              "\ud83d\udd32 \u958b\u95dc\u83dc\u55ae": "Toggle Menu",
          },
          ja: {
              "\u5716\u50cf\u8a2d\u7f6e": "\u753b\u50cf\u8a2d\u5b9a",
              "\u5716\u50cf\u9593\u8ddd": "\u753b\u50cf\u9593\u9694",
              "\u57fa\u672c\u5bec\u5ea6": "\u57fa\u672c\u5e45",
              "\u6700\u5927\u5bec\u5ea6": "\u6700\u5927\u5e45",
              "\u57fa\u672c\u9ad8\u5ea6": "\u57fa\u672c\u9ad8\u3055",
              "\u6700\u5927\u9ad8\u5ea6": "\u6700\u5927\u9ad8\u3055",
              "\u80cc\u666f\u984f\u8272": "\u80cc\u666f\u8272",
              "\u4fdd\u5b58\u8a2d\u7f6e": "\u8a2d\u5b9a\u306e\u4fdd\u5b58",
              "\u6efe\u52d5\u95b1\u8b80":
                  "\u30b9\u30af\u30ed\u30fc\u30eb\u8aad\u307f\u53d6\u308a",
              "\u7ffb\u9801\u95b1\u8b80":
                  "\u30da\u30fc\u30b8\u8aad\u307f\u53d6\u308a",
              "\ud83d\udd32 \u958b\u95dc\u83dc\u55ae":
                  "\u30e1\u30cb\u30e5\u30fc\u306e\u5207\u308a\u66ff\u3048",
          },
      };
      const q = f[Syn.Device.Lang] ?? f["en-US"];
      f = (d) => q[d] ?? d;
      const {
          SwitchStatus: p,
          MenuTop: m,
          MenuLeft: n,
          ImageBasicWidth: c,
          ImageMaxWidth: b,
          ImageBasicHight: g,
          ImageMaxHight: k,
          ImageSpacing: t,
          BackgroundColor: l,
      } = a();
      Syn.AddStyle(`
          .ImageOptimization {
              display: block;
              margin: ${t} auto;
              width: ${c};
              height: ${g};
              max-width: ${b};
              max-height: ${k};
          }
          body {
              overflow-x: visible !important;
              background-color: ${l} !important;
          }
          a, em {
              color: #fff !important;
          }
          .nav li a {
              float: left;
              line-height: 40px;
              height: 40px;
              width: 85px;
              font-size: 14px;
              color: #fff !important;
              text-decoration: none;
              text-align: center;
              font-weight: bold;
              text-align: center;
              background: #5F5F5F !important;
          }
          .tocaowrap {
              width: 100%;
              margin: 0 auto;
              padding: 0.1rem;
              max-width: ${b};
          }
          .btntuzao {
              margin: 0 5px;
              background-color: #5F5F5F;
          }
          #header {
              background: #5F5F5F;
              border-bottom: 1px solid #dfe1e1;
              transform: translateY(-1.6rem);
              opacity: 0;
              transition: 0.8s;
          }
          #header:hover {
              opacity: 1;
              transform: translateY(0rem);
          }
          .modal-background {
              top: 0;
              left: 0;
              width: 100%;
              height: 100%;
              display: flex;
              z-index: 9999;
              position: fixed;
              overflow: auto;
              pointer-events: none;
          }
          .modal-interface {
              top: ${m};
              left: ${n};
              margin: auto;
              color: #3d8fe7;
              padding: 1% 2%;
              border-radius: 5px;
              background-color: #f3f3f3;
              border: 2px solid #c0d8fc;
              pointer-events: auto;
          }
          .slider {
              width: 21rem;
              cursor: pointer;
          }
          .color {
              width: 4rem;
              cursor: pointer;
          }
          .Cshow {
              font-size: 1.25rem;
              margin: auto 1rem;
              font-weight: bold;
          }
          .button-sty {
              color: #ffffff;
              font-size: 1rem;
              padding: 0.3rem;
              font-weight: bold;
              border-radius: 5px;
              background-color: #3d8fe7;
              border: 2px solid #f3f3f3;
          }
          .button-sty:hover,
          .button-sty:focus {
              color: #c0d8fc;
              cursor: pointer;
              text-decoration: none;
          }
          p {
              display: flex;
              align-items: center;
              white-space: nowrap;
          }
          Cins {
              font-size: 1.2rem;
              font-weight: bold;
              padding: 1rem;
              margin-right: 1rem;
          }
          /*--------------------*/
          .DMS {
              position: absolute;
              width: 8.2rem;
              margin-left: 27rem;
          }
          .DMS-checkbox {
              display: none;
          }
          .DMS-label {
              display: block;
              overflow: hidden;
              cursor: pointer;
              border: 2px solid #c0d8fc;
              border-radius: 20px;
          }
          .DMS-inner {
              display: block;
              width: 200%;
              margin-left: -100%;
              transition: margin 0.3s ease-in 0s;
          }
          .DMS-inner:before,
          .DMS-inner:after {
              display: block;
              float: left;
              width: 50%;
              height: 30px;
              padding: 0;
              line-height: 30px;
              font-size: 14px;
              font-family: Trebuchet, Arial, sans-serif;
              font-weight: bold;
              box-sizing: border-box;
          }
          .DMS-inner:before {
              content: "${f("\u6efe\u52d5\u95b1\u8b80")}";
              padding-left: 1.7rem;
              background-color: #3d8fe7;
              color: #FFFFFF;
          }
          .DMS-inner:after {
              content: "${f("\u7ffb\u9801\u95b1\u8b80")}";
              padding-right: 1.5rem;
              background-color: #FFFFFF;
              color: #3d8fe7;
              text-align: right;
          }
          .DMS-switch {
              display: block;
              width: 18px;
              margin: 6px;
              background: #FFFFFF;
              position: absolute;
              top: 0;
              bottom: 0;
              right: 96px;
              border: 2px solid #999999;
              border-radius: 20px;
              transition: all 0.3s ease-in 0s;
          }
          .DMS-checkbox:checked+.DMS-label .DMS-inner {
              margin-left: 0;
          }
          .DMS-checkbox:checked+.DMS-label .DMS-switch {
              right: 0px;
          }
      `);
      setTimeout(() => {
          e = Syn.$$("#New-Style").sheet.cssRules;
      }, 1300);
      return {
          IsMobile: Syn.Device.Url.includes("photos-slist-aid"),
          LoadingConfig: a,
          SwitchStatus: p,
          ConfigAnalyze: (d) =>
              "auto" === d
                  ? { RangeValue: 9, DisplayText: "auto" }
                  : d.endsWith("rem") || d.endsWith("%")
                      ? { RangeValue: parseInt(d), DisplayText: d }
                      : { RangeValue: d, DisplayText: "color" },
          StylePointer: {
              MenuTop: (d) => (e[9].style.top = d),
              MenuLeft: (d) => (e[9].style.left = d),
              ImageSpacing: (d) => (e[0].style.margin = `${d} auto`),
              ImageBasicWidth: (d) => (e[0].style.width = d),
              ImageMaxWidth: (d) => {
                  e[0].style.maxWidth = d;
                  e[2].style.maxWidth = d;
              },
              ImageBasicHight: (d) => (e[0].style.height = d),
              ImageMaxHight: (d) => (e[0].style.maxHeight = d),
              BackgroundColor: (d, v) => {
                  d.style.setProperty("background-color", v, "important");
              },
          },
          Transl: f,
      };
  })();
  (async () => {
      if ("Mobile" != Syn.Device.Type())
          if (
              (GM_registerMenuCommand(
                  h.Transl("\ud83d\udd32 \u958b\u95dc\u83dc\u55ae"),
                  () => w(!0)
              ),
                  Syn.AddListener(
                      window,
                      "keydown",
                      (a) => {
                          const e = a.key;
                          "Shift" === e
                              ? (a.preventDefault(), w())
                              : "Escape" === e &&
                              (a.preventDefault(), Syn.$$(".modal-background")?.remove());
                      },
                      { capture: !0 }
                  ),
                  h.IsMobile)
          ) {
              const a = new Map();
              Syn.WaitElem(
                  "#img_list",
                  (e) => {
                      Syn.Observer(
                          e,
                          () => {
                              Syn.$$("div", { root: e, all: !0 }).forEach((f) => {
                                  a.has(f) ||
                                      (a.set(f, !0),
                                          (f.style.cssText = "text-align: center"),
                                          (f = Syn.$$("img", { root: f })),
                                          f.removeAttribute("width"),
                                          f.classList.add("ImageOptimization"));
                              });
                          },
                          { throttle: 1500 }
                      );
                  },
                  { raf: !0, timeout: 10 }
              );
          } else
              Syn.WaitMap(
                  ".png.bread;#bread;#photo_body;span.newpagelabel b;#bodywrap;.newpagewrap;.footer.wrap".split(
                      ";"
                  ),
                  (a) => {
                      const [e, f, r, q, p, m, n] = a;
                      ReactDOM.render(
                          React.createElement("div", {
                              dangerouslySetInnerHTML: { __html: e.innerHTML },
                          }),
                          f
                      );
                      r.classList.remove("photo_body");
                      [p, m, n].forEach((c) => {
                          c.style.display = "none";
                      });
                      x(r, +q.textContent);
                  },
                  { raf: !0, timeout: 10 }
              );
  })();
})();