토끼 뷰어

i,j,k 키를 눌러보세요

Version au 17/02/2024. Voir la dernière version.

  1. // ==UserScript==
  2. // @name 토끼 뷰어
  3. // @name:ko 토끼 뷰어
  4. // @name:en toki viewer
  5. // @description i,j,k 키를 눌러보세요
  6. // @description:ko i,j,k 키를 눌러보세요
  7. // @description:en press i to open
  8. // @version 240217102149
  9. // @match https://*.net/bbs/*
  10. // @match https://*.net/comic/*
  11. // @match https://*.com/webtoon/*
  12. // @author nanikit
  13. // @namespace https://greasyfork.org/ko/users/713014-nanikit
  14. // @license MIT
  15. // @connect *
  16. // @grant GM_addValueChangeListener
  17. // @grant GM_getResourceText
  18. // @grant GM_getValue
  19. // @grant GM_removeValueChangeListener
  20. // @grant GM_setValue
  21. // @grant GM_xmlhttpRequest
  22. // @grant unsafeWindow
  23. // @require https://cdn.jsdelivr.net/npm/requirejs@2.3.6/require.js
  24. // @resource link:@headlessui/react https://cdn.jsdelivr.net/npm/@headlessui/react@1.7.17/dist/headlessui.prod.cjs
  25. // @resource link:@stitches/react https://cdn.jsdelivr.net/npm/@stitches/react@1.3.1-1/dist/index.cjs
  26. // @resource link:clsx https://cdn.jsdelivr.net/npm/clsx@2.0.0/dist/clsx.js
  27. // @resource link:fflate https://cdn.jsdelivr.net/npm/fflate@0.8.1/lib/browser.cjs
  28. // @resource link:jotai https://cdn.jsdelivr.net/npm/jotai@2.4.2/index.js
  29. // @resource link:jotai/react https://cdn.jsdelivr.net/npm/jotai@2.4.2/react.js
  30. // @resource link:jotai/react/utils https://cdn.jsdelivr.net/npm/jotai@2.4.2/react/utils.js
  31. // @resource link:jotai/utils https://cdn.jsdelivr.net/npm/jotai@2.4.2/utils.js
  32. // @resource link:jotai/vanilla https://cdn.jsdelivr.net/npm/jotai@2.4.2/vanilla.js
  33. // @resource link:jotai/vanilla/utils https://cdn.jsdelivr.net/npm/jotai@2.4.2/vanilla/utils.js
  34. // @resource link:react https://cdn.jsdelivr.net/npm/react@18.2.0/cjs/react.production.min.js
  35. // @resource link:react-dom https://cdn.jsdelivr.net/npm/react-dom@18.2.0/cjs/react-dom.production.min.js
  36. // @resource link:react-toastify https://cdn.jsdelivr.net/npm/react-toastify@9.1.3/dist/react-toastify.js
  37. // @resource link:scheduler https://cdn.jsdelivr.net/npm/scheduler@0.23.0/cjs/scheduler.production.min.js
  38. // @resource link:vcv-inject-node-env data:,unsafeWindow.process=%7Benv:%7BNODE_ENV:%22production%22%7D%7D
  39. // @resource link:vim_comic_viewer https://update.greasyfork.org/scripts/417893/1328507/vim%20comic%20viewer.js
  40. // @resource react-toastify-css https://cdn.jsdelivr.net/npm/react-toastify@9.1.3/dist/ReactToastify.css
  41. // ==/UserScript==
  42. "use strict";
  43.  
  44. define("main", (require, exports, module) => {
  45. var import_vim_comic_viewer = require("vim_comic_viewer");
  46. async function main() {
  47. const isToki = location.origin.match(/manatoki|newtoki/);
  48. if (!isToki) {
  49. return;
  50. }
  51. markVisitedLinks();
  52. const buttons = duplicateViewerButton();
  53. const controller = await (0, import_vim_comic_viewer.initialize)({ source: comicSource });
  54. for (const button of buttons) {
  55. button.addEventListener("click", async () => {
  56. await controller.setImmersive(true);
  57. });
  58. }
  59. }
  60. function duplicateViewerButton() {
  61. const template = document.createElement("template");
  62. template.innerHTML = `<a class="show_viewer" alt="뷰어로 보기">
  63. <i class="ion-ios-book at-tip" aria-hidden="true" style="color: blue;"></i>
  64. </a>`;
  65. const templateButton = template.content.firstElementChild;
  66. const buttons = [];
  67. const divs = document.querySelectorAll(".toon-nav");
  68. for (const div of divs) {
  69. const button = templateButton.cloneNode(true);
  70. div.prepend(button);
  71. buttons.push(button);
  72. }
  73. return buttons;
  74. }
  75. function comicSource() {
  76. registerEpisodeNavigator();
  77. return getUrls();
  78. }
  79. function registerEpisodeNavigator() {
  80. addEventListener("keydown", (event) => {
  81. const { ctrlKey, shiftKey, altKey } = event;
  82. if (ctrlKey || shiftKey || altKey || import_vim_comic_viewer.utils.isTyping(event)) {
  83. return;
  84. }
  85. switch (event.key) {
  86. case "h":
  87. case "ArrowLeft":
  88. document.getElementById("goPrevBtn")?.click?.();
  89. break;
  90. case "l":
  91. case "ArrowRight":
  92. document.getElementById("goNextBtn")?.click?.();
  93. break;
  94. case "t":
  95. document.getElementById("sticky-wrapper")?.scrollIntoView({
  96. block: "center"
  97. });
  98. break;
  99. case "m":
  100. document.querySelector(".view-good")?.scrollIntoView({
  101. block: "center"
  102. });
  103. break;
  104. }
  105. });
  106. }
  107. function getUrls() {
  108. const imgs = document.querySelectorAll(
  109. "div.view-padding img"
  110. );
  111. const urls = [...imgs].flatMap(getUrl);
  112. return urls;
  113. }
  114. function getUrl(image) {
  115. if (image.offsetParent === null) {
  116. return [];
  117. }
  118. const data = Object.values(image.dataset);
  119. return data.length ? data : [image.src];
  120. }
  121. function markVisitedLinks() {
  122. const links = document.querySelectorAll(".post-row a");
  123. const visitedLinks = new Set(GM_getValue("visitedPaths", []));
  124. for (const link of links) {
  125. const url = link.getAttribute("href");
  126. if (!url)
  127. return;
  128. const path = new URL(url).pathname;
  129. if (visitedLinks.has(path)) {
  130. link.style.color = "#e2e2e2";
  131. }
  132. link.addEventListener("click", () => {
  133. visitedLinks.add(path);
  134. GM_setValue("visitedPaths", [...visitedLinks]);
  135. });
  136. }
  137. }
  138. main();
  139.  
  140. });
  141.  
  142. define("tampermonkey_grants", function() { Object.assign(this.window, { GM, GM_addValueChangeListener, GM_getResourceText, GM_getValue, GM_removeValueChangeListener, GM_setValue, GM_xmlhttpRequest, unsafeWindow }); });
  143. requirejs.config({ deps: ["tampermonkey_grants"] });
  144. for (const { name } of GM.info.script.resources.filter(x => x.name.startsWith("link:"))) {
  145. define(name.replace("link:", ""), Function("require", "exports", "module", GM_getResourceText(name)));
  146. }
  147.  
  148. require(["main"], () => {}, console.error);