diff --git a/flow-typed/Comment.js b/flow-typed/Comment.js
index 36c970fac9..ecc30f9ea1 100644
--- a/flow-typed/Comment.js
+++ b/flow-typed/Comment.js
@@ -73,6 +73,8 @@ declare type PerChannelSettings = {
comments_enabled?: boolean,
min_tip_amount_comment?: number,
min_tip_amount_super_chat?: number,
+ min_usdc_tip_amount_comment?: number,
+ min_usdc_tip_amount_super_chat?: number,
slow_mode_min_gap?: number,
time_since_first_comment?: number,
livestream_chat_members_only?: boolean,
@@ -345,6 +347,8 @@ declare type SettingsResponse = {
comments_enabled: boolean,
min_tip_amount_comment: number,
min_tip_amount_super_chat: number,
+ min_usdc_tip_amount_comment: number,
+ min_usdc_tip_amount_super_chat: number,
slow_mode_min_gap: number,
curse_jar_amount: number,
filters_enabled?: boolean,
@@ -360,6 +364,8 @@ declare type UpdateSettingsParams = {
comments_enabled?: boolean,
min_tip_amount_comment?: number,
min_tip_amount_super_chat?: number,
+ min_usdc_tip_amount_comment?: number,
+ min_usdc_tip_amount_super_chat?: number,
slow_mode_min_gap?: number,
time_since_first_comment?: number,
livestream_chat_members_only?: boolean,
diff --git a/ui/component/commentCreate/internal/extra-contents.jsx b/ui/component/commentCreate/internal/extra-contents.jsx
index e74c275809..cc8b6acdfb 100644
--- a/ui/component/commentCreate/internal/extra-contents.jsx
+++ b/ui/component/commentCreate/internal/extra-contents.jsx
@@ -30,19 +30,31 @@ type HelpTextProps = {
minAmount: number,
minSuper: number,
minTip: number,
+ minUSDCAmount: number,
+ minUSDCSuper: number,
+ minUSDCTip: number,
};
export const HelpText = (helpTextProps: HelpTextProps) => {
- const { deletedComment, minAmount, minSuper, minTip } = helpTextProps;
+ const { deletedComment, minAmount, minSuper, minTip, minUSDCAmount, minUSDCSuper, minUSDCTip } = helpTextProps;
return (
<>
{deletedComment &&
{__('This comment has been deleted.')}
}
- {!!minAmount && (
+ {(!!minAmount || !!minUSDCAmount) && (
- }}>
- {minTip ? 'Comment min: %lbc%' : minSuper ? 'HyperChat min: %lbc%' : ''}
+ ,
+ minUSDCAmount,
+ lbc: ,
+ }}
+ >
+ {(minTip || minUSDCTip ? 'Comment min: ' : minSuper || minUSDCSuper ? 'HyperChat min: ' : '') +
+ (minTip || minSuper ? '%lbc%' : '') +
+ (minAmount && minUSDCAmount ? ' or ' : '') +
+ (minUSDCTip || minUSDCSuper ? '%usdc%' : '')}
= minAmount;
+ const minUSDCAmount = minUSDCTip || minUSDCSuper || 0;
+ const minAmountMet =
+ (activeTab !== TAB_LBC && activeTab !== TAB_FIAT && !minTip && !minUSDCTip) ||
+ (activeTab === TAB_LBC && tipAmount >= minAmount) ||
+ (activeTab === TAB_FIAT && tipAmount >= minUSDCAmount);
const stickerPrice = selectedSticker && selectedSticker.price;
const tipSelectorError = tipError || disableReviewButton;
const fiatIcon = STRIPE.CURRENCY[preferredCurrency].icon;
const minAmountRef = React.useRef(minAmount);
minAmountRef.current = minAmount;
+ const minUSDCAmountRef = React.useRef(minUSDCAmount);
+ minUSDCAmountRef.current = minUSDCAmount;
const addEmoteToComment = React.useCallback((emote: string) => {
setCommentValue((prev) => prev + (prev && prev.charAt(prev.length - 1) !== ' ' ? ` ${emote} ` : `${emote} `));
@@ -389,7 +397,13 @@ export function CommentCreate(props: Props) {
const lockedMinAmount = minAmount; // value during closure.
const currentMinAmount = minAmountRef.current; // value from latest doFetchCreatorSettings().
- if (lockedMinAmount !== currentMinAmount) {
+ const lockedMinUSDCAmount = minUSDCAmount; // value during closure.
+ const currentMinUSDCAmount = minUSDCAmountRef.current; // value from latest doFetchCreatorSettings().
+
+ if (
+ (activeTab === TAB_LBC && lockedMinAmount !== currentMinAmount) ||
+ (activeTab === TAB_FIAT && lockedMinUSDCAmount !== currentMinUSDCAmount)
+ ) {
doToast({
message: __('The creator just updated the minimum setting. Please revise or double-check your tip amount.'),
isError: true,
@@ -524,7 +538,8 @@ export function CommentCreate(props: Props) {
environment,
sticker: !!stickerValue,
is_protected: Boolean(isLivestreamChatMembersOnly || areCommentsMembersOnly),
- amount: activeTab === TAB_LBC ? tipAmount * 100000000 : undefined,
+ amount: activeTab === TAB_LBC || activeTab === TAB_FIAT ? tipAmount : undefined,
+ currency: activeTab === TAB_LBC ? 'LBC' : activeTab === TAB_FIAT ? 'USDC' : undefined,
dry_run: dryRun,
})
.then((res) => {
@@ -764,8 +779,16 @@ export function CommentCreate(props: Props) {
isLivestream={isLivestream}
label={}
noticeLabel={
- isMobile && (
-
+ (isMobile || isLivestream) && (
+
)
}
name={isReply ? 'create__reply' : 'create__comment'}
@@ -860,7 +883,7 @@ export function CommentCreate(props: Props) {
/>
) : (
(!isMobile || selectedSticker) &&
- (!minTip || claimIsMine) && (
+ ((!minTip && !minUSDCTip) || claimIsMine) && (
)}
-
-
+ {!isLivestream && (
+
+ )}
)}
diff --git a/ui/component/settingsRow/view.jsx b/ui/component/settingsRow/view.jsx
index 916c6a79c4..ba670aa68f 100644
--- a/ui/component/settingsRow/view.jsx
+++ b/ui/component/settingsRow/view.jsx
@@ -7,6 +7,7 @@ import classnames from 'classnames';
type Props = {
title: string,
subtitle?: string,
+ warning?: string,
multirow?: boolean, // Displays the Value widget(s) below the Label instead of on the right.
useVerticalSeparator?: boolean, // Show a separator line between Label and Value. Useful when there are multiple Values.
disabled?: boolean,
@@ -16,7 +17,8 @@ type Props = {
};
export default function SettingsRow(props: Props) {
- const { title, subtitle, multirow, useVerticalSeparator, disabled, highlighted, membersOnly, children } = props;
+ const { title, subtitle, warning, multirow, useVerticalSeparator, disabled, highlighted, membersOnly, children } =
+ props;
return (
+ {warning &&
{warning}
}
debounce(pushSlowModeMin, 1000), []); // eslint-disable-line react-hooks/exhaustive-deps
const pushMinTipDebounced = React.useMemo(() => debounce(pushMinTip, 1000), []); // eslint-disable-line react-hooks/exhaustive-deps
const pushMinSuperDebounced = React.useMemo(() => debounce(pushMinSuper, 1000), []); // eslint-disable-line react-hooks/exhaustive-deps
+ const pushMinUSDCTipDebounced = React.useMemo(() => debounce(pushMinUSDCTip, 1000), []); // eslint-disable-line react-hooks/exhaustive-deps
+ const pushMinUSDCSuperDebounced = React.useMemo(() => debounce(pushMinUSDCSuper, 1000), []); // eslint-disable-line react-hooks/exhaustive-deps
// **************************************************************************
// **************************************************************************
@@ -103,9 +116,12 @@ export default function CreatorSettingsTab(props: Props) {
if (fullSync) {
setCommentsEnabled(settings.comments_enabled || false);
- setMinTip(settings.min_tip_amount_comment || 0);
- setMinSuper(settings.min_tip_amount_super_chat || 0);
- setSlowModeMin(settings.slow_mode_min_gap || 0);
+ focusedField.current !== FIELD_NAMES.MIN_TIP && setMinTip(settings.min_tip_amount_comment || 0);
+ focusedField.current !== FIELD_NAMES.MIN_SUPER && setMinSuper(settings.min_tip_amount_super_chat || 0);
+ focusedField.current !== FIELD_NAMES.MIN_USDC_TIP && setMinUSDCTip(settings.min_usdc_tip_amount_comment || 0);
+ focusedField.current !== FIELD_NAMES.MIN_USDC_SUPER &&
+ setMinUSDCSuper(settings.min_usdc_tip_amount_super_chat || 0);
+ focusedField.current !== FIELD_NAMES.SLOW_MODE && setSlowModeMin(settings.slow_mode_min_gap || 0);
setMinChannelAgeMinutes(settings.time_since_first_comment || 0);
setCommentsMembersOnly(settings.comments_members_only);
setLivestreamChatMembersOnly(settings.livestream_chat_members_only || false);
@@ -120,6 +136,12 @@ export default function CreatorSettingsTab(props: Props) {
if (settings.min_tip_amount_super_chat !== undefined) {
setMinSuper(settings.min_tip_amount_super_chat);
}
+ if (settings.min_usdc_tip_amount_comment !== undefined) {
+ setMinUSDCTip(settings.min_usdc_tip_amount_comment);
+ }
+ if (settings.min_usdc_tip_amount_super_chat !== undefined) {
+ setMinUSDCSuper(settings.min_usdc_tip_amount_super_chat);
+ }
if (settings.slow_mode_min_gap !== undefined) {
setSlowModeMin(settings.slow_mode_min_gap);
}
@@ -152,10 +174,18 @@ export default function CreatorSettingsTab(props: Props) {
updateCreatorSettings(activeChannelClaim, { min_tip_amount_comment: value });
}
+ function pushMinUSDCTip(value: number, activeChannelClaim: ChannelClaim) {
+ updateCreatorSettings(activeChannelClaim, { min_usdc_tip_amount_comment: value });
+ }
+
function pushMinSuper(value: number, activeChannelClaim: ChannelClaim) {
updateCreatorSettings(activeChannelClaim, { min_tip_amount_super_chat: value });
}
+ function pushMinUSDCSuper(value: number, activeChannelClaim: ChannelClaim) {
+ updateCreatorSettings(activeChannelClaim, { min_usdc_tip_amount_super_chat: value });
+ }
+
function parseModUri(uri) {
try {
return parseURI(uri);
@@ -320,13 +350,14 @@ export default function CreatorSettingsTab(props: Props) {
min={0}
step={1}
type="number"
- placeholder="1"
+ placeholder="0"
value={slowModeMin}
onChange={(e) => {
const value = parseInt(e.target.value);
setSlowModeMin(value);
- pushSlowModeMinDebounced(value, activeChannelClaim);
+ pushSlowModeMinDebounced(value || 0, activeChannelClaim);
}}
+ onFocus={() => (focusedField.current = FIELD_NAMES.SLOW_MODE)}
onBlur={() => setLastUpdated(Date.now())}
/>
@@ -371,6 +402,14 @@ export default function CreatorSettingsTab(props: Props) {
}}>Minimum %lbc% tip amount for comments
}
subtitle={__(HELP.MIN_TIP)}
+ warning={
+ !minTip &&
+ !!minUSDCTip && (
+
}}>
+ All %lbc% comments allowed, please set a value if you want to limit this.
+
+ )
+ }
>
{
const newMinTip = parseFloat(e.target.value);
setMinTip(newMinTip);
- pushMinTipDebounced(newMinTip, activeChannelClaim);
- if (newMinTip !== 0 && minSuper !== 0) {
- setMinSuper(0);
- pushMinSuperDebounced(0, activeChannelClaim);
+ pushMinTipDebounced(newMinTip || 0, activeChannelClaim);
+ if (newMinTip !== 0) {
+ if (minSuper !== 0) {
+ setMinSuper(0);
+ pushMinSuperDebounced(0, activeChannelClaim);
+ }
+ if (minUSDCSuper !== 0) {
+ setMinUSDCSuper(0);
+ pushMinUSDCSuperDebounced(0, activeChannelClaim);
+ }
}
}}
+ onFocus={() => (focusedField.current = FIELD_NAMES.MIN_TIP)}
onBlur={() => setLastUpdated(Date.now())}
/>
@@ -408,6 +454,14 @@ export default function CreatorSettingsTab(props: Props) {
)}
>
}
+ warning={
+ !minSuper &&
+ !!minUSDCSuper && (
+ }}>
+ All %lbc% hyperchats allowed, please set a value if you want to limit this.
+
+ )
+ }
>
{
const newMinSuper = parseFloat(e.target.value);
setMinSuper(newMinSuper);
- pushMinSuperDebounced(newMinSuper, activeChannelClaim);
+ pushMinSuperDebounced(newMinSuper || 0, activeChannelClaim);
+ }}
+ onFocus={() => (focusedField.current = FIELD_NAMES.MIN_SUPER)}
+ onBlur={() => setLastUpdated(Date.now())}
+ />
+
+
+ Minimum %lbc% tip amount for comments}
+ subtitle={__(HELP.MIN_TIP)}
+ warning={
+ !!minTip &&
+ !minUSDCTip && (
+
+ All %lbc% comments allowed, please set a value if you want to limit this.
+
+ )
+ }
+ >
+ {
+ const newMinUSDCTip = parseFloat(e.target.value);
+ setMinUSDCTip(newMinUSDCTip);
+ pushMinUSDCTipDebounced(newMinUSDCTip || 0, activeChannelClaim);
+ if (newMinUSDCTip !== 0) {
+ if (minSuper !== 0) {
+ setMinSuper(0);
+ pushMinSuperDebounced(0, activeChannelClaim);
+ }
+ if (minUSDCSuper !== 0) {
+ setMinUSDCSuper(0);
+ pushMinUSDCSuperDebounced(0, activeChannelClaim);
+ }
+ }
+ }}
+ onFocus={() => (focusedField.current = FIELD_NAMES.MIN_USDC_TIP)}
+ onBlur={() => setLastUpdated(Date.now())}
+ />
+
+
+ Minimum %lbc% tip amount for hyperchats}
+ subtitle={
+ <>
+ {__(HELP.MIN_SUPER)}
+ {minTip !== 0 && (
+
+ {__(HELP.MIN_SUPER_OFF)}
+
+ )}
+ >
+ }
+ warning={
+ !!minSuper &&
+ !minUSDCSuper && (
+
+ All %lbc% hyperchats allowed, please set a value if you want to limit this.
+
+ )
+ }
+ >
+ {
+ const newMinUSDCSuper = parseFloat(e.target.value);
+ setMinUSDCSuper(newMinUSDCSuper);
+ pushMinUSDCSuperDebounced(newMinUSDCSuper || 0, activeChannelClaim);
}}
+ onFocus={() => (focusedField.current = FIELD_NAMES.MIN_USDC_SUPER)}
onBlur={() => setLastUpdated(Date.now())}
/>
diff --git a/ui/scss/component/_card.scss b/ui/scss/component/_card.scss
index f03cbe422b..d907affe21 100644
--- a/ui/scss/component/_card.scss
+++ b/ui/scss/component/_card.scss
@@ -694,8 +694,8 @@
.icon {
width: 12px;
height: 12px;
- margin-bottom: -1px;
- margin-right: var(--spacing-xs);
+ margin-bottom: 2px;
+ margin-right: var(--spacing-xxxxxs);
}
.button__label {
margin-top: 0;
diff --git a/ui/scss/component/_comments.scss b/ui/scss/component/_comments.scss
index 558fb53395..2538ce192e 100644
--- a/ui/scss/component/_comments.scss
+++ b/ui/scss/component/_comments.scss
@@ -370,7 +370,7 @@ $thumbnailWidthSmall: 2rem;
font-weight: var(--font-weight-bold);
color: white;
svg {
- margin-bottom: -1.5px;
+ margin-bottom: 2px;
}
}
diff --git a/ui/scss/component/section.scss b/ui/scss/component/section.scss
index 98523372f7..efdd2ef4ba 100644
--- a/ui/scss/component/section.scss
+++ b/ui/scss/component/section.scss
@@ -328,6 +328,11 @@
padding: var(--spacing-s);
border-bottom: 1px solid var(--color-border);
+ .help--warning {
+ margin-top: 0px;
+ margin-bottom: 0px;
+ }
+
&:first-child,
&:only-child {
border-top: none;