Browse Source

ref(TS) Convert always-on-top to TS (#13332)

factor2
Robert Pintilii 2 years ago
parent
commit
ae0669fa07
No account linked to committer's email address

+ 1
- 0
globals.d.ts View File

@@ -21,6 +21,7 @@ declare global {
21 21
         JitsiMeetElectron?: any;
22 22
         // selenium tests handler
23 23
         _sharedVideoPlayer: any;
24
+        alwaysOnTop: { api: any };
24 25
     }
25 26
 
26 27
     interface Document {

react/features/always-on-top/AlwaysOnTop.js → react/features/always-on-top/AlwaysOnTop.tsx View File

@@ -1,5 +1,3 @@
1
-// @flow
2
-
3 1
 import React, { Component } from 'react';
4 2
 
5 3
 // We need to reference these files directly to avoid loading things that are not available
@@ -19,15 +17,15 @@ const TOOLBAR_TIMEOUT = 4000;
19 17
 /**
20 18
  * The type of the React {@code Component} state of {@link AlwaysOnTop}.
21 19
  */
22
-type State = {
23
-    avatarURL: string,
24
-    customAvatarBackgrounds: Array<string>,
25
-    displayName: string,
26
-    formattedDisplayName: string,
27
-    isVideoDisplayed: boolean,
28
-    userID: string,
29
-    visible: boolean
30
-};
20
+interface IState {
21
+    avatarURL: string;
22
+    customAvatarBackgrounds: Array<string>;
23
+    displayName: string;
24
+    formattedDisplayName: string;
25
+    isVideoDisplayed: boolean;
26
+    userID: string;
27
+    visible: boolean;
28
+}
31 29
 
32 30
 /**
33 31
  * Represents the always on top page.
@@ -35,7 +33,7 @@ type State = {
35 33
  * @class AlwaysOnTop
36 34
  * @augments Component
37 35
  */
38
-export default class AlwaysOnTop extends Component<*, State> {
36
+export default class AlwaysOnTop extends Component<any, IState> {
39 37
     _hovered: boolean;
40 38
 
41 39
     /**
@@ -44,7 +42,7 @@ export default class AlwaysOnTop extends Component<*, State> {
44 42
      * @param {*} props - The read-only properties with which the new instance
45 43
      * is to be initialized.
46 44
      */
47
-    constructor(props: *) {
45
+    constructor(props: any) {
48 46
         super(props);
49 47
 
50 48
         this.state = {
@@ -68,28 +66,25 @@ export default class AlwaysOnTop extends Component<*, State> {
68 66
         this._onMouseOver = this._onMouseOver.bind(this);
69 67
     }
70 68
 
71
-    _avatarChangedListener: () => void;
72
-
73 69
     /**
74 70
      * Handles avatar changed api events.
75 71
      *
76 72
      * @returns {void}
77 73
      */
78
-    _avatarChangedListener({ avatarURL, id }) {
74
+    _avatarChangedListener({ avatarURL, id }: { avatarURL: string; id: string; }) {
79 75
         if (api._getOnStageParticipant() === id
80 76
                 && avatarURL !== this.state.avatarURL) {
81 77
             this.setState({ avatarURL });
82 78
         }
83 79
     }
84 80
 
85
-    _displayNameChangedListener: () => void;
86
-
87 81
     /**
88 82
      * Handles display name changed api events.
89 83
      *
90 84
      * @returns {void}
91 85
      */
92
-    _displayNameChangedListener({ displayname, formattedDisplayName, id }) {
86
+    _displayNameChangedListener({ displayname, formattedDisplayName, id }: { displayname: string;
87
+        formattedDisplayName: string; id: string; }) {
93 88
         if (api._getOnStageParticipant() === id
94 89
                 && (formattedDisplayName !== this.state.formattedDisplayName
95 90
                     || displayname !== this.state.displayName)) {
@@ -118,8 +113,6 @@ export default class AlwaysOnTop extends Component<*, State> {
118 113
             TOOLBAR_TIMEOUT);
119 114
     }
120 115
 
121
-    _videoChangedListener: () => void;
122
-
123 116
     /**
124 117
      * Handles large video changed api events.
125 118
      *
@@ -141,8 +134,6 @@ export default class AlwaysOnTop extends Component<*, State> {
141 134
         });
142 135
     }
143 136
 
144
-    _mouseMove: () => void;
145
-
146 137
     /**
147 138
      * Handles mouse move events.
148 139
      *
@@ -152,8 +143,6 @@ export default class AlwaysOnTop extends Component<*, State> {
152 143
         this.state.visible || this.setState({ visible: true });
153 144
     }
154 145
 
155
-    _onMouseOut: () => void;
156
-
157 146
     /**
158 147
      * Toolbar mouse out handler.
159 148
      *
@@ -163,8 +152,6 @@ export default class AlwaysOnTop extends Component<*, State> {
163 152
         this._hovered = false;
164 153
     }
165 154
 
166
-    _onMouseOver: () => void;
167
-
168 155
     /**
169 156
      * Toolbar mouse over handler.
170 157
      *
@@ -229,7 +216,7 @@ export default class AlwaysOnTop extends Component<*, State> {
229 216
 
230 217
         this._hideToolbarAfterTimeout();
231 218
         api.getCustomAvatarBackgrounds()
232
-            .then(res =>
219
+            .then((res: { avatarBackgrounds?: string[]; }) =>
233 220
                 this.setState({
234 221
                     customAvatarBackgrounds: res.avatarBackgrounds || []
235 222
                 }))
@@ -242,7 +229,7 @@ export default class AlwaysOnTop extends Component<*, State> {
242 229
      * @inheritdoc
243 230
      * @returns {void}
244 231
      */
245
-    componentDidUpdate(prevProps: *, prevState: State) {
232
+    componentDidUpdate(_prevProps: any, prevState: IState) {
246 233
         if (!prevState.visible && this.state.visible) {
247 234
             this._hideToolbarAfterTimeout();
248 235
         }

react/features/always-on-top/AudioMuteButton.js → react/features/always-on-top/AudioMuteButton.tsx View File

@@ -1,11 +1,9 @@
1
-// @flow
2
-
3 1
 import React, { Component } from 'react';
4 2
 
5 3
 // We need to reference these files directly to avoid loading things that are not available
6 4
 // in this environment (e.g. JitsiMeetJS or interfaceConfig)
7 5
 import { IconMic, IconMicSlash } from '../base/icons/svg';
8
-import type { Props } from '../base/toolbox/components/AbstractButton';
6
+import { IProps } from '../base/toolbox/components/AbstractButton';
9 7
 
10 8
 import ToolbarButton from './ToolbarButton';
11 9
 
@@ -14,23 +12,25 @@ const { api } = window.alwaysOnTop;
14 12
 /**
15 13
  * The type of the React {@code Component} state of {@link AudioMuteButton}.
16 14
  */
17
-type State = {
15
+interface IState {
18 16
 
19 17
     /**
20 18
      * Whether audio is available is not.
21 19
      */
22
-    audioAvailable: boolean,
20
+    audioAvailable: boolean;
23 21
 
24 22
     /**
25 23
      * Whether audio is muted or not.
26 24
      */
27
-    audioMuted: boolean
28
-};
25
+    audioMuted: boolean;
26
+}
27
+
28
+type Props = Partial<IProps>;
29 29
 
30 30
 /**
31 31
  * Stateless "mute/unmute audio" button for the Always-on-Top windows.
32 32
  */
33
-export default class AudioMuteButton extends Component<Props, State> {
33
+export default class AudioMuteButton extends Component<Props, IState> {
34 34
     icon = IconMic;
35 35
     toggledIcon = IconMicSlash;
36 36
     accessibilityLabel = 'Audio mute';
@@ -38,7 +38,7 @@ export default class AudioMuteButton extends Component<Props, State> {
38 38
     /**
39 39
      * Initializes a new {@code AudioMuteButton} instance.
40 40
      *
41
-     * @param {Props} props - The React {@code Component} props to initialize
41
+     * @param {IProps} props - The React {@code Component} props to initialize
42 42
      * the new {@code AudioMuteButton} instance with.
43 43
      */
44 44
     constructor(props: Props) {
@@ -94,27 +94,23 @@ export default class AudioMuteButton extends Component<Props, State> {
94 94
             this._audioMutedListener);
95 95
     }
96 96
 
97
-    _audioAvailabilityListener: ({ available: boolean }) => void;
98
-
99 97
     /**
100 98
      * Handles audio available api events.
101 99
      *
102 100
      * @param {{ available: boolean }} status - The new available status.
103 101
      * @returns {void}
104 102
      */
105
-    _audioAvailabilityListener({ available }) {
103
+    _audioAvailabilityListener({ available }: { available: boolean; }) {
106 104
         this.setState({ audioAvailable: available });
107 105
     }
108 106
 
109
-    _audioMutedListener: ({ muted: boolean }) => void;
110
-
111 107
     /**
112 108
      * Handles audio muted api events.
113 109
      *
114 110
      * @param {{ muted: boolean }} status - The new muted status.
115 111
      * @returns {void}
116 112
      */
117
-    _audioMutedListener({ muted }) {
113
+    _audioMutedListener({ muted }: { muted: boolean; }) {
118 114
         this.setState({ audioMuted: muted });
119 115
     }
120 116
 
@@ -144,16 +140,14 @@ export default class AudioMuteButton extends Component<Props, State> {
144 140
      * Changes the muted state.
145 141
      *
146 142
      * @override
147
-     * @param {boolean} audioMuted - Whether audio should be muted or not.
143
+     * @param {boolean} _audioMuted - Whether audio should be muted or not.
148 144
      * @protected
149 145
      * @returns {void}
150 146
      */
151
-    _setAudioMuted(audioMuted: boolean) { // eslint-disable-line no-unused-vars
147
+    _setAudioMuted(_audioMuted: boolean) {
152 148
         this.state.audioAvailable && api.executeCommand('toggleAudio');
153 149
     }
154 150
 
155
-    _onClick: () => {};
156
-
157 151
     /**
158 152
      * Handles clicking / pressing the button, and toggles the audio mute state
159 153
      * accordingly.

react/features/always-on-top/HangupButton.js → react/features/always-on-top/HangupButton.tsx View File

@@ -1,19 +1,20 @@
1
-// @flow
2 1
 import React, { Component } from 'react';
3 2
 
4 3
 // We need to reference these files directly to avoid loading things that are not available
5 4
 // in this environment (e.g. JitsiMeetJS or interfaceConfig)
6 5
 import { IconHangup } from '../base/icons/svg';
7
-import type { Props } from '../base/toolbox/components/AbstractButton';
6
+import { IProps } from '../base/toolbox/components/AbstractButton';
8 7
 
9 8
 import ToolbarButton from './ToolbarButton';
10 9
 
11 10
 const { api } = window.alwaysOnTop;
12 11
 
12
+type Props = Partial<IProps>;
13
+
13 14
 /**
14 15
  * Stateless hangup button for the Always-on-Top windows.
15 16
  */
16
-export default class HangupButton extends Component<Props, *> {
17
+export default class HangupButton extends Component<Props> {
17 18
 
18 19
     accessibilityLabel = 'Hangup';
19 20
     icon = IconHangup;
@@ -21,7 +22,7 @@ export default class HangupButton extends Component<Props, *> {
21 22
     /**
22 23
      * Initializes a new {@code HangupButton} instance.
23 24
      *
24
-     * @param {Props} props - The React {@code Component} props to initialize
25
+     * @param {IProps} props - The React {@code Component} props to initialize
25 26
      * the new {@code HangupButton} instance with.
26 27
      */
27 28
     constructor(props: Props) {
@@ -31,8 +32,6 @@ export default class HangupButton extends Component<Props, *> {
31 32
         this._onClick = this._onClick.bind(this);
32 33
     }
33 34
 
34
-    _onClick: () => {};
35
-
36 35
     /**
37 36
      * Handles clicking / pressing the button, and disconnects the conference.
38 37
      *

react/features/always-on-top/Toolbar.js → react/features/always-on-top/Toolbar.tsx View File

@@ -1,5 +1,3 @@
1
-// @flow
2
-
3 1
 import React, { Component } from 'react';
4 2
 
5 3
 import AudioMuteButton from './AudioMuteButton';
@@ -9,30 +7,30 @@ import VideoMuteButton from './VideoMuteButton';
9 7
 /**
10 8
  * The type of the React {@code Component} props of {@link Toolbar}.
11 9
  */
12
-type Props = {
10
+interface IProps {
13 11
 
14 12
     /**
15 13
      * Additional CSS class names to add to the root of the toolbar.
16 14
      */
17
-    className: string,
15
+    className: string;
18 16
 
19 17
     /**
20 18
      * Callback invoked when no longer moused over the toolbar.
21 19
      */
22
-    onMouseOut: Function,
20
+    onMouseOut: (e?: React.MouseEvent) => void;
23 21
 
24 22
     /**
25 23
      * Callback invoked when the mouse has moved over the toolbar.
26 24
      */
27
-    onMouseOver: Function
28
-};
25
+    onMouseOver: (e?: React.MouseEvent) => void;
26
+}
29 27
 
30 28
 /**
31 29
  * Represents the toolbar in the Always On Top window.
32 30
  *
33 31
  * @augments Component
34 32
  */
35
-export default class Toolbar extends Component<Props> {
33
+export default class Toolbar extends Component<IProps> {
36 34
     /**
37 35
      * Implements React's {@link Component#render()}.
38 36
      *

react/features/always-on-top/ToolbarButton.js → react/features/always-on-top/ToolbarButton.tsx View File

@@ -2,38 +2,38 @@ import React, { useCallback } from 'react';
2 2
 
3 3
 import Icon from '../base/icons/components/Icon';
4 4
 
5
-type Props = {
5
+interface IProps {
6 6
 
7 7
     /**
8 8
      * Accessibility label for button.
9 9
      */
10
-    accessibilityLabel: string,
10
+    accessibilityLabel: string;
11 11
 
12 12
     /**
13 13
      * An extra class name to be added at the end of the element's class name
14 14
      * in order to enable custom styling.
15 15
      */
16
-    customClass?: string,
16
+    customClass?: string;
17 17
 
18 18
     /**
19 19
      * Whether or not the button is disabled.
20 20
      */
21
-    disabled?: boolean,
21
+    disabled?: boolean;
22 22
 
23 23
     /**
24
-     * Click handler.
24
+     * Button icon.
25 25
      */
26
-    onClick: Function,
26
+    icon: Function;
27 27
 
28 28
     /**
29
-     * Button icon.
29
+     * Click handler.
30 30
      */
31
-    icon: Object,
31
+    onClick: (e?: React.MouseEvent) => void;
32 32
 
33 33
     /**
34 34
      * Whether or not the button is toggled.
35 35
      */
36
-    toggled?: boolean
36
+    toggled?: boolean;
37 37
 }
38 38
 
39 39
 const ToolbarButton = ({
@@ -43,7 +43,7 @@ const ToolbarButton = ({
43 43
     onClick,
44 44
     icon,
45 45
     toggled = false
46
-}: Props) => {
46
+}: IProps) => {
47 47
     const onKeyPress = useCallback(event => {
48 48
         if (event.key === 'Enter' || event.key === ' ') {
49 49
             event.preventDefault();

react/features/always-on-top/VideoMuteButton.js → react/features/always-on-top/VideoMuteButton.tsx View File

@@ -1,15 +1,16 @@
1
-// @flow
2 1
 import React, { Component } from 'react';
3 2
 
4 3
 // We need to reference these files directly to avoid loading things that are not available
5 4
 // in this environment (e.g. JitsiMeetJS or interfaceConfig)
6 5
 import { IconVideo, IconVideoOff } from '../base/icons/svg';
7
-import type { Props } from '../base/toolbox/components/AbstractButton';
6
+import { IProps } from '../base/toolbox/components/AbstractButton';
8 7
 
9 8
 import ToolbarButton from './ToolbarButton';
10 9
 
11 10
 const { api } = window.alwaysOnTop;
12 11
 
12
+type Props = Partial<IProps>;
13
+
13 14
 /**
14 15
  * The type of the React {@code Component} state of {@link VideoMuteButton}.
15 16
  */
@@ -18,12 +19,12 @@ type State = {
18 19
     /**
19 20
      * Whether video is available is not.
20 21
      */
21
-    videoAvailable: boolean,
22
+    videoAvailable: boolean;
22 23
 
23 24
     /**
24 25
      * Whether video is muted or not.
25 26
      */
26
-    videoMuted: boolean
27
+    videoMuted: boolean;
27 28
 };
28 29
 
29 30
 /**
@@ -119,40 +120,34 @@ export default class VideoMuteButton extends Component<Props, State> {
119 120
      * Changes the muted state.
120 121
      *
121 122
      * @override
122
-     * @param {boolean} videoMuted - Whether video should be muted or not.
123
+     * @param {boolean} _videoMuted - Whether video should be muted or not.
123 124
      * @protected
124 125
      * @returns {void}
125 126
      */
126
-    _setVideoMuted(videoMuted: boolean) { // eslint-disable-line no-unused-vars
127
+    _setVideoMuted(_videoMuted: boolean) {
127 128
         this.state.videoAvailable && api.executeCommand('toggleVideo', false, true);
128 129
     }
129 130
 
130
-    _videoAvailabilityListener: ({ available: boolean }) => void;
131
-
132 131
     /**
133 132
      * Handles video available api events.
134 133
      *
135 134
      * @param {{ available: boolean }} status - The new available status.
136 135
      * @returns {void}
137 136
      */
138
-    _videoAvailabilityListener({ available }) {
137
+    _videoAvailabilityListener({ available }: { available: boolean; }) {
139 138
         this.setState({ videoAvailable: available });
140 139
     }
141 140
 
142
-    _videoMutedListener: ({ muted: boolean }) => void;
143
-
144 141
     /**
145 142
      * Handles video muted api events.
146 143
      *
147 144
      * @param {{ muted: boolean }} status - The new muted status.
148 145
      * @returns {void}
149 146
      */
150
-    _videoMutedListener({ muted }) {
147
+    _videoMutedListener({ muted }: { muted: boolean; }) {
151 148
         this.setState({ videoMuted: muted });
152 149
     }
153 150
 
154
-    _onClick: () => {};
155
-
156 151
     /**
157 152
      * Handles clicking / pressing the button, and toggles the video mute state
158 153
      * accordingly.

react/features/always-on-top/index.js → react/features/always-on-top/index.tsx View File

@@ -1,14 +1,11 @@
1
-// @flow
2
-
3 1
 import React from 'react';
4 2
 import ReactDOM from 'react-dom';
5 3
 
6 4
 import AlwaysOnTop from './AlwaysOnTop';
7 5
 
8 6
 // Render the main/root Component.
9
-// $FlowExpectedError
10 7
 ReactDOM.render(<AlwaysOnTop />, document.getElementById('react'));
11 8
 
12 9
 window.addEventListener(
13 10
     'beforeunload',
14
-    () => ReactDOM.unmountComponentAtNode(document.getElementById('react')));
11
+    () => ReactDOM.unmountComponentAtNode(document.getElementById('react') ?? document.body));

+ 1
- 0
tsconfig.native.json View File

@@ -16,6 +16,7 @@
16 16
     },
17 17
     "exclude": [
18 18
         "node_modules",
19
+        "react/features/always-on-top",
19 20
         "react/features/analytics/handlers/GoogleAnalyticsHandler.ts",
20 21
         "react/features/base/components/participants-pane-list",
21 22
         "react/features/base/tooltip",

+ 1
- 1
webpack.config.js View File

@@ -299,7 +299,7 @@ module.exports = (_env, argv) => {
299 299
         }),
300 300
         Object.assign({}, config, {
301 301
             entry: {
302
-                'alwaysontop': './react/features/always-on-top/index.js'
302
+                'alwaysontop': './react/features/always-on-top/index.tsx'
303 303
             },
304 304
             plugins: [
305 305
                 ...config.plugins,

Loading…
Cancel
Save