您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Keep Navigation buttons at the top.Add infinite scrolling to Browse, Search and Gallery.
当前为
// ==UserScript== // @name FA Mobile Enhancer // @namespace Userscripts // @match https://www.furaffinity.net/* // @grant GM.addStyle // @version 0.0.1 // @author LinHQ1999 // @license AGPLv3 // @description Keep Navigation buttons at the top.Add infinite scrolling to Browse, Search and Gallery. // ==/UserScript== (async function () { const S = { gallery: 'section.gallery', blocked: 'blocked-content', searchForm: 'search-form' } const C = [ { key: 'browse', navigatorStr: 'body div.navigation', navigator: document.querySelector('body div.navigation'), boundry: document.querySelectorAll('body div.navigation')[1], update(doc) { const newNav = doc.querySelector(this.navigatorStr) this.navigator.replaceWith(newNav) this.navigator = newNav }, next() { const next = this.navigator.querySelectorAll('form')[1] return fetch(next.action, { method: 'POST', body: new FormData(next) }) } }, { key: 'search', navigator: document.querySelector('.pagination'), navigatorStr: '.pagination', boundry: document.querySelectorAll('.pagination')[1], next() { const form = document.getElementById(S.searchForm) console.log(form) const data = new FormData(form) data.set('next_page', 'Next') return fetch(form.action, { method: 'POST', body: data }) }, update(doc) { const newNav = doc.querySelector(this.navigatorStr) this.navigator.replaceWith(newNav) this.navigator = newNav const newPage = doc.getElementById("page") document.querySelector('#page').replaceWith(newPage) } }, { key: 'gallery', navigator: document.querySelector('.gallery-navigation'), navigatorStr:'.gallery-navigation', boundry: document.querySelectorAll('.gallery-navigation')[1], next() { const nextBtns = this.navigator.querySelectorAll('form') const next = nextBtns[nextBtns.length - 1] return fetch(next.action, { method: 'POST', body: new FormData(next) }) }, update(doc) { const newNav = doc.querySelector(this.navigatorStr) this.navigator.replaceWith(newNav) this.navigator = newNav } } ] const cfg = C.find(c => window.location.pathname.includes(c.key)) if (!cfg) return GM.addStyle(` .news-block, .main-window>*:not(.site-content) { display: none; } body { height: 100vh; overflow: auto; } #pageid-browse .navigation:nth-child(1), .pagination, .gallery-navigation { position: sticky; top: 0; -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); z-index: 9; } `) const parser = new DOMParser() let loading = false const ob = new IntersectionObserver(([entry]) => { const { y, height } = entry.boundingClientRect const total = entry.rootBounds.height if (entry.isIntersecting && (y + height) >= total && !loading) { loading = true cfg.next() .then(async (resp) => { const docStr = await resp.text() const doc = parser.parseFromString(docStr, 'text/html') cfg?.update(doc) const gallery = doc.querySelector(S.gallery) gallery.querySelectorAll('img') .forEach(img => img.classList.remove(S.blocked)) document.querySelector(S.gallery)?.append(...gallery.childNodes) }) .catch(err => { alert(err) console.error(err) }) .finally(() => loading = false) } }, { root: document.body, threshold: 0.5 }) ob.observe(cfg.boundry) })()