From dce101c1bdea9a65308776a2a17e3090a72d1f37 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]. --- package.json | 2 +- static/app-strings.json | 7 +++ ui/comments.js | 13 +++- ui/component/settingCommentsServer/index.js | 17 +++++ ui/component/settingCommentsServer/view.jsx | 69 +++++++++++++++++++++ ui/page/settingsAdvanced/view.jsx | 5 ++ ui/redux/actions/comments.js | 43 ++++++++----- ui/redux/reducers/settings.js | 10 +++ web/package.json | 2 +- web/yarn.lock | 4 +- yarn.lock | 4 +- 11 files changed, 153 insertions(+), 23 deletions(-) create mode 100644 ui/component/settingCommentsServer/index.js create mode 100644 ui/component/settingCommentsServer/view.jsx diff --git a/package.json b/package.json index 7bcf84d59..1d8b5f729 100644 --- a/package.json +++ b/package.json @@ -152,7 +152,7 @@ "imagesloaded": "^4.1.4", "json-loader": "^0.5.4", "lbry-format": "https://github.com/lbryio/lbry-format.git", - "lbry-redux": "lbryio/lbry-redux#a327385cdf71568dbd15a17f3dcf5f4b83e0966d", + "lbry-redux": "lbryio/lbry-redux#aabae5ce5922ad019b7db9a6b6e551cfad50d49d", "lbryinc": "lbryio/lbryinc#8f9a58bfc8312a65614fd7327661cdcc502c4e59", "lint-staged": "^7.0.2", "localforage": "^1.7.1", diff --git a/static/app-strings.json b/static/app-strings.json index e0e559fa5..5a9db255f 100644 --- a/static/app-strings.json +++ b/static/app-strings.json @@ -2034,6 +2034,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", + "Use official Odysee comments server": "Use official Odysee comments server", + "Use custom comments server": "Use 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.", + "Comments-server URL not defined.": "Comments-server URL not defined.", + "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..ef2e9cb86 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('Comments-server URL not defined.')); + } 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..48f8e302f --- /dev/null +++ b/ui/component/settingCommentsServer/view.jsx @@ -0,0 +1,69 @@ +// @flow +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 77cfe58df..d51da8081 100644 --- a/ui/redux/actions/comments.js +++ b/ui/redux/actions/comments.js @@ -29,6 +29,8 @@ import { doAlertWaitingForSync } from 'redux/actions/app'; const isDev = process.env.NODE_ENV !== 'production'; +const FETCH_API_FAILED_TO_FETCH = 'Failed to fetch'; + function devToast(dispatch, msg) { if (isDev) { console.error(msg); // eslint-disable-line @@ -96,20 +98,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 }); } }); }; @@ -246,7 +260,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, diff --git a/web/package.json b/web/package.json index c75e33d12..b2bbb812f 100644 --- a/web/package.json +++ b/web/package.json @@ -31,7 +31,7 @@ "koa-logger": "^3.2.1", "koa-send": "^5.0.0", "koa-static": "^5.0.0", - "lbry-redux": "lbryio/lbry-redux#508e8d36fd91106beb7d6b4edb9f726dae0e6264", + "lbry-redux": "lbryio/lbry-redux#aabae5ce5922ad019b7db9a6b6e551cfad50d49d", "lbryinc": "lbryio/lbryinc#8f9a58bfc8312a65614fd7327661cdcc502c4e59", "mysql": "^2.17.1", "node-fetch": "^2.6.1", diff --git a/web/yarn.lock b/web/yarn.lock index 3a43acd81..6f642593d 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -3331,9 +3331,9 @@ latest-version@^3.0.0: dependencies: package-json "^4.0.0" -lbry-redux@lbryio/lbry-redux#508e8d36fd91106beb7d6b4edb9f726dae0e6264: +lbry-redux@lbryio/lbry-redux#aabae5ce5922ad019b7db9a6b6e551cfad50d49d: version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/508e8d36fd91106beb7d6b4edb9f726dae0e6264" + resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/aabae5ce5922ad019b7db9a6b6e551cfad50d49d" dependencies: proxy-polyfill "0.1.6" reselect "^3.0.0" diff --git a/yarn.lock b/yarn.lock index c5df20d3d..dff12a877 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10136,9 +10136,9 @@ lazy-val@^1.0.4: yargs "^13.2.2" zstd-codec "^0.1.1" -lbry-redux@lbryio/lbry-redux#a327385cdf71568dbd15a17f3dcf5f4b83e0966d: +lbry-redux@lbryio/lbry-redux#aabae5ce5922ad019b7db9a6b6e551cfad50d49d: version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/a327385cdf71568dbd15a17f3dcf5f4b83e0966d" + resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/aabae5ce5922ad019b7db9a6b6e551cfad50d49d" dependencies: proxy-polyfill "0.1.6" reselect "^3.0.0"