Infini-Gallery

Makes so that the gallery continues loading the next page when you reach its bottom

当前为 2023-04-06 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        Infini-Gallery
// @namespace   Violentmonkey Scripts
// @match       *://*.furaffinity.net/*
// @grant       none
// @version     1.3
// @author      Midori Dragon
// @description Makes so that the gallery continues loading the next page when you reach its bottom
// @icon        https://www.furaffinity.net/themes/beta/img/banners/fa_logo.png?v2
// @homepageURL https://greasyfork.org/de/scripts/462632-infini-gallery
// @supportURL  https://greasyfork.org/de/scripts/462632-infini-gallery/feedback
// @license     MIT
// ==/UserScript==

// jshint esversion: 8

//User Options:
let showPageSeperator = JSON.parse(localStorage.getItem("igsetting_01"));
if (showPageSeperator == null)
  showPageSeperator = true;
let showDisableButton = JSON.parse(localStorage.getItem("igsetting_02"));
if (showDisableButton == null)
  showDisableButton = true;
const matchList = ['net/browse', 'net/gallery', 'net/search', 'net/favorites' ];

const isSettings = window.location.toString().includes('controls/settings');
let exSettings = JSON.parse(localStorage.getItem("igsettings"));
if (exSettings == null)
  exSettings = false;
addExSettings();
if (isSettings) {
  addExSettingsSidebar();
  if (exSettings)
    createSettings();
}

if (window.parent !== window)
  return;
if (!matchList.some(x => window.location.toString().includes(x)))
  return;

console.info('%cRunning: Infini-Gallery', 'color: blue');


const isGallery = window.location.toString().includes('net/gallery');
const isFavorites = window.location.toString().includes('net/favorites');
const isBrowse = window.location.toString().includes('net/browse');

let allowScan = true;
let nextButtons;
let lastNextButton;
let gallery;
let lastLink;
let lastNextPageButton;
let pageCount;

if (!isSettings) {
  if (isGallery)
    nextButtons = document.querySelectorAll('button[class*="button standard"][type="submit"]');
  else if (isFavorites)
    nextButtons = document.querySelectorAll('a[class*="button mobile-button right"][href]');
  else if (isBrowse)
    nextButtons = document.querySelectorAll('a[class*="button standard"][href]');
  if (!nextButtons || nextButtons.length == 0)
    return;

  if (showDisableButton) {
    let navPage = document.querySelector('userpage-nav-links').querySelector('ul');
    let disableIGButton = document.createElement('button');
    disableIGButton.id = "disableIGButton";
    disableIGButton.type = "button";
    disableIGButton.className = "button standard mobile-fix";
    disableIGButton.textContent = "Disable Infini Gallery";
    disableIGButton.style.marginTop = "8px";
    disableIGButton.style.marginRight = "18px";
    disableIGButton.onclick = function() {
      allowScan = !allowScan;
      if (allowScan) {
        disableIGButton.textContent = "Disable Infini Gallery";
        scan();
      } else
        disableIGButton.textContent = "Enable Infini Gallery";
    };
    navPage.appendChild(disableIGButton);
  }

  lastNextButton = nextButtons[nextButtons.length - 1];
  gallery = document.querySelector('section[id*="gallery"]');
  lastLink = window.location.toString();
  lastNextPageButton = lastNextButton;
  pageCount = 1;
  scan();
}

async function scan() {
  const interval = setInterval(() => {
    if (!allowScan)
      clearInterval(interval);
    if (isElementOnScreen(lastNextButton)) {
      clearInterval(interval);
      loadNextPage();
    }
  }, 100);
}

async function loadNextPage() {
  let figures;
  if (isGallery)
    figures = await getNextPageFiguresGallery();
  else if (isFavorites)
    figures = await getNextPageFiguresFavorites();
  else if (isBrowse)
    figures = await getNextPageFiguresGallery();
  if (!figures || figures.length == 0) {
    lastNextButton.parentNode.removeChild(lastNextButton);
    return;
  }
  pageCount++;
  let nextPageDescContainer = document.createElement('div');
  nextPageDescContainer.className = 'folder-description';
  nextPageDescContainer.style.marginTop = '6px';
  nextPageDescContainer.style.marginBottom = '6px';
  let nextPageDesc = document.createElement('div');
  nextPageDesc.className = 'container-item-top';
  let nextPageDescText = document.createElement('h3');
  nextPageDescText.textContent = 'Page: ' + pageCount;
  nextPageDesc.appendChild(nextPageDescText);
  nextPageDescContainer.appendChild(nextPageDesc);
  gallery.appendChild(nextPageDescContainer);
  for (const figure of figures)
    gallery.appendChild(figure);
  try { window.updateEmbedded(); } catch {} //Embedded Image Viewer Integration
  try { window.updateFastFavoriter(); } catch {} //Fast Favoriter 2 Integration

  await scan();
}

async function getNextPageFiguresGallery() {
  const nextLink = await incrementUrlLastNumber(lastLink);
  console.log(nextLink);
  lastLink = nextLink;
  const nextPage = await getHTML(nextLink);
  const figures = nextPage.querySelectorAll('figure[class*="t"]');
  return figures;
}
async function getNextPageFiguresFavorites() {
  const nextLink = lastNextPageButton.href;
  console.log(nextLink);
  lastLink = nextLink;
  const nextPage = await getHTML(nextLink);
  let currNextPageButton = nextPage.querySelectorAll('a[class="button mobile-button right"][href]');
  lastNextPageButton = currNextPageButton[currNextPageButton.length - 1];
  const figures = nextPage.querySelectorAll('figure[class*="t"]');
  return figures;
}

async function incrementUrlLastNumber(url) {
  if (url.endsWith('/?'))
    url = url.slice(0, -1);
  if (url.endsWith('/'))
    url = url.slice(0, -1);

  var segments = url.split('/');
  var lastSegment = segments[segments.length - 1];

  var match = lastSegment.match(/^\d+/);

  if (match) {
    var nextNumber = parseInt(match[0]) + 1;
    return url.replace(/\d+$/, nextNumber);
  } else
    return url + '/2';
}


function isElementOnScreen(element) {
  var rect = element.getBoundingClientRect();
  var windowHeight = (window.innerHeight || document.documentElement.clientHeight) * 2;
  return (rect.top <= windowHeight) && ((rect.top + rect.height) >= 0);
}

async function getHTML(url) {
  try {
    const response = await fetch(url);
    const html = await response.text();
    const parser = new DOMParser();
    const doc = parser.parseFromString(html, 'text/html');
    return doc;
  } catch (error) {
    console.error(error);
  }
}

async function addExSettings() {
  const settings = document.querySelector('ul[class="navhideonmobile"]').querySelector('a[href="/controls/settings/"]').parentNode;

  if (document.getElementById("extension_settings")) {
    document.getElementById('midori_settings').addEventListener('click', function() { localStorage.setItem("igsettings", true.toString()); });
    return;
  }
  let exSettingsHeader = document.createElement("h3");
  exSettingsHeader.id = "extension_settings";
  exSettingsHeader.textContent = "Extension Settings";
  settings.appendChild(exSettingsHeader);

  let wfsettings = document.createElement("a");
  wfsettings.id = "midori_settings";
  wfsettings.textContent = "Midori's Script Settings";
  wfsettings.style.cursor = "pointer";
  wfsettings.onclick = function() {
    localStorage.setItem("igsettings", true.toString());
    window.location = "https://www.furaffinity.net/controls/settings";
  }
  settings.appendChild(wfsettings);
}

async function addExSettingsSidebar() {
  const settings = document.getElementById('controlpanelnav');

  if (document.getElementById("extension_settings_side")) {
    document.getElementById('midori_settings_side').addEventListener('click', function() { localStorage.setItem("igsettings", true.toString()); });
    return;
  }
  let exSettingsHeader = document.createElement("h3");
  exSettingsHeader.id = "extension_settings_side";
  exSettingsHeader.textContent = "Extension Settings";
  settings.appendChild(exSettingsHeader);

  let wfsettings = document.createElement("a");
  wfsettings.id = "midori_settings_side";
  wfsettings.textContent = "Midori's Script Settings";
  wfsettings.style.cursor = "pointer";
  wfsettings.onclick = function() {
    localStorage.setItem("igsettings", true.toString());
    window.location = "https://www.furaffinity.net/controls/settings";
  }
  settings.appendChild(wfsettings);
}

async function createSettings() {
  localStorage.setItem("igsettings", false.toString());
  const columnPage = document.getElementById("columnpage");
  let content = columnPage.querySelector('div[class="content"]');
  for (const section of content.querySelectorAll('section:not([class="exsettings"])'))
    section.parentNode.removeChild(section);

  let section = document.createElement("section");
  section.className = 'exsettings';
    let headerContainer = document.createElement("div");
    headerContainer.className = "section-header";
      let header = document.createElement("h2");
      header.textContent = "Infini Gallery Settings";
      headerContainer.appendChild(header);
    section.appendChild(headerContainer);
    let bodyContainer = document.createElement("div");
    bodyContainer.className = "section-body";
      let Item1 = document.createElement("div");
      Item1.className = "control-panel-item-container";
        let Item1Name = document.createElement("div");
        Item1Name.className = "control-panel-item-name";
          let Item1NameText = document.createElement("h4");
          Item1NameText.textContent = "Page Seperator";
          Item1Name.appendChild(Item1NameText);
        Item1.appendChild(Item1Name);
        let Item1Desc = document.createElement("div");
        Item1Desc.className = "control-panel-item-description";
          let Item1DescText = document.createTextNode('Sets wether a Page Seperator is shown foreach new Page loaded.');
          Item1Desc.appendChild(Item1DescText);
        Item1.appendChild(Item1Desc);
        let Item1Option = document.createElement("div");
        Item1Option.className = "control-panel-item-options";
          let Item1OptionContainer = document.createElement("div");
            let Item1OptionElem1 = document.createElement("input");
            Item1OptionElem1.id = 'igsettings_01';
            Item1OptionElem1.type = "checkbox";
            Item1OptionElem1.style.cursor = 'pointer';
            Item1OptionElem1.style.marginRight = '4px';
            Item1OptionElem1.addEventListener('change', function() {
              showPageSeperator = Item1OptionElem1.checked;
              localStorage.setItem("igsetting_01", showPageSeperator.toString());
            });
            Item1OptionContainer.appendChild(Item1OptionElem1);
            let Item1OptionElem2 = document.createTextNode('Show Page Seperators');
            Item1OptionContainer.appendChild(Item1OptionElem2);
          Item1Option.appendChild(Item1OptionContainer);
        Item1.appendChild(Item1Option);
      bodyContainer.appendChild(Item1);
        let Item2 = document.createElement("div");
        Item2.className = "control-panel-item-container";
        let Item2Name = document.createElement("div");
        Item2Name.className = "control-panel-item-name";
          let Item2NameText = document.createElement("h4");
          Item2NameText.textContent = "Disable Button";
          Item2Name.appendChild(Item2NameText);
        Item2.appendChild(Item2Name);
        let Item2Desc = document.createElement("div");
        Item2Desc.className = "control-panel-item-description";
          let Item2DescText = document.createTextNode("Sets wether the disable Infini Gallery button is shown in each Gallery");
          Item2Desc.appendChild(Item2DescText);
        Item2.appendChild(Item2Desc);
        let Item2Option = document.createElement("div");
        Item2Option.className = "control-panel-item-options";
          let Item2OptionContainer = document.createElement("div");
            let Item2OptionElem1 = document.createElement("input");
            Item2OptionElem1.id = 'igsettings_02';
            Item2OptionElem1.type = "checkbox";
            Item2OptionElem1.style.cursor = 'pointer';
            Item2OptionElem1.style.marginRight = '4px';
            Item2OptionElem1.addEventListener('change', function() {
              showDisableButton = Item2OptionElem1.checked;
              localStorage.setItem("igsetting_02", showDisableButton.toString());
            });
            Item2OptionContainer.appendChild(Item2OptionElem1);
            let Item2OptionElem2 = document.createTextNode('Show disable Infini Gallery button');
            Item2OptionContainer.appendChild(Item2OptionElem2);
          Item2Option.appendChild(Item2OptionContainer);
        Item2.appendChild(Item2Option);
      bodyContainer.appendChild(Item2);
    section.appendChild(bodyContainer);
  content.appendChild(section);

  fillSettings();
}

async function fillSettings() {
  let setting1 = document.getElementById('igsettings_01');
  setting1.checked = showPageSeperator;

  let setting2 = document.getElementById('igsettings_02');
  setting2.checked = showDisableButton;
}