refactor: migrate infinite scroll feature to a new architecture
This CL introduces a new architecture for the features source code.
Bug: twpowertools:176
Change-Id: I9abc4df2fb67f9bb0c9114aaffc6916d34f1b7ff
diff --git a/src/contentScripts/communityConsole/infiniteScroll.js b/src/contentScripts/communityConsole/infiniteScroll.js
deleted file mode 100644
index 447974e..0000000
--- a/src/contentScripts/communityConsole/infiniteScroll.js
+++ /dev/null
@@ -1,89 +0,0 @@
-import {getOptions, isOptionEnabled} from '../../common/optionsUtils.js';
-
-const kInteropLoadMoreClasses = {
- // New (interop) UI without nested replies
- 'scTailwindThreadMorebuttonload-all': 'threadall',
- 'scTailwindThreadMorebuttonload-more': 'thread',
-
- // New (interop) UI with nested replies
- 'scTailwindThreadMessagegapload-all': 'threadall',
- 'scTailwindThreadMessagegapload-more': 'thread',
-};
-const kArtificialScrollingDelay = 3500;
-
-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();
- }
- });
- }
-
- isPotentiallyArtificialScroll() {
- return window.location.href.includes('/message/');
- }
-
- observeWithPotentialDelay(node) {
- if (this.intersectionObserver === null) {
- console.warn(
- '[infinitescroll] ' +
- 'The intersectionObserver is not ready yet.');
- return;
- }
-
- if (this.isPotentiallyArtificialScroll()) {
- window.setTimeout(
- () => {this.intersectionObserver.observe(node)},
- kArtificialScrollingDelay);
- } else {
- this.intersectionObserver.observe(node);
- }
- }
-
- observeLoadMoreBar(bar) {
- getOptions(['thread', 'threadall']).then(threadOptions => {
- if (threadOptions.thread)
- this.observeWithPotentialDelay(bar.querySelector('.load-more-button'));
- if (threadOptions.threadall)
- this.observeWithPotentialDelay(bar.querySelector('.load-all-button'));
- });
- }
-
- observeLoadMoreInteropBtn(btn) {
- 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.observeWithPotentialDelay(btn);
- });
- }
-};
diff --git a/src/contentScripts/communityConsole/main.js b/src/contentScripts/communityConsole/main.js
index 0200394..ea9cb8c 100644
--- a/src/contentScripts/communityConsole/main.js
+++ b/src/contentScripts/communityConsole/main.js
@@ -12,12 +12,11 @@
import {applyDragAndDropFixIfEnabled} from './dragAndDropFix.js';
// #!endif
import {default as FlattenThreads, kMatchingSelectors as kFlattenThreadMatchingSelectors} from './flattenThreads/flattenThreads.js';
-import InfiniteScroll from './infiniteScroll.js';
import {kRepliesSectionSelector} from './threadToolbar/constants.js';
import ThreadToolbar from './threadToolbar/threadToolbar.js';
import Workflows from './workflows/workflows.js';
-var mutationObserver, options, avatars, infiniteScroll, workflows,
+var mutationObserver, options, avatars, workflows,
threadToolbar, flattenThreads, reportDialogColorThemeFix;
const watchedNodesSelectors = [
@@ -88,8 +87,6 @@
function handleCandidateNode(node) {
if (typeof node.classList !== 'undefined') {
if (('tagName' in node) && node.tagName == 'EC-APP') {
- infiniteScroll.setUpIntersectionObserver(node, false);
-
// Inject the dark mode button
// TODO(avm99963): make this feature dynamic.
if (options.ccdarktheme && options.ccdarktheme_mode == 'switch') {
@@ -100,21 +97,6 @@
}
}
- // To set up infinite scroll
- if (node.classList.contains('scrollable-content')) {
- infiniteScroll.setUpIntersectionObserver(node, true);
- }
-
- // Start the intersectionObserver for the "load more"/"load all" buttons
- // inside a thread if the option is currently enabled.
- if (node.classList.contains('load-more-bar')) {
- infiniteScroll.observeLoadMoreBar(node);
- }
- if (node.classList.contains('scTailwindThreadMorebuttonbutton') ||
- node.classList.contains('scTailwindThreadMessagegapbutton')) {
- infiniteScroll.observeLoadMoreInteropBtn(node);
- }
-
// Show additional details in the profile view.
if (node.matches('ec-unified-user .scTailwindUser_profileUsercardmain')) {
window.TWPTExtraInfo.injectAbuseChipsAtProfileIfEnabled(node);
@@ -284,7 +266,6 @@
// Initialize classes needed by the mutation observer
avatars = new AvatarsHandler();
- infiniteScroll = new InfiniteScroll();
workflows = new Workflows();
threadToolbar = new ThreadToolbar();
flattenThreads = new FlattenThreads();