// SPDX-License-Identifier: AGPL-3.0-or-later import {PRODUCT_NAME} from '@app/features/app/config/I18nDisplayConstants'; import {openClaimAccountModal} from '@app/features/auth/components/modals/ClaimAccountModal'; import styles from '@app/features/channel/components/barriers/BarrierComponents.module.css'; import wrapperStyles from '@app/features/channel/components/textarea/InputWrapper.module.css'; import textareaStyles from '@app/features/channel/components/textarea/TextareaInput.module.css'; import {CLAIM_ACCOUNT_DESCRIPTOR, VERIFY_EMAIL_DESCRIPTOR} from '@app/features/i18n/utils/CommonMessageDescriptors'; import {unblockUser} from '@app/features/relationship/utils/RelationshipActionUtils'; import {remFromPx} from '@app/features/theme/layout/RemFromPx'; import {Button} from '@app/features/ui/button/Button'; import * as ModalCommands from '@app/features/ui/commands/ModalCommands'; import {modal} from '@app/features/ui/commands/ModalCommands'; import {PhoneAddModal} from '@app/features/user/components/modals/PhoneAddModal'; import {UserSettingsModal} from '@app/features/user/components/modals/UserSettingsModal'; import {msg} from '@lingui/core/macro'; import {Trans, useLingui} from '@lingui/react/macro'; import { ClockIcon, EnvelopeSimpleIcon, InfoIcon, PhoneIcon, ProhibitIcon, ShieldWarningIcon, TimerIcon, WarningCircleIcon, } from '@phosphor-icons/react'; import {clsx} from 'clsx'; import {observer} from 'mobx-react-lite'; import {useEffect, useState} from 'react'; interface BarrierProps { onAction?: () => void; } interface TimedBarrierProps extends BarrierProps { initialTimeRemaining?: number; } interface BarrierBaseProps { message: React.ReactNode; action?: React.ReactNode; icon: React.ReactElement; } const SYSTEM_ANNOUNCEMENTS_FROM_STAFF_DESCRIPTOR = msg({ message: "System announcements from {productName} staff. You can't reply here.", comment: 'Read-only system DM barrier message. productName is the Fluxer product name.', }); const BarrierBase = observer(({message, action, icon}: BarrierBaseProps) => { const hasAction = Boolean(action); return (
{icon}
{message}
{hasAction && (
{action}
)}
); }); const CountdownTimer = observer(({initialTime}: {initialTime: number}) => { const [timeRemaining, setTimeRemaining] = useState(initialTime); useEffect(() => { if (timeRemaining <= 0) return; const interval = setInterval(() => { setTimeRemaining((prev) => { if (prev <= 1000) { clearInterval(interval); return 0; } return prev - 1000; }); }, 1000); return () => clearInterval(interval); }, []); const formatTime = (ms: number): string => { const totalSeconds = Math.ceil(ms / 1000); const minutes = Math.floor(totalSeconds / 60); const seconds = totalSeconds % 60; return `${minutes}:${seconds.toString().padStart(2, '0')}`; }; if (timeRemaining <= 0) { return null; } return (
{formatTime(timeRemaining)}
); }); export const UnclaimedAccountBarrier = observer(({onAction}: BarrierProps) => { const {i18n} = useLingui(); return ( You need to claim your account to send messages in this community.} icon={ } action={ } data-flx="channel.barriers.barrier-components.unclaimed-account-barrier.barrier-base" /> ); }); export const UnverifiedEmailBarrier = observer(({onAction}: BarrierProps) => { const {i18n} = useLingui(); return ( You need to verify your email to send messages in this community.} icon={ } action={ } data-flx="channel.barriers.barrier-components.unverified-email-barrier.barrier-base" /> ); }); export const AccountTooNewBarrier = observer(({initialTimeRemaining = 5 * 60 * 1000}: TimedBarrierProps) => { return ( Your account is too new to send messages in this community.} icon={ } action={ initialTimeRemaining > 0 ? ( ) : null } data-flx="channel.barriers.barrier-components.account-too-new-barrier.barrier-base" /> ); }); export const NotMemberLongEnoughBarrier = observer(({initialTimeRemaining = 10 * 60 * 1000}: TimedBarrierProps) => { return ( You haven't been a member of this community long enough to send messages.} icon={ } action={ initialTimeRemaining > 0 ? ( ) : null } data-flx="channel.barriers.barrier-components.not-member-long-enough-barrier.barrier-base" /> ); }); export const NoPhoneNumberBarrier = observer(({onAction}: BarrierProps) => { return ( You need to verify a phone number to send messages in this community.} icon={ } action={ } data-flx="channel.barriers.barrier-components.no-phone-number-barrier.barrier-base" /> ); }); export const SendMessageDisabledBarrier = observer(() => { return ( Messaging is temporarily paused in this community.} icon={ } action={null} data-flx="channel.barriers.barrier-components.send-message-disabled-barrier.barrier-base" /> ); }); export const TimeoutBarrier = observer(({initialTimeRemaining = 0}: TimedBarrierProps) => { return ( You're timed out. Messaging, reactions, and voice are paused until the timeout expires.} icon={ } action={ initialTimeRemaining > 0 ? ( ) : null } data-flx="channel.barriers.barrier-components.timeout-barrier.barrier-base" /> ); }); export const DefaultBarrier = observer(() => { return ( You can't send messages in this community.} icon={ } action={null} data-flx="channel.barriers.barrier-components.default-barrier.barrier-base" /> ); }); export const SystemDmBarrier = observer(() => { const {i18n} = useLingui(); return ( } action={null} data-flx="channel.barriers.barrier-components.system-dm-barrier.barrier-base" /> ); }); interface BlockedUserBarrierProps extends BarrierProps { userId: string; username: string; } export const BlockedUserBarrier = observer(({userId, username, onAction}: BlockedUserBarrierProps) => { const {i18n} = useLingui(); const handleUnblock = async () => { await unblockUser(i18n, userId); onAction?.(); }; return ( You have blocked {username}. Unblock them to send messages.} icon={ } action={ } data-flx="channel.barriers.barrier-components.blocked-user-barrier.barrier-base" /> ); }); export const UnclaimedDMBarrier = observer(({onAction}: BarrierProps) => { const {i18n} = useLingui(); return ( You need to claim your account to send direct messages.} icon={ } action={ } data-flx="channel.barriers.barrier-components.unclaimed-dm-barrier.barrier-base" /> ); });