diff --git a/apps/admin/src/comments/components/comment-menu.tsx b/apps/admin/src/comments/components/comment-menu.tsx
index 82362737a2b..15e8a0ea035 100644
--- a/apps/admin/src/comments/components/comment-menu.tsx
+++ b/apps/admin/src/comments/components/comment-menu.tsx
@@ -2,7 +2,6 @@ import {Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMen
import {type Comment, usePinComment, useUnpinComment} from '@tryghost/admin-x-framework/api/comments';
import {DisableCommentingDialog} from './disable-commenting-dialog';
import {LucideIcon} from '@tryghost/shade/utils';
-import {useCommentsPinningEnabled} from '@/comments/hooks/use-comments-pinning-enabled';
import {useDisableMemberCommenting, useEnableMemberCommenting} from '@tryghost/admin-x-framework/api/members';
import {useState} from 'react';
@@ -18,13 +17,12 @@ export function CommentMenu({
const {mutate: pinComment} = usePinComment();
const {mutate: unpinComment} = useUnpinComment();
const [disableDialogOpen, setDisableDialogOpen] = useState(false);
- const commentsPinningEnabled = useCommentsPinningEnabled();
const {id: commentId, post, member} = comment;
const postUrl = post?.url;
const memberId = member?.id;
const canComment = member?.can_comment;
- const canPin = commentsPinningEnabled && !comment.parent_id && comment.status !== 'deleted';
+ const canPin = !comment.parent_id && comment.status !== 'deleted';
const handleDisableCommenting = (hideComments: boolean) => {
if (memberId) {
diff --git a/apps/admin/src/comments/components/comment-thread-list.tsx b/apps/admin/src/comments/components/comment-thread-list.tsx
index ab92caa62e6..7d816295070 100644
--- a/apps/admin/src/comments/components/comment-thread-list.tsx
+++ b/apps/admin/src/comments/components/comment-thread-list.tsx
@@ -8,7 +8,6 @@ import {CommentMetrics} from './comment-metrics';
import {buildThreadLink} from './thread-link';
import {Link, useSearchParams} from '@tryghost/admin-x-framework';
import {LucideIcon, cn} from '@tryghost/shade/utils';
-import {useCommentsPinningEnabled} from '@/comments/hooks/use-comments-pinning-enabled';
function RepliesLine({hasReplies}: {hasReplies: boolean}) {
if (!hasReplies) {
@@ -36,7 +35,6 @@ function CommentRow({comment, dislikesEnabled, isReply = false, isSelectedCommen
const {mutate: hideComment} = useHideComment();
const {mutate: showComment} = useShowComment();
const {mutate: unpinComment} = useUnpinComment();
- const commentsPinningEnabled = useCommentsPinningEnabled();
// Check replies array for loaded objects, or count.direct_replies for unloaded
// TODO: remove count.replies fallback once backend is fully rolled out
@@ -64,10 +62,10 @@ function CommentRow({comment, dislikesEnabled, isReply = false, isSelectedCommen
canComment={comment.member?.can_comment}
createdAt={comment.created_at}
isHidden={comment.status === 'hidden'}
- isPinned={commentsPinningEnabled && comment.pinned}
+ isPinned={comment.pinned}
memberId={comment.member?.id}
memberName={comment.member?.name}
- onUnpinClick={commentsPinningEnabled ? () => unpinComment({id: comment.id}) : undefined}
+ onUnpinClick={() => unpinComment({id: comment.id})}
/>
{comment.in_reply_to_snippet && isSelectedComment && (
diff --git a/apps/admin/src/comments/components/comments-list.tsx b/apps/admin/src/comments/components/comments-list.tsx
index b0480d6d1f5..d379320cf6d 100644
--- a/apps/admin/src/comments/components/comments-list.tsx
+++ b/apps/admin/src/comments/components/comments-list.tsx
@@ -10,7 +10,6 @@ import {Link, useSearchParams} from '@tryghost/admin-x-framework';
import {LoadMoreButton, useInfiniteVirtualScroll, useScrollRestoration, useVirtualListWindow} from '@/shared/virtual-list';
import {LucideIcon, cn} from '@tryghost/shade/utils';
import {forwardRef, useEffect, useRef, useState} from 'react';
-import {useCommentsPinningEnabled} from '@/comments/hooks/use-comments-pinning-enabled';
const SpacerRow = ({height}: { height: number }) => (
@@ -67,7 +66,6 @@ function CommentsList({
const {mutate: hideComment} = useHideComment();
const {mutate: showComment} = useShowComment();
const {mutate: unpinComment} = useUnpinComment();
- const commentsPinningEnabled = useCommentsPinningEnabled();
const handleCloseSidebar = (open: boolean) => {
setThreadSidebarOpen(open);
@@ -157,13 +155,13 @@ function CommentsList({
canComment={item.member?.can_comment}
createdAt={item.created_at}
isHidden={item.status === 'hidden'}
- isPinned={commentsPinningEnabled && item.pinned}
+ isPinned={item.pinned}
memberId={item.member?.id}
memberName={item.member?.name}
postTitle={item.post?.title}
onAuthorClick={item.member?.id ? () => onAddFilter('author', item.member!.id) : undefined}
onPostClick={item.post?.id ? () => onAddFilter('post', item.post!.id) : undefined}
- onUnpinClick={commentsPinningEnabled ? () => unpinComment({id: item.id}) : undefined}
+ onUnpinClick={() => unpinComment({id: item.id})}
/>
{item.in_reply_to_snippet && (
diff --git a/apps/admin/src/comments/hooks/use-comments-pinning-enabled.ts b/apps/admin/src/comments/hooks/use-comments-pinning-enabled.ts
deleted file mode 100644
index 7fee5612dd1..00000000000
--- a/apps/admin/src/comments/hooks/use-comments-pinning-enabled.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import {useFeatureFlag} from '@tryghost/admin-x-framework/hooks';
-
-/**
- * Returns true when the `commentsPinning` private labs flag is enabled.
- *
- * Reads the config query so it works on routes that don't mount
- * PostAnalyticsProvider (e.g. the site-wide /ghost#/comments view).
- */
-export const useCommentsPinningEnabled = (): boolean => {
- return useFeatureFlag('commentsPinning');
-};
diff --git a/apps/comments-ui/package.json b/apps/comments-ui/package.json
index 9eb26dea357..019ddb31eb4 100644
--- a/apps/comments-ui/package.json
+++ b/apps/comments-ui/package.json
@@ -1,7 +1,7 @@
{
"name": "@tryghost/comments-ui",
"type": "module",
- "version": "1.5.22",
+ "version": "1.6.0",
"license": "MIT",
"repository": "https://github.com/TryGhost/Ghost",
"author": "Ghost Foundation",
diff --git a/apps/comments-ui/src/components/content/comment.tsx b/apps/comments-ui/src/components/content/comment.tsx
index 30d5e32e631..1ee9dc12d0e 100644
--- a/apps/comments-ui/src/components/content/comment.tsx
+++ b/apps/comments-ui/src/components/content/comment.tsx
@@ -11,7 +11,7 @@ import ThreadedReplies from './threaded-replies';
import {Avatar, BlankAvatar} from './avatar';
import {Comment, OpenCommentForm, useAppContext} from '../../app-context';
import {Transition} from '@headlessui/react';
-import {buildCommentPermalink, findCommentById, formatExplicitTime, getCommentInReplyToSnippet, getMemberNameFromComment} from '../../utils/helpers';
+import {buildCommentPermalink, formatExplicitTime, getCommentInReplyToSnippet, getMemberNameFromComment} from '../../utils/helpers';
import {useRelativeTime} from '../../utils/hooks';
type CommentLayoutVariant = 'root' | 'reply';
@@ -19,12 +19,11 @@ type CommentLayoutVariant = 'root' | 'reply';
type AnimatedCommentProps = {
comment: Comment;
parent?: Comment;
- useThreading?: boolean;
layoutVariant?: CommentLayoutVariant;
isLastSibling?: boolean;
};
-const AnimatedComment: React.FC
> = ({children, comment, parent, useThreading, layoutVariant, isLastSibling}) => {
+const AnimatedComment: React.FC> = ({children, comment, parent, layoutVariant, isLastSibling}) => {
const {commentsIsLoading} = useAppContext();
return (
@@ -40,14 +39,14 @@ const AnimatedComment: React.FC> =
show={true}
appear
>
-
+
{children}
);
};
-export const CommentComponent: React.FC = ({children, comment, parent, useThreading = false, layoutVariant = 'root', isLastSibling = false}) => {
+export const CommentComponent: React.FC = ({children, comment, parent, layoutVariant = 'root', isLastSibling = false}) => {
const {dispatchAction, isAdmin} = useAppContext();
const hasNestedReplies = React.Children.count(children) > 0;
const {showDeletedMessage, showHiddenMessage, showCommentContent} = useCommentVisibility(comment, isAdmin, hasNestedReplies);
@@ -64,9 +63,9 @@ export const CommentComponent: React.FC = ({children, comment, par
}, [comment.id, dispatchAction]);
if (showDeletedMessage || showHiddenMessage) {
- return {children};
+ return {children};
} else if (showCommentContent && !showHiddenMessage) {
- return {children};
+ return {children};
}
return null;
@@ -74,21 +73,9 @@ export const CommentComponent: React.FC = ({children, comment, par
type CommentProps = React.PropsWithChildren;
-const getReplyFormState = (comment: Comment, openCommentForms: OpenCommentForm[], useThreading: boolean) => {
- // Non-threaded replies to replies are displayed inside the top-level comment,
- // so match either the comment id or parent id. Threaded replies render their
- // own reply form inline, so only match the current comment.
- const activeReplyForm = useThreading
- ? openCommentForms.find(f => f.id === comment.id && f.type === 'reply')
- : openCommentForms.find(f => (f.id === comment.id || f.parent_id === comment.id) && f.type === 'reply');
- const visibleReplyForm = activeReplyForm && (useThreading || !activeReplyForm.parent_id || activeReplyForm.parent_id === comment.id)
- ? activeReplyForm
- : undefined;
-
- return {
- activeReplyForm,
- visibleReplyForm
- };
+// Threaded replies render their own reply form inline, so only match the current comment
+const getActiveReplyForm = (comment: Comment, openCommentForms: OpenCommentForm[]) => {
+ return openCommentForms.find(f => f.id === comment.id && f.type === 'reply');
};
const useCommentVisibility = (comment: Comment, admin: boolean, hasNestedReplies?: boolean) => {
@@ -108,9 +95,8 @@ const useCommentVisibility = (comment: Comment, admin: boolean, hasNestedReplies
type PublishedCommentProps = CommentProps & {
openEditMode: () => void;
- useThreading: boolean;
}
-const PublishedComment: React.FC = ({children, comment, parent, openEditMode, useThreading, layoutVariant = 'root', isLastSibling = false}) => {
+const PublishedComment: React.FC = ({children, comment, parent, openEditMode, layoutVariant = 'root', isLastSibling = false}) => {
const {dispatchAction, openCommentForms, isAdmin, commentIdToHighlight, commentIdFromHash} = useAppContext();
const hasNestedReplies = React.Children.count(children) > 0;
@@ -122,7 +108,7 @@ const PublishedComment: React.FC = ({children, comment, p
const editForm = openCommentForms.find(openForm => openForm.id === comment.id && openForm.type === 'edit');
const isInEditMode = !!editForm;
- const {activeReplyForm, visibleReplyForm} = getReplyFormState(comment, openCommentForms, useThreading);
+ const activeReplyForm = getActiveReplyForm(comment, openCommentForms);
// only highlight the reply button for the comment that is being replied to
const highlightReplyButton = !!(activeReplyForm && activeReplyForm.id === comment.id);
@@ -150,7 +136,7 @@ const PublishedComment: React.FC = ({children, comment, p
}, [comment, parent, activeReplyForm, dispatchAction]);
const hasChildReplies = hasNestedReplies || (comment.replies && comment.replies.length > 0);
- const hasReplies = !!visibleReplyForm || hasChildReplies;
+ const hasReplies = !!activeReplyForm || hasChildReplies;
const avatar = ();
const replyFormParent = parent || comment;
const isHighlighted = commentIdFromHash
@@ -162,22 +148,20 @@ const PublishedComment: React.FC = ({children, comment, p
className={hiddenClass}
hasReplies={hasReplies}
isLastSibling={isLastSibling}
- isPinned={comment.pinned}
layoutVariant={layoutVariant}
memberUuid={comment.member?.uuid}
- replies={{children}}
- replyForm={visibleReplyForm ? : null}
- useThreading={useThreading}
+ replies={{children}}
+ replyForm={activeReplyForm ? : null}
>