diff --git a/ui/redux/actions/comments.js b/ui/redux/actions/comments.js index db5f77ed8..164041d6d 100644 --- a/ui/redux/actions/comments.js +++ b/ui/redux/actions/comments.js @@ -4,8 +4,9 @@ import * as REACTION_TYPES from 'constants/reactions'; import * as PAGES from 'constants/pages'; import { SORT_BY, BLOCK_LEVEL } from 'constants/comment'; import Lbry from 'lbry'; +import { resolveApiMessage } from 'util/api-message'; import { parseURI, buildURI, isURIEqual } from 'util/lbryURI'; -import { devToast, doFailedSignatureToast, resolveCommentronError } from 'util/commentron-error'; +import { devToast, doFailedSignatureToast } from 'util/toast-wrappers'; import { selectClaimForUri, selectClaimsByUri, selectMyChannelClaims } from 'redux/selectors/claims'; import { doResolveUris, doClaimSearch } from 'redux/actions/claims'; import { doToast, doSeeNotifications } from 'redux/actions/notifications'; @@ -558,7 +559,7 @@ export function doCommentCreate(uri: string, livestream: boolean, params: Commen }) .catch((error) => { dispatch({ type: ACTIONS.COMMENT_CREATE_FAILED, data: error }); - dispatch(doToast(resolveCommentronError(error.message))); + dispatch(doToast({ message: resolveApiMessage(error.message), isError: true })); return Promise.reject(error); }); }; diff --git a/ui/util/api-message.js b/ui/util/api-message.js new file mode 100644 index 000000000..e2fae3fdb --- /dev/null +++ b/ui/util/api-message.js @@ -0,0 +1,74 @@ +// @flow + +type ApiMsgConfig = { + originalMsg: string | RegExp, + replacement: string, +}; + +// prettier-ignore +const MESSAGE_MAP: Array = Object.freeze([ + { + originalMsg: /^your user name (.*) is too close to the creator's user name (.*) and may cause confusion. Please use another identity.$/, + replacement: 'Your user name "%1%" is too close to the creator\'s user name "%2%" and may cause confusion. Please use another identity.', + }, + { + originalMsg: /^Slow mode is on. Please wait at most (.*) seconds before commenting again.$/, + replacement: 'Slow mode is on. Please wait up to %1% seconds before commenting again.', + }, + { + originalMsg: /^the comment contents are blocked by (.*)$/, + replacement: 'The comment contains contents that are blocked by %1%.', + }, + { + originalMsg: 'channel is blocked by publisher', + replacement: 'Unable to comment. This channel has blocked you.', + }, + { + originalMsg: 'channel is not allowed to post comments', + replacement: 'Unable to comment. Your channel has been blocked by an admin.', + }, + { + originalMsg: 'comments are disabled by the creator', + replacement: 'Unable to comment. The content owner has disabled comments.', + }, + { + originalMsg: 'duplicate comment!', + replacement: 'Please do not spam.', + }, + { + originalMsg: 'this creator has set minimum account age requirements that are not currently met', + replacement: "Your channel does not meet the creator's minimum channel-age limit.", + }, +]); + +/** + * Returns a re-mapped and localized version of the given API string. + * + * Ideally, the API should be returning a code and variable values, but + * that won't be happening anytime soon (or ever), so this is the alternative. + * + * @param message + * @returns {string} + */ +export function resolveApiMessage(message: string) { + for (let n = 0; n < MESSAGE_MAP.length; ++n) { + const config: ApiMsgConfig = MESSAGE_MAP[n]; + + if (typeof config.originalMsg === 'string') { + if (config.originalMsg === message) { + return __(config.replacement); + } + } else { + const match = message.match(config.originalMsg); + if (match) { + const subs = {}; + for (let i = 1; i < match.length; ++i) { + subs[`${i}`] = match[i]; + } + return __(config.replacement, subs); + } + } + } + + return __(message); +} diff --git a/ui/util/commentron-error.js b/ui/util/commentron-error.js deleted file mode 100644 index 0bc492694..000000000 --- a/ui/util/commentron-error.js +++ /dev/null @@ -1,110 +0,0 @@ -// @flow -import { doToast } from 'redux/actions/notifications'; - -// **************************************************************************** -// Helpers -// **************************************************************************** - -export function doFailedSignatureToast(dispatch: Dispatch, channelName: string) { - dispatch( - doToast({ - message: __('Unable to verify signature for %channel%.', { channel: channelName }), - isError: true, - }) - ); -} - -export function devToast(dispatch: Dispatch, msg: string) { - // @if process.env.NODE_ENV!='production' - console.error(msg); // eslint-disable-line - dispatch(doToast({ isError: true, message: `DEV: ${msg}` })); - // @endif -} - -// **************************************************************************** -// Error mapping -// **************************************************************************** - -declare type CommentronErrorMap = { - [string]: { - commentron: string | RegExp, - replacement: string, - linkText?: string, - linkTarget?: string, - }, -}; - -// prettier-ignore -const ERR_MAP: CommentronErrorMap = { - SIMILAR_NAME: { - commentron: /^your user name (.*) is too close to the creator's user name (.*) and may cause confusion. Please use another identity.$/, - replacement: 'Your user name "%1%" is too close to the creator\'s user name "%2%" and may cause confusion. Please use another identity.', - }, - SLOW_MODE_IS_ON: { - commentron: /^Slow mode is on. Please wait at most (.*) seconds before commenting again.$/, - replacement: 'Slow mode is on. Please wait up to %1% seconds before commenting again.', - }, - HAS_MUTED_WORDS: { - commentron: /^the comment contents are blocked by (.*)$/, - replacement: 'The comment contains contents that are blocked by %1%.', - }, - BLOCKED_BY_CREATOR: { - commentron: 'channel is blocked by publisher', - replacement: 'Unable to comment. This channel has blocked you.', - }, - BLOCKED_BY_ADMIN: { - commentron: 'channel is not allowed to post comments', - replacement: 'Unable to comment. Your channel has been blocked by an admin.', - }, - CREATOR_DISABLED: { - commentron: 'comments are disabled by the creator', - replacement: 'Unable to comment. The content owner has disabled comments.', - }, - STOP_SPAMMING: { - commentron: 'duplicate comment!', - replacement: 'Please do not spam.', - }, - CHANNEL_AGE: { - commentron: 'this creator has set minimum account age requirements that are not currently met', - replacement: "Your channel does not meet the creator's minimum channel-age limit.", - }, -}; - -export function resolveCommentronError(commentronMsg: string) { - for (const key in ERR_MAP) { - // noinspection JSUnfilteredForInLoop - const data = ERR_MAP[key]; - if (typeof data.commentron === 'string') { - if (data.commentron === commentronMsg) { - return { - message: __(data.replacement), - linkText: data.linkText ? __(data.linkText) : undefined, - linkTarget: data.linkTarget, - isError: true, - }; - } - } else { - const match = commentronMsg.match(data.commentron); - if (match) { - const subs = {}; - for (let i = 1; i < match.length; ++i) { - subs[`${i}`] = match[i]; - } - - return { - message: __(data.replacement, subs), - linkText: data.linkText ? __(data.linkText) : undefined, - linkTarget: data.linkTarget, - isError: true, - }; - } - } - } - - return { - // Fallback to commentron original message. It will be in English - // only and most likely not capitalized correctly. - message: commentronMsg, - isError: true, - }; -} diff --git a/ui/util/toast-wrappers.js b/ui/util/toast-wrappers.js new file mode 100644 index 000000000..c258eb066 --- /dev/null +++ b/ui/util/toast-wrappers.js @@ -0,0 +1,18 @@ +// @flow +import { doToast } from 'redux/actions/notifications'; + +export function doFailedSignatureToast(dispatch: Dispatch, channelName: string) { + dispatch( + doToast({ + message: __('Unable to verify signature for %channel%.', { channel: channelName }), + isError: true, + }) + ); +} + +export function devToast(dispatch: Dispatch, msg: string) { + // @if process.env.NODE_ENV!='production' + console.error(msg); // eslint-disable-line + dispatch(doToast({ isError: true, message: `DEV: ${msg}` })); + // @endif +}