// @flow import type { ElementRef } from 'react'; import { SIMPLE_SITE } from 'config'; import * as PAGES from 'constants/pages'; import * as ICONS from 'constants/icons'; import React from 'react'; import classnames from 'classnames'; import { FormField, Form } from 'component/common/form'; import Button from 'component/button'; import SelectChannel from 'component/selectChannel'; import usePersistedState from 'effects/use-persisted-state'; import { FF_MAX_CHARS_IN_COMMENT, FF_MAX_CHARS_IN_LIVESTREAM_COMMENT } from 'constants/form-field'; import { useHistory } from 'react-router'; import WalletTipAmountSelector from 'component/walletTipAmountSelector'; import CreditAmount from 'component/common/credit-amount'; import ChannelThumbnail from 'component/channelThumbnail'; import UriIndicator from 'component/uriIndicator'; const COMMENT_SLOW_MODE_SECONDS = 5; type Props = { uri: string, claim: StreamClaim, createComment: (string, string, string, ?string) => Promise, channels: ?Array, onDoneReplying?: () => void, onCancelReplying?: () => void, isNested: boolean, isFetchingChannels: boolean, parentId: string, isReply: boolean, activeChannel: string, activeChannelClaim: ?ChannelClaim, bottom: boolean, onSubmit: (string, string) => void, livestream: boolean, embed?: boolean, toast: (string) => void, claimIsMine: boolean, sendTip: ({}, (any) => void, (any) => void) => void, justCommented: Array, commentingEnabled: boolean, }; export function CommentCreate(props: Props) { const { createComment, claim, channels, onDoneReplying, onCancelReplying, isNested, isFetchingChannels, isReply, parentId, activeChannelClaim, onSubmit, bottom, livestream, embed, toast, claimIsMine, sendTip, commentingEnabled, justCommented, } = props; const buttonref: ElementRef = React.useRef(); const { push, location: { pathname }, } = useHistory(); const [isSubmitting, setIsSubmitting] = React.useState(false); const [commentFailure, setCommentFailure] = React.useState(false); const [successTip, setSuccessTip] = React.useState({ txid: undefined, tipAmount: undefined }); const { claim_id: claimId } = claim; const [isSupportComment, setIsSupportComment] = React.useState(); const [isReviewingSupportComment, setIsReviewingSupportComment] = React.useState(); const [tipAmount, setTipAmount] = React.useState(1); const [commentValue, setCommentValue] = React.useState(''); const [lastCommentTime, setLastCommentTime] = React.useState(); const [advancedEditor, setAdvancedEditor] = usePersistedState('comment-editor-mode', false); const hasChannels = channels && channels.length; const disabled = isSubmitting || !activeChannelClaim || !commentValue.length; const charCount = commentValue.length; function handleCommentChange(event) { let commentValue; if (isReply) { commentValue = event.target.value; } else { commentValue = !SIMPLE_SITE && advancedEditor ? event : event.target.value; } setCommentValue(commentValue); } function altEnterListener(e: SyntheticKeyboardEvent<*>) { const KEYCODE_ENTER = 13; if ((livestream || e.ctrlKey || e.metaKey) && e.keyCode === KEYCODE_ENTER) { e.preventDefault(); buttonref.current.click(); } } function onTextareaFocus() { window.addEventListener('keydown', altEnterListener); } function onTextareaBlur() { window.removeEventListener('keydown', altEnterListener); } function handleSubmit() { if (activeChannelClaim && commentValue.length) { const timeUntilCanComment = !lastCommentTime ? 0 : (lastCommentTime - Date.now()) / 1000 + COMMENT_SLOW_MODE_SECONDS; if (livestream && !claimIsMine && timeUntilCanComment > 0) { toast(__('Slowmode is on. You can comment again in %time% seconds.', { time: Math.ceil(timeUntilCanComment) })); return; } handleCreateComment(); } } function handleSupportComment() { if (!activeChannelClaim) { return; } if (commentFailure && tipAmount === successTip.tipAmount) { handleCreateComment(successTip.txid); return; } else { setSuccessTip({ txid: undefined, tipAmount: undefined }); } const params = { amount: tipAmount, claim_id: claimId, channel_id: activeChannelClaim.claim_id, }; setIsSubmitting(true); sendTip( params, (response) => { const { txid } = response; setTimeout(() => { handleCreateComment(txid); }, 1500); setSuccessTip({ txid, tipAmount }); }, () => { setIsSubmitting(false); } ); } function handleCreateComment(txid) { setIsSubmitting(true); createComment(commentValue, claimId, parentId, txid) .then((res) => { setIsSubmitting(false); if (res && res.signature) { setCommentValue(''); setLastCommentTime(Date.now()); setIsReviewingSupportComment(false); setIsSupportComment(false); setCommentFailure(false); justCommented.push(res.comment_id); if (onSubmit) { onSubmit(commentValue, activeChannelClaim.name); } if (onDoneReplying) { onDoneReplying(); } } }) .catch(() => { setIsSubmitting(false); setCommentFailure(true); }); } function toggleEditorMode() { setAdvancedEditor(!advancedEditor); } if (!commentingEnabled || !hasChannels) { return (
{ if (embed) { window.open(`https://odysee.com/$/${PAGES.AUTH}?redirect=/$/${PAGES.LIVESTREAM}`); return; } const pathPlusRedirect = `/$/${PAGES.CHANNEL_NEW}?redirect=${pathname}`; if (livestream) { window.open(pathPlusRedirect); } else { push(pathPlusRedirect); } }} >
); } if (isReviewingSupportComment && activeChannelClaim) { return (
{commentValue}
); } return (
{!livestream && (
{isReply ? __('Replying as') + ' ' : __('Comment as') + ' '}
)} } quickActionLabel={ !SIMPLE_SITE && (isReply ? undefined : advancedEditor ? __('Simple Editor') : __('Advanced Editor')) } quickActionHandler={!SIMPLE_SITE && toggleEditorMode} onFocus={onTextareaFocus} onBlur={onTextareaBlur} placeholder={__('Say something about this...')} value={commentValue} charCount={charCount} onChange={handleCommentChange} autoFocus={isReply} textAreaMaxLength={livestream ? FF_MAX_CHARS_IN_LIVESTREAM_COMMENT : FF_MAX_CHARS_IN_COMMENT} /> {isSupportComment && setTipAmount(amount)} />}
{isSupportComment ? ( <>
); }