summaryrefslogtreecommitdiff
path: root/source/features/infinite-scroll.tsx
blob: 7b58d77409bbf12a51885e6ec54f4fb68cd00b11 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import select from 'select-dom';
import debounce from 'debounce-fn';
import * as pageDetect from 'github-url-detection';
import features from '../libs/features';

let button: HTMLButtonElement | undefined;

const loadMore = debounce(() => {
	button!.click();
	button!.textContent = 'Loading…';

	// If GH hasn't loaded the JS, the click will not load anything.
	// We can detect if it worked by looking at the button's state,
	// and then trying again (auto-debounced)
	if (!button!.disabled) {
		loadMore();
	}
}, {wait: 200});

const inView = new IntersectionObserver(([{isIntersecting}]) => {
	if (isIntersecting) {
		loadMore();
	} else {
		// The button may have been changed after it's gone out of view, so try finding it again
		findButton();
	}
}, {
	rootMargin: '500px' // https://github.com/sindresorhus/refined-github/pull/505#issuecomment-309273098
});

const findButton = (): void => {
	// If the old button is still there, leave
	if (button && document.contains(button)) {
		return;
	}

	// Forget the old button
	inView.disconnect();

	// Watch the new button, or stop everything
	button = select<HTMLButtonElement>('.ajax-pagination-btn')!;
	if (button) {
		inView.observe(button);
	}
};

function init(): void {
	const form = select('.ajax-pagination-form');
	if (form) {
		// If GH hasn't loaded the JS,
		// the fake click will submit the form without ajax.
		form.addEventListener('submit', event => event.preventDefault());

		findButton();
	}
}

features.add({
	id: __filebasename,
	description: 'Automagically expands the newsfeed when you scroll down.',
	screenshot: false
}, {
	include: [
		pageDetect.isDashboard
	],
	onlyAdditionalListeners: true,
	repeatOnAjax: false,
	init
});