Parcourir la source

ref(AOT) Change buttons to not use abstract classes (#11302)

This reduces the bundle size by about 100KB
It also decouples the AOT buttons from the classes that are used to implement other features
master
Robert Pintilii il y a 3 ans
Parent
révision
c2399deb55
Aucun compte lié à l'adresse e-mail de l'auteur

+ 38
- 4
react/features/always-on-top/AudioMuteButton.js Voir le fichier

@@ -1,10 +1,14 @@
1 1
 // @flow
2 2
 
3
+import React, { Component } from 'react';
4
+
3 5
 // We need to reference these files directly to avoid loading things that are not available
4 6
 // in this environment (e.g. JitsiMeetJS or interfaceConfig)
5
-import AbstractAudioMuteButton from '../base/toolbox/components/AbstractAudioMuteButton';
7
+import { IconMicrophoneEmpty, IconMicrophoneEmptySlash } from '../base/icons';
6 8
 import type { Props } from '../base/toolbox/components/AbstractButton';
7 9
 
10
+import ToolbarButton from './ToolbarButton';
11
+
8 12
 const { api } = window.alwaysOnTop;
9 13
 
10 14
 /**
@@ -26,9 +30,9 @@ type State = {
26 30
 /**
27 31
  * Stateless "mute/unmute audio" button for the Always-on-Top windows.
28 32
  */
29
-export default class AudioMuteButton
30
-    extends AbstractAudioMuteButton<Props, State> {
31
-
33
+export default class AudioMuteButton extends Component<Props, State> {
34
+    icon = IconMicrophoneEmpty;
35
+    toggledIcon = IconMicrophoneEmptySlash;
32 36
     accessibilityLabel = 'Audio mute';
33 37
 
34 38
     /**
@@ -49,6 +53,7 @@ export default class AudioMuteButton
49 53
         this._audioAvailabilityListener
50 54
             = this._audioAvailabilityListener.bind(this);
51 55
         this._audioMutedListener = this._audioMutedListener.bind(this);
56
+        this._onClick = this._onClick.bind(this);
52 57
     }
53 58
 
54 59
     /**
@@ -145,4 +150,33 @@ export default class AudioMuteButton
145 150
     _setAudioMuted(audioMuted: boolean) { // eslint-disable-line no-unused-vars
146 151
         this.state.audioAvailable && api.executeCommand('toggleAudio');
147 152
     }
153
+
154
+    _onClick: () => {};
155
+
156
+    /**
157
+     * Handles clicking / pressing the button, and toggles the audio mute state
158
+     * accordingly.
159
+     *
160
+     * @returns {void}
161
+     */
162
+    _onClick() {
163
+        this._setAudioMuted(!this._isAudioMuted());
164
+    }
165
+
166
+    /**
167
+     * Implements React's {@link Component#render()}.
168
+     *
169
+     * @inheritdoc
170
+     * @returns {ReactElement}
171
+     */
172
+    render() {
173
+        const toggled = this._isAudioMuted();
174
+
175
+        return (<ToolbarButton
176
+            accessibilityLabel = { this.accessibilityLabel }
177
+            disabled = { this._isDisabled() }
178
+            icon = { toggled ? this.toggledIcon : this.icon }
179
+            onClick = { this._onClick }
180
+            toggled = { toggled } />);
181
+    }
148 182
 }

+ 37
- 5
react/features/always-on-top/HangupButton.js Voir le fichier

@@ -1,27 +1,59 @@
1 1
 // @flow
2
+import React, { Component } from 'react';
2 3
 
3 4
 // We need to reference these files directly to avoid loading things that are not available
4 5
 // in this environment (e.g. JitsiMeetJS or interfaceConfig)
6
+import { IconHangup } from '../base/icons';
5 7
 import type { Props } from '../base/toolbox/components/AbstractButton';
6
-import AbstractHangupButton from '../base/toolbox/components/AbstractHangupButton';
8
+
9
+import ToolbarButton from './ToolbarButton';
7 10
 
8 11
 const { api } = window.alwaysOnTop;
9 12
 
10 13
 /**
11 14
  * Stateless hangup button for the Always-on-Top windows.
12 15
  */
13
-export default class HangupButton extends AbstractHangupButton<Props, *> {
16
+export default class HangupButton extends Component<Props, *> {
14 17
 
15 18
     accessibilityLabel = 'Hangup';
19
+    icon = IconHangup;
16 20
 
17 21
     /**
18
-     * Helper function to perform the actual hangup action.
22
+     * Initializes a new {@code HangupButton} instance.
23
+     *
24
+     * @param {Props} props - The React {@code Component} props to initialize
25
+     * the new {@code HangupButton} instance with.
26
+     */
27
+    constructor(props: Props) {
28
+        super(props);
29
+
30
+        // Bind event handlers so they are only bound once per instance.
31
+        this._onClick = this._onClick.bind(this);
32
+    }
33
+
34
+    _onClick: () => {};
35
+
36
+    /**
37
+     * Handles clicking / pressing the button, and disconnects the conference.
19 38
      *
20
-     * @override
21 39
      * @protected
22 40
      * @returns {void}
23 41
      */
24
-    _doHangup() {
42
+    _onClick() {
25 43
         api.executeCommand('hangup');
26 44
     }
45
+
46
+    /**
47
+     * Implements React's {@link Component#render()}.
48
+     *
49
+     * @inheritdoc
50
+     * @returns {ReactElement}
51
+     */
52
+    render() {
53
+        return (<ToolbarButton
54
+            accessibilityLabel = { this.accessibilityLabel }
55
+            customClass = 'hangup-button'
56
+            icon = { this.icon }
57
+            onClick = { this._onClick } />);
58
+    }
27 59
 }

+ 69
- 0
react/features/always-on-top/ToolbarButton.js Voir le fichier

@@ -0,0 +1,69 @@
1
+import React, { useCallback } from 'react';
2
+
3
+import { Icon } from '../base/icons';
4
+
5
+type Props = {
6
+
7
+    /**
8
+     * Accessibility label for button.
9
+     */
10
+    accessibilityLabel: string,
11
+
12
+    /**
13
+     * An extra class name to be added at the end of the element's class name
14
+     * in order to enable custom styling.
15
+     */
16
+    customClass?: string,
17
+
18
+    /**
19
+     * Whether or not the button is disabled.
20
+     */
21
+    disabled?: boolean,
22
+
23
+    /**
24
+     * Click handler.
25
+     */
26
+    onClick: Function,
27
+
28
+    /**
29
+     * Button icon.
30
+     */
31
+    icon: Object,
32
+
33
+    /**
34
+     * Whether or not the button is toggled.
35
+     */
36
+    toggled?: boolean
37
+}
38
+
39
+const ToolbarButton = ({
40
+    accessibilityLabel,
41
+    customClass,
42
+    disabled = false,
43
+    onClick,
44
+    icon,
45
+    toggled = false
46
+}: Props) => {
47
+    const onKeyPress = useCallback(event => {
48
+        if (event.key === 'Enter' || event.key === ' ') {
49
+            event.preventDefault();
50
+            onClick();
51
+        }
52
+    }, [ onClick ]);
53
+
54
+    return (<div
55
+        aria-disabled = { disabled }
56
+        aria-label = { accessibilityLabel }
57
+        aria-pressed = { toggled }
58
+        className = { `toolbox-button ${disabled ? ' disabled' : ''}` }
59
+        onClick = { disabled ? undefined : onClick }
60
+        onKeyPress = { disabled ? undefined : onKeyPress }
61
+        role = 'button'
62
+        tabIndex = { 0 }>
63
+        <div className = { `toolbox-icon ${disabled ? 'disabled' : ''} ${customClass ?? ''}` }>
64
+            <Icon src = { icon } />
65
+        </div>
66
+    </div>);
67
+};
68
+
69
+export default ToolbarButton;

+ 38
- 3
react/features/always-on-top/VideoMuteButton.js Voir le fichier

@@ -1,9 +1,12 @@
1 1
 // @flow
2
+import React, { Component } from 'react';
2 3
 
3 4
 // We need to reference these files directly to avoid loading things that are not available
4 5
 // in this environment (e.g. JitsiMeetJS or interfaceConfig)
6
+import { IconCameraEmpty, IconCameraEmptyDisabled } from '../base/icons';
5 7
 import type { Props } from '../base/toolbox/components/AbstractButton';
6
-import AbstractVideoMuteButton from '../base/toolbox/components/AbstractVideoMuteButton';
8
+
9
+import ToolbarButton from './ToolbarButton';
7 10
 
8 11
 const { api } = window.alwaysOnTop;
9 12
 
@@ -26,9 +29,10 @@ type State = {
26 29
 /**
27 30
  * Stateless "mute/unmute video" button for the Always-on-Top windows.
28 31
  */
29
-export default class VideoMuteButton
30
-    extends AbstractVideoMuteButton<Props, State> {
32
+export default class VideoMuteButton extends Component<Props, State> {
31 33
 
34
+    icon = IconCameraEmpty;
35
+    toggledIcon = IconCameraEmptyDisabled;
32 36
     accessibilityLabel = 'Video mute';
33 37
 
34 38
     /**
@@ -49,6 +53,7 @@ export default class VideoMuteButton
49 53
         this._videoAvailabilityListener
50 54
             = this._videoAvailabilityListener.bind(this);
51 55
         this._videoMutedListener = this._videoMutedListener.bind(this);
56
+        this._onClick = this._onClick.bind(this);
52 57
     }
53 58
 
54 59
     /**
@@ -145,4 +150,34 @@ export default class VideoMuteButton
145 150
     _videoMutedListener({ muted }) {
146 151
         this.setState({ videoMuted: muted });
147 152
     }
153
+
154
+    _onClick: () => {};
155
+
156
+    /**
157
+     * Handles clicking / pressing the button, and toggles the video mute state
158
+     * accordingly.
159
+     *
160
+     * @protected
161
+     * @returns {void}
162
+     */
163
+    _onClick() {
164
+        this._setVideoMuted(!this._isVideoMuted());
165
+    }
166
+
167
+    /**
168
+     * Implements React's {@link Component#render()}.
169
+     *
170
+     * @inheritdoc
171
+     * @returns {ReactElement}
172
+     */
173
+    render() {
174
+        const toggled = this._isVideoMuted();
175
+
176
+        return (<ToolbarButton
177
+            accessibilityLabel = { this.accessibilityLabel }
178
+            disabled = { this._isDisabled() }
179
+            icon = { toggled ? this.toggledIcon : this.icon }
180
+            onClick = { this._onClick }
181
+            toggled = { toggled } />);
182
+    }
148 183
 }

Chargement…
Annuler
Enregistrer