Greasy Fork 支持简体中文。

Cohost post scroller

Lets you jump between post by pressing Home/End

// ==UserScript==
// @name         Cohost post scroller
// @namespace    https://yal.cc
// @version      0.11
// @description  Lets you jump between post by pressing Home/End
// @author       YellowAfterlife
// @match        https://cohost.org/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=cohost.org
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
	let within = (value, a, b) => value >= a && value <= b;
	document.addEventListener("keydown", function(e) {
		let finish = () => {
			e.preventDefault();
			return;
		}
		let delta;
		switch (e.key) {
			case "Home": delta = -1; break;
			case "End": delta = 1; break;
			default: return;
		}
		let viewport = window.visualViewport;
		let header = document.querySelector("#app header");
		let headerHeight = (header?.offsetHeight ?? 0);
		let scrollPad = 15;
		let lastScrollPad = 100;
		let viewportHeight = viewport.height - headerHeight;
		let viewportMid = headerHeight + viewportHeight / 2;
		let scrollToPair = (pair) => {
			document.documentElement.scrollTop += pair.rect.top - headerHeight - scrollPad;
		}
		
		let posts = Array.prototype.slice.apply(document.querySelectorAll(`div.renderIfVisible article`));
		if (posts.length == 0) return;
		let pairs = posts.map(post => {
			return { post: post, rect: post.getBoundingClientRect() };
		});
		
		let best = null;
		for (let pair of pairs) {
			let isWithin = within(headerHeight, pair.rect.top, pair.rect.bottom);
			if (isWithin && delta < 0) {
				scrollToPair(pair);
				return finish();
			}
			pair.dist = pair.rect.top - headerHeight;
			if (pair.dist < 0 && !isWithin) continue;
			if (!best || pair.dist < best.dist) best = pair;
		}
		
		if (!best) best = pairs[pairs.length - 1];
		if (!best) return;
		
		if (best == pairs[0] && best.dist > 200 && delta > 0) {
			// scroll first post into view
			scrollToPair(best);
			return finish();
		}
		
		let next = pairs[pairs.indexOf(best) + delta];
		console.log(pairs);
		console.log(best, next);
		if (next) {	
			scrollToPair(next);
		} else {
			if (best.rect.height >= viewportHeight - lastScrollPad && delta > 0) {
				// scroll so that the bottom of the last post (and possibly the "next page" button) is visible
				document.documentElement.scrollTop += best.rect.bottom - headerHeight - viewportHeight + lastScrollPad;
			} else {
				scrollToPair(best);
			}
		}
		e.preventDefault();
	});
})();