Add infinite scroll support to CC interop threads
Bug: twpowertools:96
Change-Id: I90eeae09d8bdcb777c69fa4dc2bc0fe8c034cd09
diff --git a/src/contentScripts/communityConsole/infiniteScroll.js b/src/contentScripts/communityConsole/infiniteScroll.js
new file mode 100644
index 0000000..55dc0ae
--- /dev/null
+++ b/src/contentScripts/communityConsole/infiniteScroll.js
@@ -0,0 +1,78 @@
+import {getOptions, isOptionEnabled} from '../../common/optionsUtils.js';
+
+const kInteropLoadMoreClasses = {
+ 'scTailwindThreadMorebuttonload-all': 'threadall',
+ 'scTailwindThreadMorebuttonload-more': 'thread',
+};
+
+export default class InfiniteScroll {
+ constructor() {
+ this.intersectionObserver = null;
+ }
+
+ setUpIntersectionObserver(node, isScrollableContent) {
+ if (this.intersectionObserver === null) {
+ var scrollableContent = isScrollableContent ?
+ node :
+ node.querySelector('.scrollable-content');
+ if (scrollableContent !== null) {
+ let intersectionOptions = {
+ root: scrollableContent,
+ rootMargin: '0px',
+ threshold: 1.0,
+ };
+ this.intersectionObserver = new IntersectionObserver(
+ this.intersectionCallback, intersectionOptions);
+ }
+ }
+ }
+
+ intersectionCallback(entries, observer) {
+ entries.forEach(entry => {
+ if (entry.isIntersecting) {
+ console.debug('[infinitescroll] Clicking button: ', entry.target);
+ entry.target.click();
+ }
+ });
+ }
+
+ observeLoadMoreBar(bar) {
+ if (this.intersectionObserver === null) {
+ console.warn(
+ '[infinitescroll] ' +
+ 'The intersectionObserver is not ready yet.');
+ return;
+ }
+
+ getOptions(['thread', 'threadall']).then(threadOptions => {
+ if (threadOptions.thread)
+ this.intersectionObserver.observe(
+ bar.querySelector('.load-more-button'));
+ if (threadOptions.threadall)
+ this.intersectionObserver.observe(
+ bar.querySelector('.load-all-button'));
+ });
+ }
+
+ observeLoadMoreInteropBtn(btn) {
+ if (this.intersectionObserver === null) {
+ console.warn(
+ '[infinitescroll] ' +
+ 'The intersectionObserver is not ready yet.');
+ return;
+ }
+
+ let parentClasses = btn.parentNode?.classList;
+ let feature = null;
+ for (const [c, f] of Object.entries(kInteropLoadMoreClasses)) {
+ if (parentClasses?.contains?.(c)) {
+ feature = f;
+ break;
+ }
+ }
+ if (feature === null) return;
+ isOptionEnabled(feature).then(isEnabled => {
+ if (isEnabled) this.intersectionObserver.observe(btn);
+ });
+ }
+};