From ff9ca662f2dfba48da189bf6ed7b96e3bf55f7b9 Mon Sep 17 00:00:00 2001 From: infinite-persistence Date: Sun, 25 Jul 2021 20:52:45 +0800 Subject: [PATCH] Option to change commments-server (desktop) ## Issue > 5459 Add setting for changing your comment server. Visible on desktop (and possibly defaulting to Odysee URL), hidden on odysee. ## Comments Not sure how this would actually work properly without the user recompiling the app to handle server differences. For example, even when we use our own server but switch between v1 and v2, some code changes are need to handle the differences. At that point, it seems easier for the user to just change the .env file? Anyway... ## Changes - Added Desktop-only options to define custom server. [Settings > Advanced Settings > "Comment server" section]. --- .env.defaults | 1 + config.js | 1 + static/app-strings.json | 7 +++ ui/comments.js | 13 +++- ui/component/settingCommentsServer/index.js | 17 +++++ ui/component/settingCommentsServer/view.jsx | 70 +++++++++++++++++++++ ui/page/settingsAdvanced/view.jsx | 5 ++ ui/redux/actions/comments.js | 42 ++++++++----- ui/redux/reducers/settings.js | 10 +++ 9 files changed, 149 insertions(+), 17 deletions(-) create mode 100644 ui/component/settingCommentsServer/index.js create mode 100644 ui/component/settingCommentsServer/view.jsx 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,