linovelib

优化 linovelib 阅读体验

目前为 2022-10-11 提交的版本。查看 最新版本

// ==UserScript==
// @name         linovelib
// @namespace    https://github.com/IronKinoko/userscripts/tree/master/packages/linovelib
// @version      1.2.0
// @license      MIT
// @description  优化 linovelib 阅读体验
// @author       IronKinoko
// @match        https://www.linovelib.com/*
// @match        https://w.linovelib.com/*
// @icon         https://www.google.com/s2/favicons?domain=w.linovelib.com
// @grant        none
// @noframes
// ==/UserScript==
(function () {
  'use strict';

  function isMobile() {
    const re = /iphone|ipad|ipod|android|webos|blackberry|windows phone/i;
    const ua = navigator.userAgent;
    return re.test(ua);
  }

  const SHIFT_KEY = '~!@#$%^&*()_+{}|:"<>?\uFF5E\uFF01@#\xA5%\u2026&*\uFF08\uFF09\u2014\u2014+\u300C\u300D\uFF5C\uFF1A\u201C\u300A\u300B\uFF1F';
  function keybind(keys, keydown, keyup) {
    const isMac = /macintosh|mac os x/i.test(navigator.userAgent);
    keys = keys.filter((key) => !key.includes(isMac ? "ctrl" : "meta"));
    function createProcess(callback) {
      return function(e) {
        var _a;
        if (((_a = document.activeElement) == null ? void 0 : _a.tagName) === "INPUT")
          return;
        let keyArr = [];
        e.ctrlKey && keyArr.push("ctrl");
        e.metaKey && keyArr.push("meta");
        e.shiftKey && !SHIFT_KEY.includes(e.key) && keyArr.push("shift");
        e.altKey && keyArr.push("alt");
        if (!["Control", "Meta", "Shift", "Alt"].includes(e.key)) {
          keyArr.push(e.key);
        }
        keyArr = [...new Set(keyArr)];
        const key = keyArr.join("+");
        if (keys.includes(key)) {
          callback(e, key);
        }
      };
    }
    window.addEventListener("keydown", createProcess(keydown));
    if (keyup)
      window.addEventListener("keyup", createProcess(keyup));
  }

  async function main$1() {
    if (/novel\/\d+\.html/.test(window.location.pathname)) {
      injectDownload$1();
    }
    if (!window.ReadTools)
      return;
    resetPageEvent();
    if (isMobile())
      injectMovePageEvent();
  }
  function injectDownload$1() {
    const bookId = window.location.pathname.split("/").pop().split(".").shift();
    const dom = document.querySelector(".book-detail-btn .btn-group");
    console.log(dom);
    const a = document.createElement("a");
    dom == null ? void 0 : dom.append(a);
    a.outerHTML = `
  <li class="btn-group-cell">
    <a class="btn-normal white" href="http://www.zhidianbao.cn:8088/qs_xq_epub?bookId=${bookId}" target="_blank">Epub\u4E0B\u8F7D</a>
  </li>
  `;
  }
  function resetPageEvent() {
    const $body = document.body;
    $body.onclick = (e) => {
      const toolsId = ["#toptools", "#bottomtools", "#readset"];
      if (toolsId.some((id) => {
        var _a;
        return (_a = document.querySelector(id)) == null ? void 0 : _a.contains(e.target);
      })) {
        return;
      }
      window.ReadPages.PageClick();
    };
  }
  function injectMovePageEvent() {
    let left, startX, startY, diffX, startTime, isMoved, direction;
    const $page = document.getElementById("apage");
    const isDisabled = (e) => {
      return window.ReadTools.pagemid != 1 || e.touches.length > 1 || window.visualViewport && window.visualViewport.scale !== 1;
    };
    window.addEventListener("touchstart", (e) => {
      if (isDisabled(e))
        return;
      left = parseFloat($page.style.left.replace("px", "")) || 0;
      startX = e.touches[0].clientX;
      startY = e.touches[0].clientY;
      startTime = Date.now();
      isMoved = false;
      direction = "";
    });
    window.addEventListener("touchmove", (e) => {
      if (isDisabled(e))
        return;
      isMoved = true;
      diffX = e.touches[0].clientX - startX;
      let diffY = e.touches[0].clientY - startY;
      if (direction === "") {
        direction = Math.abs(diffX) > Math.abs(diffY) ? "x" : "y";
      }
      if (direction === "x") {
        e.preventDefault();
        $page.style.left = left + diffX + "px";
        $page.style.transition = "initail";
      }
    }, { passive: false });
    window.addEventListener("touchend", (e) => {
      if (isDisabled(e))
        return;
      if (!isMoved || direction === "y")
        return;
      const diffTime = Date.now() - startTime;
      const threshold = diffTime < 300 ? 10 : document.documentElement.clientWidth * 0.3;
      $page.style.transition = "";
      if (Math.abs(diffX) > threshold) {
        const type = diffX > 0 ? "previous" : "next";
        window.ReadPages.ShowPage(type);
        if (window.ReadPages.currentPage > window.ReadPages.totalPages || window.ReadPages.currentPage < 1) {
          window.ReadPages.ShowPage();
        }
      } else {
        window.ReadPages.ShowPage();
      }
    });
  }

  function main() {
    removeSelectEvent();
    if (/novel\/\d+\.html/.test(window.location.pathname)) {
      injectDownload();
    }
    if (document.body.id === "readbg") {
      injectEvent();
    }
  }
  function removeSelectEvent() {
    const dom = document.createElement("style");
    dom.innerHTML = `* { user-select: initial !important; }`;
    document.body.append(dom);
    document.body.removeAttribute("onselectstart");
  }
  function injectEvent() {
    const scripts = Array.from(document.scripts);
    const script = scripts.find((script2) => script2.innerHTML.includes('prevpage="'));
    if (!script)
      return;
    const res = script.innerHTML.match(new RegExp('prevpage="(?<pre>.*?)";.*nextpage="(?<next>.*?)";'));
    if (!(res == null ? void 0 : res.groups))
      return;
    const { pre, next } = res.groups;
    keybind(["w", "s", "a", "d"], (e, key) => {
      switch (key) {
        case "w":
        case "s":
          const direction = key === "w" ? -1 : 1;
          if (e.repeat)
            scroll.start(direction * 15);
          else
            window.scrollBy({ behavior: "smooth", top: direction * 200 });
          break;
        case "a":
        case "d":
          window.location.pathname = key === "a" ? pre : next;
          break;
      }
    }, (e, key) => {
      switch (key) {
        case "w":
        case "s":
          scroll.stop();
          break;
      }
    });
  }
  function injectDownload() {
    const bookId = window.location.pathname.split("/").pop().split(".").shift();
    const dom = document.querySelector(".fr.link-group");
    const a = document.createElement("a");
    dom == null ? void 0 : dom.prepend(a);
    a.outerHTML = `<a class="all-catalog" href="http://www.zhidianbao.cn:8088/qs_xq_epub?bookId=${bookId}" target="_blank"><em></em>Epub\u4E0B\u8F7D</a>`;
  }
  const scroll = (() => {
    let handle;
    function stop() {
      if (!handle)
        return;
      cancelAnimationFrame(handle);
      handle = void 0;
    }
    function start(step) {
      if (handle)
        return;
      function animate() {
        handle = requestAnimationFrame(animate);
        window.scrollBy({ top: step });
      }
      handle = requestAnimationFrame(animate);
    }
    return { start, stop };
  })();

  if (window.location.host.includes("www.")) {
    main();
  } else
    main$1();

})();