feat(reports): add server-driven report flows (#3330)

This commit is contained in:
Hampus authored and GitHub committed 2026-10-09 01:38:00 +02:00
1 parent bc17922b02
commit ece622e800
471 files changed
+56262 -35932

No files matched your search

@@ -27,10 +27,10 @@ import {
BAN_ACTION_DESCRIPTOR,
BLOCK_DESCRIPTOR,
REMOVE_TIMEOUT_DESCRIPTOR,
REPORT_USER_DESCRIPTOR,
REPORT_USER_PROFILE_DESCRIPTOR,
TIMEOUT_DESCRIPTOR,
} from '@app/features/moderation/utils/ModerationMessageDescriptors';
import {openReportMessageModal, openReportUserModal} from '@app/features/moderation/utils/ReportActionUtils';
import {openReportMessageModal, openReportUserProfileModal} from '@app/features/moderation/utils/ReportActionUtils';
import {useRoleHierarchy} from '@app/features/permissions/hooks/useRoleHierarchy';
import Permission from '@app/features/permissions/state/Permission';
import * as PermissionUtils from '@app/features/permissions/utils/PermissionUtils';
@@ -91,6 +91,7 @@ interface UserProfileActionsSheetProps {
guildId?: string;
guildMember?: GuildMember | null;
message?: Message;
showReportUserProfile?: boolean;
}
export const UserProfileActionsSheet: React.FC<UserProfileActionsSheetProps> = observer(
@@ -105,6 +106,7 @@ export const UserProfileActionsSheet: React.FC<UserProfileActionsSheetProps> = o
guildId,
guildMember,
message,
showReportUserProfile = false,
}) => {
const {i18n} = useLingui();
const relationshipType = Relationships.getRelationship(user.id)?.type;
@@ -241,8 +243,8 @@ export const UserProfileActionsSheet: React.FC<UserProfileActionsSheetProps> = o
)),
);
};
const handleReportUser = () => {
ModalCommands.runAfterBottomSheetClose(onClose, () => openReportUserModal({i18n, user, guildId, message}));
const handleReportUserProfile = () => {
ModalCommands.runAfterBottomSheetClose(onClose, () => openReportUserProfileModal({user, guildId}));
};
const handleReportMessage = () => {
if (!message || !canReportMessage(message)) {
@@ -377,12 +379,16 @@ export const UserProfileActionsSheet: React.FC<UserProfileActionsSheetProps> = o
},
]
: []),
{
icon: <FlagIcon className={styles.icon} data-flx="user.user-profile-actions-sheet.icon--12" />,
label: i18n._(REPORT_USER_DESCRIPTOR),
onClick: handleReportUser,
danger: true,
},
...(showReportUserProfile
? [
{
icon: <FlagIcon className={styles.icon} data-flx="user.user-profile-actions-sheet.icon--12" />,
label: i18n._(REPORT_USER_PROFILE_DESCRIPTOR),
onClick: handleReportUserProfile,
danger: true,
},
]
: []),
];
if (!user.system) {
if (relationshipType !== RelationshipTypes.BLOCKED) {
@@ -952,6 +952,7 @@ const UserProfileMobileSheetContent: React.FC<UserProfileMobileSheetContentProps
onToggleProfileView={() => setShowGlobalProfile(!showGlobalProfile)}
guildId={guildId}
guildMember={guildMember}
showReportUserProfile
data-flx="user.user-profile-mobile-sheet.user-profile-mobile-sheet-content.user-profile-actions-sheet"
/>
<ExpressionInfoBottomSheet
@@ -17,8 +17,11 @@ import {
START_VOICE_CALL_DESCRIPTOR,
} from '@app/features/i18n/utils/CommonMessageDescriptors';
import GuildMembers from '@app/features/member/state/GuildMembers';
import {BLOCK_DESCRIPTOR, REPORT_USER_DESCRIPTOR} from '@app/features/moderation/utils/ModerationMessageDescriptors';
import {openReportUserModal} from '@app/features/moderation/utils/ReportActionUtils';
import {
BLOCK_DESCRIPTOR,
REPORT_USER_PROFILE_DESCRIPTOR,
} from '@app/features/moderation/utils/ModerationMessageDescriptors';
import {openReportUserProfileModal} from '@app/features/moderation/utils/ReportActionUtils';
import {Logger} from '@app/features/platform/utils/AppLogger';
import MemberPresenceSubscription from '@app/features/presence/state/MemberPresenceSubscription';
import Relationships from '@app/features/relationship/state/Relationships';
@@ -339,8 +342,8 @@ export const UserProfileModal: UserProfileModalComponent = observer(
showDmActionErrorModal(error);
}
};
const handleReportUser = () => {
openReportUserModal({i18n, user: displayUser, guildId});
const handleReportUserProfile = () => {
openReportUserProfileModal({user: displayUser, guildId});
};
const handleCopyFluxerTag = () => {
TextCopyCommands.copy(i18n, displayUser.tag, true);
@@ -491,13 +494,13 @@ export const UserProfileModal: UserProfileModalComponent = observer(
<MenuItem
icon={<FlagIcon data-flx="user.user-profile-modal.open-more-options-menu.flag-icon" />}
onClick={() => {
handleReportUser();
handleReportUserProfile();
props.onClose();
}}
danger
data-flx="user.user-profile-modal.open-more-options-menu.menu-item.report-user"
data-flx="user.user-profile-modal.open-more-options-menu.menu-item.report-user-profile"
>
{i18n._(REPORT_USER_DESCRIPTOR)}
{i18n._(REPORT_USER_PROFILE_DESCRIPTOR)}
</MenuItem>
{renderBlockMenuItem(props.onClose)}
</MenuGroup>