summaryrefslogtreecommitdiff
path: root/source/libs/on-new-comments.ts
blob: 2ddc5aae25662bc28931aa05fca692ad17cb38ea (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
import select from 'select-dom';
import debounce from 'debounce-fn';
import observeEl from './simplified-element-observer';

const handlers = new Set<VoidFunction>();
const observed = new WeakSet();

const run = debounce(() => {
	// Safely run all callbacks
	// eslint-disable-next-line @typescript-eslint/require-await
	handlers.forEach(async cb => cb());
}, {wait: 200});

// On new page loads, run the callbacks and look for the new elements.
// (addEventListener doesn't add duplicate listeners)
const addListenersOnNewElements = debounce(() => {
	for (const loadMore of select.all('.js-ajax-pagination')) {
		loadMore.addEventListener('page:loaded', run);
		loadMore.addEventListener('page:loaded', addListenersOnNewElements);
	}

	// Outdated comment are loaded later using an include-fragment element
	for (const fragment of select.all('details.outdated-comment > include-fragment')) {
		fragment.addEventListener('load', run);
	}
}, {wait: 50});

const setup = (): void => {
	const discussion = select('.js-discussion');
	if (!discussion || observed.has(discussion)) {
		return;
	}

	observed.add(discussion);

	// When new comments come in via AJAX
	observeEl(discussion, run);

	// When hidden comments are loaded by clicking "Load more..."
	addListenersOnNewElements();
};

export default function (cb: VoidFunction): void {
	setup();
	handlers.add(cb);
}