浏览代码

feat: help centre

j8
Bettenbuk Zoltan 5 年前
父节点
当前提交
57d14d9517

+ 4
- 0
lang/main.json 查看文件

@@ -757,6 +757,7 @@
757 757
         "connectCalendarButton": "Connect your calendar",
758 758
         "connectCalendarText": "Connect your calendar to view all your meetings in {{app}}. Plus, add {{provider}} meetings to your calendar and start them with one click.",
759 759
         "enterRoomTitle": "Start a new meeting",
760
+        "getHelp": "Get help",
760 761
         "roomNameAllowedChars": "Meeting name should not contain any of these characters: ?, &, :, ', \", %, #.",
761 762
         "go": "GO",
762 763
         "goSmall": "GO",
@@ -776,5 +777,8 @@
776 777
     "lonelyMeetingExperience": {
777 778
         "button": "Invite others",
778 779
         "youAreAlone": "You are the only one in the meeting"
780
+    },
781
+    "helpView": {
782
+        "header": "Help centre"
779 783
     }
780 784
 }

+ 12
- 0
react/features/app/components/AbstractApp.js 查看文件

@@ -89,10 +89,22 @@ export class AbstractApp extends BaseApp<Props, *> {
89 89
         return (
90 90
             <Fragment>
91 91
                 <OverlayContainer />
92
+                { this._createExtraPlatformSpecificElement() }
92 93
             </Fragment>
93 94
         );
94 95
     }
95 96
 
97
+    /**
98
+     * Renders platform specific extra elements to be added alongside with the main element, if need be.
99
+     *
100
+     * NOTE: Overridden by child components.
101
+     *
102
+     * @returns {React$Element}
103
+     */
104
+    _createExtraPlatformSpecificElement() {
105
+        return null;
106
+    }
107
+
96 108
     _createMainElement: (React$Element<*>, Object) => ?React$Element<*>;
97 109
 
98 110
     /**

+ 12
- 0
react/features/app/components/App.native.js 查看文件

@@ -12,6 +12,7 @@ import { Platform } from '../../base/react';
12 12
 import '../../base/responsive-ui';
13 13
 import { updateSettings } from '../../base/settings';
14 14
 import '../../google-api';
15
+import { HelpView } from '../../help';
15 16
 import '../../mobile/audio-mode';
16 17
 import '../../mobile/back-button';
17 18
 import '../../mobile/background';
@@ -107,6 +108,17 @@ export class App extends AbstractApp {
107 108
         });
108 109
     }
109 110
 
111
+    /**
112
+     * Renders platform specific extra elements to be added alongside with the main element, if need be.
113
+     *
114
+     * @inheritdoc
115
+     */
116
+    _createExtraPlatformSpecificElement() {
117
+        return (
118
+            <HelpView />
119
+        );
120
+    }
121
+
110 122
     /**
111 123
      * Attempts to disable the use of React Native
112 124
      * {@link ExceptionsManager#handleException} on platforms and in

+ 1
- 0
react/features/base/color-scheme/defaultScheme.js 查看文件

@@ -39,6 +39,7 @@ export default {
39 39
         statusBarContent: ColorPalette.white,
40 40
         text: ColorPalette.white
41 41
     },
42
+    'Modal': {},
42 43
     'LargeVideo': {
43 44
         background: 'rgb(42, 58, 75)'
44 45
     },

+ 6
- 0
react/features/base/modal/actionTypes.js 查看文件

@@ -0,0 +1,6 @@
1
+// @flow
2
+
3
+/**
4
+ * Action type to set the ID of the active modal (or undefined if needs to be hidden).
5
+ */
6
+export const SET_ACTIVE_MODAL_ID = 'SET_ACTIVE_MODAL_ID';

+ 19
- 0
react/features/base/modal/actions.js 查看文件

@@ -0,0 +1,19 @@
1
+// @flow
2
+
3
+import { SET_ACTIVE_MODAL_ID } from './actionTypes';
4
+
5
+/**
6
+ * Action to set the ID of the active modal (or undefined if needs to be hidden).
7
+ *
8
+ * @param {string} activeModalId - The new modal ID or undefined.
9
+ * @returns {{
10
+ *     activeModalId: string,
11
+ *     type: SET_ACTIVE_MODAL_ID
12
+ * }}
13
+ */
14
+export function setActiveModalId(activeModalId: ?string) {
15
+    return {
16
+        activeModalId,
17
+        type: SET_ACTIVE_MODAL_ID
18
+    };
19
+}

+ 151
- 0
react/features/base/modal/components/JitsiModal.js 查看文件

@@ -0,0 +1,151 @@
1
+// @flow
2
+
3
+import React, { PureComponent } from 'react';
4
+import { SafeAreaView, View } from 'react-native';
5
+
6
+import { ColorSchemeRegistry } from '../../color-scheme';
7
+import { HeaderWithNavigation, SlidingView } from '../../react';
8
+import { connect } from '../../redux';
9
+import { StyleType } from '../../styles';
10
+
11
+import { setActiveModalId } from '../actions';
12
+
13
+import styles from './styles';
14
+
15
+type Props = {
16
+
17
+    /**
18
+     * The color schemed style of the common header component.
19
+     */
20
+    _headerStyles: StyleType,
21
+
22
+    /**
23
+     * True if the modal should be shown, false otherwise.
24
+     */
25
+    _show: boolean,
26
+
27
+    /**
28
+     * The color schemed style of the modal.
29
+     */
30
+    _styles: StyleType,
31
+
32
+    /**
33
+     * The children component(s) of the Modal, to be rendered.
34
+     */
35
+    children: React$Node,
36
+
37
+    /**
38
+     * The Redux Dispatch function.
39
+     */
40
+    dispatch: Function,
41
+
42
+    /**
43
+     * The i18n label key of the header title.
44
+     */
45
+    headerLabelKey: string,
46
+
47
+    /**
48
+     * The ID of the modal that is being rendered. This is used to show/hide the modal.
49
+     */
50
+    modalId: string,
51
+
52
+    /**
53
+     * Callback to be invoked when the modal closes.
54
+     */
55
+    onClose?: Function,
56
+
57
+    /**
58
+     * The position from where the modal should be opened. This is derived from the
59
+     * props of the {@code SlidingView} with the same name.
60
+     */
61
+    position?: string
62
+};
63
+
64
+/**
65
+ * Implements a custom Jitsi Modal that doesn't use the built in native
66
+ * Modal component of React Native.
67
+ */
68
+class JitsiModal extends PureComponent<Props> {
69
+    static defaultProps = {
70
+        position: 'bottom'
71
+    };
72
+
73
+    /**
74
+     * Instantiates a new component.
75
+     *
76
+     * @inheritdoc
77
+     */
78
+    constructor(props: Props) {
79
+        super(props);
80
+
81
+        this._onRequestClose = this._onRequestClose.bind(this);
82
+    }
83
+
84
+    /**
85
+     * Implements {@code PureComponent#render}.
86
+     *
87
+     * @inheritdoc
88
+     */
89
+    render() {
90
+        const { _headerStyles, _show, _styles, children, headerLabelKey, position } = this.props;
91
+
92
+        return (
93
+            <SlidingView
94
+                onHide = { this._onRequestClose }
95
+                position = { position }
96
+                show = { _show }>
97
+                <View
98
+                    style = { [
99
+                        _headerStyles.page,
100
+                        _styles.page
101
+                    ] }>
102
+                    <HeaderWithNavigation
103
+                        headerLabelKey = { headerLabelKey }
104
+                        onPressBack = { this._onRequestClose } />
105
+                    <SafeAreaView style = { styles.safeArea }>
106
+                        { children }
107
+                    </SafeAreaView>
108
+                </View>
109
+            </SlidingView>
110
+        );
111
+    }
112
+
113
+    _onRequestClose: () => boolean;
114
+
115
+    /**
116
+     * Callback to be invoked when the SlidingView requests closing.
117
+     *
118
+     * @returns {boolean}
119
+     */
120
+    _onRequestClose() {
121
+        const { _show, dispatch, onClose } = this.props;
122
+
123
+        if (_show) {
124
+            if (typeof onClose === 'function') {
125
+                onClose();
126
+            }
127
+            dispatch(setActiveModalId());
128
+
129
+            return true;
130
+        }
131
+
132
+        return false;
133
+    }
134
+}
135
+
136
+/**
137
+ * Maps part of the Redix state to the props of this component.
138
+ *
139
+ * @param {Object} state - The Redux state.
140
+ * @param {Props} ownProps - The own props of the component.
141
+ * @returns {Props}
142
+ */
143
+function _mapStateToProps(state, ownProps): $Shape<Props> {
144
+    return {
145
+        _headerStyles: ColorSchemeRegistry.get(state, 'Header'),
146
+        _show: state['features/base/modal'].activeModalId === ownProps.modalId,
147
+        _styles: ColorSchemeRegistry.get(state, 'Modal')
148
+    };
149
+}
150
+
151
+export default connect(_mapStateToProps)(JitsiModal);

+ 3
- 0
react/features/base/modal/components/index.native.js 查看文件

@@ -0,0 +1,3 @@
1
+// @flow
2
+
3
+export { default as JitsiModal } from './JitsiModal';

+ 6
- 0
react/features/base/modal/components/index.web.js 查看文件

@@ -0,0 +1,6 @@
1
+// @flow
2
+
3
+import { Component } from 'react';
4
+
5
+export const JitsiModal = Component;
6
+

+ 15
- 0
react/features/base/modal/components/styles.js 查看文件

@@ -0,0 +1,15 @@
1
+// @flow
2
+
3
+import { ColorSchemeRegistry, schemeColor } from '../../color-scheme';
4
+
5
+export default {
6
+    safeArea: {
7
+        flex: 1
8
+    }
9
+};
10
+
11
+ColorSchemeRegistry.register('Modal', {
12
+    page: {
13
+        backgroundColor: schemeColor('background')
14
+    }
15
+});

+ 7
- 0
react/features/base/modal/index.js 查看文件

@@ -0,0 +1,7 @@
1
+// @flow
2
+
3
+import './reducer';
4
+
5
+export * from './actions';
6
+export * from './actionTypes';
7
+export * from './components';

+ 17
- 0
react/features/base/modal/reducer.js 查看文件

@@ -0,0 +1,17 @@
1
+// @flow
2
+
3
+import { ReducerRegistry } from '../redux';
4
+
5
+import { SET_ACTIVE_MODAL_ID } from './actionTypes';
6
+
7
+ReducerRegistry.register('features/base/modal', (state = {}, action) => {
8
+    switch (action.type) {
9
+    case SET_ACTIVE_MODAL_ID:
10
+        return {
11
+            ...state,
12
+            activeModalId: action.activeModalId
13
+        };
14
+    }
15
+
16
+    return state;
17
+});

+ 54
- 0
react/features/help/components/HelpView.js 查看文件

@@ -0,0 +1,54 @@
1
+// @flow
2
+
3
+import React, { PureComponent } from 'react';
4
+import WebView from 'react-native-webview';
5
+
6
+import { JitsiModal } from '../../base/modal';
7
+import { connect } from '../../base/redux';
8
+
9
+import { HELP_VIEW_MODAL_ID } from '../constants';
10
+
11
+const DEFAULT_HELP_CENTRE_URL = 'https://web-cdn.jitsi.net/faq/meet-faq.html';
12
+
13
+type Props = {
14
+
15
+    /**
16
+     * The URL to display in the Help Centre.
17
+     */
18
+    _url: string
19
+}
20
+
21
+/**
22
+ * Implements a page that renders the help content for the app.
23
+ */
24
+class HelpView extends PureComponent<Props> {
25
+    /**
26
+     * Implements {@code PureComponent#render()}.
27
+     *
28
+     * @inheritdoc
29
+     * @returns {ReactElement}
30
+     */
31
+    render() {
32
+        return (
33
+            <JitsiModal
34
+                headerLabelKey = 'helpView.header'
35
+                modalId = { HELP_VIEW_MODAL_ID }>
36
+                <WebView source = {{ uri: this.props._url }} />
37
+            </JitsiModal>
38
+        );
39
+    }
40
+}
41
+
42
+/**
43
+ * Maps part of the Redux state to the props of this component.
44
+ *
45
+ * @param {Object} state - The Redux state.
46
+ * @returns {Props}
47
+ */
48
+function _mapStateToProps(state) {
49
+    return {
50
+        _url: state['features/base/config'].helpCentreURL || DEFAULT_HELP_CENTRE_URL
51
+    };
52
+}
53
+
54
+export default connect(_mapStateToProps)(HelpView);

+ 3
- 0
react/features/help/components/index.js 查看文件

@@ -0,0 +1,3 @@
1
+// @flow
2
+
3
+export { default as HelpView } from './HelpView';

+ 3
- 0
react/features/help/constants.js 查看文件

@@ -0,0 +1,3 @@
1
+// @flow
2
+
3
+export const HELP_VIEW_MODAL_ID = 'helpView';

+ 4
- 0
react/features/help/index.js 查看文件

@@ -0,0 +1,4 @@
1
+// @flow
2
+
3
+export * from './components';
4
+export * from './constants';

+ 21
- 9
react/features/welcome/components/WelcomePageSideBar.native.js 查看文件

@@ -4,7 +4,8 @@ import React, { Component } from 'react';
4 4
 import { SafeAreaView, ScrollView, Text } from 'react-native';
5 5
 
6 6
 import { Avatar } from '../../base/avatar';
7
-import { IconInfo, IconSettings } from '../../base/icons';
7
+import { IconInfo, IconSettings, IconHelp } from '../../base/icons';
8
+import { setActiveModalId } from '../../base/modal';
8 9
 import {
9 10
     getLocalParticipant,
10 11
     getParticipantDisplayName
@@ -14,6 +15,7 @@ import {
14 15
     SlidingView
15 16
 } from '../../base/react';
16 17
 import { connect } from '../../base/redux';
18
+import { HELP_VIEW_MODAL_ID } from '../../help';
17 19
 import { setSettingsViewVisible } from '../../settings';
18 20
 
19 21
 import { setSideBarVisible } from '../actions';
@@ -25,11 +27,6 @@ import styles, { SIDEBAR_AVATAR_SIZE } from './styles';
25 27
  */
26 28
 const PRIVACY_URL = 'https://jitsi.org/meet/privacy';
27 29
 
28
-/**
29
- * The URL at which the user may send feedback.
30
- */
31
-const SEND_FEEDBACK_URL = 'mailto:support@jitsi.org';
32
-
33 30
 /**
34 31
  * The URL at which the terms (of service/use) are available to the user.
35 32
  */
@@ -72,6 +69,7 @@ class WelcomePageSideBar extends Component<Props> {
72 69
 
73 70
         // Bind event handlers so they are only bound once per instance.
74 71
         this._onHideSideBar = this._onHideSideBar.bind(this);
72
+        this._onOpenHelpPage = this._onOpenHelpPage.bind(this);
75 73
         this._onOpenSettings = this._onOpenSettings.bind(this);
76 74
     }
77 75
 
@@ -112,9 +110,9 @@ class WelcomePageSideBar extends Component<Props> {
112 110
                             label = 'welcomepage.privacy'
113 111
                             url = { PRIVACY_URL } />
114 112
                         <SideBarItem
115
-                            icon = { IconInfo }
116
-                            label = 'welcomepage.sendFeedback'
117
-                            url = { SEND_FEEDBACK_URL } />
113
+                            icon = { IconHelp }
114
+                            label = 'welcomepage.getHelp'
115
+                            onPress = { this._onOpenHelpPage } />
118 116
                     </ScrollView>
119 117
                 </SafeAreaView>
120 118
             </SlidingView>
@@ -133,6 +131,20 @@ class WelcomePageSideBar extends Component<Props> {
133 131
         this.props.dispatch(setSideBarVisible(false));
134 132
     }
135 133
 
134
+    _onOpenHelpPage: () => void;
135
+
136
+    /**
137
+     * Shows the {@link HelpView}.
138
+     *
139
+     * @returns {void}
140
+     */
141
+    _onOpenHelpPage() {
142
+        const { dispatch } = this.props;
143
+
144
+        dispatch(setSideBarVisible(false));
145
+        dispatch(setActiveModalId(HELP_VIEW_MODAL_ID));
146
+    }
147
+
136 148
     _onOpenSettings: () => void;
137 149
 
138 150
     /**

正在加载...
取消
保存