瀏覽代碼

feat(always-on-top): Updates buttons for visitors. (#15369)

* feat(always-on-top): Updates buttons for visitors.

* squash: rename listener.

* squash: Adds visitor to the conference joined event.

* squash: fix comments and lint.

* squash: fix comments.
factor2
Дамян Минков 10 月之前
父節點
當前提交
f85d0e6469
沒有連結到貢獻者的電子郵件帳戶。

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

@@ -398,6 +398,7 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
398 398
         this._participants = {};
399 399
         this._myUserID = undefined;
400 400
         this._onStageParticipant = undefined;
401
+        this._iAmvisitor = undefined;
401 402
         this._setupListeners();
402 403
         id++;
403 404
     }
@@ -619,6 +620,7 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
619 620
                     email: data.email,
620 621
                     avatarURL: data.avatarURL
621 622
                 };
623
+                this._iAmvisitor = data.visitor;
622 624
             }
623 625
 
624 626
             // eslint-disable-next-line no-fallthrough
@@ -1168,6 +1170,15 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
1168 1170
         });
1169 1171
     }
1170 1172
 
1173
+    /**
1174
+     * Returns whether we have joined as visitor in a meeting.
1175
+     *
1176
+     * @returns {boolean} - Returns true if we have joined as visitor.
1177
+     */
1178
+    isVisitor() {
1179
+        return this._iAmvisitor;
1180
+    }
1181
+
1171 1182
     /**
1172 1183
      * Returns the avatar URL of a participant.
1173 1184
      *

+ 82
- 3
react/features/always-on-top/Toolbar.tsx 查看文件

@@ -4,6 +4,8 @@ import AudioMuteButton from './AudioMuteButton';
4 4
 import HangupButton from './HangupButton';
5 5
 import VideoMuteButton from './VideoMuteButton';
6 6
 
7
+const { api } = window.alwaysOnTop;
8
+
7 9
 /**
8 10
  * The type of the React {@code Component} props of {@link Toolbar}.
9 11
  */
@@ -25,12 +27,89 @@ interface IProps {
25 27
     onMouseOver: (e?: React.MouseEvent) => void;
26 28
 }
27 29
 
30
+/**
31
+ * The type of the React {@code Component} state of {@link Toolbar}.
32
+ */
33
+interface IState {
34
+
35
+    /**
36
+     * Whether audio button to be shown or not.
37
+     */
38
+    showAudioButton: boolean;
39
+
40
+    /**
41
+     * Whether video button to be shown or not.
42
+     */
43
+    showVideoButton: boolean;
44
+}
45
+
46
+type Props = Partial<IProps>;
47
+
28 48
 /**
29 49
  * Represents the toolbar in the Always On Top window.
30 50
  *
31 51
  * @augments Component
32 52
  */
33
-export default class Toolbar extends Component<IProps> {
53
+export default class Toolbar extends Component<Props, IState> {
54
+    /**
55
+     * Initializes a new {@code Toolbar} instance.
56
+     *
57
+     * @param {IProps} props - The React {@code Component} props to initialize the new {@code Toolbar} instance with.
58
+     */
59
+    constructor(props: Props) {
60
+        super(props);
61
+
62
+        this.state = {
63
+            showAudioButton: true,
64
+            showVideoButton: true
65
+        };
66
+
67
+        this._videoConferenceJoinedListener = this._videoConferenceJoinedListener.bind(this);
68
+    }
69
+
70
+    /**
71
+     * Sets listens for changing meetings while showing the toolbar.
72
+     *
73
+     * @inheritdoc
74
+     * @returns {void}
75
+     */
76
+    componentDidMount() {
77
+        api.on('videoConferenceJoined', this._videoConferenceJoinedListener);
78
+
79
+        this._videoConferenceJoinedListener();
80
+    }
81
+
82
+    /**
83
+     * Handles is visitor changes.
84
+     *
85
+     * @returns {void}
86
+     */
87
+    _videoConferenceJoinedListener() {
88
+        // for electron clients that embed the api and are not updated
89
+        if (!api.isVisitor) {
90
+            console.warn('external API not updated');
91
+
92
+            return;
93
+        }
94
+
95
+        const isNotVisitor = !api.isVisitor();
96
+
97
+        this.setState({
98
+            showAudioButton: isNotVisitor,
99
+            showVideoButton: isNotVisitor
100
+        });
101
+    }
102
+
103
+    /**
104
+     * Removes all listeners.
105
+     *
106
+     * @inheritdoc
107
+     * @returns {void}
108
+     */
109
+    componentWillUnmount() {
110
+        api.removeListener('videoConferenceJoined', this._videoConferenceJoinedListener);
111
+    }
112
+
34 113
     /**
35 114
      * Implements React's {@link Component#render()}.
36 115
      *
@@ -49,8 +128,8 @@ export default class Toolbar extends Component<IProps> {
49 128
                 className = { `toolbox-content-items always-on-top-toolbox ${className}` }
50 129
                 onMouseOut = { onMouseOut }
51 130
                 onMouseOver = { onMouseOver }>
52
-                <AudioMuteButton />
53
-                <VideoMuteButton />
131
+                { this.state.showAudioButton && <AudioMuteButton /> }
132
+                { this.state.showVideoButton && <VideoMuteButton /> }
54 133
                 <HangupButton customClass = 'hangup-button' />
55 134
             </div>
56 135
         );

+ 3
- 1
react/features/external-api/middleware.ts 查看文件

@@ -29,6 +29,7 @@ import { getBaseUrl } from '../base/util/helpers';
29 29
 import { appendSuffix } from '../display-name/functions';
30 30
 import { SUBMIT_FEEDBACK_ERROR, SUBMIT_FEEDBACK_SUCCESS } from '../feedback/actionTypes';
31 31
 import { SET_FILMSTRIP_VISIBLE } from '../filmstrip/actionTypes';
32
+import { iAmVisitor } from '../visitors/functions';
32 33
 
33 34
 import './subscriber';
34 35
 
@@ -120,7 +121,8 @@ MiddlewareRegistry.register(store => next => action => {
120 121
                 ),
121 122
                 avatarURL: loadableAvatarUrl,
122 123
                 breakoutRoom,
123
-                email
124
+                email,
125
+                visitor: iAmVisitor(state)
124 126
             }
125 127
         );
126 128
         break;

+ 3
- 1
react/features/toolbox/functions.any.ts 查看文件

@@ -2,6 +2,7 @@ import { IReduxState } from '../app/types';
2 2
 import { isJwtFeatureEnabledStateless } from '../base/jwt/functions';
3 3
 import { IGUMPendingState } from '../base/media/types';
4 4
 import { IParticipantFeatures } from '../base/participants/types';
5
+import { iAmVisitor } from '../visitors/functions';
5 6
 
6 7
 /**
7 8
  * Indicates if the audio mute button is disabled or not.
@@ -13,7 +14,8 @@ export function isAudioMuteButtonDisabled(state: IReduxState) {
13 14
     const { available, muted, unmuteBlocked, gumPending } = state['features/base/media'].audio;
14 15
     const { startSilent } = state['features/base/config'];
15 16
 
16
-    return Boolean(!available || startSilent || (muted && unmuteBlocked) || gumPending !== IGUMPendingState.NONE);
17
+    return Boolean(!available || startSilent || (muted && unmuteBlocked) || gumPending !== IGUMPendingState.NONE
18
+        || iAmVisitor(state));
17 19
 }
18 20
 
19 21
 /**

Loading…
取消
儲存