From efaa2ca913c3527c2da8db299e78567c8d2e9fbe Mon Sep 17 00:00:00 2001 From: nemanjam Date: Tue, 23 Apr 2024 11:18:06 +0200 Subject: [PATCH] sort by new works --- docs/work-notes/todo2.md | 7 +++-- source/reddit-comments/constants/selectors.ts | 5 ++-- source/reddit-comments/dom/sort-by-new.ts | 9 ++----- source/reddit-comments/dom/thread.ts | 4 +++ .../reddit-comments/dom/wait-for-comments.ts | 27 ++++++++++++------- source/reddit-comments/events/on-thread.ts | 15 +++++------ 6 files changed, 37 insertions(+), 30 deletions(-) diff --git a/docs/work-notes/todo2.md b/docs/work-notes/todo2.md index 7fa170b..f4060fb 100644 --- a/docs/work-notes/todo2.md +++ b/docs/work-notes/todo2.md @@ -41,11 +41,14 @@ onScroll, onKeyDown treba attach samo jednom 3. wait - retry for comments to load or error, or timeout, on dropdown change too 4. onCommentsLoaded, onThreadArrived, onNewThreadArrived, onThreadLeft dispatch custom events -debounce koji ne ceka na prvi call + debounce koji ne ceka na prvi call - leading lodash attach listeners only once lock fix highlight on focus remove delayExecution(markAsRead) - needed, cancels on debounce isElementInViewport broken - fixed with debounceTrailing -sortByNew + sortByNew + +use retry-async with exception +poenta je ista kao u cypress ili react-testing-library retry da async element loaded, cela filozofija diff --git a/source/reddit-comments/constants/selectors.ts b/source/reddit-comments/constants/selectors.ts index dc4332d..47c11fd 100644 --- a/source/reddit-comments/constants/selectors.ts +++ b/source/reddit-comments/constants/selectors.ts @@ -43,6 +43,8 @@ export const threadPostIdRegexValidate = /^t3_[a-z0-9]+$/; export const threadWithZeroCommentsSelector = 'comment-forest-empty-state[post-id^="t3_"]'; +export const brokenCommentsThreadSelector = '#main-content > shreddit-forbidden'; + /*----------------- header ----------------*/ export const pageHeaderSelector = 'reddit-header-large'; @@ -57,6 +59,3 @@ export const sortMenuClickSelector = '#comment-sort-button'; // dropdown item new export const sortByNewMenuItemSelector = 'div[slot="dropdown-items"] span.text-14'; - -// for blur, outside of shadow dom, simple selector -export const mainContentForBlurSelector = '#main-content'; diff --git a/source/reddit-comments/dom/sort-by-new.ts b/source/reddit-comments/dom/sort-by-new.ts index ed6fa48..ef3a76e 100644 --- a/source/reddit-comments/dom/sort-by-new.ts +++ b/source/reddit-comments/dom/sort-by-new.ts @@ -4,7 +4,6 @@ import { sortByNewMenuItemSelector, sortMenuShadowHostSelector, sortMenuClickSelector, - mainContentForBlurSelector, } from '../constants/selectors'; import { MyElementNotFoundDOMException } from '../exceptions'; import { wait } from '../utils'; @@ -16,6 +15,7 @@ export const clickSortByNewMenuItem = async (): Promise => { // same shadowHost is reused for currently selected item and dropdown menu click const shadowHost = document.querySelector(sortMenuShadowHostSelector); const shadowRoot = shadowHost?.shadowRoot; + if (!shadowRoot) throw new MyElementNotFoundDOMException( `shadowRoot not found. sortMenuShadowHostSelector: ${sortMenuShadowHostSelector}` @@ -61,12 +61,7 @@ export const clickSortByNewMenuItem = async (): Promise => { (sortByNewMenuItem as HTMLElement).click(); // remove :focus-visible border - const mainContent = document.querySelector(mainContentForBlurSelector); - if (!mainContent) - throw new MyElementNotFoundDOMException( - `mainContent not found. mainContentForBlurSelector: ${mainContentForBlurSelector}` - ); - mainContent?.click(); + sortMenu.blur(); } return true; diff --git a/source/reddit-comments/dom/thread.ts b/source/reddit-comments/dom/thread.ts index b41f378..54e9392 100644 --- a/source/reddit-comments/dom/thread.ts +++ b/source/reddit-comments/dom/thread.ts @@ -1,4 +1,5 @@ import { + brokenCommentsThreadSelector, threadPostSelector, threadWithZeroCommentsSelector, } from '../constants/selectors'; @@ -21,3 +22,6 @@ export const getThreadIdFromDom = (): string => { export const isZeroCommentsThread = (): boolean => Boolean(document.querySelector(threadWithZeroCommentsSelector)); + +export const isBrokenCommentsThread = (): boolean => + Boolean(document.querySelector(brokenCommentsThreadSelector)); diff --git a/source/reddit-comments/dom/wait-for-comments.ts b/source/reddit-comments/dom/wait-for-comments.ts index b609ec9..746fcf2 100644 --- a/source/reddit-comments/dom/wait-for-comments.ts +++ b/source/reddit-comments/dom/wait-for-comments.ts @@ -1,6 +1,6 @@ import { defaultRetryOptions, RetryOptions } from '../constants/config'; import { getElapsedTime, isActiveTabAndRedditThreadAndHasComments, wait } from '../utils'; -import { isZeroCommentsThread } from './thread'; +import { isBrokenCommentsThread, isZeroCommentsThread } from './thread'; export interface RetryAndWaitResult { /** if should proceed with highlight */ @@ -11,6 +11,7 @@ export interface RetryAndWaitResult { | 'timeout' | 'left-thread' | 'zero-comments' + | 'broken-comments' | 'initial'; elapsedTime: number; retryIndex: number; @@ -20,41 +21,47 @@ export type RetryAndWaitCallbackResult = Pick RetryAndWaitCallbackResult; export const waitForCommentsCallback: RetryAndWaitCallback = () => { - let result: RetryAndWaitCallbackResult = { - isSuccess: false, - reason: 'initial', - }; - // check 0 comments const hasZeroComments = isZeroCommentsThread(); if (hasZeroComments) { - result = { + return { isSuccess: false, reason: 'zero-comments', }; } // select broken comments dom + const hasBrokenComments = isBrokenCommentsThread(); + + if (hasBrokenComments) { + return { + isSuccess: false, + reason: 'broken-comments', + }; + } const { isOk, isActiveTab, isRedditThread } = isActiveTabAndRedditThreadAndHasComments(); if (isOk) { - result = { + return { isSuccess: true, reason: 'has-comments', }; } if (!(isActiveTab && isRedditThread)) { - result = { + return { isSuccess: false, reason: 'left-thread', }; } - return result; + return { + isSuccess: false, + reason: 'initial', + }; }; export const retryAndWaitForCommentsToLoad = () => diff --git a/source/reddit-comments/events/on-thread.ts b/source/reddit-comments/events/on-thread.ts index d59b742..6cd2795 100644 --- a/source/reddit-comments/events/on-thread.ts +++ b/source/reddit-comments/events/on-thread.ts @@ -1,6 +1,5 @@ import { threadArrivedDebounceWait } from '../constants/config'; import { debounceLeading } from '../utils'; -import { waitAfterSortByNew } from '../constants/config'; import { getSettings } from '../database/models/settings'; import { openDatabase } from '../database/schema'; import { highlightByDate } from '../dom/highlight-by-date'; @@ -12,7 +11,6 @@ import { clickSortByNewMenuItem } from '../dom/sort-by-new'; import { isActiveTabAndRedditThread, isActiveTabAndRedditThreadAndHasComments, - wait, } from '../utils'; import logger from '../logger'; import { ARRIVED_TO_REDDIT_THREAD_EVENT_NAME } from '../constants/events'; @@ -27,19 +25,20 @@ export const handleArrivedToRedditThread = async () => { try { const db = await openDatabase(); const { sortAllByNew } = await getSettings(db); + if (sortAllByNew) { - const hasSorted = await clickSortByNewMenuItem(); - if (hasSorted) { - // delay must be AFTER sort - await wait(waitAfterSortByNew); - } + // when comments are loaded, sort menu is loaded too + const { isSuccess } = await retryAndWaitForCommentsToLoad(); + if (!isSuccess) return; + + await clickSortByNewMenuItem(); } + // wait for sorted comments to reload const { isSuccess } = await retryAndWaitForCommentsToLoad(); if (!isSuccess) return; //! important, must select element AFTER sort - // only root check, child functions must have commentElements array filled const { isOk, commentElements } = isActiveTabAndRedditThreadAndHasComments(); if (!isOk) return;