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: Report and block users #4056

Merged
merged 30 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8707453
feat: ReportUserModal (#4051)
AmarTrebinjac Jan 9, 2025
bf10e3a
feat: Add block and report to user profile (#4054)
AmarTrebinjac Jan 9, 2025
dc04928
Merge branch 'main' into MI-655-report-and-block-user
AmarTrebinjac Jan 9, 2025
4b3a1e4
Merge branch 'main' into MI-655-report-and-block-user
ilasw Jan 13, 2025
8961302
feat: Block, report, share on profile available for everyone (#4059)
AmarTrebinjac Jan 14, 2025
303ed50
fix: Should not show following when blocked (#4064)
AmarTrebinjac Jan 14, 2025
5188e43
fix: No longer open report modal when reporting user (#4069)
AmarTrebinjac Jan 16, 2025
13bf6b0
Merge branch 'main' into MI-655-report-and-block-user
AmarTrebinjac Jan 16, 2025
6cb0889
feat: add block user option on post context menu (#4053)
ilasw Jan 16, 2025
1ca01ac
Merge branch 'main' into MI-655-report-and-block-user
AmarTrebinjac Jan 16, 2025
83cb918
update hateful key
AmarTrebinjac Jan 16, 2025
f04673f
Update packages/shared/src/components/modals/report/ReportUserModal.tsx
AmarTrebinjac Jan 17, 2025
4975dfa
fix: cache invalidation (#4078)
AmarTrebinjac Jan 17, 2025
667c867
move query invalidation
AmarTrebinjac Jan 17, 2025
6639d50
remove unused hook
AmarTrebinjac Jan 17, 2025
fc15e64
remove follow button on profile when blocked
AmarTrebinjac Jan 17, 2025
f783008
feat: Remove default add btn in advanced settings, add block btn on u…
AmarTrebinjac Jan 17, 2025
5048c40
invalidate specific feed
AmarTrebinjac Jan 17, 2025
3186941
undo feed key
AmarTrebinjac Jan 17, 2025
3133439
use onsettled to close
AmarTrebinjac Jan 17, 2025
034cf24
Merge branch 'main' into MI-655-report-and-block-user
AmarTrebinjac Jan 17, 2025
e9372fa
add author block
AmarTrebinjac Jan 17, 2025
b18fc2f
use username instead of name
AmarTrebinjac Jan 17, 2025
b91a7b9
try invalidate userblocked request key
AmarTrebinjac Jan 17, 2025
21b0e07
use correct username
AmarTrebinjac Jan 17, 2025
aa9ff36
remove unnecessary feed invalidation
AmarTrebinjac Jan 17, 2025
b9e48ed
fix: block button inside link in source list (#4077)
ilasw Jan 17, 2025
78fa6d8
Merge branch 'main' into MI-655-report-and-block-user
AmarTrebinjac Jan 20, 2025
7552d6d
fix: invalidation of blocked users for settings
capJavert Jan 20, 2025
a3e9f3e
Merge branch 'main' into MI-655-report-and-block-user
AmarTrebinjac Jan 20, 2025
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
15 changes: 11 additions & 4 deletions packages/shared/src/components/CustomFeedOptionsMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type CustomFeedOptionsMenuProps = {
onUndo?: (feedId: string) => void;
className?: string;
shareProps: UseShareOrCopyLinkProps;
additionalOptions?: MenuItemProps[];
};

const CustomFeedOptionsMenu = ({
Expand All @@ -28,6 +29,7 @@ const CustomFeedOptionsMenu = ({
onAdd,
onUndo,
onCreateNewFeed,
additionalOptions = [],
}: CustomFeedOptionsMenuProps): ReactElement => {
const { showPlusSubscription } = usePlusSubscription();
const { openModal } = useLazyModal();
Expand Down Expand Up @@ -57,14 +59,17 @@ const CustomFeedOptionsMenu = ({
label: 'Share',
action: () => onShareOrCopyLink(),
},
{
];

if (showPlusSubscription) {
options.push({
icon: <MenuIcon Icon={HashtagIcon} />,
label: 'Add to custom feed',
action: handleOpenModal,
},
];
});
}

if (!showPlusSubscription) {
if (additionalOptions.length === 0 && !showPlusSubscription) {
AmarTrebinjac marked this conversation as resolved.
Show resolved Hide resolved
return (
<Button
variant={ButtonVariant.Float}
Expand All @@ -75,6 +80,8 @@ const CustomFeedOptionsMenu = ({
);
}

options.push(...additionalOptions);

return (
<>
<Button
Expand Down
4 changes: 2 additions & 2 deletions packages/shared/src/components/Feed.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ describe('Feed logged in', () => {
);
expect(data).toBeTruthy();
});
const contextBtn = await screen.findByText("Don't show posts from Echo JS");
const contextBtn = await screen.findByText('Block Echo JS');
fireEvent.click(contextBtn);
await waitForNock();
await waitFor(() => expect(mutationCalled).toBeTruthy());
Expand Down Expand Up @@ -673,7 +673,7 @@ describe('Feed logged in', () => {
);
expect(data).toBeTruthy();
});
const contextBtn = await screen.findByText('Show posts from Echo JS');
const contextBtn = await screen.findByText('Unblock Echo JS');

await waitFor(async () => {
fireEvent.click(contextBtn);
Expand Down
123 changes: 96 additions & 27 deletions packages/shared/src/components/PostOptionsMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,30 @@ import classNames from 'classnames';
import useFeedSettings from '../hooks/useFeedSettings';
import useReportPost from '../hooks/useReportPost';
import type { Post } from '../graphql/posts';
import { UserVote, isVideoPost } from '../graphql/posts';
import { isVideoPost, UserVote } from '../graphql/posts';
import {
TrashIcon,
HammerIcon,
EyeIcon,
AddUserIcon,
BellAddIcon,
BellSubscribedIcon,
BlockIcon,
FlagIcon,
PlusIcon,
EditIcon,
UpvoteIcon,
DownvoteIcon,
SendBackwardIcon,
BringForwardIcon,
PinIcon,
BellSubscribedIcon,
ShareIcon,
DownvoteIcon,
EditIcon,
EyeIcon,
FlagIcon,
FolderIcon,
HammerIcon,
MiniCloseIcon,
MinusIcon,
BellAddIcon,
AddUserIcon,
PinIcon,
PlusIcon,
RemoveUserIcon,
FolderIcon,
SendBackwardIcon,
ShareIcon,
ShieldIcon,
ShieldWarningIcon,
TrashIcon,
UpvoteIcon,
} from './icons';
import type { ReportedCallback } from './modals';
import useTagAndSource from '../hooks/useTagAndSource';
Expand All @@ -50,7 +50,10 @@ import { generateQueryKey } from '../lib/query';
import AuthContext from '../contexts/AuthContext';
import { LogEvent, Origin } from '../lib/log';
import { usePostMenuActions } from '../hooks/usePostMenuActions';
import usePostById, { getPostByIdKey } from '../hooks/usePostById';
import usePostById, {
getPostByIdKey,
invalidatePostCacheById,
} from '../hooks/usePostById';
import { useLazyModal } from '../hooks/useLazyModal';
import { LazyModal } from './modals/common/types';
import { labels } from '../lib';
Expand All @@ -63,7 +66,10 @@ import { useBookmarkReminder } from '../hooks/notifications';
import { BookmarkReminderIcon } from './icons/Bookmark/Reminder';
import { useSourceActionsFollow } from '../hooks/source/useSourceActionsFollow';
import { useContentPreference } from '../hooks/contentPreference/useContentPreference';
import { ContentPreferenceType } from '../graphql/contentPreference';
import {
ContentPreferenceStatus,
ContentPreferenceType,
} from '../graphql/contentPreference';
import { isFollowingContent } from '../hooks/contentPreference/types';
import { useIsSpecialUser } from '../hooks/auth/useIsSpecialUser';
import { useActiveFeedContext } from '../contexts';
Expand Down Expand Up @@ -91,6 +97,26 @@ export interface PostOptionsMenuProps {
allowPin?: boolean;
}

const getBlockLabel = (
name: string,
{ isCustomFeed, isBlocked }: Record<'isCustomFeed' | 'isBlocked', boolean>,
) => {
const blockLabel = {
global: {
block: `Block ${name}`,
unblock: `Unblock ${name}`,
},
feed: {
block: `Remove ${name} from this feed`,
unblock: `Add ${name} to this feed`,
},
};

return blockLabel[isCustomFeed ? 'feed' : 'global'][
isBlocked ? 'unblock' : 'block'
];
};

export default function PostOptionsMenu({
postIndex,
post: initialPost,
Expand Down Expand Up @@ -135,8 +161,7 @@ export default function PostOptionsMenu({
const { logEvent } = useContext(LogContext);
const { hidePost, unhidePost } = useReportPost();
const { openSharePost } = useSharePost(origin);
const { follow, unfollow } = useContentPreference();

const { follow, unfollow, unblock, block } = useContentPreference();
const { openModal } = useLazyModal();

const {
Expand All @@ -156,6 +181,8 @@ export default function PostOptionsMenu({
(excludedSource) => excludedSource.id === post?.source?.id,
);
}, [feedSettings?.excludeSources, post?.source?.id]);
const isBlockedAuthor =
post?.author?.contentPreference?.status === ContentPreferenceStatus.Blocked;

const shouldShowSubscribe =
isLoggedIn &&
Expand Down Expand Up @@ -456,6 +483,7 @@ export default function PostOptionsMenu({
const shouldShowFollow =
!useIsSpecialUser({ userId: post?.author?.id }) &&
post?.author &&
!isBlockedAuthor &&
isLoggedIn;

if (shouldShowFollow) {
Expand Down Expand Up @@ -492,13 +520,54 @@ export default function PostOptionsMenu({
});
}

postOptions.push({
icon: <MenuIcon Icon={BlockIcon} />,
label: isSourceBlocked
? `Show posts from ${post?.source?.name}`
: `Don't show posts from ${post?.source?.name}`,
action: isSourceBlocked ? onUnblockSourceClick : onBlockSourceClick,
});
if (post?.source?.name) {
postOptions.push({
icon: <MenuIcon Icon={BlockIcon} />,
label: getBlockLabel(post.source.name, {
isCustomFeed,
isBlocked: isSourceBlocked,
}),
action: isSourceBlocked ? onUnblockSourceClick : onBlockSourceClick,
});
}

if (post?.author && post?.author?.id !== user?.id) {
postOptions.push({
icon: <MenuIcon Icon={BlockIcon} />,
label: getBlockLabel(post.author.name, {
isCustomFeed,
isBlocked: isBlockedAuthor,
}),
action: async () => {
const params = {
id: post.author.id,
entity: ContentPreferenceType.User,
entityName: post.author.name,
feedId: router.query.slugOrId ? `${router.query.slugOrId}` : null,
};

if (isBlockedAuthor) {
await unblock(params);
} else {
await block({
...params,
opts: {
hideToast: true,
},
});
await showMessageAndRemovePost(
`🚫 ${post.author.name} has been ${
isCustomFeed ? 'removed' : 'blocked'
}`,
postIndex,
() => unblock(params),
);
}

invalidatePostCacheById(client, post.id);
},
});
}

if (video && isVideoPost(post)) {
const isEnabled = checkSettingsEnabledState(video.id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,15 @@ export const FollowButton = ({
return null;
}

const isFollowing = [
ContentPreferenceStatus.Subscribed,
ContentPreferenceStatus.Follow,
].includes(currentStatus);

return (
<div className={classNames('relative z-1 inline-flex gap-2', className)}>
<SourceActionsFollow
isSubscribed={!!currentStatus}
isSubscribed={isFollowing}
AmarTrebinjac marked this conversation as resolved.
Show resolved Hide resolved
isFetching={isLoading}
variant={variant}
onClick={(e) => {
Expand All @@ -108,7 +113,7 @@ export const FollowButton = ({
}}
copyType={copyType}
/>
{!!currentStatus && showSubscribe && (
{isFollowing && showSubscribe && (
<SourceActionsNotify
haveNotificationsOn={
currentStatus === ContentPreferenceStatus.Subscribed
Expand Down
8 changes: 8 additions & 0 deletions packages/shared/src/components/modals/common.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,13 @@ const AddToCustomFeedModal = dynamic(
),
);

const ReportUserModal = dynamic(
() =>
import(
/* webpackChunkName: "reportUserModal" */ './report/ReportUserModal'
),
);

export const modals = {
[LazyModal.SquadMember]: SquadMemberModal,
[LazyModal.UpvotedPopup]: UpvotedPopupModal,
Expand Down Expand Up @@ -250,6 +257,7 @@ export const modals = {
[LazyModal.ClickbaitShield]: ClickbaitShieldModal,
[LazyModal.MoveBookmark]: MoveBookmarkModal,
[LazyModal.AddToCustomFeed]: AddToCustomFeedModal,
[LazyModal.ReportUser]: ReportUserModal,
};

type GetComponentProps<T> = T extends
Expand Down
1 change: 1 addition & 0 deletions packages/shared/src/components/modals/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export enum LazyModal {
ClickbaitShield = 'clickbaitShield',
MoveBookmark = 'moveBookmark',
AddToCustomFeed = 'addToCustomFeed',
ReportUser = 'reportUser',
}

export type ModalTabItem = {
Expand Down
Loading
Loading