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

pull/13344/head jitsi-meet_8656
Robert Pintilii 2 years ago committed by GitHub
parent 71627f97f7
commit ae0669fa07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      globals.d.ts
  2. 45
      react/features/always-on-top/AlwaysOnTop.tsx
  3. 32
      react/features/always-on-top/AudioMuteButton.tsx
  4. 11
      react/features/always-on-top/HangupButton.tsx
  5. 14
      react/features/always-on-top/Toolbar.tsx
  6. 20
      react/features/always-on-top/ToolbarButton.tsx
  7. 23
      react/features/always-on-top/VideoMuteButton.tsx
  8. 5
      react/features/always-on-top/index.tsx
  9. 1
      tsconfig.native.json
  10. 2
      webpack.config.js

1
globals.d.ts vendored

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

@ -1,5 +1,3 @@
// @flow
import React, { Component } from 'react';
// We need to reference these files directly to avoid loading things that are not available
@ -19,15 +17,15 @@ const TOOLBAR_TIMEOUT = 4000;
/**
* The type of the React {@code Component} state of {@link AlwaysOnTop}.
*/
type State = {
avatarURL: string,
customAvatarBackgrounds: Array<string>,
displayName: string,
formattedDisplayName: string,
isVideoDisplayed: boolean,
userID: string,
visible: boolean
};
interface IState {
avatarURL: string;
customAvatarBackgrounds: Array<string>;
displayName: string;
formattedDisplayName: string;
isVideoDisplayed: boolean;
userID: string;
visible: boolean;
}
/**
* Represents the always on top page.
@ -35,7 +33,7 @@ type State = {
* @class AlwaysOnTop
* @augments Component
*/
export default class AlwaysOnTop extends Component<*, State> {
export default class AlwaysOnTop extends Component<any, IState> {
_hovered: boolean;
/**
@ -44,7 +42,7 @@ export default class AlwaysOnTop extends Component<*, State> {
* @param {*} props - The read-only properties with which the new instance
* is to be initialized.
*/
constructor(props: *) {
constructor(props: any) {
super(props);
this.state = {
@ -68,28 +66,25 @@ export default class AlwaysOnTop extends Component<*, State> {
this._onMouseOver = this._onMouseOver.bind(this);
}
_avatarChangedListener: () => void;
/**
* Handles avatar changed api events.
*
* @returns {void}
*/
_avatarChangedListener({ avatarURL, id }) {
_avatarChangedListener({ avatarURL, id }: { avatarURL: string; id: string; }) {
if (api._getOnStageParticipant() === id
&& avatarURL !== this.state.avatarURL) {
this.setState({ avatarURL });
}
}
_displayNameChangedListener: () => void;
/**
* Handles display name changed api events.
*
* @returns {void}
*/
_displayNameChangedListener({ displayname, formattedDisplayName, id }) {
_displayNameChangedListener({ displayname, formattedDisplayName, id }: { displayname: string;
formattedDisplayName: string; id: string; }) {
if (api._getOnStageParticipant() === id
&& (formattedDisplayName !== this.state.formattedDisplayName
|| displayname !== this.state.displayName)) {
@ -118,8 +113,6 @@ export default class AlwaysOnTop extends Component<*, State> {
TOOLBAR_TIMEOUT);
}
_videoChangedListener: () => void;
/**
* Handles large video changed api events.
*
@ -141,8 +134,6 @@ export default class AlwaysOnTop extends Component<*, State> {
});
}
_mouseMove: () => void;
/**
* Handles mouse move events.
*
@ -152,8 +143,6 @@ export default class AlwaysOnTop extends Component<*, State> {
this.state.visible || this.setState({ visible: true });
}
_onMouseOut: () => void;
/**
* Toolbar mouse out handler.
*
@ -163,8 +152,6 @@ export default class AlwaysOnTop extends Component<*, State> {
this._hovered = false;
}
_onMouseOver: () => void;
/**
* Toolbar mouse over handler.
*
@ -229,7 +216,7 @@ export default class AlwaysOnTop extends Component<*, State> {
this._hideToolbarAfterTimeout();
api.getCustomAvatarBackgrounds()
.then(res =>
.then((res: { avatarBackgrounds?: string[]; }) =>
this.setState({
customAvatarBackgrounds: res.avatarBackgrounds || []
}))
@ -242,7 +229,7 @@ export default class AlwaysOnTop extends Component<*, State> {
* @inheritdoc
* @returns {void}
*/
componentDidUpdate(prevProps: *, prevState: State) {
componentDidUpdate(_prevProps: any, prevState: IState) {
if (!prevState.visible && this.state.visible) {
this._hideToolbarAfterTimeout();
}

@ -1,11 +1,9 @@
// @flow
import React, { Component } from 'react';
// We need to reference these files directly to avoid loading things that are not available
// in this environment (e.g. JitsiMeetJS or interfaceConfig)
import { IconMic, IconMicSlash } from '../base/icons/svg';
import type { Props } from '../base/toolbox/components/AbstractButton';
import { IProps } from '../base/toolbox/components/AbstractButton';
import ToolbarButton from './ToolbarButton';
@ -14,23 +12,25 @@ const { api } = window.alwaysOnTop;
/**
* The type of the React {@code Component} state of {@link AudioMuteButton}.
*/
type State = {
interface IState {
/**
* Whether audio is available is not.
*/
audioAvailable: boolean,
audioAvailable: boolean;
/**
* Whether audio is muted or not.
*/
audioMuted: boolean
};
audioMuted: boolean;
}
type Props = Partial<IProps>;
/**
* Stateless "mute/unmute audio" button for the Always-on-Top windows.
*/
export default class AudioMuteButton extends Component<Props, State> {
export default class AudioMuteButton extends Component<Props, IState> {
icon = IconMic;
toggledIcon = IconMicSlash;
accessibilityLabel = 'Audio mute';
@ -38,7 +38,7 @@ export default class AudioMuteButton extends Component<Props, State> {
/**
* Initializes a new {@code AudioMuteButton} instance.
*
* @param {Props} props - The React {@code Component} props to initialize
* @param {IProps} props - The React {@code Component} props to initialize
* the new {@code AudioMuteButton} instance with.
*/
constructor(props: Props) {
@ -94,27 +94,23 @@ export default class AudioMuteButton extends Component<Props, State> {
this._audioMutedListener);
}
_audioAvailabilityListener: ({ available: boolean }) => void;
/**
* Handles audio available api events.
*
* @param {{ available: boolean }} status - The new available status.
* @returns {void}
*/
_audioAvailabilityListener({ available }) {
_audioAvailabilityListener({ available }: { available: boolean; }) {
this.setState({ audioAvailable: available });
}
_audioMutedListener: ({ muted: boolean }) => void;
/**
* Handles audio muted api events.
*
* @param {{ muted: boolean }} status - The new muted status.
* @returns {void}
*/
_audioMutedListener({ muted }) {
_audioMutedListener({ muted }: { muted: boolean; }) {
this.setState({ audioMuted: muted });
}
@ -144,16 +140,14 @@ export default class AudioMuteButton extends Component<Props, State> {
* Changes the muted state.
*
* @override
* @param {boolean} audioMuted - Whether audio should be muted or not.
* @param {boolean} _audioMuted - Whether audio should be muted or not.
* @protected
* @returns {void}
*/
_setAudioMuted(audioMuted: boolean) { // eslint-disable-line no-unused-vars
_setAudioMuted(_audioMuted: boolean) {
this.state.audioAvailable && api.executeCommand('toggleAudio');
}
_onClick: () => {};
/**
* Handles clicking / pressing the button, and toggles the audio mute state
* accordingly.

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

@ -1,5 +1,3 @@
// @flow
import React, { Component } from 'react';
import AudioMuteButton from './AudioMuteButton';
@ -9,30 +7,30 @@ import VideoMuteButton from './VideoMuteButton';
/**
* The type of the React {@code Component} props of {@link Toolbar}.
*/
type Props = {
interface IProps {
/**
* Additional CSS class names to add to the root of the toolbar.
*/
className: string,
className: string;
/**
* Callback invoked when no longer moused over the toolbar.
*/
onMouseOut: Function,
onMouseOut: (e?: React.MouseEvent) => void;
/**
* Callback invoked when the mouse has moved over the toolbar.
*/
onMouseOver: Function
};
onMouseOver: (e?: React.MouseEvent) => void;
}
/**
* Represents the toolbar in the Always On Top window.
*
* @augments Component
*/
export default class Toolbar extends Component<Props> {
export default class Toolbar extends Component<IProps> {
/**
* Implements React's {@link Component#render()}.
*

@ -2,38 +2,38 @@ import React, { useCallback } from 'react';
import Icon from '../base/icons/components/Icon';
type Props = {
interface IProps {
/**
* Accessibility label for button.
*/
accessibilityLabel: string,
accessibilityLabel: string;
/**
* An extra class name to be added at the end of the element's class name
* in order to enable custom styling.
*/
customClass?: string,
customClass?: string;
/**
* Whether or not the button is disabled.
*/
disabled?: boolean,
disabled?: boolean;
/**
* Click handler.
* Button icon.
*/
onClick: Function,
icon: Function;
/**
* Button icon.
* Click handler.
*/
icon: Object,
onClick: (e?: React.MouseEvent) => void;
/**
* Whether or not the button is toggled.
*/
toggled?: boolean
toggled?: boolean;
}
const ToolbarButton = ({
@ -43,7 +43,7 @@ const ToolbarButton = ({
onClick,
icon,
toggled = false
}: Props) => {
}: IProps) => {
const onKeyPress = useCallback(event => {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();

@ -1,15 +1,16 @@
// @flow
import React, { Component } from 'react';
// We need to reference these files directly to avoid loading things that are not available
// in this environment (e.g. JitsiMeetJS or interfaceConfig)
import { IconVideo, IconVideoOff } from '../base/icons/svg';
import type { Props } from '../base/toolbox/components/AbstractButton';
import { IProps } from '../base/toolbox/components/AbstractButton';
import ToolbarButton from './ToolbarButton';
const { api } = window.alwaysOnTop;
type Props = Partial<IProps>;
/**
* The type of the React {@code Component} state of {@link VideoMuteButton}.
*/
@ -18,12 +19,12 @@ type State = {
/**
* Whether video is available is not.
*/
videoAvailable: boolean,
videoAvailable: boolean;
/**
* Whether video is muted or not.
*/
videoMuted: boolean
videoMuted: boolean;
};
/**
@ -119,40 +120,34 @@ export default class VideoMuteButton extends Component<Props, State> {
* Changes the muted state.
*
* @override
* @param {boolean} videoMuted - Whether video should be muted or not.
* @param {boolean} _videoMuted - Whether video should be muted or not.
* @protected
* @returns {void}
*/
_setVideoMuted(videoMuted: boolean) { // eslint-disable-line no-unused-vars
_setVideoMuted(_videoMuted: boolean) {
this.state.videoAvailable && api.executeCommand('toggleVideo', false, true);
}
_videoAvailabilityListener: ({ available: boolean }) => void;
/**
* Handles video available api events.
*
* @param {{ available: boolean }} status - The new available status.
* @returns {void}
*/
_videoAvailabilityListener({ available }) {
_videoAvailabilityListener({ available }: { available: boolean; }) {
this.setState({ videoAvailable: available });
}
_videoMutedListener: ({ muted: boolean }) => void;
/**
* Handles video muted api events.
*
* @param {{ muted: boolean }} status - The new muted status.
* @returns {void}
*/
_videoMutedListener({ muted }) {
_videoMutedListener({ muted }: { muted: boolean; }) {
this.setState({ videoMuted: muted });
}
_onClick: () => {};
/**
* Handles clicking / pressing the button, and toggles the video mute state
* accordingly.

@ -1,14 +1,11 @@
// @flow
import React from 'react';
import ReactDOM from 'react-dom';
import AlwaysOnTop from './AlwaysOnTop';
// Render the main/root Component.
// $FlowExpectedError
ReactDOM.render(<AlwaysOnTop />, document.getElementById('react'));
window.addEventListener(
'beforeunload',
() => ReactDOM.unmountComponentAtNode(document.getElementById('react')));
() => ReactDOM.unmountComponentAtNode(document.getElementById('react') ?? document.body));

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

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

Loading…
Cancel
Save