From be9dca362d25a95f3d73fc188c6ea64c9d98bec3 Mon Sep 17 00:00:00 2001 From: infinite-persistence Date: Wed, 1 Sep 2021 15:55:00 +0800 Subject: [PATCH] Fix linked-comment auto scroll ## Ticket 6946: Linked-comment scroll position is inconsistent ## Issues - If it is a deeply-nested reply, the positioning is incorrect. - If there are pinned comments, the positioning is way off. - If there is a delay in mounting, the positioning doesn't happen. - When clicking on the comment's date to highlight it, the comment goes missing and the scroll position is weird. ## Changes - Take into account that replies can be linked-comments. - Perform a "one-time" search for the linked-comment after the initial fetch, if necessary. The expensive DOM search is only be executed minimally. --- ui/component/comment/view.jsx | 3 ++- ui/component/commentsList/view.jsx | 25 +++++++++++++++++++------ ui/constants/classnames.js | 1 + 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/ui/component/comment/view.jsx b/ui/component/comment/view.jsx index 2ed27afa0..aaaafebec 100644 --- a/ui/component/comment/view.jsx +++ b/ui/component/comment/view.jsx @@ -1,6 +1,7 @@ // @flow import * as ICONS from 'constants/icons'; import * as PAGES from 'constants/pages'; +import { COMMENT_HIGHLIGHTED } from 'constants/classnames'; import { SORT_BY, COMMENT_PAGE_SIZE_REPLIES } from 'constants/comment'; import { FF_MAX_CHARS_IN_COMMENT } from 'constants/form-field'; import { SITE_NAME, SIMPLE_SITE, ENABLE_COMMENT_REACTIONS } from 'config'; @@ -220,7 +221,7 @@ function Comment(props: Props) { >
diff --git a/ui/component/commentsList/view.jsx b/ui/component/commentsList/view.jsx index ae3ee5b12..230619ab8 100644 --- a/ui/component/commentsList/view.jsx +++ b/ui/component/commentsList/view.jsx @@ -1,6 +1,7 @@ // @flow import * as REACTION_TYPES from 'constants/reactions'; import * as ICONS from 'constants/icons'; +import { COMMENT_HIGHLIGHTED } from 'constants/classnames'; import { COMMENT_PAGE_SIZE_TOP_LEVEL, SORT_BY } from 'constants/comment'; import React, { useEffect } from 'react'; import classnames from 'classnames'; @@ -18,6 +19,9 @@ import { getChannelIdFromClaim } from 'util/claim'; const DEBOUNCE_SCROLL_HANDLER_MS = 200; +// "3" due to 2 separate fetches needed + 1 buffer just in case. +const MAX_LINKED_COMMENT_SCROLL_ATTEMPTS = 3; + function scaleToDevicePixelRatio(value) { const devicePixelRatio = window.devicePixelRatio || 1.0; if (devicePixelRatio < 1.0) { @@ -75,11 +79,13 @@ function CommentList(props: Props) { settingsByChannelId, } = props; - const commentRef = React.useRef(); const spinnerRef = React.useRef(); const DEFAULT_SORT = ENABLE_COMMENT_REACTIONS ? SORT_BY.POPULARITY : SORT_BY.NEWEST; const [sort, setSort] = usePersistedState('comment-sort-by', DEFAULT_SORT); const [page, setPage] = React.useState(0); + const [lcScrollAttempts, setLcScrollAttempts] = React.useState( + linkedCommentId ? 0 : MAX_LINKED_COMMENT_SCROLL_ATTEMPTS + ); const isMobile = useIsMobile(); const [expandedComments, setExpandedComments] = React.useState(!isMobile); const totalFetchedComments = allCommentIds ? allCommentIds.length : 0; @@ -196,11 +202,19 @@ function CommentList(props: Props) { // Scroll to linked-comment useEffect(() => { - if (readyToDisplayComments && linkedCommentId && commentRef && commentRef.current) { - commentRef.current.scrollIntoView({ block: 'start' }); - window.scrollBy(0, -125); + if (lcScrollAttempts < MAX_LINKED_COMMENT_SCROLL_ATTEMPTS && readyToDisplayComments && !isFetchingComments) { + const elems = document.getElementsByClassName(COMMENT_HIGHLIGHTED); + if (elems.length > 0) { + setLcScrollAttempts(MAX_LINKED_COMMENT_SCROLL_ATTEMPTS); + const linkedComment = elems[0]; + linkedComment.scrollIntoView({ block: 'start' }); + window.scrollBy(0, -125); + } else { + setLcScrollAttempts(lcScrollAttempts + 1); + } } - }, [readyToDisplayComments, linkedCommentId]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [readyToDisplayComments, isFetchingComments]); // We just want to respond to these, nothing else. // Infinite scroll useEffect(() => { @@ -321,7 +335,6 @@ function CommentList(props: Props) { comments: expandedComments, 'comments--contracted': !expandedComments, })} - ref={commentRef} > {readyToDisplayComments && pinnedComments && getCommentElems(pinnedComments)} {readyToDisplayComments && topLevelComments && getCommentElems(topLevelComments)} diff --git a/ui/constants/classnames.js b/ui/constants/classnames.js index e69de29bb..f6411605b 100644 --- a/ui/constants/classnames.js +++ b/ui/constants/classnames.js @@ -0,0 +1 @@ +export const COMMENT_HIGHLIGHTED = 'comment--highlighted';