CommentCreate: handle minimum tips

To avoid calling `setting.Get` excessively, we'll do the following:

(a) Call `setting.Get` once per encountered channel, and stash it.

(b) Before sending **each** comment **with a tip**, call `setting.Get` again to get the latest `min_tip`. Report any over- or under-paid values in the confirmation widget before user hits Send.

(c) For regular comments (no tips), just send as normal based on stashed data from `a`.
    - If `min_tip` was `0` but creator later changed to non-zero, Commentron would trigger an error anyway, and the app can get the latest `min_tip` amount to inform the user.
    - If `min_tip` was not `0` but creator later changed to `0`, the app would be incorrectly forcing the user to pay based on the old amount from `a`.  But when he hits `b`, he now knows he has overpaid, and can still cancel.
This commit is contained in:
infinite-persistence 2021-08-04 16:54:20 +08:00
parent 635b0a0c15
commit 0e0e2359f2
No known key found for this signature in database
GPG key ID: B9C3252EDC3D0AA0

View file

@ -15,6 +15,7 @@ import WalletTipAmountSelector from 'component/walletTipAmountSelector';
import CreditAmount from 'component/common/credit-amount'; import CreditAmount from 'component/common/credit-amount';
import ChannelThumbnail from 'component/channelThumbnail'; import ChannelThumbnail from 'component/channelThumbnail';
import UriIndicator from 'component/uriIndicator'; import UriIndicator from 'component/uriIndicator';
import I18nMessage from 'component/i18nMessage';
import Empty from 'component/common/empty'; import Empty from 'component/common/empty';
import { Lbryio } from 'lbryinc'; import { Lbryio } from 'lbryinc';
import { getChannelIdFromClaim } from 'util/claim'; import { getChannelIdFromClaim } from 'util/claim';
@ -97,6 +98,17 @@ export function CommentCreate(props: Props) {
const [shouldDisableReviewButton, setShouldDisableReviewButton] = React.useState(); const [shouldDisableReviewButton, setShouldDisableReviewButton] = React.useState();
const channelId = getChannelIdFromClaim(claim); const channelId = getChannelIdFromClaim(claim);
const channelSettings = channelId ? settingsByChannelId[channelId] : undefined; const channelSettings = channelId ? settingsByChannelId[channelId] : undefined;
const minTip = (channelSettings && channelSettings.min_tip_amount_comment) || 0;
const minTipMet = minTip === 0 || tipAmount >= minTip;
const MinTipNotice =
minTip !== 0 ? (
<div className="help--notice">
<I18nMessage tokens={{ lbc: <CreditAmount noFormat amount={minTip} /> }}>
This channel requires a minimum tip of %lbc% to post a comment.
</I18nMessage>
</div>
) : null;
function handleCommentChange(event) { function handleCommentChange(event) {
let commentValue; let commentValue;
@ -125,6 +137,14 @@ export function CommentCreate(props: Props) {
window.removeEventListener('keydown', altEnterListener); window.removeEventListener('keydown', altEnterListener);
} }
function handleReview() {
if (channelId) {
// Get the latest minTip value for final review.
doFetchCreatorSettings(channelId);
}
setIsReviewingSupportComment(true);
}
function handleSubmit() { function handleSubmit() {
if (activeChannelClaim && commentValue.length) { if (activeChannelClaim && commentValue.length) {
handleCreateComment(); handleCreateComment();
@ -238,7 +258,7 @@ export function CommentCreate(props: Props) {
} }
/** /**
* * handleCreateComment
* @param {string} [txid] Optional transaction id generated by * @param {string} [txid] Optional transaction id generated by
* @param {string} [payment_intent_id] Optional payment_intent_id from Stripe payment * @param {string} [payment_intent_id] Optional payment_intent_id from Stripe payment
* @param {string} [environment] Optional environment for Stripe (test|live) * @param {string} [environment] Optional environment for Stripe (test|live)
@ -271,6 +291,7 @@ export function CommentCreate(props: Props) {
setAdvancedEditor(!advancedEditor); setAdvancedEditor(!advancedEditor);
} }
// Fetch channel constraints if not already.
React.useEffect(() => { React.useEffect(() => {
if (!channelSettings && channelId) { if (!channelSettings && channelId) {
doFetchCreatorSettings(channelId); doFetchCreatorSettings(channelId);
@ -333,7 +354,7 @@ export function CommentCreate(props: Props) {
<Button <Button
autoFocus autoFocus
button="primary" button="primary"
disabled={disabled} disabled={disabled || !minTipMet}
label={ label={
isSubmitting isSubmitting
? __('Sending...') ? __('Sending...')
@ -344,6 +365,7 @@ export function CommentCreate(props: Props) {
onClick={handleSupportComment} onClick={handleSupportComment}
/> />
<Button button="link" label={__('Cancel')} onClick={() => setIsReviewingSupportComment(false)} /> <Button button="link" label={__('Cancel')} onClick={() => setIsReviewingSupportComment(false)} />
{MinTipNotice}
</div> </div>
</div> </div>
); );
@ -397,34 +419,36 @@ export function CommentCreate(props: Props) {
{isSupportComment ? ( {isSupportComment ? (
<> <>
<Button <Button
disabled={disabled || tipError || shouldDisableReviewButton} disabled={disabled || tipError || shouldDisableReviewButton || !minTipMet}
type="button" type="button"
button="primary" button="primary"
icon={activeTab === TAB_LBC ? ICONS.LBC : ICONS.FINANCE} icon={activeTab === TAB_LBC ? ICONS.LBC : ICONS.FINANCE}
label={__('Review')} label={__('Review')}
onClick={() => setIsReviewingSupportComment(true)} onClick={handleReview}
/> />
<Button disabled={disabled} button="link" label={__('Cancel')} onClick={() => setIsSupportComment(false)} /> <Button disabled={disabled} button="link" label={__('Cancel')} onClick={() => setIsSupportComment(false)} />
</> </>
) : ( ) : (
<> <>
<Button {minTip === 0 && (
ref={buttonRef} <Button
button="primary" ref={buttonRef}
disabled={disabled} button="primary"
type="submit" disabled={disabled}
label={ type="submit"
isReply label={
? isSubmitting isReply
? __('Replying...') ? isSubmitting
: __('Reply') ? __('Replying...')
: isSubmitting : __('Reply')
? __('Commenting...') : isSubmitting
: __('Comment --[button to submit something]--') ? __('Commenting...')
} : __('Comment --[button to submit something]--')
requiresAuth={IS_WEB} }
/> requiresAuth={IS_WEB}
/>
)}
{!claimIsMine && ( {!claimIsMine && (
<Button <Button
disabled={disabled} disabled={disabled}
@ -449,7 +473,7 @@ export function CommentCreate(props: Props) {
}} }}
/> />
)} )}
{isReply && ( {isReply && minTip === 0 && (
<Button <Button
button="link" button="link"
label={__('Cancel')} label={__('Cancel')}
@ -462,6 +486,7 @@ export function CommentCreate(props: Props) {
)} )}
</> </>
)} )}
{MinTipNotice}
</div> </div>
</Form> </Form>
); );