// SPDX-License-Identifier: AGPL-3.0-or-later import {ConfirmModal} from '@app/features/app/components/dialogs/ConfirmModal'; import Authentication from '@app/features/auth/state/Authentication'; import styles from '@app/features/channel/components/ChannelReplyBar.module.css'; import wrapperStyles from '@app/features/channel/components/textarea/InputWrapper.module.css'; import type {Channel} from '@app/features/channel/models/Channel'; import Guilds from '@app/features/guild/state/Guilds'; import * as MessageCommands from '@app/features/messaging/commands/MessageCommands'; import type {Message} from '@app/features/messaging/models/MessagingMessage'; import {goToMessage} from '@app/features/messaging/utils/MessageNavigator'; import { getReplyMentionPreferenceConflict, resolveMentionReplyPreference, } from '@app/features/notification/utils/MentionReplyPreferenceUtils'; import * as ModalCommands from '@app/features/ui/commands/ModalCommands'; import {modal} from '@app/features/ui/commands/ModalCommands'; import FocusRing from '@app/features/ui/focus_ring/FocusRing'; import {Tooltip} from '@app/features/ui/tooltip/Tooltip'; import * as NicknameUtils from '@app/features/user/utils/NicknameUtils'; import {msg} from '@lingui/core/macro'; import {Trans, useLingui} from '@lingui/react/macro'; import {AtIcon, XCircleIcon} from '@phosphor-icons/react'; import {clsx} from 'clsx'; import {observer} from 'mobx-react-lite'; const OVERRIDE_MENTION_PREFERENCE_DESCRIPTOR = msg({ message: 'Override mention preference?', comment: 'Title of the confirmation alert shown when sending a reply against the recipient mention-on-reply preference.', }); const PREFERS_TO_BE_MENTIONED_ON_REPLIES_SEND_WITHOUT_DESCRIPTOR = msg({ message: '{authorNickname} prefers to be @mentioned on replies. Send without the mention anyway?', comment: 'Confirmation body when the recipient prefers @mentions on replies but the user disabled it. authorNickname is the recipient display name. The @ character is literal.', }); const PREFERS_REPLIES_WITHOUT_AN_MENTION_SEND_WITH_THE_DESCRIPTOR = msg({ message: '{authorNickname} prefers replies without an @mention. Send with the mention anyway?', comment: 'Confirmation body when the recipient prefers no @mention on replies but the user enabled it. authorNickname is the recipient display name. The @ character is literal.', }); const IGNORE_MENTION_PREFERENCE_DESCRIPTOR = msg({ message: 'Ignore preference', comment: 'Confirm button label on the override-mention-preference alert.', }); const CLICK_TO_DISABLE_PINGING_THE_USER_YOU_RE_DESCRIPTOR = msg({ message: "Click to disable pinging the user you're replying to.", comment: 'Tooltip on the reply bar mention toggle when mention-on-reply is currently on.', }); const CLICK_TO_ENABLE_PINGING_THE_USER_YOU_RE_DESCRIPTOR = msg({ message: "Click to enable pinging the user you're replying to.", comment: 'Tooltip on the reply bar mention toggle when mention-on-reply is currently off.', }); const MENTION_REPLIED_USER_DESCRIPTOR = msg({ message: 'Mention replied user', comment: 'Label next to the mention toggle in the reply bar.', }); const ON_DESCRIPTOR = msg({ message: 'On', comment: 'On state suffix appended to the reply bar mention toggle label.', }); const OFF_DESCRIPTOR = msg({ message: 'Off', comment: 'Off state suffix appended to the reply bar mention toggle label.', }); const CANCEL_REPLY_DESCRIPTOR = msg({ message: 'Cancel reply', comment: 'Accessible label and tooltip for the cancel-reply button in the reply bar.', }); const JUMP_TO_REPLIED_MESSAGE_FROM_DESCRIPTOR = msg({ message: 'Jump to the message from {authorNickname}', comment: 'Accessible label for the reply bar target button. Preserve {authorNickname}; it is inserted by code.', }); interface ReplyBarProps { replyingMessageObject: Message; shouldReplyMention: boolean; setShouldReplyMention: (mentioning: boolean) => void; channel: Channel; } export const ReplyBar = observer(function ReplyBar({ replyingMessageObject, shouldReplyMention: initialShouldMention, setShouldReplyMention, channel, }: ReplyBarProps) { const {i18n} = useLingui(); const guild = Guilds.getGuild(channel.guildId ?? ''); const currentUserId = Authentication.currentUserId; const isOwnMessage = replyingMessageObject.author.id === currentUserId; const isInGuild = channel.guildId != null; const isWebhook = replyingMessageObject.webhookId != null; const canMention = !isOwnMessage && isInGuild && !isWebhook; const shouldMention = initialShouldMention && canMention; const authorNickname = NicknameUtils.getNickname(replyingMessageObject.author, guild?.id); const handleStopReply = () => { MessageCommands.stopReply(channel.id); }; const handleJumpToReplyTarget = () => { goToMessage(replyingMessageObject.channelId, replyingMessageObject.id); }; const toggleMention = () => { const next = !shouldMention; const preference = resolveMentionReplyPreference({ authorId: replyingMessageObject.author.id, guildId: channel.guildId, }); const conflict = getReplyMentionPreferenceConflict(next, preference); if (conflict) { ModalCommands.push( modal(() => ( setShouldReplyMention(next)} data-flx="channel.reply-bar.toggle-mention.confirm-modal" /> )), ); return; } setShouldReplyMention(next); }; return (
{canMention && ( )}
); });