feat: help centre
This commit is contained in:
parent
c5e693f14a
commit
57d14d9517
|
@ -757,6 +757,7 @@
|
||||||
"connectCalendarButton": "Connect your calendar",
|
"connectCalendarButton": "Connect your calendar",
|
||||||
"connectCalendarText": "Connect your calendar to view all your meetings in {{app}}. Plus, add {{provider}} meetings to your calendar and start them with one click.",
|
"connectCalendarText": "Connect your calendar to view all your meetings in {{app}}. Plus, add {{provider}} meetings to your calendar and start them with one click.",
|
||||||
"enterRoomTitle": "Start a new meeting",
|
"enterRoomTitle": "Start a new meeting",
|
||||||
|
"getHelp": "Get help",
|
||||||
"roomNameAllowedChars": "Meeting name should not contain any of these characters: ?, &, :, ', \", %, #.",
|
"roomNameAllowedChars": "Meeting name should not contain any of these characters: ?, &, :, ', \", %, #.",
|
||||||
"go": "GO",
|
"go": "GO",
|
||||||
"goSmall": "GO",
|
"goSmall": "GO",
|
||||||
|
@ -776,5 +777,8 @@
|
||||||
"lonelyMeetingExperience": {
|
"lonelyMeetingExperience": {
|
||||||
"button": "Invite others",
|
"button": "Invite others",
|
||||||
"youAreAlone": "You are the only one in the meeting"
|
"youAreAlone": "You are the only one in the meeting"
|
||||||
|
},
|
||||||
|
"helpView": {
|
||||||
|
"header": "Help centre"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,10 +89,22 @@ export class AbstractApp extends BaseApp<Props, *> {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<OverlayContainer />
|
<OverlayContainer />
|
||||||
|
{ this._createExtraPlatformSpecificElement() }
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders platform specific extra elements to be added alongside with the main element, if need be.
|
||||||
|
*
|
||||||
|
* NOTE: Overridden by child components.
|
||||||
|
*
|
||||||
|
* @returns {React$Element}
|
||||||
|
*/
|
||||||
|
_createExtraPlatformSpecificElement() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
_createMainElement: (React$Element<*>, Object) => ?React$Element<*>;
|
_createMainElement: (React$Element<*>, Object) => ?React$Element<*>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { Platform } from '../../base/react';
|
||||||
import '../../base/responsive-ui';
|
import '../../base/responsive-ui';
|
||||||
import { updateSettings } from '../../base/settings';
|
import { updateSettings } from '../../base/settings';
|
||||||
import '../../google-api';
|
import '../../google-api';
|
||||||
|
import { HelpView } from '../../help';
|
||||||
import '../../mobile/audio-mode';
|
import '../../mobile/audio-mode';
|
||||||
import '../../mobile/back-button';
|
import '../../mobile/back-button';
|
||||||
import '../../mobile/background';
|
import '../../mobile/background';
|
||||||
|
@ -107,6 +108,17 @@ export class App extends AbstractApp {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders platform specific extra elements to be added alongside with the main element, if need be.
|
||||||
|
*
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
_createExtraPlatformSpecificElement() {
|
||||||
|
return (
|
||||||
|
<HelpView />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to disable the use of React Native
|
* Attempts to disable the use of React Native
|
||||||
* {@link ExceptionsManager#handleException} on platforms and in
|
* {@link ExceptionsManager#handleException} on platforms and in
|
||||||
|
|
|
@ -39,6 +39,7 @@ export default {
|
||||||
statusBarContent: ColorPalette.white,
|
statusBarContent: ColorPalette.white,
|
||||||
text: ColorPalette.white
|
text: ColorPalette.white
|
||||||
},
|
},
|
||||||
|
'Modal': {},
|
||||||
'LargeVideo': {
|
'LargeVideo': {
|
||||||
background: 'rgb(42, 58, 75)'
|
background: 'rgb(42, 58, 75)'
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action type to set the ID of the active modal (or undefined if needs to be hidden).
|
||||||
|
*/
|
||||||
|
export const SET_ACTIVE_MODAL_ID = 'SET_ACTIVE_MODAL_ID';
|
|
@ -0,0 +1,19 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { SET_ACTIVE_MODAL_ID } from './actionTypes';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action to set the ID of the active modal (or undefined if needs to be hidden).
|
||||||
|
*
|
||||||
|
* @param {string} activeModalId - The new modal ID or undefined.
|
||||||
|
* @returns {{
|
||||||
|
* activeModalId: string,
|
||||||
|
* type: SET_ACTIVE_MODAL_ID
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
export function setActiveModalId(activeModalId: ?string) {
|
||||||
|
return {
|
||||||
|
activeModalId,
|
||||||
|
type: SET_ACTIVE_MODAL_ID
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import { SafeAreaView, View } from 'react-native';
|
||||||
|
|
||||||
|
import { ColorSchemeRegistry } from '../../color-scheme';
|
||||||
|
import { HeaderWithNavigation, SlidingView } from '../../react';
|
||||||
|
import { connect } from '../../redux';
|
||||||
|
import { StyleType } from '../../styles';
|
||||||
|
|
||||||
|
import { setActiveModalId } from '../actions';
|
||||||
|
|
||||||
|
import styles from './styles';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The color schemed style of the common header component.
|
||||||
|
*/
|
||||||
|
_headerStyles: StyleType,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the modal should be shown, false otherwise.
|
||||||
|
*/
|
||||||
|
_show: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The color schemed style of the modal.
|
||||||
|
*/
|
||||||
|
_styles: StyleType,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The children component(s) of the Modal, to be rendered.
|
||||||
|
*/
|
||||||
|
children: React$Node,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Redux Dispatch function.
|
||||||
|
*/
|
||||||
|
dispatch: Function,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The i18n label key of the header title.
|
||||||
|
*/
|
||||||
|
headerLabelKey: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID of the modal that is being rendered. This is used to show/hide the modal.
|
||||||
|
*/
|
||||||
|
modalId: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to be invoked when the modal closes.
|
||||||
|
*/
|
||||||
|
onClose?: Function,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The position from where the modal should be opened. This is derived from the
|
||||||
|
* props of the {@code SlidingView} with the same name.
|
||||||
|
*/
|
||||||
|
position?: string
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements a custom Jitsi Modal that doesn't use the built in native
|
||||||
|
* Modal component of React Native.
|
||||||
|
*/
|
||||||
|
class JitsiModal extends PureComponent<Props> {
|
||||||
|
static defaultProps = {
|
||||||
|
position: 'bottom'
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new component.
|
||||||
|
*
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this._onRequestClose = this._onRequestClose.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements {@code PureComponent#render}.
|
||||||
|
*
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
const { _headerStyles, _show, _styles, children, headerLabelKey, position } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SlidingView
|
||||||
|
onHide = { this._onRequestClose }
|
||||||
|
position = { position }
|
||||||
|
show = { _show }>
|
||||||
|
<View
|
||||||
|
style = { [
|
||||||
|
_headerStyles.page,
|
||||||
|
_styles.page
|
||||||
|
] }>
|
||||||
|
<HeaderWithNavigation
|
||||||
|
headerLabelKey = { headerLabelKey }
|
||||||
|
onPressBack = { this._onRequestClose } />
|
||||||
|
<SafeAreaView style = { styles.safeArea }>
|
||||||
|
{ children }
|
||||||
|
</SafeAreaView>
|
||||||
|
</View>
|
||||||
|
</SlidingView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onRequestClose: () => boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to be invoked when the SlidingView requests closing.
|
||||||
|
*
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
_onRequestClose() {
|
||||||
|
const { _show, dispatch, onClose } = this.props;
|
||||||
|
|
||||||
|
if (_show) {
|
||||||
|
if (typeof onClose === 'function') {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
dispatch(setActiveModalId());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps part of the Redix state to the props of this component.
|
||||||
|
*
|
||||||
|
* @param {Object} state - The Redux state.
|
||||||
|
* @param {Props} ownProps - The own props of the component.
|
||||||
|
* @returns {Props}
|
||||||
|
*/
|
||||||
|
function _mapStateToProps(state, ownProps): $Shape<Props> {
|
||||||
|
return {
|
||||||
|
_headerStyles: ColorSchemeRegistry.get(state, 'Header'),
|
||||||
|
_show: state['features/base/modal'].activeModalId === ownProps.modalId,
|
||||||
|
_styles: ColorSchemeRegistry.get(state, 'Modal')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(_mapStateToProps)(JitsiModal);
|
|
@ -0,0 +1,3 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
export { default as JitsiModal } from './JitsiModal';
|
|
@ -0,0 +1,6 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { Component } from 'react';
|
||||||
|
|
||||||
|
export const JitsiModal = Component;
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { ColorSchemeRegistry, schemeColor } from '../../color-scheme';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
safeArea: {
|
||||||
|
flex: 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ColorSchemeRegistry.register('Modal', {
|
||||||
|
page: {
|
||||||
|
backgroundColor: schemeColor('background')
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,7 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import './reducer';
|
||||||
|
|
||||||
|
export * from './actions';
|
||||||
|
export * from './actionTypes';
|
||||||
|
export * from './components';
|
|
@ -0,0 +1,17 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { ReducerRegistry } from '../redux';
|
||||||
|
|
||||||
|
import { SET_ACTIVE_MODAL_ID } from './actionTypes';
|
||||||
|
|
||||||
|
ReducerRegistry.register('features/base/modal', (state = {}, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case SET_ACTIVE_MODAL_ID:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
activeModalId: action.activeModalId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
});
|
|
@ -0,0 +1,54 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import WebView from 'react-native-webview';
|
||||||
|
|
||||||
|
import { JitsiModal } from '../../base/modal';
|
||||||
|
import { connect } from '../../base/redux';
|
||||||
|
|
||||||
|
import { HELP_VIEW_MODAL_ID } from '../constants';
|
||||||
|
|
||||||
|
const DEFAULT_HELP_CENTRE_URL = 'https://web-cdn.jitsi.net/faq/meet-faq.html';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL to display in the Help Centre.
|
||||||
|
*/
|
||||||
|
_url: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements a page that renders the help content for the app.
|
||||||
|
*/
|
||||||
|
class HelpView extends PureComponent<Props> {
|
||||||
|
/**
|
||||||
|
* Implements {@code PureComponent#render()}.
|
||||||
|
*
|
||||||
|
* @inheritdoc
|
||||||
|
* @returns {ReactElement}
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<JitsiModal
|
||||||
|
headerLabelKey = 'helpView.header'
|
||||||
|
modalId = { HELP_VIEW_MODAL_ID }>
|
||||||
|
<WebView source = {{ uri: this.props._url }} />
|
||||||
|
</JitsiModal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps part of the Redux state to the props of this component.
|
||||||
|
*
|
||||||
|
* @param {Object} state - The Redux state.
|
||||||
|
* @returns {Props}
|
||||||
|
*/
|
||||||
|
function _mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
_url: state['features/base/config'].helpCentreURL || DEFAULT_HELP_CENTRE_URL
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(_mapStateToProps)(HelpView);
|
|
@ -0,0 +1,3 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
export { default as HelpView } from './HelpView';
|
|
@ -0,0 +1,3 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
export const HELP_VIEW_MODAL_ID = 'helpView';
|
|
@ -0,0 +1,4 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
export * from './components';
|
||||||
|
export * from './constants';
|
|
@ -4,7 +4,8 @@ import React, { Component } from 'react';
|
||||||
import { SafeAreaView, ScrollView, Text } from 'react-native';
|
import { SafeAreaView, ScrollView, Text } from 'react-native';
|
||||||
|
|
||||||
import { Avatar } from '../../base/avatar';
|
import { Avatar } from '../../base/avatar';
|
||||||
import { IconInfo, IconSettings } from '../../base/icons';
|
import { IconInfo, IconSettings, IconHelp } from '../../base/icons';
|
||||||
|
import { setActiveModalId } from '../../base/modal';
|
||||||
import {
|
import {
|
||||||
getLocalParticipant,
|
getLocalParticipant,
|
||||||
getParticipantDisplayName
|
getParticipantDisplayName
|
||||||
|
@ -14,6 +15,7 @@ import {
|
||||||
SlidingView
|
SlidingView
|
||||||
} from '../../base/react';
|
} from '../../base/react';
|
||||||
import { connect } from '../../base/redux';
|
import { connect } from '../../base/redux';
|
||||||
|
import { HELP_VIEW_MODAL_ID } from '../../help';
|
||||||
import { setSettingsViewVisible } from '../../settings';
|
import { setSettingsViewVisible } from '../../settings';
|
||||||
|
|
||||||
import { setSideBarVisible } from '../actions';
|
import { setSideBarVisible } from '../actions';
|
||||||
|
@ -25,11 +27,6 @@ import styles, { SIDEBAR_AVATAR_SIZE } from './styles';
|
||||||
*/
|
*/
|
||||||
const PRIVACY_URL = 'https://jitsi.org/meet/privacy';
|
const PRIVACY_URL = 'https://jitsi.org/meet/privacy';
|
||||||
|
|
||||||
/**
|
|
||||||
* The URL at which the user may send feedback.
|
|
||||||
*/
|
|
||||||
const SEND_FEEDBACK_URL = 'mailto:support@jitsi.org';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The URL at which the terms (of service/use) are available to the user.
|
* The URL at which the terms (of service/use) are available to the user.
|
||||||
*/
|
*/
|
||||||
|
@ -72,6 +69,7 @@ class WelcomePageSideBar extends Component<Props> {
|
||||||
|
|
||||||
// Bind event handlers so they are only bound once per instance.
|
// Bind event handlers so they are only bound once per instance.
|
||||||
this._onHideSideBar = this._onHideSideBar.bind(this);
|
this._onHideSideBar = this._onHideSideBar.bind(this);
|
||||||
|
this._onOpenHelpPage = this._onOpenHelpPage.bind(this);
|
||||||
this._onOpenSettings = this._onOpenSettings.bind(this);
|
this._onOpenSettings = this._onOpenSettings.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,9 +110,9 @@ class WelcomePageSideBar extends Component<Props> {
|
||||||
label = 'welcomepage.privacy'
|
label = 'welcomepage.privacy'
|
||||||
url = { PRIVACY_URL } />
|
url = { PRIVACY_URL } />
|
||||||
<SideBarItem
|
<SideBarItem
|
||||||
icon = { IconInfo }
|
icon = { IconHelp }
|
||||||
label = 'welcomepage.sendFeedback'
|
label = 'welcomepage.getHelp'
|
||||||
url = { SEND_FEEDBACK_URL } />
|
onPress = { this._onOpenHelpPage } />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
</SlidingView>
|
</SlidingView>
|
||||||
|
@ -133,6 +131,20 @@ class WelcomePageSideBar extends Component<Props> {
|
||||||
this.props.dispatch(setSideBarVisible(false));
|
this.props.dispatch(setSideBarVisible(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onOpenHelpPage: () => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the {@link HelpView}.
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_onOpenHelpPage() {
|
||||||
|
const { dispatch } = this.props;
|
||||||
|
|
||||||
|
dispatch(setSideBarVisible(false));
|
||||||
|
dispatch(setActiveModalId(HELP_VIEW_MODAL_ID));
|
||||||
|
}
|
||||||
|
|
||||||
_onOpenSettings: () => void;
|
_onOpenSettings: () => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue