浏览代码

[RN] Add conference navigation bar

j8
Bettenbuk Zoltan 6 年前
父节点
当前提交
9f3ef43daa

+ 2
- 0
ios/Podfile 查看文件

@@ -43,6 +43,8 @@ target 'JitsiMeet' do
43 43
     :path => '../node_modules/react-native-fast-image'
44 44
   pod 'react-native-keep-awake',
45 45
     :path => '../node_modules/react-native-keep-awake'
46
+  pod 'BVLinearGradient',
47
+    :path => '../node_modules/react-native-linear-gradient'
46 48
   pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
47 49
   pod 'RNGoogleSignin',
48 50
     :path => '../node_modules/react-native-google-signin'

+ 7
- 1
ios/Podfile.lock 查看文件

@@ -1,5 +1,7 @@
1 1
 PODS:
2 2
   - boost-for-react-native (1.63.0)
3
+  - BVLinearGradient (2.5.3):
4
+    - React
3 5
   - Crashlytics (3.12.0):
4 6
     - Fabric (~> 1.9.0)
5 7
   - DoubleConversion (1.1.6)
@@ -152,6 +154,7 @@ PODS:
152 154
   - yoga (0.57.8.React)
153 155
 
154 156
 DEPENDENCIES:
157
+  - BVLinearGradient (from `../node_modules/react-native-linear-gradient`)
155 158
   - Crashlytics
156 159
   - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
157 160
   - Fabric
@@ -202,6 +205,8 @@ SPEC REPOS:
202 205
     - SDWebImage
203 206
 
204 207
 EXTERNAL SOURCES:
208
+  BVLinearGradient:
209
+    :path: "../node_modules/react-native-linear-gradient"
205 210
   DoubleConversion:
206 211
     :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
207 212
   Folly:
@@ -231,6 +236,7 @@ EXTERNAL SOURCES:
231 236
 
232 237
 SPEC CHECKSUMS:
233 238
   boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
239
+  BVLinearGradient: b0b70acf63ee888829b7c2ebbf6b50e227396e55
234 240
   Crashlytics: 07fb167b1694128c1c9a5a5cc319b0e9c3ca0933
235 241
   DoubleConversion: bb338842f62ab1d708ceb63ec3d999f0f3d98ecd
236 242
   Fabric: f988e33c97f08930a413e08123064d2e5f68d655
@@ -262,6 +268,6 @@ SPEC CHECKSUMS:
262 268
   SDWebImage: c5594f1a19c48d526d321e548902b56b479cd508
263 269
   yoga: b1ce48b6cf950b98deae82838f5173ea7cf89e85
264 270
 
265
-PODFILE CHECKSUM: b5218184626a027e8b1ca12361d46100e2fa2f1f
271
+PODFILE CHECKSUM: 7d1909450626f31f9ea2de80122a66a50af2e1ea
266 272
 
267 273
 COCOAPODS: 1.5.3

+ 16
- 0
react/features/base/conference/functions.js 查看文件

@@ -145,6 +145,22 @@ export function forEachConference(
145 145
     return true;
146 146
 }
147 147
 
148
+/**
149
+ * Returns the display name of the conference.
150
+ *
151
+ * @param {Function | Object} stateful - Reference that can be resolved to Redux
152
+ * state with the {@code toState} function.
153
+ * @returns {string}
154
+ */
155
+export function getConferenceName(stateful: Function | Object): string {
156
+    const state = toState(stateful);
157
+    const { callee } = state['features/base/jwt'];
158
+
159
+    return state['features/base/config'].callDisplayName
160
+                || (callee && callee.name)
161
+                || state['features/base/conference'].room;
162
+}
163
+
148 164
 /**
149 165
  * Returns the current {@code JitsiConference} which is joining or joined and is
150 166
  * not leaving. Please note the contrast with merely reading the

+ 3
- 0
react/features/conference/components/native/Conference.js 查看文件

@@ -29,6 +29,7 @@ import { shouldDisplayTileView } from '../../../video-layout';
29 29
 
30 30
 import DisplayNameLabel from './DisplayNameLabel';
31 31
 import Labels from './Labels';
32
+import NavigationBar from './NavigationBar';
32 33
 import styles from './styles';
33 34
 
34 35
 /**
@@ -306,6 +307,8 @@ class Conference extends Component<Props> {
306 307
                     }
307 308
                 </View>
308 309
 
310
+                <NavigationBar />
311
+
309 312
                 <TestConnectionInfo />
310 313
 
311 314
                 {

+ 16
- 3
react/features/conference/components/native/Labels.js 查看文件

@@ -12,7 +12,9 @@ import {
12 12
 import {
13 13
     RecordingExpandedLabel
14 14
 } from '../../../recording';
15
+import { isToolboxVisible } from '../../../toolbox';
15 16
 import { TranscribingExpandedLabel } from '../../../transcribing';
17
+import { shouldDisplayTileView } from '../../../video-layout';
16 18
 import { VideoQualityExpandedLabel } from '../../../video-quality';
17 19
 
18 20
 import AbstractLabels, {
@@ -37,7 +39,12 @@ type Props = AbstractLabelsProps & {
37 39
      *
38 40
      * @private
39 41
      */
40
-    _reducedUI: boolean
42
+    _reducedUI: boolean,
43
+
44
+    /**
45
+     * True if the labels should be visible, false otherwise.
46
+     */
47
+    _visible: boolean
41 48
 };
42 49
 
43 50
 type State = {
@@ -148,6 +155,10 @@ class Labels extends AbstractLabels<Props, State> {
148 155
      * @inheritdoc
149 156
      */
150 157
     render() {
158
+        if (!this.props._visible) {
159
+            return null;
160
+        }
161
+
151 162
         const wide = !isNarrowAspectRatio(this);
152 163
         const { _filmstripVisible, _reducedUI } = this.props;
153 164
 
@@ -344,13 +355,15 @@ class Labels extends AbstractLabels<Props, State> {
344 355
  * @private
345 356
  * @returns {{
346 357
  *     _filmstripVisible: boolean,
347
- *     _reducedUI: boolean
358
+ *     _reducedUI: boolean,
359
+ *     _visible: boolean
348 360
  * }}
349 361
  */
350 362
 function _mapStateToProps(state) {
351 363
     return {
352 364
         ..._abstractMapStateToProps(state),
353
-        _reducedUI: state['features/base/responsive-ui'].reducedUI
365
+        _reducedUI: state['features/base/responsive-ui'].reducedUI,
366
+        _visible: !isToolboxVisible(state) && !shouldDisplayTileView(state)
354 367
     };
355 368
 }
356 369
 

+ 96
- 0
react/features/conference/components/native/NavigationBar.js 查看文件

@@ -0,0 +1,96 @@
1
+// @flow
2
+
3
+import _ from 'lodash';
4
+import React, { Component } from 'react';
5
+import { SafeAreaView, Text, View } from 'react-native';
6
+import LinearGradient from 'react-native-linear-gradient';
7
+import { connect } from 'react-redux';
8
+
9
+import { getConferenceName } from '../../../base/conference';
10
+import { PictureInPictureButton } from '../../../mobile/picture-in-picture';
11
+import { isToolboxVisible } from '../../../toolbox';
12
+
13
+import styles, { NAVBAR_GRADIENT_COLORS } from './styles';
14
+
15
+type Props = {
16
+
17
+    /**
18
+     * Name of the meeting we're currently in.
19
+     */
20
+    _meetingName: string,
21
+
22
+    /**
23
+     * True if the navigation bar should be visible.
24
+     */
25
+    _visible: boolean
26
+};
27
+
28
+/**
29
+ * Implements a navigation bar component that is rendered on top of the
30
+ * conference screen.
31
+ */
32
+class NavigationBar extends Component<Props> {
33
+    /**
34
+     * Implements {@Component#render}.
35
+     *
36
+     * @inheritdoc
37
+     */
38
+    render() {
39
+        if (!this.props._visible) {
40
+            return null;
41
+        }
42
+
43
+        return (
44
+            <View
45
+                pointerEvents = 'box-none'
46
+                style = { styles.navBarContainer }>
47
+                <LinearGradient
48
+                    colors = { NAVBAR_GRADIENT_COLORS }
49
+                    pointerEvents = 'none'
50
+                    style = { styles.gradient }>
51
+                    <SafeAreaView>
52
+                        <View style = { styles.gradientStretch } />
53
+                    </SafeAreaView>
54
+                </LinearGradient>
55
+                <SafeAreaView
56
+                    pointerEvents = 'box-none'
57
+                    style = { styles.navBarSafeView }>
58
+                    <View
59
+                        pointerEvents = 'box-none'
60
+                        style = { styles.navBarWrapper }>
61
+                        <PictureInPictureButton
62
+                            styles = { styles.navBarButton } />
63
+                        <View
64
+                            pointerEvents = 'box-none'
65
+                            style = { styles.roomNameWrapper }>
66
+                            <Text
67
+                                numberOfLines = { 1 }
68
+                                style = { styles.roomName }>
69
+                                { this.props._meetingName }
70
+                            </Text>
71
+                        </View>
72
+                    </View>
73
+                </SafeAreaView>
74
+            </View>
75
+        );
76
+    }
77
+
78
+}
79
+
80
+/**
81
+ * Maps part of the Redux store to the props of this component.
82
+ *
83
+ * @param {Object} state - The Redux state.
84
+ * @returns {{
85
+ *     _meetingName: string,
86
+ *     _visible: boolean
87
+ * }}
88
+ */
89
+function _mapStateToProps(state) {
90
+    return {
91
+        _meetingName: _.startCase(getConferenceName(state)),
92
+        _visible: isToolboxVisible(state)
93
+    };
94
+}
95
+
96
+export default connect(_mapStateToProps)(NavigationBar);

+ 58
- 0
react/features/conference/components/native/styles.js 查看文件

@@ -7,6 +7,8 @@ import {
7 7
 
8 8
 import { FILMSTRIP_SIZE } from '../../../filmstrip';
9 9
 
10
+export const NAVBAR_GRADIENT_COLORS = [ 'black', '#00000000' ];
11
+
10 12
 /**
11 13
  * The styles of the feature conference.
12 14
  */
@@ -34,6 +36,14 @@ export default createStyleSheet({
34 36
         fontSize: 14
35 37
     },
36 38
 
39
+    gradient: {
40
+        flex: 1
41
+    },
42
+
43
+    gradientStretch: {
44
+        height: 116
45
+    },
46
+
37 47
     /**
38 48
      * View that contains the indicators.
39 49
      */
@@ -58,6 +68,54 @@ export default createStyleSheet({
58 68
         top: 0
59 69
     },
60 70
 
71
+    navBarButton: {
72
+        iconStyle: {
73
+            color: ColorPalette.white,
74
+            fontSize: 24
75
+        },
76
+
77
+        underlayColor: 'transparent'
78
+    },
79
+
80
+    navBarContainer: {
81
+        flexDirection: 'column',
82
+        left: 0,
83
+        position: 'absolute',
84
+        right: 0,
85
+        top: 0
86
+    },
87
+
88
+    navBarSafeView: {
89
+        left: 0,
90
+        position: 'absolute',
91
+        right: 0,
92
+        top: 0
93
+    },
94
+
95
+    navBarWrapper: {
96
+        alignItems: 'center',
97
+        flex: 1,
98
+        flexDirection: 'row',
99
+        height: 44,
100
+        justifyContent: 'space-between',
101
+        paddingHorizontal: 14
102
+    },
103
+
104
+    roomName: {
105
+        color: ColorPalette.white,
106
+        fontSize: 17,
107
+        fontWeight: '400'
108
+    },
109
+
110
+    roomNameWrapper: {
111
+        flexDirection: 'row',
112
+        justifyContent: 'center',
113
+        left: 0,
114
+        paddingHorizontal: 48,
115
+        position: 'absolute',
116
+        right: 0
117
+    },
118
+
61 119
     /**
62 120
      * The style of the {@link View} which expands over the whole
63 121
      * {@link Conference} area and splits it between the {@link Filmstrip} and

+ 2
- 6
react/features/mobile/call-integration/middleware.js 查看文件

@@ -12,6 +12,7 @@ import {
12 12
     CONFERENCE_WILL_JOIN,
13 13
     CONFERENCE_JOINED,
14 14
     SET_AUDIO_ONLY,
15
+    getConferenceName,
15 16
     getCurrentConference
16 17
 } from '../../base/conference';
17 18
 import { getInviteURL } from '../../base/connection';
@@ -226,12 +227,7 @@ function _conferenceWillJoin({ dispatch, getState }, next, action) {
226 227
 
227 228
     CallIntegration.startCall(conference.callUUID, handle, hasVideo)
228 229
         .then(() => {
229
-            const { callee } = state['features/base/jwt'];
230
-            const displayName
231
-                 = state['features/base/config'].callDisplayName
232
-                     || (callee && callee.name)
233
-                     || state['features/base/conference'].room;
234
-
230
+            const displayName = getConferenceName(state);
235 231
             const muted
236 232
                 = isLocalTrackMuted(
237 233
                     state['features/base/tracks'],

+ 0
- 2
react/features/toolbox/components/native/OverflowMenu.js 查看文件

@@ -11,7 +11,6 @@ import {
11 11
 } from '../../../base/dialog';
12 12
 import { InviteButton } from '../../../invite';
13 13
 import { AudioRouteButton } from '../../../mobile/audio-mode';
14
-import { PictureInPictureButton } from '../../../mobile/picture-in-picture';
15 14
 import { LiveStreamButton, RecordButton } from '../../../recording';
16 15
 import { RoomLockButton } from '../../../room-lock';
17 16
 import { ClosedCaptionButton } from '../../../subtitles';
@@ -90,7 +89,6 @@ class OverflowMenu extends Component<Props> {
90 89
                 <LiveStreamButton { ...buttonProps } />
91 90
                 <TileViewButton { ...buttonProps } />
92 91
                 <InviteButton { ...buttonProps } />
93
-                <PictureInPictureButton { ...buttonProps } />
94 92
             </BottomSheet>
95 93
         );
96 94
     }

正在加载...
取消
保存