浏览代码

feat(toolbox): Adaptive toolbar on mobile

master
Vlad Piersec 4 年前
父节点
当前提交
e7297714c6

+ 1
- 0
react/features/base/styles/components/styles/ColorPalette.js 查看文件

29
     overflowMenuItemUnderlay: '#EEEEEE',
29
     overflowMenuItemUnderlay: '#EEEEEE',
30
     red: '#D00000',
30
     red: '#D00000',
31
     transparent: 'rgba(0, 0, 0, 0)',
31
     transparent: 'rgba(0, 0, 0, 0)',
32
+    toggled: 'rgba(255,255,255,.15)',
32
     warning: 'rgb(215, 121, 118)',
33
     warning: 'rgb(215, 121, 118)',
33
     white: '#FFFFFF',
34
     white: '#FFFFFF',
34
 
35
 

+ 14
- 6
react/features/toolbox/components/native/OverflowMenu.js 查看文件

18
 import { SharedVideoButton } from '../../../shared-video/components';
18
 import { SharedVideoButton } from '../../../shared-video/components';
19
 import { ClosedCaptionButton } from '../../../subtitles';
19
 import { ClosedCaptionButton } from '../../../subtitles';
20
 import { TileViewButton } from '../../../video-layout';
20
 import { TileViewButton } from '../../../video-layout';
21
+import { getMovableButtons } from '../../functions.native';
21
 import HelpButton from '../HelpButton';
22
 import HelpButton from '../HelpButton';
22
 import MuteEveryoneButton from '../MuteEveryoneButton';
23
 import MuteEveryoneButton from '../MuteEveryoneButton';
23
 
24
 
48
      */
49
      */
49
     _recordingEnabled: boolean,
50
     _recordingEnabled: boolean,
50
 
51
 
52
+    /**
53
+     * The width of the screen.
54
+     */
55
+    _width: number,
56
+
51
     /**
57
     /**
52
      * Used for hiding the dialog when the selection was completed.
58
      * Used for hiding the dialog when the selection was completed.
53
      */
59
      */
108
      * @returns {ReactElement}
114
      * @returns {ReactElement}
109
      */
115
      */
110
     render() {
116
     render() {
111
-        const { _bottomSheetStyles } = this.props;
117
+        const { _bottomSheetStyles, _width } = this.props;
112
         const { showMore } = this.state;
118
         const { showMore } = this.state;
119
+        const toolbarButtons = getMovableButtons(_width);
113
 
120
 
114
         const buttonProps = {
121
         const buttonProps = {
115
             afterClick: this._onCancel,
122
             afterClick: this._onCancel,
129
                 onSwipe = { this._onSwipe }
136
                 onSwipe = { this._onSwipe }
130
                 renderHeader = { this._renderMenuExpandToggle }>
137
                 renderHeader = { this._renderMenuExpandToggle }>
131
                 <AudioRouteButton { ...buttonProps } />
138
                 <AudioRouteButton { ...buttonProps } />
132
-                <InviteButton { ...buttonProps } />
139
+                {!toolbarButtons.has('invite') && <InviteButton { ...buttonProps } />}
133
                 <AudioOnlyButton { ...buttonProps } />
140
                 <AudioOnlyButton { ...buttonProps } />
134
-                <RaiseHandButton { ...buttonProps } />
141
+                {!toolbarButtons.has('raisehand') && <RaiseHandButton { ...buttonProps } />}
135
                 <LobbyModeButton { ...buttonProps } />
142
                 <LobbyModeButton { ...buttonProps } />
136
                 <ScreenSharingButton { ...buttonProps } />
143
                 <ScreenSharingButton { ...buttonProps } />
137
                 <MoreOptionsButton { ...moreOptionsButtonProps } />
144
                 <MoreOptionsButton { ...moreOptionsButtonProps } />
138
                 <Collapsible collapsed = { !showMore }>
145
                 <Collapsible collapsed = { !showMore }>
139
-                    <ToggleCameraButton { ...buttonProps } />
140
-                    <TileViewButton { ...buttonProps } />
146
+                    {!toolbarButtons.has('togglecamera') && <ToggleCameraButton { ...buttonProps } />}
147
+                    {!toolbarButtons.has('tileview') && <TileViewButton { ...buttonProps } />}
141
                     <RecordButton { ...buttonProps } />
148
                     <RecordButton { ...buttonProps } />
142
                     <LiveStreamButton { ...buttonProps } />
149
                     <LiveStreamButton { ...buttonProps } />
143
                     <SharedVideoButton { ...buttonProps } />
150
                     <SharedVideoButton { ...buttonProps } />
244
 function _mapStateToProps(state) {
251
 function _mapStateToProps(state) {
245
     return {
252
     return {
246
         _bottomSheetStyles: ColorSchemeRegistry.get(state, 'BottomSheet'),
253
         _bottomSheetStyles: ColorSchemeRegistry.get(state, 'BottomSheet'),
247
-        _isOpen: isDialogOpen(state, OverflowMenu_)
254
+        _isOpen: isDialogOpen(state, OverflowMenu_),
255
+        _width: state['features/base/responsive-ui'].clientWidth
248
     };
256
     };
249
 }
257
 }
250
 
258
 

+ 66
- 72
react/features/toolbox/components/native/Toolbox.js 查看文件

1
 // @flow
1
 // @flow
2
 
2
 
3
-import React, { PureComponent } from 'react';
3
+import React from 'react';
4
 import { SafeAreaView, View } from 'react-native';
4
 import { SafeAreaView, View } from 'react-native';
5
 
5
 
6
 import { ColorSchemeRegistry } from '../../../base/color-scheme';
6
 import { ColorSchemeRegistry } from '../../../base/color-scheme';
7
 import { connect } from '../../../base/redux';
7
 import { connect } from '../../../base/redux';
8
 import { StyleType } from '../../../base/styles';
8
 import { StyleType } from '../../../base/styles';
9
 import { ChatButton } from '../../../chat';
9
 import { ChatButton } from '../../../chat';
10
-import { isToolboxVisible } from '../../functions';
10
+import { InviteButton } from '../../../invite';
11
+import { TileViewButton } from '../../../video-layout';
12
+import { isToolboxVisible, getMovableButtons } from '../../functions.native';
11
 import AudioMuteButton from '../AudioMuteButton';
13
 import AudioMuteButton from '../AudioMuteButton';
12
 import HangupButton from '../HangupButton';
14
 import HangupButton from '../HangupButton';
13
 import VideoMuteButton from '../VideoMuteButton';
15
 import VideoMuteButton from '../VideoMuteButton';
14
 
16
 
15
 import OverflowMenuButton from './OverflowMenuButton';
17
 import OverflowMenuButton from './OverflowMenuButton';
18
+import RaiseHandButton from './RaiseHandButton';
19
+import ToggleCameraButton from './ToggleCameraButton';
16
 import styles from './styles';
20
 import styles from './styles';
17
 
21
 
18
 /**
22
 /**
30
      */
34
      */
31
     _visible: boolean,
35
     _visible: boolean,
32
 
36
 
37
+    /**
38
+     * The width of the screen.
39
+     */
40
+    _width: number,
41
+
33
     /**
42
     /**
34
      * The redux {@code dispatch} function.
43
      * The redux {@code dispatch} function.
35
      */
44
      */
37
 };
46
 };
38
 
47
 
39
 /**
48
 /**
40
- * Implements the conference toolbox on React Native.
49
+ * Implements the conference Toolbox on React Native.
50
+ *
51
+ * @param {Object} props - The props of the component.
52
+ * @returns {React$Element}.
41
  */
53
  */
42
-class Toolbox extends PureComponent<Props> {
43
-    /**
44
-     * Implements React's {@link Component#render()}.
45
-     *
46
-     * @inheritdoc
47
-     * @returns {ReactElement}
48
-     */
49
-    render() {
50
-        if (!this.props._visible) {
51
-            return null;
52
-        }
53
-
54
-        const { _styles } = this.props;
55
-        const { buttonStylesBorderless, hangupButtonStyles, toggledButtonStyles } = _styles;
56
-
57
-        return (
58
-            <View
59
-                pointerEvents = 'box-none'
60
-                style = { styles.toolboxContainer }>
61
-                <SafeAreaView
62
-                    accessibilityRole = 'toolbar'
63
-                    pointerEvents = 'box-none'
64
-                    style = { styles.toolbox }>
65
-                    <AudioMuteButton
66
-                        styles = { buttonStylesBorderless }
67
-                        toggledStyles = { toggledButtonStyles } />
68
-                    <VideoMuteButton
69
-                        styles = { buttonStylesBorderless }
70
-                        toggledStyles = { toggledButtonStyles } />
71
-                    <ChatButton
72
-                        styles = { buttonStylesBorderless }
73
-                        toggledStyles = { this._getChatButtonToggledStyle(toggledButtonStyles) } />
74
-                    <OverflowMenuButton
75
-                        styles = { buttonStylesBorderless }
76
-                        toggledStyles = { toggledButtonStyles } />
77
-                    <HangupButton
78
-                        styles = { hangupButtonStyles } />
79
-                </SafeAreaView>
80
-            </View>
81
-        );
54
+function Toolbox(props: Props) {
55
+    if (!props._visible) {
56
+        return null;
82
     }
57
     }
83
 
58
 
84
-    /**
85
-     * Constructs the toggled style of the chat button. This cannot be done by
86
-     * simple style inheritance due to the size calculation done in this
87
-     * component.
88
-     *
89
-     * @param {Object} baseStyle - The base style that was originally
90
-     * calculated.
91
-     * @returns {Object | Array}
92
-     */
93
-    _getChatButtonToggledStyle(baseStyle) {
94
-        const { _styles } = this.props;
59
+    const { _styles, _width } = props;
60
+    const { buttonStylesBorderless, hangupButtonStyles, toggledButtonStyles } = _styles;
61
+    const additionalButtons = getMovableButtons(_width);
62
+    const backgroundToggledStyle = {
63
+        ...toggledButtonStyles,
64
+        style: [
65
+            toggledButtonStyles.style,
66
+            _styles.backgroundToggle
67
+        ]
68
+    };
95
 
69
 
96
-        if (Array.isArray(baseStyle.style)) {
97
-            return {
98
-                ...baseStyle,
99
-                style: [
100
-                    ...baseStyle.style,
101
-                    _styles.chatButtonOverride.toggled
102
-                ]
103
-            };
104
-        }
70
+    return (
71
+        <View
72
+            pointerEvents = 'box-none'
73
+            style = { styles.toolboxContainer }>
74
+            <SafeAreaView
75
+                accessibilityRole = 'toolbar'
76
+                pointerEvents = 'box-none'
77
+                style = { styles.toolbox }>
78
+                <AudioMuteButton
79
+                    styles = { buttonStylesBorderless }
80
+                    toggledStyles = { toggledButtonStyles } />
81
+                <VideoMuteButton
82
+                    styles = { buttonStylesBorderless }
83
+                    toggledStyles = { toggledButtonStyles } />
84
+                { additionalButtons.has('chat')
85
+                      && <ChatButton
86
+                          styles = { buttonStylesBorderless }
87
+                          toggledStyles = { backgroundToggledStyle } />}
105
 
88
 
106
-        return {
107
-            ...baseStyle,
108
-            style: [
109
-                baseStyle.style,
110
-                _styles.chatButtonOverride.toggled
111
-            ]
112
-        };
113
-    }
89
+                { additionalButtons.has('raisehand')
90
+                      && <RaiseHandButton
91
+                          styles = { buttonStylesBorderless }
92
+                          toggledStyles = { backgroundToggledStyle } />}
93
+                {additionalButtons.has('tileview') && <TileViewButton styles = { buttonStylesBorderless } />}
94
+                {additionalButtons.has('invite') && <InviteButton styles = { buttonStylesBorderless } />}
95
+                {additionalButtons.has('togglecamera')
96
+                      && <ToggleCameraButton
97
+                          styles = { buttonStylesBorderless }
98
+                          toggledStyles = { backgroundToggledStyle } />}
99
+                <OverflowMenuButton
100
+                    styles = { buttonStylesBorderless }
101
+                    toggledStyles = { toggledButtonStyles } />
102
+                <HangupButton
103
+                    styles = { hangupButtonStyles } />
104
+            </SafeAreaView>
105
+        </View>
106
+    );
114
 }
107
 }
115
 
108
 
116
 /**
109
 /**
125
 function _mapStateToProps(state: Object): Object {
118
 function _mapStateToProps(state: Object): Object {
126
     return {
119
     return {
127
         _styles: ColorSchemeRegistry.get(state, 'Toolbox'),
120
         _styles: ColorSchemeRegistry.get(state, 'Toolbox'),
128
-        _visible: isToolboxVisible(state)
121
+        _visible: isToolboxVisible(state),
122
+        _width: state['features/base/responsive-ui'].clientWidth
129
     };
123
     };
130
 }
124
 }
131
 
125
 

+ 6
- 13
react/features/toolbox/components/native/styles.js 查看文件

17
     flexDirection: 'row',
17
     flexDirection: 'row',
18
     height: BUTTON_SIZE,
18
     height: BUTTON_SIZE,
19
     justifyContent: 'center',
19
     justifyContent: 'center',
20
-
21
-    // XXX We probably tested BoxModel.margin and discovered it to be too small
22
-    // for our taste.
23
-    marginHorizontal: 7,
20
+    marginHorizontal: 6,
21
+    marginTop: 6,
24
     width: BUTTON_SIZE
22
     width: BUTTON_SIZE
25
 };
23
 };
26
 
24
 
65
     toolbox: {
63
     toolbox: {
66
         alignItems: 'center',
64
         alignItems: 'center',
67
         backgroundColor: ColorPalette.darkBackground,
65
         backgroundColor: ColorPalette.darkBackground,
68
-        borderRadius: 3,
66
+        borderTopLeftRadius: 3,
67
+        borderTopRightRadius: 3,
69
         flexDirection: 'row',
68
         flexDirection: 'row',
70
         flexGrow: 0,
69
         flexGrow: 0,
71
         justifyContent: 'space-between',
70
         justifyContent: 'space-between',
108
         }
107
         }
109
     },
108
     },
110
 
109
 
111
-    /**
112
-     * Overrides to the standard styles that we apply to the chat button, as
113
-     * that behaves slightly differently to other buttons.
114
-     */
115
-    chatButtonOverride: {
116
-        toggled: {
117
-            backgroundColor: ColorPalette.blue
118
-        }
110
+    backgroundToggle: {
111
+        backgroundColor: ColorPalette.toggled
119
     },
112
     },
120
 
113
 
121
     hangupButtonStyles: {
114
     hangupButtonStyles: {

+ 45
- 0
react/features/toolbox/functions.native.js 查看文件

5
 import { toState } from '../base/redux';
5
 import { toState } from '../base/redux';
6
 import { isLocalVideoTrackDesktop } from '../base/tracks';
6
 import { isLocalVideoTrackDesktop } from '../base/tracks';
7
 
7
 
8
+const WIDTH = {
9
+    FIT_9_ICONS: 560,
10
+    FIT_8_ICONS: 500,
11
+    FIT_7_ICONS: 440,
12
+    FIT_6_ICONS: 380
13
+};
14
+
15
+/**
16
+ * Returns a set of the buttons that are shown in the toolbar
17
+ * but removed from the overflow menu, based on the width of the screen.
18
+ *
19
+ * @param {number} width - The width of the screen.
20
+ * @returns {Set}
21
+ */
22
+export function getMovableButtons(width: number): Set<string> {
23
+    let buttons = [];
24
+
25
+    switch (true) {
26
+    case width >= WIDTH.FIT_9_ICONS: {
27
+        buttons = [ 'togglecamera', 'chat', 'invite', 'raisehand', 'tileview' ];
28
+        break;
29
+    }
30
+    case width >= WIDTH.FIT_8_ICONS: {
31
+        buttons = [ 'chat', 'invite', 'raisehand', 'tileview' ];
32
+        break;
33
+    }
34
+
35
+    case width >= WIDTH.FIT_7_ICONS: {
36
+        buttons = [ 'chat', 'raisehand', 'invite' ];
37
+        break;
38
+    }
39
+
40
+    case width >= WIDTH.FIT_6_ICONS: {
41
+        buttons = [ 'chat', 'raisehand' ];
42
+        break;
43
+    }
44
+
45
+    default: {
46
+        buttons = [ 'chat' ];
47
+    }
48
+    }
49
+
50
+    return new Set(buttons);
51
+}
52
+
8
 /**
53
 /**
9
  * Returns true if the toolbox is visible.
54
  * Returns true if the toolbox is visible.
10
  *
55
  *

正在加载...
取消
保存