// @flow import React from 'react'; import classnames from 'classnames'; import parseDuration from 'parse-duration'; import Button from 'component/button'; import ChannelThumbnail from 'component/channelThumbnail'; import ClaimPreview from 'component/claimPreview'; import Card from 'component/common/card'; import { FormField } from 'component/common/form'; import Icon from 'component/common/icon'; import * as ICONS from 'constants/icons'; import usePersistedState from 'effects/use-persisted-state'; import { Modal } from 'modal/modal'; const TAB = { PERSONAL: 'personal', MODERATOR: 'moderator', ADMIN: 'admin', }; const BLOCK = { PERMANENT: 'permanent', TIMEOUT: 'timeout', }; type Props = { contentUri: string, commenterUri: string, // --- select --- activeChannelClaim: ?ChannelClaim, contentClaim: ?Claim, moderationDelegatorsById: { [string]: { global: boolean, delegators: { name: string, claimId: string } } }, // --- perform --- closeModal: () => void, commentModBlock: (string, ?number) => void, commentModBlockAsAdmin: (string, string, ?number) => void, commentModBlockAsModerator: (string, string, string, ?number) => void, }; export default function ModalBlockChannel(props: Props) { const { commenterUri, activeChannelClaim, contentClaim, moderationDelegatorsById, closeModal, commentModBlock, commentModBlockAsAdmin, commentModBlockAsModerator, } = props; const contentChannelClaim = !contentClaim ? null : contentClaim.value_type === 'channel' ? contentClaim : contentClaim.signing_channel && contentClaim.is_channel_signature_valid ? contentClaim.signing_channel : null; const activeModeratorInfo = activeChannelClaim && moderationDelegatorsById[activeChannelClaim.claim_id]; const activeChannelIsAdmin = activeChannelClaim && activeModeratorInfo && activeModeratorInfo.global; const activeChannelIsModerator = activeChannelClaim && contentChannelClaim && activeModeratorInfo && Object.values(activeModeratorInfo.delegators).includes(contentChannelClaim.claim_id); const [tab, setTab] = usePersistedState('ModalBlockChannel:tab', TAB.PERSONAL); const [blockType, setBlockType] = usePersistedState('ModalBlockChannel:blockType', BLOCK.PERMANENT); const [timeoutInput, setTimeoutInput] = usePersistedState('ModalBlockChannel:timeoutInput', '10m'); const [timeoutInputErr, setTimeoutInputErr] = React.useState(''); const [timeoutSec, setTimeoutSec] = React.useState(-1); const isPersonalTheOnlyTab = !activeChannelIsModerator && !activeChannelIsAdmin; const isTimeoutAvail = contentClaim && contentClaim.is_my_output; const blockButtonDisabled = blockType === BLOCK.TIMEOUT && timeoutSec < 1; // ************************************************************************** // ************************************************************************** // Check settings validity on mount. React.useEffect(() => { if ( isPersonalTheOnlyTab || (tab === TAB.MODERATOR && !activeChannelIsModerator) || (tab === TAB.ADMIN && !activeChannelIsAdmin) ) { setTab(TAB.PERSONAL); } if (!isTimeoutAvail && blockType === BLOCK.TIMEOUT) { setBlockType(BLOCK.PERMANENT); } }, []); // eslint-disable-line react-hooks/exhaustive-deps // 'timeoutInput' to 'timeoutSec' conversion. React.useEffect(() => { const setInvalid = (errMsg: string) => { if (timeoutSec !== -1) { setTimeoutSec(-1); } if (!timeoutInputErr) { setTimeoutInputErr(errMsg); } }; const setValid = (seconds) => { if (seconds !== timeoutSec) { setTimeoutSec(seconds); } if (timeoutInputErr) { setTimeoutInputErr(''); } }; const ONE_HUNDRED_YEARS_IN_SECONDS = 3154000000; const seconds = parseDuration(timeoutInput, 's'); if (Number.isInteger(seconds) && seconds > 0) { if (seconds > ONE_HUNDRED_YEARS_IN_SECONDS) { setInvalid('Wow, banned for more than 100 years?'); } else { setValid(seconds); } } else { setInvalid('Invalid duration.'); } }, [timeoutInput, timeoutInputErr, timeoutSec]); // ************************************************************************** // ************************************************************************** function getTabElem(value, label) { return (