瀏覽代碼

feat(subject): UI

master
Hristo Terezov 6 年之前
父節點
當前提交
cb8e9eed5e

+ 3
- 13
conference.js 查看文件

38
     conferenceFailed,
38
     conferenceFailed,
39
     conferenceJoined,
39
     conferenceJoined,
40
     conferenceLeft,
40
     conferenceLeft,
41
+    conferenceSubjectChanged,
41
     conferenceWillJoin,
42
     conferenceWillJoin,
42
     conferenceWillLeave,
43
     conferenceWillLeave,
43
     dataChannelOpened,
44
     dataChannelOpened,
45
     onStartMutedPolicyChanged,
46
     onStartMutedPolicyChanged,
46
     p2pStatusChanged,
47
     p2pStatusChanged,
47
     sendLocalParticipant,
48
     sendLocalParticipant,
48
-    setDesktopSharingEnabled,
49
-    setSubject
49
+    setDesktopSharingEnabled
50
 } from './react/features/base/conference';
50
 } from './react/features/base/conference';
51
 import {
51
 import {
52
     getAvailableDevices,
52
     getAvailableDevices,
1834
             APP.UI.showToolbar(6000);
1834
             APP.UI.showToolbar(6000);
1835
         });
1835
         });
1836
         room.on(JitsiConferenceEvents.SUBJECT_CHANGED,
1836
         room.on(JitsiConferenceEvents.SUBJECT_CHANGED,
1837
-            subject => APP.API.notifySubjectChanged(subject));
1837
+            subject => APP.store.dispatch(conferenceSubjectChanged(subject)));
1838
 
1838
 
1839
         room.on(
1839
         room.on(
1840
             JitsiConferenceEvents.LAST_N_ENDPOINTS_CHANGED,
1840
             JitsiConferenceEvents.LAST_N_ENDPOINTS_CHANGED,
2767
         APP.API.notifyAudioMutedStatusChanged(muted);
2767
         APP.API.notifyAudioMutedStatusChanged(muted);
2768
     },
2768
     },
2769
 
2769
 
2770
-    /**
2771
-     * Changes the subject of the conference.
2772
-     * Note: available only for moderator.
2773
-     *
2774
-     * @param subject {string} the new subject for the conference.
2775
-     */
2776
-    setSubject(subject) {
2777
-        APP.store.dispatch(setSubject(subject));
2778
-    },
2779
-
2780
     /**
2770
     /**
2781
      * Dispatches the passed in feedback for submission. The submitted score
2771
      * Dispatches the passed in feedback for submission. The submitted score
2782
      * should be a number inclusively between 1 through 5, or -1 for no score.
2772
      * should be a number inclusively between 1 through 5, or -1 for no score.

+ 21
- 0
css/_subject.scss 查看文件

1
+.subject {
2
+    top: -120px;
3
+    transition: top .3s ease-in;
4
+    height: 95px;
5
+    width: 100%;
6
+    position: absolute;
7
+    padding: 25px 140px 0 140px;
8
+    text-align: center;
9
+    font-size: 17px;
10
+    color: #fff;
11
+    z-index: $toolbarBackgroundZ;
12
+    overflow: hidden;
13
+    text-overflow: ellipsis;
14
+    box-sizing: border-box;
15
+    white-space: nowrap;
16
+    background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
17
+
18
+    &.visible {
19
+        top: 0px;
20
+    }
21
+}

+ 1
- 0
css/main.scss 查看文件

49
 @import 'modals/local-recording/local-recording';
49
 @import 'modals/local-recording/local-recording';
50
 @import 'videolayout_default';
50
 @import 'videolayout_default';
51
 @import 'notice';
51
 @import 'notice';
52
+@import 'subject';
52
 @import 'popup_menu';
53
 @import 'popup_menu';
53
 @import 'recording';
54
 @import 'recording';
54
 @import 'login_menu';
55
 @import 'login_menu';

+ 2
- 1
modules/API/API.js 查看文件

5
     createApiEvent,
5
     createApiEvent,
6
     sendAnalytics
6
     sendAnalytics
7
 } from '../../react/features/analytics';
7
 } from '../../react/features/analytics';
8
+import { setSubject } from '../../react/features/base/conference';
8
 import { parseJWTFromURLParams } from '../../react/features/base/jwt';
9
 import { parseJWTFromURLParams } from '../../react/features/base/jwt';
9
 import { invite } from '../../react/features/invite';
10
 import { invite } from '../../react/features/invite';
10
 import { getJitsiMeetTransport } from '../transport';
11
 import { getJitsiMeetTransport } from '../transport';
65
         },
66
         },
66
         'subject': subject => {
67
         'subject': subject => {
67
             sendAnalytics(createApiEvent('subject.changed'));
68
             sendAnalytics(createApiEvent('subject.changed'));
68
-            APP.conference.setSubject(subject);
69
+            APP.store.dispatch(setSubject(subject));
69
         },
70
         },
70
         'submit-feedback': feedback => {
71
         'submit-feedback': feedback => {
71
             sendAnalytics(createApiEvent('submit.feedback'));
72
             sendAnalytics(createApiEvent('submit.feedback'));

+ 1
- 1
modules/API/external/external_api.js 查看文件

548
      * {@code displayName} - Sets the display name of the local participant to
548
      * {@code displayName} - Sets the display name of the local participant to
549
      * the value passed in the arguments array.
549
      * the value passed in the arguments array.
550
      * {@code subject} - Sets the subject of the conference, the value passed
550
      * {@code subject} - Sets the subject of the conference, the value passed
551
-     * in the arguments array. Note: available only for moderator.
551
+     * in the arguments array. Note: Available only for moderator.
552
      *
552
      *
553
      * {@code toggleAudio} - Mutes / unmutes audio with no arguments.
553
      * {@code toggleAudio} - Mutes / unmutes audio with no arguments.
554
      * {@code toggleVideo} - Mutes / unmutes video with no arguments.
554
      * {@code toggleVideo} - Mutes / unmutes video with no arguments.

+ 20
- 10
react/features/base/conference/actionTypes.js 查看文件

42
  */
42
  */
43
 export const CONFERENCE_LEFT = Symbol('CONFERENCE_LEFT');
43
 export const CONFERENCE_LEFT = Symbol('CONFERENCE_LEFT');
44
 
44
 
45
+/**
46
+ * The type of (redux) action, which indicates conference subject changes.
47
+ *
48
+ * {
49
+ *     type: CONFERENCE_SUBJECT_CHANGED
50
+ *     subject: string
51
+ * }
52
+ */
53
+export const CONFERENCE_SUBJECT_CHANGED = Symbol('CONFERENCE_SUBJECT_CHANGED');
54
+
45
 /**
55
 /**
46
  * The type of (redux) action which signals that a specific conference will be
56
  * The type of (redux) action which signals that a specific conference will be
47
  * joined.
57
  * joined.
119
  */
129
  */
120
 export const SET_AUDIO_ONLY = Symbol('SET_AUDIO_ONLY');
130
 export const SET_AUDIO_ONLY = Symbol('SET_AUDIO_ONLY');
121
 
131
 
122
-/**
123
- * The type of (redux) action, which indicates to set conference subject.
124
- *
125
- * {
126
- *     type: SET_CONFERENCE_SUBJECT
127
- *     subject: string
128
- * }
129
- */
130
-export const SET_CONFERENCE_SUBJECT = Symbol('SET_CONFERENCE_SUBJECT');
131
-
132
 /**
132
 /**
133
  * The type of (redux) action which sets the desktop sharing enabled flag for
133
  * The type of (redux) action which sets the desktop sharing enabled flag for
134
  * the current conference.
134
  * the current conference.
199
  */
199
  */
200
 export const SET_PASSWORD_FAILED = Symbol('SET_PASSWORD_FAILED');
200
 export const SET_PASSWORD_FAILED = Symbol('SET_PASSWORD_FAILED');
201
 
201
 
202
+/**
203
+ * The type of (redux) action which signals for pending subject changes.
204
+ *
205
+ * {
206
+ *     type: SET_PENDING_SUBJECT_CHANGE,
207
+ *     subject: string
208
+ * }
209
+ */
210
+export const SET_PENDING_SUBJECT_CHANGE = Symbol('SET_PENDING_SUBJECT_CHANGE');
211
+
202
 /**
212
 /**
203
  * The type of (redux) action which sets the preferred maximum video height that
213
  * The type of (redux) action which sets the preferred maximum video height that
204
  * should be received from remote participants.
214
  * should be received from remote participants.

+ 34
- 5
react/features/base/conference/actions.js 查看文件

26
     CONFERENCE_FAILED,
26
     CONFERENCE_FAILED,
27
     CONFERENCE_JOINED,
27
     CONFERENCE_JOINED,
28
     CONFERENCE_LEFT,
28
     CONFERENCE_LEFT,
29
+    CONFERENCE_SUBJECT_CHANGED,
29
     CONFERENCE_WILL_JOIN,
30
     CONFERENCE_WILL_JOIN,
30
     CONFERENCE_WILL_LEAVE,
31
     CONFERENCE_WILL_LEAVE,
31
     DATA_CHANNEL_OPENED,
32
     DATA_CHANNEL_OPENED,
33
     LOCK_STATE_CHANGED,
34
     LOCK_STATE_CHANGED,
34
     P2P_STATUS_CHANGED,
35
     P2P_STATUS_CHANGED,
35
     SET_AUDIO_ONLY,
36
     SET_AUDIO_ONLY,
36
-    SET_CONFERENCE_SUBJECT,
37
     SET_DESKTOP_SHARING_ENABLED,
37
     SET_DESKTOP_SHARING_ENABLED,
38
     SET_FOLLOW_ME,
38
     SET_FOLLOW_ME,
39
     SET_LASTN,
39
     SET_LASTN,
42
     SET_PASSWORD_FAILED,
42
     SET_PASSWORD_FAILED,
43
     SET_PREFERRED_RECEIVER_VIDEO_QUALITY,
43
     SET_PREFERRED_RECEIVER_VIDEO_QUALITY,
44
     SET_ROOM,
44
     SET_ROOM,
45
+    SET_PENDING_SUBJECT_CHANGE,
45
     SET_START_MUTED_POLICY
46
     SET_START_MUTED_POLICY
46
 } from './actionTypes';
47
 } from './actionTypes';
47
 import {
48
 import {
272
     };
273
     };
273
 }
274
 }
274
 
275
 
276
+/**
277
+ * Signals that the conference subject has been changed.
278
+ *
279
+ * @param {string} subject - The new subject.
280
+ * @returns {{
281
+ *     type: CONFERENCE_SUBJECT_CHANGED,
282
+ *     subject: string
283
+ * }}
284
+ */
285
+export function conferenceSubjectChanged(subject: string) {
286
+    return {
287
+        type: CONFERENCE_SUBJECT_CHANGED,
288
+        subject
289
+    };
290
+}
291
+
275
 /**
292
 /**
276
  * Adds any existing local tracks to a specific conference before the conference
293
  * Adds any existing local tracks to a specific conference before the conference
277
  * is joined. Then signals the intention of the application to have the local
294
  * is joined. Then signals the intention of the application to have the local
736
  * @param {string} subject - The new subject.
753
  * @param {string} subject - The new subject.
737
  * @returns {void}
754
  * @returns {void}
738
  */
755
  */
739
-export function setSubject(subject: String) {
740
-    return {
741
-        type: SET_CONFERENCE_SUBJECT,
742
-        subject
756
+export function setSubject(subject: string = '') {
757
+    return (dispatch: Dispatch<*>, getState: Function) => {
758
+        const { conference } = getState()['features/base/conference'];
759
+
760
+        if (conference) {
761
+            dispatch({
762
+                type: SET_PENDING_SUBJECT_CHANGE,
763
+                subject: undefined
764
+            });
765
+            conference.setSubject(subject);
766
+        } else {
767
+            dispatch({
768
+                type: SET_PENDING_SUBJECT_CHANGE,
769
+                subject
770
+            });
771
+        }
743
     };
772
     };
744
 }
773
 }

+ 38
- 29
react/features/base/conference/middleware.js 查看文件

27
     conferenceLeft,
27
     conferenceLeft,
28
     conferenceWillLeave,
28
     conferenceWillLeave,
29
     createConference,
29
     createConference,
30
-    setLastN
30
+    setLastN,
31
+    setSubject
31
 } from './actions';
32
 } from './actions';
32
 import {
33
 import {
33
     CONFERENCE_FAILED,
34
     CONFERENCE_FAILED,
34
     CONFERENCE_JOINED,
35
     CONFERENCE_JOINED,
36
+    CONFERENCE_SUBJECT_CHANGED,
35
     CONFERENCE_WILL_LEAVE,
37
     CONFERENCE_WILL_LEAVE,
36
     DATA_CHANNEL_OPENED,
38
     DATA_CHANNEL_OPENED,
37
     SET_AUDIO_ONLY,
39
     SET_AUDIO_ONLY,
38
-    SET_CONFERENCE_SUBJECT,
39
     SET_LASTN,
40
     SET_LASTN,
40
     SET_ROOM
41
     SET_ROOM
41
 } from './actionTypes';
42
 } from './actionTypes';
75
     case CONNECTION_FAILED:
76
     case CONNECTION_FAILED:
76
         return _connectionFailed(store, next, action);
77
         return _connectionFailed(store, next, action);
77
 
78
 
79
+    case CONFERENCE_SUBJECT_CHANGED:
80
+        return _conferenceSubjectChanged(store, next, action);
81
+
78
     case CONFERENCE_WILL_LEAVE:
82
     case CONFERENCE_WILL_LEAVE:
79
         _conferenceWillLeave();
83
         _conferenceWillLeave();
80
         break;
84
         break;
91
     case SET_AUDIO_ONLY:
95
     case SET_AUDIO_ONLY:
92
         return _setAudioOnly(store, next, action);
96
         return _setAudioOnly(store, next, action);
93
 
97
 
94
-    case SET_CONFERENCE_SUBJECT:
95
-        return _setSubject(store, next, action);
96
-
97
     case SET_LASTN:
98
     case SET_LASTN:
98
         return _setLastN(store, next, action);
99
         return _setLastN(store, next, action);
99
 
100
 
192
 function _conferenceJoined({ dispatch, getState }, next, action) {
193
 function _conferenceJoined({ dispatch, getState }, next, action) {
193
     const result = next(action);
194
     const result = next(action);
194
 
195
 
195
-    const { audioOnly, conference } = getState()['features/base/conference'];
196
+    const {
197
+        audioOnly,
198
+        conference,
199
+        pendingSubjectChange
200
+    } = getState()['features/base/conference'];
201
+
202
+    if (pendingSubjectChange) {
203
+        dispatch(setSubject(pendingSubjectChange));
204
+    }
196
 
205
 
197
     // FIXME On Web the audio only mode for "start audio only" is toggled before
206
     // FIXME On Web the audio only mode for "start audio only" is toggled before
198
     // conference is added to the redux store ("on conference joined" action)
207
     // conference is added to the redux store ("on conference joined" action)
305
     return result;
314
     return result;
306
 }
315
 }
307
 
316
 
317
+/**
318
+ * Notifies the feature base/conference that the action
319
+ * {@code CONFERENCE_SUBJECT_CHANGED} is being dispatched within a specific
320
+ *  redux store.
321
+ *
322
+ * @param {Store} store - The redux store in which the specified {@code action}
323
+ * is being dispatched.
324
+ * @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
325
+ * specified {@code action} to the specified {@code store}.
326
+ * @param {Action} action - The redux action {@code CONFERENCE_SUBJECT_CHANGED}
327
+ * which is being dispatched in the specified {@code store}.
328
+ * @private
329
+ * @returns {Object} The value returned by {@code next(action)}.
330
+ */
331
+function _conferenceSubjectChanged({ getState }, next, action) {
332
+    const result = next(action);
333
+    const { subject } = getState()['features/base/conference'];
334
+
335
+    typeof APP === 'object' && APP.API.notifySubjectChanged(subject);
336
+
337
+    return result;
338
+}
339
+
308
 /**
340
 /**
309
  * Notifies the feature base/conference that the action
341
  * Notifies the feature base/conference that the action
310
  * {@code CONFERENCE_WILL_LEAVE} is being dispatched within a specific redux
342
  * {@code CONFERENCE_WILL_LEAVE} is being dispatched within a specific redux
683
 
715
 
684
     return result;
716
     return result;
685
 }
717
 }
686
-
687
-/**
688
- * Changing conference subject.
689
- *
690
- * @param {Store} store - The redux store in which the specified {@code action}
691
- * is being dispatched.
692
- * @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
693
- * specified {@code action} to the specified {@code store}.
694
- * @param {Action} action - The redux action which is being dispatched in the
695
- * specified {@code store}.
696
- * @private
697
- * @returns {Object} The value returned by {@code next(action)}.
698
- */
699
-function _setSubject({ getState }, next, action) {
700
-    const { conference } = getState()['features/base/conference'];
701
-    const { subject } = action;
702
-
703
-    if (subject) {
704
-        conference.setSubject(subject);
705
-    }
706
-
707
-    return next(action);
708
-}

+ 8
- 0
react/features/base/conference/reducer.js 查看文件

10
     CONFERENCE_FAILED,
10
     CONFERENCE_FAILED,
11
     CONFERENCE_JOINED,
11
     CONFERENCE_JOINED,
12
     CONFERENCE_LEFT,
12
     CONFERENCE_LEFT,
13
+    CONFERENCE_SUBJECT_CHANGED,
13
     CONFERENCE_WILL_JOIN,
14
     CONFERENCE_WILL_JOIN,
14
     CONFERENCE_WILL_LEAVE,
15
     CONFERENCE_WILL_LEAVE,
15
     LOCK_STATE_CHANGED,
16
     LOCK_STATE_CHANGED,
19
     SET_FOLLOW_ME,
20
     SET_FOLLOW_ME,
20
     SET_MAX_RECEIVER_VIDEO_QUALITY,
21
     SET_MAX_RECEIVER_VIDEO_QUALITY,
21
     SET_PASSWORD,
22
     SET_PASSWORD,
23
+    SET_PENDING_SUBJECT_CHANGE,
22
     SET_PREFERRED_RECEIVER_VIDEO_QUALITY,
24
     SET_PREFERRED_RECEIVER_VIDEO_QUALITY,
23
     SET_ROOM,
25
     SET_ROOM,
24
     SET_SIP_GATEWAY_ENABLED,
26
     SET_SIP_GATEWAY_ENABLED,
55
         case CONFERENCE_JOINED:
57
         case CONFERENCE_JOINED:
56
             return _conferenceJoined(state, action);
58
             return _conferenceJoined(state, action);
57
 
59
 
60
+        case CONFERENCE_SUBJECT_CHANGED:
61
+            return set(state, 'subject', action.subject);
62
+
58
         case CONFERENCE_LEFT:
63
         case CONFERENCE_LEFT:
59
         case CONFERENCE_WILL_LEAVE:
64
         case CONFERENCE_WILL_LEAVE:
60
             return _conferenceLeftOrWillLeave(state, action);
65
             return _conferenceLeftOrWillLeave(state, action);
92
         case SET_PASSWORD:
97
         case SET_PASSWORD:
93
             return _setPassword(state, action);
98
             return _setPassword(state, action);
94
 
99
 
100
+        case SET_PENDING_SUBJECT_CHANGE:
101
+            return set(state, 'pendingSubjectChange', action.subject);
102
+
95
         case SET_PREFERRED_RECEIVER_VIDEO_QUALITY:
103
         case SET_PREFERRED_RECEIVER_VIDEO_QUALITY:
96
             return set(
104
             return set(
97
                 state,
105
                 state,

+ 2
- 0
react/features/conference/components/web/Conference.js 查看文件

31
 
31
 
32
 import Labels from './Labels';
32
 import Labels from './Labels';
33
 import { default as Notice } from './Notice';
33
 import { default as Notice } from './Notice';
34
+import { default as Subject } from './Subject';
34
 
35
 
35
 declare var APP: Object;
36
 declare var APP: Object;
36
 declare var config: Object;
37
 declare var config: Object;
217
                 id = 'videoconference_page'
218
                 id = 'videoconference_page'
218
                 onMouseMove = { this._onShowToolbar }>
219
                 onMouseMove = { this._onShowToolbar }>
219
                 <Notice />
220
                 <Notice />
221
+                <Subject />
220
                 <div id = 'videospace'>
222
                 <div id = 'videospace'>
221
                     <LargeVideo />
223
                     <LargeVideo />
222
                     { hideVideoQualityLabel
224
                     { hideVideoQualityLabel

+ 67
- 0
react/features/conference/components/web/Subject.js 查看文件

1
+/* @flow */
2
+
3
+import React, { Component } from 'react';
4
+import { connect } from 'react-redux';
5
+
6
+import { isToolboxVisible } from '../../../toolbox';
7
+
8
+/**
9
+ * The type of the React {@code Component} props of {@link Subject}.
10
+ */
11
+type Props = {
12
+
13
+    /**
14
+     * The subject of the conference.
15
+     */
16
+    _subject: string,
17
+
18
+    /**
19
+     * Indicates whether the component should be visible or not.
20
+     */
21
+    _visible: boolean
22
+};
23
+
24
+/**
25
+ * Subject react component.
26
+ *
27
+ * @class Subject
28
+ */
29
+class Subject extends Component<Props> {
30
+
31
+    /**
32
+     * Implements React's {@link Component#render()}.
33
+     *
34
+     * @inheritdoc
35
+     * @returns {ReactElement}
36
+     */
37
+    render() {
38
+        const { _subject, _visible } = this.props;
39
+
40
+        return (
41
+            <div className = { `subject ${_visible ? 'visible' : ''}` }>
42
+                { _subject }
43
+            </div>
44
+        );
45
+    }
46
+}
47
+
48
+/**
49
+ * Maps (parts of) the Redux state to the associated
50
+ * {@code Subject}'s props.
51
+ *
52
+ * @param {Object} state - The Redux state.
53
+ * @private
54
+ * @returns {{
55
+ *     _subject: string,
56
+ *     _visible: boolean
57
+ * }}
58
+ */
59
+function _mapStateToProps(state) {
60
+    const { subject } = state['features/base/conference'];
61
+
62
+    return {
63
+        _subject: subject,
64
+        _visible: isToolboxVisible(state)
65
+    };
66
+}
67
+export default connect(_mapStateToProps)(Subject);

+ 3
- 5
react/features/toolbox/components/web/Toolbox.js 查看文件

55
     setToolbarHovered
55
     setToolbarHovered
56
 } from '../../actions';
56
 } from '../../actions';
57
 import AudioMuteButton from '../AudioMuteButton';
57
 import AudioMuteButton from '../AudioMuteButton';
58
+import { isToolboxVisible } from '../../functions';
58
 import HangupButton from '../HangupButton';
59
 import HangupButton from '../HangupButton';
59
 import OverflowMenuButton from './OverflowMenuButton';
60
 import OverflowMenuButton from './OverflowMenuButton';
60
 import OverflowMenuProfileItem from './OverflowMenuProfileItem';
61
 import OverflowMenuProfileItem from './OverflowMenuProfileItem';
1281
     } = state['features/base/config'];
1282
     } = state['features/base/config'];
1282
     const sharedVideoStatus = state['features/shared-video'].status;
1283
     const sharedVideoStatus = state['features/shared-video'].status;
1283
     const {
1284
     const {
1284
-        alwaysVisible,
1285
         fullScreen,
1285
         fullScreen,
1286
-        overflowMenuVisible,
1287
-        timeoutID,
1288
-        visible
1286
+        overflowMenuVisible
1289
     } = state['features/toolbox'];
1287
     } = state['features/toolbox'];
1290
     const localParticipant = getLocalParticipant(state);
1288
     const localParticipant = getLocalParticipant(state);
1291
     const localRecordingStates = state['features/local-recording'];
1289
     const localRecordingStates = state['features/local-recording'];
1333
         _sharingVideo: sharedVideoStatus === 'playing'
1331
         _sharingVideo: sharedVideoStatus === 'playing'
1334
             || sharedVideoStatus === 'start'
1332
             || sharedVideoStatus === 'start'
1335
             || sharedVideoStatus === 'pause',
1333
             || sharedVideoStatus === 'pause',
1336
-        _visible: Boolean(timeoutID || visible || alwaysVisible),
1334
+        _visible: isToolboxVisible(state),
1337
 
1335
 
1338
         // XXX: We are not currently using state here, but in the future, when
1336
         // XXX: We are not currently using state here, but in the future, when
1339
         // interfaceConfig is part of redux we will.
1337
         // interfaceConfig is part of redux we will.

+ 0
- 17
react/features/toolbox/functions.any.js 查看文件

1
-// @flow
2
-
3
-import { toState } from '../base/redux';
4
-
5
-/**
6
- * Returns true if the toolbox is visible.
7
- *
8
- * @param {Object | Function} stateful - A function or object that can be
9
- * resolved to Redux state by the function {@code toState}.
10
- * @returns {boolean}
11
- */
12
-export function isToolboxVisible(stateful: Object | Function) {
13
-    const { alwaysVisible, enabled, visible }
14
-        = toState(stateful)['features/toolbox'];
15
-
16
-    return enabled && (alwaysVisible || visible);
17
-}

+ 15
- 1
react/features/toolbox/functions.native.js 查看文件

1
 // @flow
1
 // @flow
2
 
2
 
3
-export * from './functions.any';
3
+import { toState } from '../base/redux';
4
+
5
+/**
6
+ * Returns true if the toolbox is visible.
7
+ *
8
+ * @param {Object | Function} stateful - A function or object that can be
9
+ * resolved to Redux state by the function {@code toState}.
10
+ * @returns {boolean}
11
+ */
12
+export function isToolboxVisible(stateful: Object | Function) {
13
+    const { alwaysVisible, enabled, visible }
14
+        = toState(stateful)['features/toolbox'];
15
+
16
+    return enabled && (alwaysVisible || visible);
17
+}

+ 18
- 2
react/features/toolbox/functions.web.js 查看文件

1
 // @flow
1
 // @flow
2
 
2
 
3
-export * from './functions.any';
4
-
5
 declare var interfaceConfig: Object;
3
 declare var interfaceConfig: Object;
6
 
4
 
7
 /**
5
 /**
26
 export function isButtonEnabled(name: string) {
24
 export function isButtonEnabled(name: string) {
27
     return interfaceConfig.TOOLBAR_BUTTONS.indexOf(name) !== -1;
25
     return interfaceConfig.TOOLBAR_BUTTONS.indexOf(name) !== -1;
28
 }
26
 }
27
+
28
+
29
+/**
30
+ * Indicates if the toolbox is visible or not.
31
+ *
32
+ * @param {string} state - The state from the Redux store.
33
+ * @returns {boolean} - True to indicate that the toolbox is visible, false -
34
+ * otherwise.
35
+ */
36
+export function isToolboxVisible(state: Object) {
37
+    const {
38
+        alwaysVisible,
39
+        timeoutID,
40
+        visible
41
+    } = state['features/toolbox'];
42
+
43
+    return Boolean(timeoutID || visible || alwaysVisible);
44
+}

Loading…
取消
儲存