diff --git a/src/components/common/NodeHorizontalCard/index.tsx b/src/components/common/NodeHorizontalCard/index.tsx index 3c0847be..d132ee90 100644 --- a/src/components/common/NodeHorizontalCard/index.tsx +++ b/src/components/common/NodeHorizontalCard/index.tsx @@ -8,6 +8,8 @@ import { URLS } from '~/constants/urls'; import { INode } from '~/types'; import { getPrettyDate } from '~/utils/dom'; +import { getNewCommentAnchor } from '../../../constants/dom/links'; + import styles from './styles.module.scss'; interface Props { @@ -16,32 +18,30 @@ interface Props { onClick?: MouseEventHandler; } -const NodeHorizontalCard: FC = ({ node, hasNew, onClick }) => { - return ( - = ({ node, hasNew, onClick }) => ( + +
-
- -
+ +
-
-
{node.title || '...'}
+
+
{node.title || '...'}
-
- {getPrettyDate(node.created_at)} -
+
+ {getPrettyDate(node.created_at)}
- - ); -}; +
+ +); export { NodeHorizontalCard }; diff --git a/src/components/notifications/NotificationComment/index.tsx b/src/components/notifications/NotificationComment/index.tsx index 194a60bb..e707a27f 100644 --- a/src/components/notifications/NotificationComment/index.tsx +++ b/src/components/notifications/NotificationComment/index.tsx @@ -9,6 +9,8 @@ import { Square } from '~/components/common/Square'; import { NotificationItem } from '~/types/notifications'; import { formatText, getURLFromString } from '~/utils/dom'; +import { getCommentAnchor } from '../../../constants/dom/links'; + import styles from './styles.module.scss'; interface NotificationCommentProps { @@ -17,7 +19,10 @@ interface NotificationCommentProps { } const NotificationComment: FC = ({ item, isNew }) => ( - +
+ [COMMENT_ANCHOR_PREFIX, id].join('-'); + +export const getNewCommentAnchor = (url: string) => + [url, NEW_COMMENT_ANCHOR_NAME].join('#'); + +export const getCommentAnchor = (url: string, commentId: number) => + [url, getCommentId(commentId)].join('#'); + +export const isCommentAnchor = (hash: string | undefined) => + hash?.startsWith(COMMENT_ANCHOR_PREFIX) || + hash?.startsWith(NEW_COMMENT_ANCHOR_NAME); diff --git a/src/containers/node/NodeComments/components/Comment/index.tsx b/src/containers/node/NodeComments/components/Comment/index.tsx index 121d8051..1e3f2b60 100644 --- a/src/containers/node/NodeComments/components/Comment/index.tsx +++ b/src/containers/node/NodeComments/components/Comment/index.tsx @@ -8,6 +8,7 @@ import { CommentWrapper } from '~/containers/comments/CommentWrapper'; import { IComment, ICommentGroup, IFile } from '~/types'; import { CommendDeleted } from '../../../../../components/node/CommendDeleted'; +import { getCommentId } from '../../../../../constants/dom/links'; import { CommentContent } from './components/CommentContent'; import { CommentDistance } from './components/CommentDistance'; @@ -83,18 +84,22 @@ const Comment: FC = memo( ); return ( - onLike(comment.id, !comment.liked)} - onDelete={(val: boolean) => onDelete(comment.id, val)} - onShowImageModal={onShowImageModal} - key={comment.id} - /> + <> + + + onLike(comment.id, !comment.liked)} + onDelete={(val: boolean) => onDelete(comment.id, val)} + onShowImageModal={onShowImageModal} + key={comment.id} + /> + ); })}
diff --git a/src/containers/node/NodeComments/components/Comment/styles.module.scss b/src/containers/node/NodeComments/components/Comment/styles.module.scss index 01c1e131..92cd93b4 100644 --- a/src/containers/node/NodeComments/components/Comment/styles.module.scss +++ b/src/containers/node/NodeComments/components/Comment/styles.module.scss @@ -15,3 +15,9 @@ .highlighted { box-shadow: $color_primary 0 0 0px 2px; } + +.anchor { + display: block; + position: relative; + top: -($header_height * 2); +} diff --git a/src/containers/node/NodeComments/index.tsx b/src/containers/node/NodeComments/index.tsx index acba75b0..a1d93732 100644 --- a/src/containers/node/NodeComments/index.tsx +++ b/src/containers/node/NodeComments/index.tsx @@ -1,9 +1,13 @@ -import { FC, useMemo } from 'react'; +import { FC, useEffect, useMemo } from 'react'; import { observer } from 'mobx-react-lite'; import { LoadMoreButton } from '~/components/input/LoadMoreButton'; import { ANNOUNCE_USER_ID, BORIS_NODE_ID } from '~/constants/boris/constants'; +import { + isCommentAnchor, + NEW_COMMENT_ANCHOR_NAME, +} from '~/constants/dom/links'; import { Comment } from '~/containers/node/NodeComments/components/Comment'; import { useGrouppedComments } from '~/hooks/node/useGrouppedComments'; import { ICommentGroup } from '~/types'; @@ -18,6 +22,11 @@ interface Props { order: 'ASC' | 'DESC'; } +const isFirstGroupWithNewCommentt = ( + group: ICommentGroup, + prevGroup: ICommentGroup | undefined, +) => group.hasNew && (!prevGroup || !prevGroup.hasNew); + const NodeComments: FC = observer(({ order }) => { const user = useUserContext(); const { node } = useNodeContext(); @@ -35,7 +44,7 @@ const NodeComments: FC = observer(({ order }) => { onSaveComment, } = useCommentContext(); - const groupped: ICommentGroup[] = useGrouppedComments( + const groupped = useGrouppedComments( comments, order, lastSeenCurrent ?? undefined, @@ -59,26 +68,49 @@ const NodeComments: FC = observer(({ order }) => { return null; } + useEffect(() => { + const anchor = location.hash?.replace('#', ''); + + if (!isLoading && isCommentAnchor(anchor)) { + setTimeout( + () => + document + .getElementById(anchor) + ?.scrollIntoView({ behavior: 'smooth' }), + 300, + ); + } + }, [isLoading]); + return (
{order === 'DESC' && more} - {groupped.map((group) => ( - + {groupped.map((group, index) => ( + <> + {isFirstGroupWithNewCommentt(group, groupped.at(index - 1)) && ( + + )} + + + ))} {order === 'ASC' && more} diff --git a/src/containers/node/NodeComments/styles.module.scss b/src/containers/node/NodeComments/styles.module.scss index 3cd52e5a..1d006bd7 100644 --- a/src/containers/node/NodeComments/styles.module.scss +++ b/src/containers/node/NodeComments/styles.module.scss @@ -13,3 +13,9 @@ .more { margin-bottom: $gap; } + +.newCommentAnchor { + position: relative; + top: -($header_height * 2); + display: block; +} \ No newline at end of file diff --git a/src/types/notifications/index.ts b/src/types/notifications/index.ts index 5a34538f..c23b3f90 100644 --- a/src/types/notifications/index.ts +++ b/src/types/notifications/index.ts @@ -2,6 +2,7 @@ import { ShallowUser } from '../auth'; export interface NotificationItem { id: number; + itemId: number; url: string; type: NotificationType; title: string;