瀏覽代碼

feat(shortcuts) Update dialog (#12993)

Create Shortcuts tab in Settings Dialog
Move keyboard shortcut option from More to this tab
Move shortcuts info from KeyboardShortcuts dialog to this tab
Remove KeyboardShortcuts dialog
factor2
Robert Pintilii 2 年之前
父節點
當前提交
7b8b911fee
No account linked to committer's email address

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

@@ -1006,6 +1006,7 @@
1006 1006
         "selectCamera": "Camera",
1007 1007
         "selectMic": "Microphone",
1008 1008
         "selfView": "Self view",
1009
+        "shortcuts": "Shortcuts",
1009 1010
         "speakers": "Speakers",
1010 1011
         "startAudioMuted": "Everyone starts muted",
1011 1012
         "startReactionsMuted": "Mute reaction sounds for everyone",

+ 8
- 7
modules/keyboardshortcut/keyboardshortcut.js 查看文件

@@ -8,10 +8,9 @@ import {
8 8
     createShortcutEvent,
9 9
     sendAnalytics
10 10
 } from '../../react/features/analytics';
11
-import { toggleDialog } from '../../react/features/base/dialog';
12 11
 import { clickOnVideo } from '../../react/features/filmstrip/actions';
13
-import { KeyboardShortcutsDialog }
14
-    from '../../react/features/keyboard-shortcuts';
12
+import { openSettingsDialog } from '../../react/features/settings/actions';
13
+import { SETTINGS_TABS } from '../../react/features/settings/constants';
15 14
 
16 15
 const logger = Logger.getLogger(__filename);
17 16
 
@@ -120,15 +119,17 @@ const KeyboardShortcut = {
120 119
         return jitsiLocalStorage.getItem(_enableShortcutsKey) === 'false' ? false : true;
121 120
     },
122 121
 
122
+    getShortcutsDescriptions() {
123
+        return _shortcutsHelp;
124
+    },
125
+
123 126
     /**
124
-     * Opens the {@KeyboardShortcutsDialog} dialog.
127
+     * Opens the {@SettingsDialog} dialog on the  Shortcuts page.
125 128
      *
126 129
      * @returns {void}
127 130
      */
128 131
     openDialog() {
129
-        APP.store.dispatch(toggleDialog(KeyboardShortcutsDialog, {
130
-            shortcutDescriptions: _shortcutsHelp
131
-        }));
132
+        APP.store.dispatch(openSettingsDialog(SETTINGS_TABS.SHORTCUTS, false));
132 133
     },
133 134
 
134 135
     /**

+ 0
- 1
react/features/app/middlewares.web.ts 查看文件

@@ -5,7 +5,6 @@ import '../base/media/middleware';
5 5
 import '../dynamic-branding/middleware';
6 6
 import '../e2ee/middleware';
7 7
 import '../external-api/middleware';
8
-import '../keyboard-shortcuts/middleware';
9 8
 import '../no-audio-signal/middleware';
10 9
 import '../notifications/middleware';
11 10
 import '../noise-detection/middleware';

+ 1
- 0
react/features/base/ui/components/web/DialogWithTabs.tsx 查看文件

@@ -131,6 +131,7 @@ const useStyles = makeStyles()(theme => {
131 131
 
132 132
         footer: {
133 133
             justifyContent: 'flex-end',
134
+            paddingTop: theme.spacing(4),
134 135
 
135 136
             '& button:last-child': {
136 137
                 marginLeft: '16px'

+ 0
- 10
react/features/keyboard-shortcuts/actionTypes.ts 查看文件

@@ -1,10 +0,0 @@
1
-/**
2
- * The type of the action which signals the keyboard shortcuts dialog should
3
- * be displayed.
4
- *
5
- * {
6
- *     type: OPEN_KEYBOARD_SHORTCUTS_DIALOG
7
- * }
8
- */
9
-export const OPEN_KEYBOARD_SHORTCUTS_DIALOG
10
-    = 'OPEN_KEYBOARD_SHORTCUTS_DIALOG';

+ 0
- 14
react/features/keyboard-shortcuts/actions.ts 查看文件

@@ -1,14 +0,0 @@
1
-import { OPEN_KEYBOARD_SHORTCUTS_DIALOG } from './actionTypes';
2
-
3
-/**
4
- * Opens the dialog showing available keyboard shortcuts.
5
- *
6
- * @returns {{
7
- *     type: OPEN_KEYBOARD_SHORTCUTS_DIALOG
8
- * }}
9
- */
10
-export function openKeyboardShortcutsDialog() {
11
-    return {
12
-        type: OPEN_KEYBOARD_SHORTCUTS_DIALOG
13
-    };
14
-}

+ 3
- 2
react/features/keyboard-shortcuts/components/web/KeyboardShortcutsButton.js 查看文件

@@ -5,7 +5,8 @@ import { translate } from '../../../base/i18n';
5 5
 import { IconShortcuts } from '../../../base/icons';
6 6
 import { connect } from '../../../base/redux';
7 7
 import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
8
-import { openKeyboardShortcutsDialog } from '../../actions';
8
+import { openSettingsDialog } from '../../../settings/actions';
9
+import { SETTINGS_TABS } from '../../../settings/constants';
9 10
 
10 11
 /**
11 12
  * The type of the React {@code Component} props of {@link KeyboardShortcutsButton}.
@@ -37,7 +38,7 @@ class KeyboardShortcutsButton extends AbstractButton<Props, *> {
37 38
         const { dispatch } = this.props;
38 39
 
39 40
         sendAnalytics(createToolbarEvent('shortcuts'));
40
-        dispatch(openKeyboardShortcutsDialog());
41
+        dispatch(openSettingsDialog(SETTINGS_TABS.SHORTCUTS));
41 42
     }
42 43
 }
43 44
 

+ 0
- 102
react/features/keyboard-shortcuts/components/web/KeyboardShortcutsDialog.tsx 查看文件

@@ -1,102 +0,0 @@
1
-import React from 'react';
2
-import { useTranslation } from 'react-i18next';
3
-import { makeStyles } from 'tss-react/mui';
4
-
5
-import { withPixelLineHeight } from '../../../base/styles/functions.web';
6
-import Dialog from '../../../base/ui/components/web/Dialog';
7
-
8
-/**
9
- * The type of the React {@code Component} props of
10
- * {@link KeyboardShortcutsDialog}.
11
- */
12
-interface IProps {
13
-
14
-    /**
15
-     * A Map with keyboard keys as keys and translation keys as values.
16
-     */
17
-    shortcutDescriptions: Map<string, string>;
18
-}
19
-
20
-/**
21
- * Creates the styles for the component.
22
- *
23
- * @param {Object} theme - The current UI theme.
24
- *
25
- * @returns {Object}
26
- */
27
-const useStyles = makeStyles()(theme => {
28
-    return {
29
-        list: {
30
-            listStyleType: 'none',
31
-            padding: 0,
32
-
33
-            '& .shortcuts-list__item': {
34
-                display: 'flex',
35
-                justifyContent: 'space-between',
36
-                alignItems: 'center',
37
-                padding: `${theme.spacing(1)} 0`,
38
-                ...withPixelLineHeight(theme.typography.bodyShortRegular),
39
-                color: theme.palette.text01
40
-            },
41
-
42
-            '& .item-action': {
43
-                backgroundColor: theme.palette.ui04,
44
-                ...withPixelLineHeight(theme.typography.labelBold),
45
-                padding: `${theme.spacing(1)} ${theme.spacing(2)}`,
46
-                borderRadius: `${Number(theme.shape.borderRadius) / 2}px`
47
-            }
48
-        }
49
-    };
50
-});
51
-
52
-const KeyboardShortcutsDialog = ({ shortcutDescriptions }: IProps) => {
53
-    const { classes, cx } = useStyles();
54
-    const { t } = useTranslation();
55
-
56
-    // eslint-disable-next-line react/no-multi-comp
57
-    const _renderShortcutsListItem = (keyboardKey: string, translationKey: string) => {
58
-        let modifierKey = 'Alt';
59
-
60
-        if (window.navigator?.platform) {
61
-            if (window.navigator.platform.indexOf('Mac') !== -1) {
62
-                modifierKey = '⌥';
63
-            }
64
-        }
65
-
66
-        return (
67
-            <li
68
-                className = 'shortcuts-list__item'
69
-                key = { keyboardKey }>
70
-                <span
71
-                    aria-label = { t(translationKey) }
72
-                    className = 'shortcuts-list__description'>
73
-                    {t(translationKey)}
74
-                </span>
75
-                <span className = 'item-action'>
76
-                    {keyboardKey.startsWith(':')
77
-                        ? `${modifierKey} + ${keyboardKey.slice(1)}`
78
-                        : keyboardKey}
79
-                </span>
80
-            </li>
81
-        );
82
-    };
83
-
84
-    return (
85
-        <Dialog
86
-            cancel = {{ hidden: true }}
87
-            ok = {{ hidden: true }}
88
-            titleKey = 'keyboardShortcuts.keyboardShortcuts'>
89
-            <div
90
-                id = 'keyboard-shortcuts'>
91
-                <ul
92
-                    className = { cx('shortcuts-list', classes.list) }
93
-                    id = 'keyboard-shortcuts-list'>
94
-                    {Array.from(shortcutDescriptions)
95
-                        .map(description => _renderShortcutsListItem(...description))}
96
-                </ul>
97
-            </div>
98
-        </Dialog>
99
-    );
100
-};
101
-
102
-export default KeyboardShortcutsDialog;

+ 0
- 1
react/features/keyboard-shortcuts/components/web/index.js 查看文件

@@ -1,2 +1 @@
1 1
 export { default as KeyboardShortcutsButton } from './KeyboardShortcutsButton';
2
-export { default as KeyboardShortcutsDialog } from './KeyboardShortcutsDialog';

+ 0
- 1
react/features/keyboard-shortcuts/index.js 查看文件

@@ -1,2 +1 @@
1
-export * from './actions';
2 1
 export * from './components';

+ 0
- 21
react/features/keyboard-shortcuts/middleware.ts 查看文件

@@ -1,21 +0,0 @@
1
-import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
2
-
3
-import { OPEN_KEYBOARD_SHORTCUTS_DIALOG } from './actionTypes';
4
-
5
-/**
6
- * Implements the middleware of the feature keyboard-shortcuts.
7
- *
8
- * @param {Store} store - The redux store.
9
- * @returns {Function}
10
- */
11
-MiddlewareRegistry.register(_store => next => action => {
12
-    switch (action.type) {
13
-    case OPEN_KEYBOARD_SHORTCUTS_DIALOG:
14
-        if (typeof APP === 'object') {
15
-            APP.keyboardshortcut.openDialog();
16
-        }
17
-        break;
18
-    }
19
-
20
-    return next(action);
21
-});

+ 20
- 1
react/features/settings/actions.ts 查看文件

@@ -1,5 +1,7 @@
1 1
 import { batch } from 'react-redux';
2 2
 
3
+// @ts-expect-error
4
+import keyboardShortcut from '../../../modules/keyboardshortcut/keyboardshortcut';
3 5
 import { IStore } from '../app/types';
4 6
 import {
5 7
     setFollowMe,
@@ -22,7 +24,8 @@ import {
22 24
     getModeratorTabProps,
23 25
     getMoreTabProps,
24 26
     getNotificationsTabProps,
25
-    getProfileTabProps
27
+    getProfileTabProps,
28
+    getShortcutsTabProps
26 29
 } from './functions';
27 30
 
28 31
 /**
@@ -237,3 +240,19 @@ export function toggleVideoSettings() {
237 240
         dispatch(setVideoSettingsVisibility(!value));
238 241
     };
239 242
 }
243
+
244
+/**
245
+ * Submits the settings from the "Shortcuts" tab of the settings dialog.
246
+ *
247
+ * @param {Object} newState - The new settings.
248
+ * @returns {Function}
249
+ */
250
+export function submitShortcutsTab(newState: any) {
251
+    return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
252
+        const currentState = getShortcutsTabProps(getState());
253
+
254
+        if (newState.keyboardShortcutsEnabled !== currentState.keyboardShortcutsEnabled) {
255
+            keyboardShortcut.enable(newState.keyboardShortcutsEnabled);
256
+        }
257
+    };
258
+}

+ 0
- 42
react/features/settings/components/web/MoreTab.tsx 查看文件

@@ -1,8 +1,6 @@
1 1
 import React from 'react';
2 2
 import { WithTranslation } from 'react-i18next';
3 3
 
4
-// @ts-expect-error
5
-import keyboardShortcut from '../../../../../modules/keyboardshortcut/keyboardshortcut';
6 4
 import AbstractDialogTab, {
7 5
     IProps as AbstractDialogTabProps
8 6
 } from '../../../base/dialog/components/web/AbstractDialogTab';
@@ -81,7 +79,6 @@ class MoreTab extends AbstractDialogTab<Props, any> {
81 79
         // Bind event handler so it is only bound once for every instance.
82 80
         this._onFramerateItemSelect = this._onFramerateItemSelect.bind(this);
83 81
         this._onShowPrejoinPageChanged = this._onShowPrejoinPageChanged.bind(this);
84
-        this._onKeyboardShortcutEnableChanged = this._onKeyboardShortcutEnableChanged.bind(this);
85 82
         this._renderMaxStageParticipantsSelect = this._renderMaxStageParticipantsSelect.bind(this);
86 83
         this._onMaxStageParticipantsSelect = this._onMaxStageParticipantsSelect.bind(this);
87 84
     }
@@ -132,19 +129,6 @@ class MoreTab extends AbstractDialogTab<Props, any> {
132 129
         super._onChange({ showPrejoinPage: checked });
133 130
     }
134 131
 
135
-    /**
136
-     * Callback invoked to select if global keyboard shortcuts
137
-     * should be enabled.
138
-     *
139
-     * @param {Object} e - The key event to handle.
140
-     *
141
-     * @returns {void}
142
-     */
143
-    _onKeyboardShortcutEnableChanged({ target: { checked } }: React.ChangeEvent<HTMLInputElement>) {
144
-        keyboardShortcut.enable(checked);
145
-        super._onChange({ keyboardShortcutEnable: checked });
146
-    }
147
-
148 132
     /**
149 133
      * Callback invoked to select a max number of stage participants from the select dropdown.
150 134
      *
@@ -190,31 +174,6 @@ class MoreTab extends AbstractDialogTab<Props, any> {
190 174
         );
191 175
     }
192 176
 
193
-    /**
194
-     * Returns the React Element for keyboardShortcut settings.
195
-     *
196
-     * @private
197
-     * @returns {ReactElement}
198
-     */
199
-    _renderKeyboardShortcutCheckbox() {
200
-        const { t } = this.props;
201
-
202
-        return (
203
-            <div
204
-                className = 'settings-sub-pane-element'
205
-                key = 'keyboard-shortcut'>
206
-                <span className = 'checkbox-label'>
207
-                    { t('keyboardShortcuts.keyboardShortcuts') }
208
-                </span>
209
-                <Checkbox
210
-                    checked = { keyboardShortcut.getEnabled() }
211
-                    label = { t('prejoin.keyboardShortcuts') }
212
-                    name = 'enable-keyboard-shortcuts'
213
-                    onChange = { this._onKeyboardShortcutEnableChanged } />
214
-            </div>
215
-        );
216
-    }
217
-
218 177
     /**
219 178
      * Returns the React Element for modifying prejoin screen settings.
220 179
      *
@@ -304,7 +263,6 @@ class MoreTab extends AbstractDialogTab<Props, any> {
304 263
                 className = 'settings-sub-pane left'
305 264
                 key = 'settings-sub-pane-left'>
306 265
                 { showPrejoinSettings && this._renderPrejoinScreenSettings() }
307
-                { this._renderKeyboardShortcutCheckbox() }
308 266
             </div>
309 267
         );
310 268
     }

+ 32
- 3
react/features/settings/components/web/SettingsDialog.tsx 查看文件

@@ -4,7 +4,15 @@ import { withStyles } from '@mui/styles';
4 4
 import React, { Component } from 'react';
5 5
 
6 6
 import { IReduxState } from '../../../app/types';
7
-import { IconBell, IconCalendar, IconGear, IconHost, IconUser, IconVolumeUp } from '../../../base/icons/svg';
7
+import {
8
+    IconBell,
9
+    IconCalendar,
10
+    IconGear,
11
+    IconHost,
12
+    IconShortcuts,
13
+    IconUser,
14
+    IconVolumeUp
15
+} from '../../../base/icons/svg';
8 16
 import { connect } from '../../../base/redux/functions';
9 17
 import { withPixelLineHeight } from '../../../base/styles/functions.web';
10 18
 import DialogWithTabs, { IDialogTab } from '../../../base/ui/components/web/DialogWithTabs';
@@ -19,7 +27,8 @@ import {
19 27
     submitModeratorTab,
20 28
     submitMoreTab,
21 29
     submitNotificationsTab,
22
-    submitProfileTab
30
+    submitProfileTab,
31
+    submitShortcutsTab
23 32
 } from '../../actions';
24 33
 import { SETTINGS_TABS } from '../../constants';
25 34
 import {
@@ -27,7 +36,8 @@ import {
27 36
     getMoreTabProps,
28 37
     getNotificationsMap,
29 38
     getNotificationsTabProps,
30
-    getProfileTabProps
39
+    getProfileTabProps,
40
+    getShortcutsTabProps
31 41
 } from '../../functions';
32 42
 
33 43
 // @ts-ignore
@@ -36,6 +46,7 @@ import ModeratorTab from './ModeratorTab';
36 46
 import MoreTab from './MoreTab';
37 47
 import NotificationsTab from './NotificationsTab';
38 48
 import ProfileTab from './ProfileTab';
49
+import ShortcutsTab from './ShortcutsTab';
39 50
 /* eslint-enable lines-around-comment */
40 51
 
41 52
 /**
@@ -342,6 +353,24 @@ function _mapStateToProps(state: IReduxState, ownProps: any) {
342 353
         });
343 354
     }
344 355
 
356
+    tabs.push({
357
+        name: SETTINGS_TABS.SHORTCUTS,
358
+        component: ShortcutsTab,
359
+        labelKey: 'settings.shortcuts',
360
+        props: getShortcutsTabProps(state, isDisplayedOnWelcomePage),
361
+        propsUpdateFunction: (tabState: any, newProps: any) => {
362
+            // Updates tab props, keeping users selection
363
+
364
+            return {
365
+                ...newProps,
366
+                keyboardShortcutsEnabled: tabState?.keyboardShortcutsEnabled
367
+            };
368
+        },
369
+        className: `settings-pane ${classes.settingsDialog}`,
370
+        submit: submitShortcutsTab,
371
+        icon: IconShortcuts
372
+    });
373
+
345 374
     if (showMoreTab) {
346 375
         tabs.push({
347 376
             name: SETTINGS_TABS.MORE,

+ 174
- 0
react/features/settings/components/web/ShortcutsTab.tsx 查看文件

@@ -0,0 +1,174 @@
1
+import { Theme } from '@mui/material';
2
+import { withStyles } from '@mui/styles';
3
+import React from 'react';
4
+import { WithTranslation } from 'react-i18next';
5
+
6
+// @ts-expect-error
7
+import keyboardShortcut from '../../../../../modules/keyboardshortcut/keyboardshortcut';
8
+import AbstractDialogTab, {
9
+    IProps as AbstractDialogTabProps } from '../../../base/dialog/components/web/AbstractDialogTab';
10
+import { translate } from '../../../base/i18n/functions';
11
+import { withPixelLineHeight } from '../../../base/styles/functions.web';
12
+import Checkbox from '../../../base/ui/components/web/Checkbox';
13
+
14
+/**
15
+ * The type of the React {@code Component} props of {@link ShortcutsTab}.
16
+ */
17
+export interface IProps extends AbstractDialogTabProps, WithTranslation {
18
+
19
+    /**
20
+     * CSS classes object.
21
+     */
22
+    classes: any;
23
+
24
+    /**
25
+     * Whether to display the shortcuts or not.
26
+     */
27
+    displayShortcuts: boolean;
28
+
29
+    /**
30
+     * Wether the keyboard shortcuts are enabled or not.
31
+     */
32
+    keyboardShortcutsEnabled: boolean;
33
+}
34
+
35
+const styles = (theme: Theme) => {
36
+    return {
37
+        container: {
38
+            display: 'flex',
39
+            flexDirection: 'column' as const,
40
+            width: '100%',
41
+            paddingBottom: theme.spacing(3)
42
+        },
43
+
44
+        checkbox: {
45
+            marginBottom: theme.spacing(3)
46
+        },
47
+
48
+        listContainer: {
49
+            listStyleType: 'none',
50
+            padding: 0,
51
+            margin: 0
52
+        },
53
+
54
+        listItem: {
55
+            display: 'flex',
56
+            justifyContent: 'space-between',
57
+            alignItems: 'center',
58
+            padding: `${theme.spacing(1)} 0`,
59
+            ...withPixelLineHeight(theme.typography.bodyShortRegular),
60
+            color: theme.palette.text01
61
+        },
62
+
63
+        listItemKey: {
64
+            backgroundColor: theme.palette.ui04,
65
+            ...withPixelLineHeight(theme.typography.labelBold),
66
+            padding: `${theme.spacing(1)} ${theme.spacing(2)}`,
67
+            borderRadius: `${Number(theme.shape.borderRadius) / 2}px`
68
+        }
69
+    };
70
+};
71
+
72
+/**
73
+ * React {@code Component} for modifying the local user's profile.
74
+ *
75
+ * @augments Component
76
+ */
77
+class ShortcutsTab extends AbstractDialogTab<IProps, any> {
78
+    /**
79
+     * Initializes a new {@code MoreTab} instance.
80
+     *
81
+     * @param {Object} props - The read-only properties with which the new
82
+     * instance is to be initialized.
83
+     */
84
+    constructor(props: IProps) {
85
+        super(props);
86
+
87
+        // Bind event handler so it is only bound once for every instance.
88
+        this._onKeyboardShortcutEnableChanged = this._onKeyboardShortcutEnableChanged.bind(this);
89
+        this._renderShortcutsListItem = this._renderShortcutsListItem.bind(this);
90
+    }
91
+
92
+    /**
93
+     * Callback invoked to select if global keyboard shortcuts
94
+     * should be enabled.
95
+     *
96
+     * @param {Object} e - The key event to handle.
97
+     *
98
+     * @returns {void}
99
+     */
100
+    _onKeyboardShortcutEnableChanged({ target: { checked } }: React.ChangeEvent<HTMLInputElement>) {
101
+        super._onChange({ keyboardShortcutsEnabled: checked });
102
+    }
103
+
104
+    /**
105
+     * Render a keyboard shortcut with key and description.
106
+     *
107
+     * @param {string} keyboardKey - The keyboard key for the shortcut.
108
+     * @param {string} translationKey - The translation key for the shortcut description.
109
+     * @returns {JSX}
110
+     */
111
+    _renderShortcutsListItem(keyboardKey: string, translationKey: string) {
112
+        const { classes, t } = this.props;
113
+        let modifierKey = 'Alt';
114
+
115
+        if (window.navigator?.platform) {
116
+            if (window.navigator.platform.indexOf('Mac') !== -1) {
117
+                modifierKey = '⌥';
118
+            }
119
+        }
120
+
121
+        return (
122
+            <li
123
+                className = { classes.listItem }
124
+                key = { keyboardKey }>
125
+                <span
126
+                    aria-label = { t(translationKey) }>
127
+                    {t(translationKey)}
128
+                </span>
129
+                <span className = { classes.listItemKey }>
130
+                    {keyboardKey.startsWith(':')
131
+                        ? `${modifierKey} + ${keyboardKey.slice(1)}`
132
+                        : keyboardKey}
133
+                </span>
134
+            </li>
135
+        );
136
+    }
137
+
138
+    /**
139
+     * Implements React's {@link Component#render()}.
140
+     *
141
+     * @inheritdoc
142
+     * @returns {ReactElement}
143
+     */
144
+    render() {
145
+        const {
146
+            classes,
147
+            displayShortcuts,
148
+            keyboardShortcutsEnabled,
149
+            t
150
+        } = this.props;
151
+        const shortcutDescriptions: Map<string, string> = displayShortcuts
152
+            ? keyboardShortcut.getShortcutsDescriptions()
153
+            : new Map();
154
+
155
+        return (
156
+            <div className = { classes.container }>
157
+                <Checkbox
158
+                    checked = { keyboardShortcutsEnabled }
159
+                    className = { classes.checkbox }
160
+                    label = { t('prejoin.keyboardShortcuts') }
161
+                    name = 'enable-keyboard-shortcuts'
162
+                    onChange = { this._onKeyboardShortcutEnableChanged } />
163
+                {displayShortcuts && (
164
+                    <ul className = { classes.listContainer }>
165
+                        {Array.from(shortcutDescriptions)
166
+                            .map(description => this._renderShortcutsListItem(...description))}
167
+                    </ul>
168
+                )}
169
+            </div>
170
+        );
171
+    }
172
+}
173
+
174
+export default withStyles(styles)(translate(ShortcutsTab));

+ 2
- 1
react/features/settings/constants.ts 查看文件

@@ -4,7 +4,8 @@ export const SETTINGS_TABS = {
4 4
     MORE: 'more_tab',
5 5
     MODERATOR: 'moderator-tab',
6 6
     NOTIFICATIONS: 'notifications_tab',
7
-    PROFILE: 'profile_tab'
7
+    PROFILE: 'profile_tab',
8
+    SHORTCUTS: 'shortcuts_tab'
8 9
 };
9 10
 
10 11
 /**

+ 23
- 0
react/features/settings/functions.any.ts 查看文件

@@ -1,3 +1,5 @@
1
+// @ts-expect-error
2
+import keyboardShortcut from '../../../modules/keyboardshortcut/keyboardshortcut';
1 3
 import { IReduxState } from '../app/types';
2 4
 import { IStateful } from '../base/app/types';
3 5
 import { isNameReadOnly } from '../base/config/functions';
@@ -14,6 +16,7 @@ import { parseStandardURIString } from '../base/util/uri';
14 16
 import { isStageFilmstripEnabled } from '../filmstrip/functions';
15 17
 import { isFollowMeActive } from '../follow-me/functions';
16 18
 import { getParticipantsPaneConfig } from '../participants-pane/functions';
19
+import { isPrejoinPageVisible } from '../prejoin/functions';
17 20
 import { isReactionsEnabled } from '../reactions/functions.any';
18 21
 
19 22
 import { SS_DEFAULT_FRAME_RATE, SS_SUPPORTED_FRAMERATES } from './constants';
@@ -275,3 +278,23 @@ export function getAudioSettingsVisibility(state: IReduxState) {
275 278
 export function getVideoSettingsVisibility(state: IReduxState) {
276 279
     return state['features/settings'].videoSettingsVisible;
277 280
 }
281
+
282
+/**
283
+ * Returns the properties for the "Shortcuts" tab from settings dialog from Redux
284
+ * state.
285
+ *
286
+ * @param {(Function|Object)} stateful -The (whole) redux state, or redux's
287
+ * {@code getState} function to be used to retrieve the state.
288
+ * @param {boolean} isDisplayedOnWelcomePage - Indicates whether the shortcuts dialog is displayed on the
289
+ * welcome page or not.
290
+ * @returns {Object} - The properties for the "Shortcuts" tab from settings
291
+ * dialog.
292
+ */
293
+export function getShortcutsTabProps(stateful: IStateful, isDisplayedOnWelcomePage?: boolean) {
294
+    const state = toState(stateful);
295
+
296
+    return {
297
+        displayShortcuts: !isDisplayedOnWelcomePage && !isPrejoinPageVisible(state),
298
+        keyboardShortcutsEnabled: keyboardShortcut.getEnabled()
299
+    };
300
+}

Loading…
取消
儲存