Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add hidden comments #4557

Merged
merged 10 commits into from
Feb 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions apps/web/src/components/Comment/Feed.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import type { Comment, PublicationsRequest } from '@hey/lens';
import type { FC } from 'react';

import { useHiddenCommentFeedStore } from '@components/Publication';
import QueuedPublication from '@components/Publication/QueuedPublication';
import SinglePublication from '@components/Publication/SinglePublication';
import PublicationsShimmer from '@components/Shared/Shimmer/PublicationsShimmer';
import { ChatBubbleLeftRightIcon } from '@heroicons/react/24/outline';
import {
CommentRankingFilterType,
CustomFiltersType,
HiddenCommentsType,
LimitType,
usePublicationsQuery
} from '@hey/lens';
Expand All @@ -24,6 +26,9 @@ interface FeedProps {

const Feed: FC<FeedProps> = ({ isHidden, publicationId }) => {
const txnQueue = useTransactionStore((state) => state.txnQueue);
const showHiddenComments = useHiddenCommentFeedStore(
(state) => state.showHiddenComments
);
const fetchAndStoreViews = useImpressionsStore(
(state) => state.fetchAndStoreViews
);
Expand All @@ -33,6 +38,9 @@ const Feed: FC<FeedProps> = ({ isHidden, publicationId }) => {
limit: LimitType.TwentyFive,
where: {
commentOn: {
hiddenComments: showHiddenComments
? HiddenCommentsType.HiddenOnly
: HiddenCommentsType.Hide,
id: publicationId,
ranking: { filter: CommentRankingFilterType.Relevant }
},
Expand Down
8 changes: 8 additions & 0 deletions apps/web/src/components/Comment/NoneRelevantFeed.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { Comment, PublicationsRequest } from '@hey/lens';
import type { FC } from 'react';

import { useHiddenCommentFeedStore } from '@components/Publication';
import SinglePublication from '@components/Publication/SinglePublication';
import {
CommentRankingFilterType,
CustomFiltersType,
HiddenCommentsType,
LimitType,
usePublicationsQuery
} from '@hey/lens';
Expand All @@ -17,13 +19,19 @@ interface NoneRelevantFeedProps {
}

const NoneRelevantFeed: FC<NoneRelevantFeedProps> = ({ publicationId }) => {
const showHiddenComments = useHiddenCommentFeedStore(
(state) => state.showHiddenComments
);
const [showMore, setShowMore] = useState(false);

// Variables
const request: PublicationsRequest = {
limit: LimitType.TwentyFive,
where: {
commentOn: {
hiddenComments: showHiddenComments
? HiddenCommentsType.HiddenOnly
: HiddenCommentsType.Hide,
id: publicationId,
ranking: { filter: CommentRankingFilterType.NoneRelevant }
},
Expand Down
118 changes: 118 additions & 0 deletions apps/web/src/components/Publication/Actions/Menu/HideComment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import type {
AnyPublication,
HideCommentRequest,
UnhideCommentRequest
} from '@hey/lens';
import type { ApolloCache } from '@hey/lens/apollo';
import type { FC } from 'react';

import { useHiddenCommentFeedStore } from '@components/Publication';
import { Menu } from '@headlessui/react';
import { CheckCircleIcon, NoSymbolIcon } from '@heroicons/react/24/outline';
import { PUBLICATION } from '@hey/data/tracking';
import { useHideCommentMutation, useUnhideCommentMutation } from '@hey/lens';
import { isMirrorPublication } from '@hey/lib/publicationHelpers';
import stopEventPropagation from '@hey/lib/stopEventPropagation';
import cn from '@hey/ui/cn';
import errorToast from '@lib/errorToast';
import { Leafwatch } from '@lib/leafwatch';
import { toast } from 'react-hot-toast';
import useProfileStore from 'src/store/persisted/useProfileStore';

interface HideCommentProps {
publication: AnyPublication;
}

const HideComment: FC<HideCommentProps> = ({ publication }) => {
const currentProfile = useProfileStore((state) => state.currentProfile);
const targetPublication = isMirrorPublication(publication)
? publication?.mirrorOn
: publication;
const showHiddenComments = useHiddenCommentFeedStore(
(state) => state.showHiddenComments
);

const request: HideCommentRequest | UnhideCommentRequest = {
for: publication.id
};

const updateCache = (cache: ApolloCache<any>) => {
cache.evict({ id: cache.identify(publication) });
};

const onError = (error: any) => {
errorToast(error);
};

const [hideComment] = useHideCommentMutation({
onCompleted: () => {
toast.success('Comment hidden');
Leafwatch.track(PUBLICATION.TOGGLE_HIDE_COMMENT, {
hidden: true,
publication_id: publication.id
});
},
onError,
update: updateCache,
variables: { request }
});

const [unhideComment] = useUnhideCommentMutation({
onCompleted: () => {
toast.success('Comment unhidden');
Leafwatch.track(PUBLICATION.TOGGLE_HIDE_COMMENT, {
hidden: false,
publication_id: publication.id
});
},
onError,
update: updateCache,
variables: { request }
});

const canHideComment = currentProfile?.id !== targetPublication?.by?.id;

if (!canHideComment) {
return null;
}

const toggleHideComment = async () => {
if (showHiddenComments) {
return await unhideComment();
}

return await hideComment();
};

return (
<Menu.Item
as="div"
className={({ active }) =>
cn(
{ 'dropdown-active': active },
'm-2 block cursor-pointer rounded-lg px-2 py-1.5 text-sm'
)
}
onClick={(event) => {
stopEventPropagation(event);
toggleHideComment();
}}
>
<div className="flex items-center space-x-2">
{showHiddenComments ? (
<>
<CheckCircleIcon className="size-4" />
<div>Unhide comment</div>
</>
) : (
<>
<NoSymbolIcon className="size-4" />
<div>Hide comment</div>
</>
)}
</div>
</Menu.Item>
);
};

export default HideComment;
2 changes: 2 additions & 0 deletions apps/web/src/components/Publication/Actions/Menu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import useProfileStore from 'src/store/persisted/useProfileStore';
import Bookmark from './Bookmark';
import CopyPostText from './CopyPostText';
import Delete from './Delete';
import HideComment from './HideComment';
import NotInterested from './NotInterested';
import Report from './Report';
import Share from './Share';
Expand Down Expand Up @@ -52,6 +53,7 @@ const PublicationMenu: FC<PublicationMenuProps> = ({ publication }) => {
<Report publication={publication} />
)}
<NotInterested publication={publication} />
<HideComment publication={publication} />
<Bookmark publication={publication} />
</>
) : null}
Expand Down
49 changes: 47 additions & 2 deletions apps/web/src/components/Publication/FullPublication.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import type { AnyPublication } from '@hey/lens';
import type { FC } from 'react';

import { QueueListIcon } from '@heroicons/react/24/outline';
import formatDate from '@hey/lib/datetime/formatDate';
import getAppName from '@hey/lib/getAppName';
import { isMirrorPublication } from '@hey/lib/publicationHelpers';
import { Tooltip } from '@hey/ui';
import cn from '@hey/ui/cn';
import pushToImpressions from '@lib/pushToImpressions';
import { motion } from 'framer-motion';
import { useEffectOnce } from 'usehooks-ts';

import { useHiddenCommentFeedStore } from '.';
import PublicationActions from './Actions';
import FeaturedGroup from './FeaturedGroup';
import HiddenPublication from './HiddenPublication';
Expand All @@ -17,10 +22,21 @@ import PublicationStats from './PublicationStats';
import PublicationType from './Type';

interface FullPublicationProps {
hasHiddenComments: boolean;
publication: AnyPublication;
}

const FullPublication: FC<FullPublicationProps> = ({ publication }) => {
const FullPublication: FC<FullPublicationProps> = ({
hasHiddenComments,
publication
}) => {
const showHiddenComments = useHiddenCommentFeedStore(
(state) => state.showHiddenComments
);
const setShowHiddenComments = useHiddenCommentFeedStore(
(state) => state.setShowHiddenComments
);

const targetPublication = isMirrorPublication(publication)
? publication?.mirrorOn
: publication;
Expand Down Expand Up @@ -60,7 +76,36 @@ const FullPublication: FC<FullPublicationProps> = ({ publication }) => {
publicationStats={targetPublication.stats}
/>
<div className="divider" />
<PublicationActions publication={targetPublication} showCount />
<div className="flex items-center justify-between">
<PublicationActions publication={targetPublication} showCount />
{hasHiddenComments ? (
<div className="mt-2">
<motion.button
aria-label="Like"
className={cn(
showHiddenComments
? 'text-green-500 outline-green-500 hover:bg-green-300/20'
: 'ld-text-gray-500 outline-gray-400 hover:bg-gray-300/20',
'rounded-full p-1.5 outline-offset-2'
)}
onClick={() => setShowHiddenComments(!showHiddenComments)}
whileTap={{ scale: 0.9 }}
>
<Tooltip
content={
showHiddenComments
? 'Hide hidden comments'
: 'Show hidden comments'
}
placement="top"
withDelay
>
<QueueListIcon className="size-5" />
</Tooltip>
</motion.button>
</div>
) : null}
</div>
</>
)}
</div>
Expand Down
44 changes: 42 additions & 2 deletions apps/web/src/components/Publication/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ import UserProfile from '@components/Shared/UserProfile';
import PublicationStaffTool from '@components/StaffTools/Panels/Publication';
import { APP_NAME } from '@hey/data/constants';
import { PAGEVIEW } from '@hey/data/tracking';
import { TriStateValue, usePublicationQuery } from '@hey/lens';
import {
HiddenCommentsType,
LimitType,
TriStateValue,
usePublicationQuery,
usePublicationsQuery
} from '@hey/lens';
import getProfile from '@hey/lib/getProfile';
import { isMirrorPublication } from '@hey/lib/publicationHelpers';
import { Card, GridItemEight, GridItemFour, GridLayout } from '@hey/ui';
Expand All @@ -24,12 +30,25 @@ import { useProfileRestriction } from 'src/store/non-persisted/useProfileRestric
import { useFeatureFlagsStore } from 'src/store/persisted/useFeatureFlagsStore';
import useProfileStore from 'src/store/persisted/useProfileStore';
import { useEffectOnce } from 'usehooks-ts';
import { create } from 'zustand';

import FullPublication from './FullPublication';
import OnchainMeta from './OnchainMeta';
import RelevantPeople from './RelevantPeople';
import PublicationPageShimmer from './Shimmer';

interface HiddenCommentFeedState {
setShowHiddenComments: (show: boolean) => void;
showHiddenComments: boolean;
}

export const useHiddenCommentFeedStore = create<HiddenCommentFeedState>(
(set) => ({
setShowHiddenComments: (show) => set({ showHiddenComments: show }),
showHiddenComments: false
})
);

const ViewPublication: NextPage = () => {
const currentProfile = useProfileStore((state) => state.currentProfile);
const { isSuspended } = useProfileRestriction();
Expand All @@ -52,6 +71,23 @@ const ViewPublication: NextPage = () => {
variables: { request: { forId: id } }
});

const { data: comments } = usePublicationsQuery({
skip: !id,
variables: {
request: {
limit: LimitType.Ten,
where: {
commentOn: {
hiddenComments: HiddenCommentsType.HiddenOnly,
id
}
}
}
}
});

const hasHiddenComments = (comments?.publications.items.length || 0) > 0;

if (!isReady || loading) {
return <PublicationPageShimmer />;
}
Expand Down Expand Up @@ -80,7 +116,11 @@ const ViewPublication: NextPage = () => {
/>
<GridItemEight className="space-y-5">
<Card>
<FullPublication key={publication?.id} publication={publication} />
<FullPublication
hasHiddenComments={hasHiddenComments}
key={publication?.id}
publication={publication}
/>
</Card>
{currentProfile &&
!publication.isHidden &&
Expand Down
1 change: 1 addition & 0 deletions packages/data/tracking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export const PUBLICATION = {
REPORT: 'Report publication',
SHARE: 'Share publication',
TOGGLE_BOOKMARK: 'Toggle publication bookmark',
TOGGLE_HIDE_COMMENT: 'Toggle publication hide comment',
TOGGLE_NOT_INTERESTED: 'Toggle publication not interested',
TRANSLATE: 'Translate publication',
UNDO_MIRROR: 'Undo mirror publication',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mutation HideComment($request: HideCommentRequest!) {
hideComment(request: $request)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mutation UnhideComment($request: UnhideCommentRequest!) {
unhideComment(request: $request)
}
Loading
Loading