Add "min channel age" setting

This commit is contained in:
infinite-persistence 2022-02-23 14:29:14 +08:00
parent 8ace40522e
commit f70e631953
No known key found for this signature in database
GPG key ID: B9C3252EDC3D0AA0
5 changed files with 55 additions and 1 deletions

View file

@ -37,6 +37,7 @@ declare type PerChannelSettings = {
min_tip_amount_comment?: number, min_tip_amount_comment?: number,
min_tip_amount_super_chat?: number, min_tip_amount_super_chat?: number,
slow_mode_min_gap?: number, slow_mode_min_gap?: number,
time_since_first_comment?: number,
}; };
// todo: relate individual comments to their commentId // todo: relate individual comments to their commentId
@ -318,6 +319,7 @@ declare type UpdateSettingsParams = {
min_tip_amount_comment?: number, min_tip_amount_comment?: number,
min_tip_amount_super_chat?: number, min_tip_amount_super_chat?: number,
slow_mode_min_gap?: number, slow_mode_min_gap?: number,
time_since_first_comment?: number,
}; };
declare type BlockWordParams = { declare type BlockWordParams = {

View file

@ -2197,6 +2197,8 @@
"When do you want to go live?": "When do you want to go live?", "When do you want to go live?": "When do you want to go live?",
"Anytime": "Anytime", "Anytime": "Anytime",
"Scheduled Time": "Scheduled Time", "Scheduled Time": "Scheduled Time",
"Minimum channel age for comments": "Minimum channel age for comments",
"Channels with a lifespan lower than the specified duration will not be able to comment on your content.": "Channels with a lifespan lower than the specified duration will not be able to comment on your content.",
"Set minimum channel age": "Set minimum channel age", "Set minimum channel age": "Set minimum channel age",
"Note that the restriction can only be applied to channels created after Feb 8th, 2022.": "Note that the restriction can only be applied to channels created after Feb 8th, 2022.", "Note that the restriction can only be applied to channels created after Feb 8th, 2022.": "Note that the restriction can only be applied to channels created after Feb 8th, 2022.",
"No limit": "No limit", "No limit": "No limit",

View file

@ -1,5 +1,6 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import SettingsCreatorPage from './view'; import SettingsCreatorPage from './view';
import { doOpenModal } from 'redux/actions/app';
import { import {
doCommentBlockWords, doCommentBlockWords,
doCommentUnblockWords, doCommentUnblockWords,
@ -35,6 +36,7 @@ const perform = (dispatch) => ({
commentModRemoveDelegate: (modChanId, modChanName, creatorChannelClaim) => commentModRemoveDelegate: (modChanId, modChanName, creatorChannelClaim) =>
dispatch(doCommentModRemoveDelegate(modChanId, modChanName, creatorChannelClaim)), dispatch(doCommentModRemoveDelegate(modChanId, modChanName, creatorChannelClaim)),
commentModListDelegates: (creatorChannelClaim) => dispatch(doCommentModListDelegates(creatorChannelClaim)), commentModListDelegates: (creatorChannelClaim) => dispatch(doCommentModListDelegates(creatorChannelClaim)),
doOpenModal: (modal, props) => dispatch(doOpenModal(modal, props)),
}); });
export default connect(select, perform)(SettingsCreatorPage); export default connect(select, perform)(SettingsCreatorPage);

View file

@ -1,5 +1,9 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import humanizeDuration from 'humanize-duration';
import * as ICONS from 'constants/icons';
import * as MODALS from 'constants/modal_types';
import Button from 'component/button';
import Card from 'component/common/card'; import Card from 'component/common/card';
import TagsSearch from 'component/tagsSearch'; import TagsSearch from 'component/tagsSearch';
import Page from 'component/page'; import Page from 'component/page';
@ -36,6 +40,7 @@ type Props = {
fetchCreatorSettings: (channelId: string) => void, fetchCreatorSettings: (channelId: string) => void,
updateCreatorSettings: (ChannelClaim, PerChannelSettings) => void, updateCreatorSettings: (ChannelClaim, PerChannelSettings) => void,
doToast: ({ message: string }) => void, doToast: ({ message: string }) => void,
doOpenModal: (id: string, {}) => void,
}; };
export default function SettingsCreatorPage(props: Props) { export default function SettingsCreatorPage(props: Props) {
@ -50,6 +55,7 @@ export default function SettingsCreatorPage(props: Props) {
commentModListDelegates, commentModListDelegates,
fetchCreatorSettings, fetchCreatorSettings,
updateCreatorSettings, updateCreatorSettings,
doOpenModal,
} = props; } = props;
const [commentsEnabled, setCommentsEnabled] = React.useState(true); const [commentsEnabled, setCommentsEnabled] = React.useState(true);
@ -58,6 +64,7 @@ export default function SettingsCreatorPage(props: Props) {
const [minTip, setMinTip] = React.useState(0); const [minTip, setMinTip] = React.useState(0);
const [minSuper, setMinSuper] = React.useState(0); const [minSuper, setMinSuper] = React.useState(0);
const [slowModeMin, setSlowModeMin] = React.useState(0); const [slowModeMin, setSlowModeMin] = React.useState(0);
const [minChannelAgeMinutes, setMinChannelAgeMinutes] = React.useState(0);
const [lastUpdated, setLastUpdated] = React.useState(1); const [lastUpdated, setLastUpdated] = React.useState(1);
const pushSlowModeMinDebounced = React.useMemo(() => debounce(pushSlowModeMin, 1000), []); // eslint-disable-line react-hooks/exhaustive-deps const pushSlowModeMinDebounced = React.useMemo(() => debounce(pushSlowModeMin, 1000), []); // eslint-disable-line react-hooks/exhaustive-deps
@ -91,6 +98,7 @@ export default function SettingsCreatorPage(props: Props) {
setMinTip(settings.min_tip_amount_comment || 0); setMinTip(settings.min_tip_amount_comment || 0);
setMinSuper(settings.min_tip_amount_super_chat || 0); setMinSuper(settings.min_tip_amount_super_chat || 0);
setSlowModeMin(settings.slow_mode_min_gap || 0); setSlowModeMin(settings.slow_mode_min_gap || 0);
setMinChannelAgeMinutes(settings.time_since_first_comment || 0);
doSetMutedWordTags(settings.words || []); doSetMutedWordTags(settings.words || []);
} else { } else {
if (settings.comments_enabled !== undefined) { if (settings.comments_enabled !== undefined) {
@ -105,6 +113,9 @@ export default function SettingsCreatorPage(props: Props) {
if (settings.slow_mode_min_gap !== undefined) { if (settings.slow_mode_min_gap !== undefined) {
setSlowModeMin(settings.slow_mode_min_gap); setSlowModeMin(settings.slow_mode_min_gap);
} }
if (settings.time_since_first_comment) {
setMinChannelAgeMinutes(settings.time_since_first_comment);
}
if (settings.words) { if (settings.words) {
doSetMutedWordTags(settings.words); doSetMutedWordTags(settings.words);
} }
@ -285,6 +296,41 @@ export default function SettingsCreatorPage(props: Props) {
/> />
</SettingsRow> </SettingsRow>
<SettingsRow title={__('Minimum channel age for comments')} subtitle={__(HELP.CHANNEL_AGE)}>
<div className="section__actions">
<FormField
name="time_since_first_comment"
className="form-field--copyable"
disabled={minChannelAgeMinutes <= 0}
type="text"
readOnly
value={
minChannelAgeMinutes > 0
? humanizeDuration(minChannelAgeMinutes * 60 * 1000, { round: true })
: __('No limit')
}
inputButton={
<Button
button="secondary"
icon={ICONS.EDIT}
title={__('Change')}
onClick={() => {
doOpenModal(MODALS.MIN_CHANNEL_AGE, {
onConfirm: (limitInMinutes: number, closeModal: () => void) => {
setMinChannelAgeMinutes(limitInMinutes);
updateCreatorSettings(activeChannelClaim, {
time_since_first_comment: limitInMinutes,
});
closeModal();
},
});
}}
/>
}
/>
</div>
</SettingsRow>
<SettingsRow <SettingsRow
title={ title={
<I18nMessage tokens={{ lbc: <LbcSymbol /> }}>Minimum %lbc% tip amount for comments</I18nMessage> <I18nMessage tokens={{ lbc: <LbcSymbol /> }}>Minimum %lbc% tip amount for comments</I18nMessage>
@ -386,6 +432,7 @@ export default function SettingsCreatorPage(props: Props) {
// prettier-ignore // prettier-ignore
const HELP = { const HELP = {
SLOW_MODE: 'Minimum time gap in seconds between comments (affects livestream chat as well).', SLOW_MODE: 'Minimum time gap in seconds between comments (affects livestream chat as well).',
CHANNEL_AGE: 'Channels with a lifespan lower than the specified duration will not be able to comment on your content.',
MIN_TIP: 'Enabling a minimum amount to comment will force all comments, including livestreams, to have tips associated with them. This can help prevent spam.', MIN_TIP: 'Enabling a minimum amount to comment will force all comments, including livestreams, to have tips associated with them. This can help prevent spam.',
MIN_SUPER: 'Enabling a minimum amount to hyperchat will force all TIPPED comments to have this value in order to be shown. This still allows regular comments to be posted.', MIN_SUPER: 'Enabling a minimum amount to hyperchat will force all TIPPED comments to have this value in order to be shown. This still allows regular comments to be posted.',
MIN_SUPER_OFF: '(This settings is not applicable if all comments require a tip.)', MIN_SUPER_OFF: '(This settings is not applicable if all comments require a tip.)',

View file

@ -340,7 +340,8 @@
//padding-left: var(--spacing-m); //padding-left: var(--spacing-m);
.button, .button,
.checkbox { .checkbox,
.section__actions {
&:only-child { &:only-child {
float: right; float: right;
} }