diff --git a/config.js b/config.js index cd10908a6..a0f75464f 100644 --- a/config.js +++ b/config.js @@ -419,6 +419,10 @@ var config = { // the menu has option to flip the locally seen video for local presentations // disableLocalVideoFlip: false + // If specified a 'Help' button will be displayed in the overflow menu with a link to the specified URL for + // user documentation. + // userDocumentationURL: 'https://docs.example.com/video-meetings.html' + // List of undocumented settings used in jitsi-meet /** _immediateReloadThreshold diff --git a/interface_config.js b/interface_config.js index d340a7f05..1bb86142d 100644 --- a/interface_config.js +++ b/interface_config.js @@ -189,12 +189,6 @@ var interfaceConfig = { */ AUTO_PIN_LATEST_SCREEN_SHARE: 'remote-only' - /** - * The link to the user documentation. - */ - // HELP_LINK: 'https://docs.example.com/video-meetings.html', - - /** * How many columns the tile view can expand to. The respected range is * between 1 and 5. diff --git a/react/features/base/util/index.js b/react/features/base/util/index.js index 85b614aec..57946dadb 100644 --- a/react/features/base/util/index.js +++ b/react/features/base/util/index.js @@ -1,4 +1,5 @@ export * from './helpers'; export * from './httpUtils'; export * from './loadScript'; +export * from './openURLInBrowser'; export * from './uri'; diff --git a/react/features/base/util/logger.js b/react/features/base/util/logger.js new file mode 100644 index 000000000..82d31be58 --- /dev/null +++ b/react/features/base/util/logger.js @@ -0,0 +1,5 @@ +// @flow + +import { getLogger } from '../logging/functions'; + +export default getLogger('features/base/util'); diff --git a/react/features/base/util/openURLInBrowser.native.js b/react/features/base/util/openURLInBrowser.native.js new file mode 100644 index 000000000..de12b5fbb --- /dev/null +++ b/react/features/base/util/openURLInBrowser.native.js @@ -0,0 +1,17 @@ +// @flow + +import { Linking } from 'react-native'; + +import logger from './logger'; + +/** + * Opens URL in the browser. + * + * @param {string} url - The URL to be opened. + * @returns {void} + */ +export function openURLInBrowser(url: string) { + Linking.openURL(url).catch(error => { + logger.error(`An error occurred while trying to open ${url}`, error); + }); +} diff --git a/react/features/base/util/openURLInBrowser.web.js b/react/features/base/util/openURLInBrowser.web.js new file mode 100644 index 000000000..cee50e12e --- /dev/null +++ b/react/features/base/util/openURLInBrowser.web.js @@ -0,0 +1,11 @@ +// @flow + +/** + * Opens URL in the browser. + * + * @param {string} url - The URL to be opened. + * @returns {void} + */ +export function openURLInBrowser(url: string) { + window.open(url, '', 'noopener'); +} diff --git a/react/features/toolbox/components/HelpButton.js b/react/features/toolbox/components/HelpButton.js new file mode 100644 index 000000000..7352e724d --- /dev/null +++ b/react/features/toolbox/components/HelpButton.js @@ -0,0 +1,56 @@ +// @flow + +import { createToolbarEvent, sendAnalytics } from '../../analytics'; +import { translate } from '../../base/i18n'; +import { IconHelp } from '../../base/icons'; +import { connect } from '../../base/redux'; +import { openURLInBrowser } from '../../base/util'; +import { AbstractButton, type AbstractButtonProps } from '../../base/toolbox'; + + +type Props = AbstractButtonProps & { + + /** + * The URL to the user documenation. + */ + _userDocumentationURL: string +}; + +/** + * Implements an {@link AbstractButton} to open the user documentation in a new window. + */ +class HelpButton extends AbstractButton { + accessibilityLabel = 'toolbar.accessibilityLabel.help'; + icon = IconHelp; + label = 'toolbar.help'; + + /** + * Handles clicking / pressing the button, and opens a new window with the user documentation. + * + * @private + * @returns {void} + */ + _handleClick() { + sendAnalytics(createToolbarEvent('help.pressed')); + openURLInBrowser(this.props._userDocumentationURL); + } +} + + +/** + * Maps part of the redux state to the component's props. + * + * @param {Object} state - The redux store/state. + * @returns {Object} + */ +function _mapStateToProps(state: Object) { + const { userDocumentationURL } = state['features/base/config']; + const visible = typeof userDocumentationURL === 'string'; + + return { + _userDocumentationURL: userDocumentationURL, + visible + }; +} + +export default translate(connect(_mapStateToProps)(HelpButton)); diff --git a/react/features/toolbox/components/native/OverflowMenu.js b/react/features/toolbox/components/native/OverflowMenu.js index 51391b493..6483039a5 100644 --- a/react/features/toolbox/components/native/OverflowMenu.js +++ b/react/features/toolbox/components/native/OverflowMenu.js @@ -17,6 +17,7 @@ import { ClosedCaptionButton } from '../../../subtitles'; import { TileViewButton } from '../../../video-layout'; import AudioOnlyButton from './AudioOnlyButton'; +import HelpButton from '../HelpButton'; import RaiseHandButton from './RaiseHandButton'; import ToggleCameraButton from './ToggleCameraButton'; @@ -110,6 +111,7 @@ class OverflowMenu extends Component { } + ); } diff --git a/react/features/toolbox/components/web/HelpButton.js b/react/features/toolbox/components/web/HelpButton.js deleted file mode 100644 index 1a3b4c4ea..000000000 --- a/react/features/toolbox/components/web/HelpButton.js +++ /dev/null @@ -1,44 +0,0 @@ -// @flow - -import { createToolbarEvent, sendAnalytics } from '../../../analytics'; -import { translate } from '../../../base/i18n'; -import { IconHelp } from '../../../base/icons'; -import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox'; - -declare var interfaceConfig: Object; - -/** - * Implements an {@link AbstractButton} to open the user documentation in a new window. - */ -class HelpButton extends AbstractButton { - accessibilityLabel = 'toolbar.accessibilityLabel.help'; - icon = IconHelp; - label = 'toolbar.help'; - - /** - * Handles clicking / pressing the button, and opens a new window with the user documentation. - * - * @private - * @returns {void} - */ - _handleClick() { - sendAnalytics(createToolbarEvent('help.pressed')); - window.open(interfaceConfig.HELP_LINK); - } - - /** - * Implements React's {@link Component#render()}. - * - * @inheritdoc - * @returns {React$Node} - */ - render(): React$Node { - if (typeof interfaceConfig.HELP_LINK === 'string') { - return super.render(); - } - - return null; - } -} - -export default translate(HelpButton); diff --git a/react/features/toolbox/components/web/Toolbox.js b/react/features/toolbox/components/web/Toolbox.js index 6488c080c..b9354fb6d 100644 --- a/react/features/toolbox/components/web/Toolbox.js +++ b/react/features/toolbox/components/web/Toolbox.js @@ -71,7 +71,7 @@ import { import AudioMuteButton from '../AudioMuteButton'; import { isToolboxVisible } from '../../functions'; import HangupButton from '../HangupButton'; -import HelpButton from './HelpButton'; +import HelpButton from '../HelpButton'; import OverflowMenuButton from './OverflowMenuButton'; import OverflowMenuProfileItem from './OverflowMenuProfileItem'; import ToolbarButton from './ToolbarButton';