Greasy Fork

Minor cleanups - asurascans.com

Keyboard navigation, inertial drag, chapter preloading and chapter-tracking bookmarks

目前为 2023-07-10 提交的版本。查看 最新版本

// ==UserScript==
// @name        Minor cleanups - asurascans.com
// @namespace   Itsnotlupus Industries
// @match       https://www.asurascans.com/*
// @noframes
// @version     1.0
// @author      Itsnotlupus
// @license     MIT
// @description Keyboard navigation, inertial drag, chapter preloading and chapter-tracking bookmarks
// @require     https://greasyfork.org/scripts/468394-itsnotlupus-tiny-utilities/code/utils.js
// ==/UserScript==

/* jshint esversion:11 */


addStyles(`
/* remove ads and blank space between images were ads would have been */
[class^="ai-viewport"], .code-block, .blox, .kln, [id^="teaser"] {
  display: none !important;
}

/* disable builtin drag behavior to allow drag scrolling */
* {
  user-select: none;
  -webkit-user-drag: none;
}
body.drag {
  cursor: grabbing;
}
`);

// keyboard navigation. good for long strips, which is apparently all this site has.
const prev = () => $`.ch-prev-btn`?.click();
const next = () => $`.ch-next-btn`?.click();
addEventListener('keydown', e => ({
  ArrowLeft: prev,
  ArrowRight: next,
  KeyA: prev,
  KeyD: next
}[e.code]?.()), true);

// inertial drag scrolling
let [ delta, drag, dragged ] = [0, false, false];
events({
  mousedown() {
    [ delta, drag, dragged ] = [0, true, false];
  },
  mousemove(e) {
    if (drag) {
      scrollBy(0, delta=-e.movementY);
      if (delta>3) {
        dragged = true;
        document.body.classList.add('drag');
      }
    }
  },
  mouseup(e) {
    if (drag) {
      drag=false;
      rAF((_, next) => Math.abs(delta*=0.95)>1 && next(scrollBy(0, delta)));
    }
    if (dragged) {
      dragged = false;
      document.body.classList.remove('drag');
      const preventClick = e => {
        e.preventDefault();
        e.stopPropagation();
        removeEventListener('click', preventClick, true);
      };
      addEventListener('click', preventClick, true);
    }
  }
});

// don't be shy about loading an entire chapter
$$`img[loading="lazy"]`.forEach(i=>i.loading="eager");

// and prefetch the next chapter for even less waiting.
const nextURL = $`.ch-next-btn`?.href;
if (nextURL) fetchHTML(nextURL).then( d => d.querySelectorAll`img[loading="lazy"]`.forEach( img => prefetch(img.src)));


// have bookmarks track the last chapter you read
const LAST_READ_CHAPTER_KEY = "lastReadChapter";
const lastReadChapters = JSON.parse(localStorage.getItem(LAST_READ_CHAPTER_KEY) ?? "{}");

function getLastReadChapter(post_id, defaultValue = {}) {
  return lastReadChapters[post_id] ?? defaultValue;
}

function setLastReadChapter(post_id, chapter_id, chapter_number) {
  lastReadChapters[post_id] = {
    id: chapter_id,
    number: chapter_number
  };
  localStorage.setItem(LAST_READ_CHAPTER_KEY, JSON.stringify(lastReadChapters));
}

const CHAPTER_REGEX = /\bChapter (?<chapter>\d+)\b/;

const chapterMatch = document.title.match(CHAPTER_REGEX);
if (chapterMatch) {
  // We're on a chapter page. Save chapter number and id if greater than last saved chapter number.
  const chapter_number = +chapterMatch.groups.chapter;
  const { post_id, chapter_id } = window;
  const { number = 0 } = getLastReadChapter(post_id);
  if (number<chapter_number) {
    setLastReadChapter(post_id, chapter_id, chapter_number);
  }
}

if (location.pathname == '/bookmark/') (async ()=> {
  // We're on a bookmark page. Wait for them to load, then tweak them to point to last read chapter, and gray out the ones that are fully read so far.
  await untilDOM("#bookmark-pool [data-id]");
  const bookmarks = $$`#bookmark-pool [data-id]`;
  bookmarks.forEach(b => {
    const post_id = b.dataset.id;
    const latest_chapter = +b.querySelector('.epxs').textContent.match(CHAPTER_REGEX)?.groups.chapter;
    const lastReadChapter = getLastReadChapter(post_id);
    if (lastReadChapter.number) {
      if (lastReadChapter.number < latest_chapter) {
        // change link to last read chapter and move to front of the line.
        const a = b.querySelector`a`;
        a.href = '/?p=' + lastReadChapter.id;
        b.parentElement.parentElement.prepend(b.parentElement);
      } else {
        // nothing new to read here. gray it out.
        b.style = 'filter: grayscale(70%);opacity:.9';
      }
    } else {
      // we don't have data on that series. leave it alone.
    }
  });
})();