diff --git a/.env.defaults b/.env.defaults index 7a244cd80..bfeb12fff 100644 --- a/.env.defaults +++ b/.env.defaults @@ -12,6 +12,7 @@ LBRY_WEB_API=https://api.na-backend.odysee.com LBRY_WEB_STREAMING_API=https://cdn.lbryplayer.xyz LBRY_WEB_BUFFER_API=https://collector-service.api.lbry.tv/api/v1/events/video COMMENT_SERVER_API=https://comments.odysee.com/api/v2 +COMMENT_SERVER_NAME=Odysee SEARCH_SERVER_API=https://lighthouse.odysee.com/search SOCKETY_SERVER_API=wss://sockety.odysee.com/ws THUMBNAIL_CDN_URL=https://image-processor.vanwanet.com/optimize/ diff --git a/config.js b/config.js index a6c6b2a5c..89c916654 100644 --- a/config.js +++ b/config.js @@ -15,6 +15,7 @@ const config = { LBRY_WEB_BUFFER_API: process.env.LBRY_WEB_BUFFER_API, SEARCH_SERVER_API: process.env.SEARCH_SERVER_API, COMMENT_SERVER_API: process.env.COMMENT_SERVER_API, + COMMENT_SERVER_NAME: process.env.COMMENT_SERVER_NAME, SOCKETY_SERVER_API: process.env.SOCKETY_SERVER_API, WELCOME_VERSION: process.env.WELCOME_VERSION, DOMAIN: process.env.DOMAIN, diff --git a/static/app-strings.json b/static/app-strings.json index a4476a78e..86ee18263 100644 --- a/static/app-strings.json +++ b/static/app-strings.json @@ -2038,6 +2038,13 @@ "Your publish is being confirmed and will be live soon": "Your publish is being confirmed and will be live soon", "Clear Edits": "Clear Edits", "Something not quite right..": "Something not quite right..", + "Comments server": "Comments server", + "Default comments server (%name%)": "Default comments server (%name%)", + "Custom comments server": "Custom comments server", + "Failed to fetch comments.": "Failed to fetch comments.", + "Failed to fetch comments. Verify custom server settings.": "Failed to fetch comments. Verify custom server settings.", + "Commenting server is not set.": "Commenting server is not set.", + "Comments are not currently enabled.": "Comments are not currently enabled.", "See All": "See All", "Supporting content requires %lbc%": "Supporting content requires %lbc%", "With %lbc%, you can send tips to your favorite creators, or help boost their content for more people to see.": "With %lbc%, you can send tips to your favorite creators, or help boost their content for more people to see.", diff --git a/ui/comments.js b/ui/comments.js index 8e9c5121e..9069e49d3 100644 --- a/ui/comments.js +++ b/ui/comments.js @@ -4,6 +4,13 @@ import { COMMENT_SERVER_API } from 'config'; const Comments = { url: COMMENT_SERVER_API, enabled: Boolean(COMMENT_SERVER_API), + isCustomServer: false, + + setServerUrl: (customUrl: ?string) => { + Comments.url = customUrl === undefined ? COMMENT_SERVER_API : customUrl; + Comments.enabled = Boolean(Comments.url); + Comments.isCustomServer = Comments.url !== COMMENT_SERVER_API; + }, moderation_block: (params: ModerationBlockParams) => fetchCommentsApi('moderation.Block', params), moderation_unblock: (params: ModerationBlockParams) => fetchCommentsApi('moderation.UnBlock', params), @@ -31,8 +38,10 @@ const Comments = { }; function fetchCommentsApi(method: string, params: {}) { - if (!Comments.enabled) { - return Promise.reject('Comments are not currently enabled'); // eslint-disable-line + if (!Comments.url) { + return Promise.reject(new Error('Commenting server is not set.')); + } else if (!Comments.enabled) { + return Promise.reject('Comments are not currently enabled.'); // eslint-disable-line } const url = `${Comments.url}?m=${method}`; diff --git a/ui/component/settingCommentsServer/index.js b/ui/component/settingCommentsServer/index.js new file mode 100644 index 000000000..9ad06707b --- /dev/null +++ b/ui/component/settingCommentsServer/index.js @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import { SETTINGS } from 'lbry-redux'; +import { doSetClientSetting } from 'redux/actions/settings'; +import { makeSelectClientSetting } from 'redux/selectors/settings'; +import SettingCommentsServer from './view'; + +const select = (state) => ({ + customServerEnabled: makeSelectClientSetting(SETTINGS.CUSTOM_COMMENTS_SERVER_ENABLED)(state), + customServerUrl: makeSelectClientSetting(SETTINGS.CUSTOM_COMMENTS_SERVER_URL)(state), +}); + +const perform = (dispatch) => ({ + setCustomServerEnabled: (val) => dispatch(doSetClientSetting(SETTINGS.CUSTOM_COMMENTS_SERVER_ENABLED, val, true)), + setCustomServerUrl: (url) => dispatch(doSetClientSetting(SETTINGS.CUSTOM_COMMENTS_SERVER_URL, url, true)), +}); + +export default connect(select, perform)(SettingCommentsServer); diff --git a/ui/component/settingCommentsServer/view.jsx b/ui/component/settingCommentsServer/view.jsx new file mode 100644 index 000000000..5421398da --- /dev/null +++ b/ui/component/settingCommentsServer/view.jsx @@ -0,0 +1,70 @@ +// @flow +import { COMMENT_SERVER_NAME } from 'config'; +import React from 'react'; +import Comments from 'comments'; +import { FormField } from 'component/common/form'; + +const DEBOUNCE_TEXT_INPUT_MS = 500; + +type Props = { + customServerEnabled: boolean, + customServerUrl: string, + setCustomServerEnabled: (boolean) => void, + setCustomServerUrl: (string) => void, +}; + +function SettingCommentsServer(props: Props) { + const { customServerEnabled, customServerUrl, setCustomServerEnabled, setCustomServerUrl } = props; + const [customUrl, setCustomUrl] = React.useState(customServerUrl); + + React.useEffect(() => { + const timer = setTimeout(() => { + setCustomServerUrl(customUrl); + Comments.url = customUrl; + }, DEBOUNCE_TEXT_INPUT_MS); + + return () => clearTimeout(timer); + }, [customUrl, setCustomServerUrl]); + + return ( + + + { + if (e.target.checked) { + setCustomServerEnabled(false); + } + }} + /> + { + if (e.target.checked) { + setCustomServerEnabled(true); + } + }} + /> + + {customServerEnabled && ( +
+ setCustomUrl(e.target.value)} + /> +
+ )} +
+
+ ); +} + +export default SettingCommentsServer; diff --git a/ui/page/settingsAdvanced/view.jsx b/ui/page/settingsAdvanced/view.jsx index 4850d35f0..4807eaa9e 100644 --- a/ui/page/settingsAdvanced/view.jsx +++ b/ui/page/settingsAdvanced/view.jsx @@ -5,6 +5,7 @@ import { FormField, FormFieldPrice } from 'component/common/form'; import Button from 'component/button'; import I18nMessage from 'component/i18nMessage'; import Page from 'component/page'; +import SettingCommentsServer from 'component/settingCommentsServer'; import SettingWalletServer from 'component/settingWalletServer'; import SettingAutoLaunch from 'component/settingAutoLaunch'; import SettingClosingBehavior from 'component/settingClosingBehavior'; @@ -507,6 +508,10 @@ class SettingsAdvancedPage extends React.PureComponent { /> )} + {/* @if TARGET='app' */} + } /> + {/* @endif */} + } /> {/* @if TARGET='app' */} diff --git a/ui/redux/actions/comments.js b/ui/redux/actions/comments.js index 36bb55353..b4eac5e5e 100644 --- a/ui/redux/actions/comments.js +++ b/ui/redux/actions/comments.js @@ -28,6 +28,7 @@ import { selectPrefsReady } from 'redux/selectors/sync'; import { doAlertWaitingForSync } from 'redux/actions/app'; const isDev = process.env.NODE_ENV !== 'production'; +const FETCH_API_FAILED_TO_FETCH = 'Failed to fetch'; const COMMENTRON_MSG_REMAP = { // <-- Commentron msg --> : <-- App msg --> @@ -111,20 +112,32 @@ export function doCommentList( return result; }) .catch((error) => { - if (error.message === 'comments are disabled by the creator') { - dispatch({ - type: ACTIONS.COMMENT_LIST_COMPLETED, - data: { - authorClaimId: authorChannelClaim ? authorChannelClaim.claim_id : undefined, - disabled: true, - }, - }); - } else { - devToast(dispatch, `doCommentList: ${error.message}`); - dispatch({ - type: ACTIONS.COMMENT_LIST_FAILED, - data: error, - }); + switch (error.message) { + case 'comments are disabled by the creator': + dispatch({ + type: ACTIONS.COMMENT_LIST_COMPLETED, + data: { + authorClaimId: authorChannelClaim ? authorChannelClaim.claim_id : undefined, + disabled: true, + }, + }); + break; + + case FETCH_API_FAILED_TO_FETCH: + dispatch( + doToast({ + isError: true, + message: Comments.isCustomServer + ? __('Failed to fetch comments. Verify custom server settings.') + : __('Failed to fetch comments.'), + }) + ); + dispatch({ type: ACTIONS.COMMENT_LIST_FAILED, data: error }); + break; + + default: + dispatch(doToast({ isError: true, message: `${error.message}` })); + dispatch({ type: ACTIONS.COMMENT_LIST_FAILED, data: error }); } }); }; @@ -261,7 +274,6 @@ export function doCommentReactList(commentIds: Array) { }); }) .catch((error) => { - devToast(dispatch, `doCommentReactList: ${error.message}`); dispatch({ type: ACTIONS.COMMENT_REACTION_LIST_FAILED, data: error, diff --git a/ui/redux/reducers/settings.js b/ui/redux/reducers/settings.js index dc87fca6b..3b791e34a 100644 --- a/ui/redux/reducers/settings.js +++ b/ui/redux/reducers/settings.js @@ -4,6 +4,7 @@ import { ACTIONS as LBRY_REDUX_ACTIONS, SETTINGS, SHARED_PREFERENCES } from 'lbr import { getSubsetFromKeysArray } from 'util/sync-settings'; import { getDefaultLanguage } from 'util/default-languages'; import { UNSYNCED_SETTINGS, SIMPLE_SITE } from 'config'; +import Comments from 'comments'; const { CLIENT_SYNC_KEYS } = SHARED_PREFERENCES; const settingsToIgnore = (UNSYNCED_SETTINGS && UNSYNCED_SETTINGS.trim().split(' ')) || []; @@ -51,6 +52,8 @@ const defaultState = { [SETTINGS.VIDEO_THEATER_MODE]: false, [SETTINGS.VIDEO_PLAYBACK_RATE]: 1, [SETTINGS.DESKTOP_WINDOW_ZOOM]: 1, + [SETTINGS.CUSTOM_COMMENTS_SERVER_ENABLED]: false, + [SETTINGS.CUSTOM_COMMENTS_SERVER_URL]: '', [SETTINGS.DARK_MODE_TIMES]: { from: { hour: '21', min: '00', formattedTime: '21:00' }, @@ -169,6 +172,13 @@ reducers[LBRY_REDUX_ACTIONS.USER_STATE_POPULATE] = (state, action) => { const selectedSettings = sharedPreferences ? getSubsetFromKeysArray(sharedPreferences, clientSyncKeys) : {}; const mergedClientSettings = { ...currentClientSettings, ...selectedSettings }; const newSharedPreferences = sharedPreferences || {}; + + Comments.setServerUrl( + mergedClientSettings[SETTINGS.CUSTOM_COMMENTS_SERVER_ENABLED] + ? mergedClientSettings[SETTINGS.CUSTOM_COMMENTS_SERVER_URL] + : undefined + ); + return Object.assign({}, state, { sharedPreferences: newSharedPreferences, clientSettings: mergedClientSettings,