SmoothRoll

Clean crunchyroll viewing experience

  1. // ==UserScript==
  2. // @name SmoothRoll
  3. // @namespace https://bengrant.dev
  4. // @version 0.7
  5. // @description Clean crunchyroll viewing experience
  6. // @author Ben Grant
  7. // @match https://www.crunchyroll.com/*/*
  8. // @icon https://www.google.com/s2/favicons?domain=crunchyroll.com
  9. // @grant GM_setValue
  10. // @grant GM_getValue
  11. // ==/UserScript==
  12.  
  13. const styles = `
  14. :root {
  15. --bg-color: #f2f2f2;
  16. --main-color: #FFF;
  17. --text-color: #000;
  18. --link-color: #0676d6;
  19. }
  20. @media (prefers-color-scheme: dark) {
  21. :root {
  22. --bg-color: #222;
  23. --main-color: #000;
  24. --text-color: #DDD;
  25. --link-color: #55b0ff;
  26. }
  27.  
  28. .collection-carousel-arrow {
  29. filter: invert(1);
  30. }
  31. }
  32.  
  33. body.smoothroll_light {
  34. --bg-color: #f2f2f2;
  35. --main-color: #FFF;
  36. --text-color: #000;
  37. --link-color: #0676d6;
  38. }
  39. body.smoothroll_light .collection-carousel-arrow {
  40. filter: invert(0);
  41. }
  42. body.smoothroll_dark {
  43. --bg-color: #222;
  44. --main-color: #000;
  45. --text-color: #DDD;
  46. --link-color: #55b0ff;
  47. }
  48. body.smoothroll_dark .collection-carousel-arrow {
  49. filter: invert(1);
  50. }
  51.  
  52. body.main-page {
  53. background-color: var(--bg-color);
  54. }
  55. .site-header {
  56. background: var(--main-color);
  57. box-shadow: none;
  58. }
  59. .header-menubar li a {
  60. color: var(--text-color);
  61. }
  62. .games, .store, .try-free-header-menu-item {
  63. display: none !important;
  64. }
  65. #template_container.template-container {
  66. background: none;
  67. }
  68. #marketing_banner {
  69. display: none;
  70. }
  71. #message_box {
  72. display: none;
  73. }
  74. #showmedia_video_player {
  75. border-radius: 8px;
  76. overflow: hidden;
  77. }
  78. .showmedia-submenu {
  79. display: none;
  80. }
  81. #main_content_white, .white-wrapper {
  82. border-radius: 8px;
  83. background: var(--main-color);
  84. }
  85. .guestbook {
  86. display: none;
  87. }
  88. body.smoothroll_comments .guestbook {
  89. display: block;
  90. }
  91. .guestbook textarea {
  92. color: inherit;
  93. background: var(--main-color);
  94. border: 1px solid var(--text-color);
  95. border-radius: 5px;
  96. }
  97. .comments .boxtitle {
  98. border-bottom: 0;
  99. }
  100. .guestbook-spoiler-checkbox {
  101. color: inherit;
  102. }
  103. .guestbook-list {
  104. border-top: 0;
  105. }
  106. .comments .more-replies {
  107. background-color: var(--bg-color);
  108. border: 1px solid var(--link-color);
  109. display: inline-block;
  110. padding: 0 5px;
  111. border-radius: 3px;
  112. margin-bottom: 10px;
  113. }
  114. .new-template-body {
  115. color: var(--text-color);
  116. }
  117. .new-template-body h3 {
  118. display: none;
  119. }
  120. .new-template-body a.block-link, .old-template-body a.block-link, a.block-link {
  121. color: var(--text-color);
  122. }
  123. .showmedia-related {
  124. display: none;
  125. }
  126. #footer {
  127. display: none;
  128. }
  129. #showmedia_about_info .rating {
  130. display: none;
  131. }
  132. body.smoothroll_info #showmedia_about_info .rating {
  133. display: block;
  134. }
  135. .new-template-body .block-link:hover, .new-template-body .pagination a, .new-template-body .para-div a, .new-template-body .sub-tabs .selectors a.text-link, .new-template-body .text-link, .new-template-body .wrapper a:hover a, .new-template-body a:hover h4, .new-template-body li a, .new-template-body p a, .new-template-body span a {
  136. color: var(--link-color);
  137. }
  138. img {
  139. border: none;
  140. }
  141. .episode-progress-bar {
  142. background: var(--bg-color);
  143. }
  144. #showmedia_about_info_details span {
  145. color: inherit;
  146. }
  147. .header-search-form {
  148. border: 0;
  149. }
  150. .header-search-form .header-searchbox {
  151. background: var(--bg-color);
  152. color: var(--text-color);
  153. border-radius: 4px;
  154. }
  155. .description .more {
  156. display: inline !important;
  157. }
  158. .description .more-dots {
  159. display: none;
  160. }
  161. .description a[href="#"] {
  162. display: none;
  163. }
  164. #showmedia_about_info_details > div:first-child,
  165. #showmedia_about_info_details > div:last-child {
  166. display: none;
  167. }
  168. body.smoothroll_info #showmedia_about_info_details > div:first-child,
  169. body.smoothroll_info #showmedia_about_info_details > div:last-child {
  170. display: block;
  171. }
  172. .game-banner-wrapper {
  173. display: none;
  174. }
  175. #showmedia_about_info_avail {
  176. display: none;
  177. }
  178. #showmedia_free_trial_signup {
  179. display: none;
  180. }
  181. #main_content > div.white-wrapper.container-shadow.large-margin-bottom::-webkit-scrollbar,
  182. #main_content > div.white-wrapper.container-shadow.large-margin-bottom::-webkit-scrollbar-track,
  183. #main_content > div.white-wrapper.container-shadow.large-margin-bottom::-webkit-scrollbar-thumb {
  184. width: 0;
  185. height: 0;
  186. background: transparent;
  187. display: none;
  188. }
  189.  
  190. #smoothroll_settings_button {
  191. border: 0;
  192. background: var(--bg-color);
  193. color: var(--text-color);
  194. cursor: pointer;
  195. margin: 0;
  196. padding: 0;
  197. font: inherit;
  198. }
  199.  
  200. #smoothroll_settings_modal {
  201. display: none;
  202. position: fixed;
  203. top: 50%;
  204. left: 50%;
  205. max-height: 90vh;
  206. max-width: 90vw;
  207. transform: translate(-50%, -50%);
  208. z-index: 10000;
  209. background: var(--bg-color);
  210. border-radius: 10px;
  211. box-shadow: 0 0 0 200vw rgba(0,0,0,.5);
  212. box-sizing: border-box;
  213. padding: 20px;
  214. color: var(--text-color);
  215. min-width: 300px;
  216. }
  217. body.smoothroll_settings_open #smoothroll_settings_modal {
  218. display: block;
  219. }
  220. #smoothroll_settings_modal h2 {
  221. margin: 0;
  222. padding: 0 0 4px;
  223. font-size: 1.2em;
  224. }
  225. #smoothroll_settings_modal label {
  226. display: block;
  227. padding: 14px 0 2px;
  228. }
  229. #smoothroll_settings_modal button,
  230. #smoothroll_settings_modal select {
  231. font: inherit;
  232. background: inherit;
  233. color: inherit;
  234. padding: 2px 4px;
  235. border-radius: 3px;
  236. border: 1px solid currentColor;
  237. box-sizing: border-box;
  238. }
  239. #smoothroll_settings_modal input[type=checkbox] {
  240. vertical-align: middle;
  241. margin-right: .5em;
  242. }
  243. #smoothroll_settings_close {
  244. margin-top: 20px;
  245. display: block;
  246. color: var(--link-color) !important;
  247. width: 100%;
  248. cursor: pointer;
  249. }
  250. `;
  251.  
  252. let setting_theme = undefined;
  253. let setting_comments = undefined;
  254. let setting_info = undefined;
  255.  
  256. function loadSettings() {
  257. // Load settings
  258. try {
  259. setting_theme = GM_getValue('smoothroll_setting_theme');
  260. if (setting_theme === undefined) throw new Error('No value set in GM, checking localStorage');
  261. } catch (e) {
  262. console.error(e);
  263. setting_theme = localStorage.getItem('smoothroll_setting_theme');
  264. }
  265. if (setting_theme && setting_theme === 'light') {
  266. document.body.classList.add('smoothroll_light');
  267. document.body.classList.remove('smoothroll_dark');
  268. } else if (setting_theme && setting_theme === 'dark') {
  269. document.body.classList.add('smoothroll_dark');
  270. document.body.classList.remove('smoothroll_light');
  271. } else {
  272. document.body.classList.remove('smoothroll_dark');
  273. document.body.classList.remove('smoothroll_light');
  274. }
  275.  
  276. try {
  277. setting_comments = GM_getValue('smoothroll_setting_comments');
  278. if (setting_comments === undefined) throw new Error('No value set in GM, checking localStorage');
  279. } catch (e) {
  280. console.error(e);
  281. setting_comments = localStorage.getItem('smoothroll_setting_comments');
  282. }
  283. if (setting_comments && setting_comments === 'show') {
  284. document.body.classList.add('smoothroll_comments');
  285. } else {
  286. document.body.classList.remove('smoothroll_comments');
  287. }
  288.  
  289. try {
  290. setting_info = GM_getValue('smoothroll_setting_info');
  291. if (setting_info === undefined) throw new Error('No value set in GM, checking localStorage');
  292. } catch (e) {
  293. console.error(e);
  294. setting_info = localStorage.getItem('smoothroll_setting_info');
  295. }
  296. if (setting_info && setting_info === 'show') {
  297. document.body.classList.add('smoothroll_info');
  298. } else {
  299. document.body.classList.remove('smoothroll_info');
  300. }
  301. }
  302.  
  303. const player = document.getElementById('showmedia_video_player');
  304.  
  305. if (player) {
  306. loadSettings();
  307.  
  308. // Styles
  309. let styleSheet = document.createElement("style");
  310. styleSheet.type = "text/css";
  311. styleSheet.innerText = styles;
  312. document.head.appendChild(styleSheet);
  313.  
  314. // Settings button
  315. const settings_button = document.createElement('button');
  316. settings_button.type = 'button';
  317. settings_button.id = 'smoothroll_settings_button';
  318. settings_button.appendChild(document.createTextNode('Smoothroll settings'));
  319. settings_button.addEventListener('click', () => {
  320. document.body.classList.toggle('smoothroll_settings_open');
  321. });
  322. document.getElementById('header_container').appendChild(settings_button);
  323.  
  324. // Settings modal
  325. const modal = document.createElement('div');
  326. modal.id = 'smoothroll_settings_modal';
  327. const modal_heading = document.createElement('h2');
  328. modal_heading.appendChild(document.createTextNode('Smoothroll Settings'));
  329. modal.appendChild(modal_heading);
  330.  
  331. // Color theme
  332. const smoothroll_setting_theme_label = document.createElement('label');
  333. smoothroll_setting_theme_label.for = 'smoothroll_setting_theme';
  334. smoothroll_setting_theme_label.appendChild(document.createTextNode('Color theme'));
  335. modal.appendChild(smoothroll_setting_theme_label);
  336. const smoothroll_setting_theme_input = document.createElement('select');
  337. smoothroll_setting_theme_input.id = 'smoothroll_setting_theme';
  338. ['System', 'Light', 'Dark'].forEach(op => {
  339. const option = document.createElement('option');
  340. option.value = op.toLowerCase();
  341. if (setting_theme && setting_theme === op.toLowerCase()) {
  342. option.selected = 'selected';
  343. }
  344. option.appendChild(document.createTextNode(op));
  345. smoothroll_setting_theme_input.appendChild(option);
  346. });
  347. smoothroll_setting_theme_input.addEventListener('change', () => {
  348. try {
  349. GM_setValue('smoothroll_setting_theme', smoothroll_setting_theme_input.value);
  350. } catch (e) {
  351. console.error(e);
  352. localStorage.setItem('smoothroll_setting_theme', smoothroll_setting_theme_input.value);
  353. }
  354. loadSettings();
  355. });
  356. modal.appendChild(smoothroll_setting_theme_input);
  357.  
  358. // Comments
  359. const smoothroll_setting_comments_label = document.createElement('label');
  360. smoothroll_setting_comments_label.for = 'smoothroll_setting_comments';
  361. const smoothroll_setting_comments_input = document.createElement('input');
  362. smoothroll_setting_comments_input.type = 'checkbox';
  363. smoothroll_setting_comments_input.id = 'smoothroll_setting_comments';
  364. smoothroll_setting_comments_input.checked = setting_comments === 'show';
  365. smoothroll_setting_comments_input.addEventListener('change', () => {
  366. try {
  367. GM_setValue('smoothroll_setting_comments', smoothroll_setting_comments_input.checked ? 'show' : 'hide');
  368. } catch (e) {
  369. console.error(e);
  370. localStorage.setItem('smoothroll_setting_comments', smoothroll_setting_comments_input.checked ? 'show' : 'hide');
  371. }
  372. loadSettings();
  373. });
  374. smoothroll_setting_comments_label.appendChild(smoothroll_setting_comments_input);
  375. smoothroll_setting_comments_label.appendChild(document.createTextNode('Show comments'));
  376. modal.appendChild(smoothroll_setting_comments_label);
  377.  
  378. // Info
  379. const smoothroll_setting_info_label = document.createElement('label');
  380. smoothroll_setting_info_label.for = 'smoothroll_setting_info';
  381. const smoothroll_setting_info_input = document.createElement('input');
  382. smoothroll_setting_info_input.type = 'checkbox';
  383. smoothroll_setting_info_input.id = 'smoothroll_setting_info';
  384. smoothroll_setting_info_input.checked = setting_info === 'show';
  385. smoothroll_setting_info_input.addEventListener('change', () => {
  386. try {
  387. GM_setValue('smoothroll_setting_info', smoothroll_setting_info_input.checked ? 'show' : 'hide');
  388. } catch (e) {
  389. console.error(e);
  390. localStorage.setItem('smoothroll_setting_info', smoothroll_setting_info_input.checked ? 'show' : 'hide');
  391. }
  392. loadSettings();
  393. });
  394. smoothroll_setting_info_label.appendChild(smoothroll_setting_info_input);
  395. smoothroll_setting_info_label.appendChild(document.createTextNode('Show additional info'));
  396. modal.appendChild(smoothroll_setting_info_label);
  397.  
  398. // Modal
  399. const modal_close_button = document.createElement('button');
  400. modal_close_button.type = 'button';
  401. modal_close_button.id = 'smoothroll_settings_close';
  402. modal_close_button.appendChild(document.createTextNode('Close settings'));
  403. modal_close_button.addEventListener('click', () => document.body.classList.remove('smoothroll_settings_open'));
  404. modal.appendChild(modal_close_button);
  405. document.body.appendChild(modal);
  406. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址