diff --git a/globals.d.ts b/globals.d.ts index 4e10c9a14e..51f817721a 100644 --- a/globals.d.ts +++ b/globals.d.ts @@ -25,6 +25,13 @@ declare global { interfaceConfig?: any; JitsiMeetJS?: any; JitsiMeetElectron?: any; + // selenium tests handler + _sharedVideoPlayer: any; + } + + interface Document { + mozCancelFullScreen?: Function; + webkitExitFullscreen?: Function; } const config: IConfig; diff --git a/package-lock.json b/package-lock.json index fe6d299b6c..5a69c358a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -143,6 +143,7 @@ "@types/react-native": "0.68.9", "@types/react-redux": "7.1.24", "@types/react-window": "1.8.5", + "@types/resemblejs": "^4.1.0", "@types/unorm": "1.3.28", "@types/uuid": "8.3.4", "@types/zxcvbn": "4.4.1", @@ -6398,6 +6399,12 @@ "@types/react": "*" } }, + "node_modules/@types/resemblejs": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@types/resemblejs/-/resemblejs-4.1.0.tgz", + "integrity": "sha512-+MIkKy/UngDfhTnvn2yK/KSzlbtLeB5BU73qqZrzIF24+e2r8enJ4cW3UbtkstByYSDV8pbheGAqg7zT8ZZ2pA==", + "dev": true + }, "node_modules/@types/retry": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", @@ -24951,6 +24958,12 @@ "@types/react": "*" } }, + "@types/resemblejs": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@types/resemblejs/-/resemblejs-4.1.0.tgz", + "integrity": "sha512-+MIkKy/UngDfhTnvn2yK/KSzlbtLeB5BU73qqZrzIF24+e2r8enJ4cW3UbtkstByYSDV8pbheGAqg7zT8ZZ2pA==", + "dev": true + }, "@types/retry": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", diff --git a/package.json b/package.json index c30fba6d25..c96de8b33a 100644 --- a/package.json +++ b/package.json @@ -148,6 +148,7 @@ "@types/react-native": "0.68.9", "@types/react-redux": "7.1.24", "@types/react-window": "1.8.5", + "@types/resemblejs": "^4.1.0", "@types/unorm": "1.3.28", "@types/uuid": "8.3.4", "@types/zxcvbn": "4.4.1", diff --git a/react/features/app/actions.native.ts b/react/features/app/actions.native.ts index f4812b9dec..e85cd05f9c 100644 --- a/react/features/app/actions.native.ts +++ b/react/features/app/actions.native.ts @@ -164,10 +164,10 @@ export function appNavigate(uri?: string, options: IReloadNowOptions = {}) { * If we have a close page enabled, redirect to it without * showing any other dialog. * - * @param {Object} options - Ignored. + * @param {Object} _options - Ignored. * @returns {Function} */ -export function maybeRedirectToWelcomePage(options: any) { // eslint-disable-line @typescript-eslint/no-unused-vars +export function maybeRedirectToWelcomePage(_options?: any): any { // Dummy. } diff --git a/react/features/base/config/configType.ts b/react/features/base/config/configType.ts index a5b3298d9f..451554ed06 100644 --- a/react/features/base/config/configType.ts +++ b/react/features/base/config/configType.ts @@ -127,6 +127,7 @@ export interface INoiseSuppressionConfig { export interface IConfig { _desktopSharingSourceDevice?: string; + _screenshotHistoryRegionUrl?: string; analytics?: { amplitudeAPPKey?: string; disabled?: boolean; diff --git a/react/features/base/toolbox/components/web/ToolboxButtonWithIconPopup.js b/react/features/base/toolbox/components/web/ToolboxButtonWithIconPopup.tsx similarity index 81% rename from react/features/base/toolbox/components/web/ToolboxButtonWithIconPopup.js rename to react/features/base/toolbox/components/web/ToolboxButtonWithIconPopup.tsx index 2ccf22aef9..9f89d665da 100644 --- a/react/features/base/toolbox/components/web/ToolboxButtonWithIconPopup.js +++ b/react/features/base/toolbox/components/web/ToolboxButtonWithIconPopup.tsx @@ -1,79 +1,75 @@ -// @flow - import React from 'react'; -import { Icon } from '../../../icons'; +import Icon from '../../../icons/components/Icon'; import Popover from '../../../popover/components/Popover.web'; -type Props = { - - /** - * Whether the element popup is expanded. - */ - ariaExpanded?: boolean, +interface IProps { /** * The id of the element this button icon controls. */ - ariaControls?: string, + ariaControls?: string; + + /** + * Whether the element popup is expanded. + */ + ariaExpanded?: boolean; /** * Whether the element has a popup. */ - ariaHasPopup?: boolean, + ariaHasPopup?: boolean; /** * Aria label for the Icon. */ - ariaLabel?: string, + ariaLabel?: string; /** * The decorated component (ToolboxButton). */ - children: React$Node, + children: React.ReactNode; /** * Icon of the button. */ - icon: Function, + icon: Function; /** * Flag used for disabling the small icon. */ - iconDisabled: boolean, + iconDisabled: boolean; /** * The ID of the icon button. */ - iconId: string, + iconId: string; /** * Popover close callback. */ - onPopoverClose: Function, + onPopoverClose: Function; /** * Popover open callback. */ - onPopoverOpen: Function, + onPopoverOpen: Function; /** * The content that will be displayed inside the popover. */ - popoverContent: React$Node, + popoverContent: React.ReactNode; /** * Additional styles. */ - styles?: Object, + styles?: Object; /** * Whether or not the popover is visible. */ - visible: boolean -}; - -declare var APP: Object; + visible: boolean; +} /** * Displays the `ToolboxButtonWithIcon` component. @@ -81,7 +77,7 @@ declare var APP: Object; * @param {Object} props - Component's props. * @returns {ReactElement} */ -export default function ToolboxButtonWithIconPopup(props: Props) { +export default function ToolboxButtonWithIconPopup(props: IProps) { const { ariaControls, ariaExpanded, @@ -98,7 +94,7 @@ export default function ToolboxButtonWithIconPopup(props: Props) { visible } = props; - const iconProps = {}; + const iconProps: any = {}; if (iconDisabled) { iconProps.className @@ -116,7 +112,7 @@ export default function ToolboxButtonWithIconPopup(props: Props) { return (
+ style = { styles }> {children}
= { /** * The entity for which the menu is context menu is raised. */ - entity?: string | Object; + entity?: T; /** * Target elements against which positioning calculations are made. @@ -18,13 +18,13 @@ type RaiseContext = { const initialState = Object.freeze({}); -const useContextMenu = (): [(force?: boolean | Object) => void, - (entity: string | Object, target: HTMLElement | null) => void, - (entity: string | Object) => (e: MouseEvent) => void, +const useContextMenu = (): [(force?: boolean | Object) => void, + (entity: T, target: HTMLElement | null) => void, + (entity: T) => (e?: MouseEvent) => void, () => void, () => void, - RaiseContext] => { - const [ raiseContext, setRaiseContext ] = useState < RaiseContext >(initialState); + RaiseContext] => { + const [ raiseContext, setRaiseContext ] = useState < RaiseContext >(initialState); const isMouseOverMenu = useRef(false); const lowerMenu = useCallback((force: boolean | Object = false) => { @@ -45,21 +45,21 @@ const useContextMenu = (): [(force?: boolean | Object) => void, }); }, [ raiseContext ]); - const raiseMenu = useCallback((entity: string | Object, target: HTMLElement | null) => { + const raiseMenu = useCallback((entity: T, target: HTMLElement | null) => { setRaiseContext({ entity, offsetTarget: findAncestorByClass(target, 'list-item-container') }); }, [ raiseContext ]); - const toggleMenu = useCallback((entity: string | Object) => (e: MouseEvent) => { - e.stopPropagation(); + const toggleMenu = useCallback((entity: T) => (e?: MouseEvent) => { + e?.stopPropagation(); const { entity: raisedEntity } = raiseContext; if (raisedEntity && raisedEntity === entity) { lowerMenu(); } else { - raiseMenu(entity, e.target as HTMLElement); + raiseMenu(entity, e?.target as HTMLElement); } }, [ raiseContext ]); diff --git a/react/features/calendar-sync/components/MicrosoftSignInButton.web.js b/react/features/calendar-sync/components/MicrosoftSignInButton.web.tsx similarity index 80% rename from react/features/calendar-sync/components/MicrosoftSignInButton.web.js rename to react/features/calendar-sync/components/MicrosoftSignInButton.web.tsx index de82411638..7fa0f774ea 100644 --- a/react/features/calendar-sync/components/MicrosoftSignInButton.web.js +++ b/react/features/calendar-sync/components/MicrosoftSignInButton.web.tsx @@ -1,38 +1,31 @@ -// @flow - import React, { Component } from 'react'; +import { WithTranslation } from 'react-i18next'; -import { translate } from '../../base/i18n'; - +import { translate } from '../../base/i18n/functions'; /** * The type of the React {@code Component} props of * {@link MicrosoftSignInButton}. */ -type Props = { +interface IProps extends WithTranslation { /** * The callback to invoke when {@code MicrosoftSignInButton} is clicked. */ - onClick: Function, + onClick: (e?: React.MouseEvent) => void; /** * The text to display within {@code MicrosoftSignInButton}. */ - text: string, - - /** - * Invoked to obtain translated strings. - */ - t: Function -}; + text: string; +} /** * A React Component showing a button to sign in with Microsoft. * * @augments Component */ -class MicrosoftSignInButton extends Component { +class MicrosoftSignInButton extends Component { /** * Implements React's {@link Component#render()}. * diff --git a/react/features/gifs/components/web/GifsMenuButton.js b/react/features/gifs/components/web/GifsMenuButton.tsx similarity index 96% rename from react/features/gifs/components/web/GifsMenuButton.js rename to react/features/gifs/components/web/GifsMenuButton.tsx index a9cca3075f..b20bb3dc9d 100644 --- a/react/features/gifs/components/web/GifsMenuButton.js +++ b/react/features/gifs/components/web/GifsMenuButton.tsx @@ -5,7 +5,7 @@ import { useDispatch, useSelector } from 'react-redux'; import ReactionButton from '../../../reactions/components/web/ReactionButton'; import { showOverflowDrawer } from '../../../toolbox/functions.web'; import { setGifDrawerVisibility, setGifMenuVisibility } from '../../actions'; -import { isGifsMenuOpen } from '../../functions'; +import { isGifsMenuOpen } from '../../functions.web'; const GifsMenuButton = () => { const menuOpen = useSelector(isGifsMenuOpen); diff --git a/react/features/google-api/components/AbstractGoogleSignInButton.ts b/react/features/google-api/components/AbstractGoogleSignInButton.ts index f54dade5e0..b866290824 100644 --- a/react/features/google-api/components/AbstractGoogleSignInButton.ts +++ b/react/features/google-api/components/AbstractGoogleSignInButton.ts @@ -1,4 +1,4 @@ -import { Component } from 'react'; +import React, { Component } from 'react'; import { WithTranslation } from 'react-i18next'; /** @@ -9,13 +9,18 @@ interface IProps extends WithTranslation { /** * The callback to invoke when the button is clicked. */ - onClick: Function; + onClick: (e?: React.MouseEvent) => void; /** * True if the user is signed in, so it needs to render a different label * and maybe different style (for the future). */ signedIn?: boolean; + + /** + * The text to display within {@code GoogleSignInButton}. + */ + text?: string; } /** diff --git a/react/features/google-api/components/GoogleSignInButton.web.js b/react/features/google-api/components/GoogleSignInButton.web.tsx similarity index 95% rename from react/features/google-api/components/GoogleSignInButton.web.js rename to react/features/google-api/components/GoogleSignInButton.web.tsx index b4a03cbd70..d3326da810 100644 --- a/react/features/google-api/components/GoogleSignInButton.web.js +++ b/react/features/google-api/components/GoogleSignInButton.web.tsx @@ -1,8 +1,6 @@ -// @flow - import React from 'react'; -import { translate } from '../../base/i18n'; +import { translate } from '../../base/i18n/functions'; import AbstractGoogleSignInButton from './AbstractGoogleSignInButton'; diff --git a/react/features/participants-pane/components/breakout-rooms/components/web/CollapsibleRoom.tsx b/react/features/participants-pane/components/breakout-rooms/components/web/CollapsibleRoom.tsx index 72089b1b1b..26a5182798 100644 --- a/react/features/participants-pane/components/breakout-rooms/components/web/CollapsibleRoom.tsx +++ b/react/features/participants-pane/components/breakout-rooms/components/web/CollapsibleRoom.tsx @@ -1,4 +1,4 @@ -import React, { ReactElement, useCallback, useState } from 'react'; +import React, { useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import { makeStyles } from 'tss-react/mui'; @@ -9,6 +9,7 @@ import Icon from '../../../../../base/icons/components/Icon'; import { IconArrowDown, IconArrowUp } from '../../../../../base/icons/svg'; import { isLocalParticipantModerator } from '../../../../../base/participants/functions'; import { withPixelLineHeight } from '../../../../../base/styles/functions.web'; +import { IRoom } from '../../../../../breakout-rooms/types'; import { showOverflowDrawer } from '../../../../../toolbox/functions.web'; import { ACTION_TRIGGER } from '../../../../constants'; import { participantMatchesSearch } from '../../../../functions'; @@ -25,7 +26,7 @@ interface IProps { /** * React children. */ - children: ReactElement; + children: React.ReactNode; /** * Is this item highlighted/raised. @@ -47,6 +48,8 @@ interface IProps { */ participantContextEntity?: { jid: string; + participantName: string; + room: IRoom; }; /** diff --git a/react/features/participants-pane/components/breakout-rooms/components/web/RoomContextMenu.js b/react/features/participants-pane/components/breakout-rooms/components/web/RoomContextMenu.tsx similarity index 75% rename from react/features/participants-pane/components/breakout-rooms/components/web/RoomContextMenu.js rename to react/features/participants-pane/components/breakout-rooms/components/web/RoomContextMenu.tsx index 65f4ab4111..7bddb7cee8 100644 --- a/react/features/participants-pane/components/breakout-rooms/components/web/RoomContextMenu.js +++ b/react/features/participants-pane/components/breakout-rooms/components/web/RoomContextMenu.tsx @@ -1,47 +1,44 @@ -// @flow - import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { useDispatch, useSelector } from 'react-redux'; -import { createBreakoutRoomsEvent, sendAnalytics } from '../../../../../analytics'; -import { - IconCloseLarge, - IconRingGroup -} from '../../../../../base/icons'; -import { isLocalParticipantModerator } from '../../../../../base/participants'; +import { createBreakoutRoomsEvent } from '../../../../../analytics/AnalyticsEvents'; +import { sendAnalytics } from '../../../../../analytics/functions'; +import { IconCloseLarge, IconRingGroup } from '../../../../../base/icons/svg'; +import { isLocalParticipantModerator } from '../../../../../base/participants/functions'; import ContextMenu from '../../../../../base/ui/components/web/ContextMenu'; import ContextMenuItemGroup from '../../../../../base/ui/components/web/ContextMenuItemGroup'; import { closeBreakoutRoom, moveToRoom, removeBreakoutRoom } from '../../../../../breakout-rooms/actions'; -import { showOverflowDrawer } from '../../../../../toolbox/functions'; +import { IRoom } from '../../../../../breakout-rooms/types'; +import { showOverflowDrawer } from '../../../../../toolbox/functions.web'; -type Props = { +interface IProps { /** * Room reference. */ - entity: Object, + entity?: IRoom; /** * Target elements against which positioning calculations are made. */ - offsetTarget: ?HTMLElement, + offsetTarget?: HTMLElement | null; /** * Callback for the mouse entering the component. */ - onEnter: Function, + onEnter: (e?: React.MouseEvent) => void; /** * Callback for the mouse leaving the component. */ - onLeave: Function, + onLeave: (e?: React.MouseEvent) => void; /** * Callback for making a selection in the menu. */ - onSelect: Function -}; + onSelect: (e?: React.MouseEvent | boolean) => void; +} export const RoomContextMenu = ({ entity: room, @@ -49,7 +46,7 @@ export const RoomContextMenu = ({ onEnter, onLeave, onSelect -}: Props) => { +}: IProps) => { const dispatch = useDispatch(); const { t } = useTranslation(); const isLocalModerator = useSelector(isLocalParticipantModerator); @@ -57,15 +54,15 @@ export const RoomContextMenu = ({ const onJoinRoom = useCallback(() => { sendAnalytics(createBreakoutRoomsEvent('join')); - dispatch(moveToRoom(room.jid)); + dispatch(moveToRoom(room?.jid)); }, [ dispatch, room ]); const onRemoveBreakoutRoom = useCallback(() => { - dispatch(removeBreakoutRoom(room.jid)); + dispatch(removeBreakoutRoom(room?.jid ?? '')); }, [ dispatch, room ]); const onCloseBreakoutRoom = useCallback(() => { - dispatch(closeBreakoutRoom(room.id)); + dispatch(closeBreakoutRoom(room?.id ?? '')); }, [ dispatch, room ]); const isRoomEmpty = !(room?.participants && Object.keys(room.participants).length > 0); @@ -86,17 +83,18 @@ export const RoomContextMenu = ({ } : null ].filter(Boolean); - const lowerMenu = useCallback(() => onSelect(true)); + const lowerMenu = useCallback(() => onSelect(true), []); return ( + {/* @ts-ignore */} ); diff --git a/react/features/participants-pane/components/breakout-rooms/components/web/RoomList.js b/react/features/participants-pane/components/breakout-rooms/components/web/RoomList.tsx similarity index 83% rename from react/features/participants-pane/components/breakout-rooms/components/web/RoomList.js rename to react/features/participants-pane/components/breakout-rooms/components/web/RoomList.tsx index 358173ed50..951aad850c 100644 --- a/react/features/participants-pane/components/breakout-rooms/components/web/RoomList.js +++ b/react/features/participants-pane/components/breakout-rooms/components/web/RoomList.tsx @@ -1,11 +1,9 @@ -// @flow - import React, { useCallback } from 'react'; import { useSelector } from 'react-redux'; import { isMobileBrowser } from '../../../../../base/environment/utils'; -import { isLocalParticipantModerator } from '../../../../../base/participants'; -import { equals } from '../../../../../base/redux'; +import { isLocalParticipantModerator } from '../../../../../base/participants/functions'; +import { equals } from '../../../../../base/redux/functions'; import useContextMenu from '../../../../../base/ui/hooks/useContextMenu.web'; import { getBreakoutRooms, @@ -14,7 +12,8 @@ import { isAutoAssignParticipantsVisible, isInBreakoutRoom } from '../../../../../breakout-rooms/functions'; -import { showOverflowDrawer } from '../../../../../toolbox/functions'; +import { IRoom } from '../../../../../breakout-rooms/types'; +import { showOverflowDrawer } from '../../../../../toolbox/functions.web'; import { AutoAssignButton } from './AutoAssignButton'; import { CollapsibleRoom } from './CollapsibleRoom'; @@ -24,36 +23,40 @@ import RoomActionEllipsis from './RoomActionEllipsis'; import { RoomContextMenu } from './RoomContextMenu'; import { RoomParticipantContextMenu } from './RoomParticipantContextMenu'; -type Props = { +interface IProps { /** * Participants search string. */ - searchString: string + searchString: string; } -export const RoomList = ({ searchString }: Props) => { +export const RoomList = ({ searchString }: IProps) => { const currentRoomId = useSelector(getCurrentRoomId); const rooms = Object.values(useSelector(getBreakoutRooms, equals)) - .filter((room: Object) => room.id !== currentRoomId) - .sort((p1: Object, p2: Object) => (p1?.name || '').localeCompare(p2?.name || '')); + .filter((room: IRoom) => room.id !== currentRoomId) + .sort((p1?: IRoom, p2?: IRoom) => (p1?.name || '').localeCompare(p2?.name || '')); const inBreakoutRoom = useSelector(isInBreakoutRoom); const isLocalModerator = useSelector(isLocalParticipantModerator); const showAutoAssign = useSelector(isAutoAssignParticipantsVisible); const { hideJoinRoomButton } = useSelector(getBreakoutRoomsConfig); const overflowDrawer = useSelector(showOverflowDrawer); - const [ lowerMenu, raiseMenu, toggleMenu, menuEnter, menuLeave, raiseContext ] = useContextMenu(); + const [ lowerMenu, raiseMenu, toggleMenu, menuEnter, menuLeave, raiseContext ] = useContextMenu(); const [ lowerParticipantMenu, raiseParticipantMenu, toggleParticipantMenu, - participantMenuEnter, participantMenuLeave, raiseParticipantContext ] = useContextMenu(); + participantMenuEnter, participantMenuLeave, raiseParticipantContext ] = useContextMenu<{ + jid: string; + participantName: string; + room: IRoom; + }>(); const hideMenu = useCallback(() => !overflowDrawer && lowerMenu(), [ overflowDrawer, lowerMenu ]); - const onRaiseMenu = useCallback(room => target => raiseMenu(room, target), [ raiseMenu ]); + const onRaiseMenu = useCallback(room => (target: HTMLElement) => raiseMenu(room, target), [ raiseMenu ]); return ( <> {inBreakoutRoom && } {showAutoAssign && }
- {rooms.map((room: Object) => ( + {rooms.map(room => ( ); } return null; }) -.filter(Boolean), [ entity, rooms ]); + .filter(Boolean), [ entity, rooms ]); - return isLocalModerator && ( + return isLocalModerator ? ( - ); + ) : null; }; diff --git a/react/features/participants-pane/components/web/MeetingParticipants.tsx b/react/features/participants-pane/components/web/MeetingParticipants.tsx index 69495f799b..4ff7df115a 100644 --- a/react/features/participants-pane/components/web/MeetingParticipants.tsx +++ b/react/features/participants-pane/components/web/MeetingParticipants.tsx @@ -83,7 +83,7 @@ function MeetingParticipants({ const dispatch = useDispatch(); const { t } = useTranslation(); - const [ lowerMenu, , toggleMenu, menuEnter, menuLeave, raiseContext ] = useContextMenu(); + const [ lowerMenu, , toggleMenu, menuEnter, menuLeave, raiseContext ] = useContextMenu(); const muteAudio = useCallback(id => () => { dispatch(muteRemote(id, MEDIA_TYPE.AUDIO)); dispatch(rejectParticipantAudio(id)); diff --git a/react/features/participants-pane/components/web/ParticipantsPane.tsx b/react/features/participants-pane/components/web/ParticipantsPane.tsx index 0a24223c5c..08dd25be20 100644 --- a/react/features/participants-pane/components/web/ParticipantsPane.tsx +++ b/react/features/participants-pane/components/web/ParticipantsPane.tsx @@ -21,8 +21,6 @@ import { isMuteAllVisible } from '../../functions'; import { AddBreakoutRoomButton } from '../breakout-rooms/components/web/AddBreakoutRoomButton'; -// eslint-disable-next-line lines-around-comment -// @ts-ignore import { RoomList } from '../breakout-rooms/components/web/RoomList'; import { FooterContextMenu } from './FooterContextMenu'; diff --git a/react/features/prejoin/components/web/Label.js b/react/features/prejoin/components/web/Label.tsx similarity index 75% rename from react/features/prejoin/components/web/Label.js rename to react/features/prejoin/components/web/Label.tsx index d772a44a31..80fd65ac4f 100644 --- a/react/features/prejoin/components/web/Label.js +++ b/react/features/prejoin/components/web/Label.tsx @@ -1,36 +1,34 @@ -// @flow - import React from 'react'; -type Props = { +interface IProps { /** * The text for the Label. */ - children: React$Node, + children: React.ReactElement; /** * The CSS class of the label. */ - className?: string, + className?: string; /** * The (round) number prefix for the Label. */ - number?: string | number, + number?: string | number; /** * The click handler. */ - onClick?: Function, -}; + onClick?: (e?: React.MouseEvent) => void; +} /** * Label for the dialogs. * * @returns {ReactElement} */ -function Label({ children, className, number, onClick }: Props) { +function Label({ children, className, number, onClick }: IProps) { const containerClass = className ? `prejoin-dialog-label ${className}` : 'prejoin-dialog-label'; diff --git a/react/features/prejoin/components/web/dialogs/CallingDialog.tsx b/react/features/prejoin/components/web/dialogs/CallingDialog.tsx index 095b5696eb..f4a12088fc 100644 --- a/react/features/prejoin/components/web/dialogs/CallingDialog.tsx +++ b/react/features/prejoin/components/web/dialogs/CallingDialog.tsx @@ -6,8 +6,6 @@ import Avatar from '../../../../base/avatar/components/Avatar'; import { translate } from '../../../../base/i18n/functions'; import Icon from '../../../../base/icons/components/Icon'; import { IconCloseLarge } from '../../../../base/icons/svg'; -// eslint-disable-next-line lines-around-comment -// @ts-ignore import Label from '../Label'; interface IProps extends WithTranslation { diff --git a/react/features/prejoin/components/web/dialogs/DialInDialog.tsx b/react/features/prejoin/components/web/dialogs/DialInDialog.tsx index 0da7c0a4f2..a5898a10aa 100644 --- a/react/features/prejoin/components/web/dialogs/DialInDialog.tsx +++ b/react/features/prejoin/components/web/dialogs/DialInDialog.tsx @@ -7,8 +7,6 @@ import Icon from '../../../../base/icons/components/Icon'; import { IconArrowLeft } from '../../../../base/icons/svg'; import Button from '../../../../base/ui/components/web/Button'; import { getCountryCodeFromPhone } from '../../../utils'; -// eslint-disable-next-line lines-around-comment -// @ts-ignore import Label from '../Label'; interface IProps extends WithTranslation { diff --git a/react/features/prejoin/components/web/dialogs/DialOutDialog.tsx b/react/features/prejoin/components/web/dialogs/DialOutDialog.tsx index 077d55cda6..e2586c4c2c 100644 --- a/react/features/prejoin/components/web/dialogs/DialOutDialog.tsx +++ b/react/features/prejoin/components/web/dialogs/DialOutDialog.tsx @@ -6,8 +6,6 @@ import { translate } from '../../../../base/i18n/functions'; import Icon from '../../../../base/icons/components/Icon'; import { IconCloseLarge } from '../../../../base/icons/svg'; import Button from '../../../../base/ui/components/web/Button'; -// eslint-disable-next-line lines-around-comment -// @ts-ignore import Label from '../Label'; import CountryPicker from '../country-picker/CountryPicker'; diff --git a/react/features/reactions/components/web/RaiseHandButton.js b/react/features/reactions/components/web/RaiseHandButton.ts similarity index 71% rename from react/features/reactions/components/web/RaiseHandButton.js rename to react/features/reactions/components/web/RaiseHandButton.ts index db9f9d57ae..a84e257b30 100644 --- a/react/features/reactions/components/web/RaiseHandButton.js +++ b/react/features/reactions/components/web/RaiseHandButton.ts @@ -1,26 +1,27 @@ import { connect } from 'react-redux'; -import { translate } from '../../../base/i18n'; -import { IconRaiseHand } from '../../../base/icons'; -import { getLocalParticipant, hasRaisedHand } from '../../../base/participants'; -import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components'; +import { IReduxState } from '../../../app/types'; +import { translate } from '../../../base/i18n/functions'; +import { IconRaiseHand } from '../../../base/icons/svg'; +import { getLocalParticipant, hasRaisedHand } from '../../../base/participants/functions'; +import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton'; /** * The type of the React {@code Component} props of {@link RaiseHandButton}. */ -type Props = AbstractButtonProps & { +interface IProps extends AbstractButtonProps { /** * Whether or not the hand is raised. */ - raisedHand: boolean, -}; + raisedHand: boolean; +} /** * Implementation of a button for raising hand. */ -class RaiseHandButton extends AbstractButton { +class RaiseHandButton extends AbstractButton { accessibilityLabel = 'toolbar.accessibilityLabel.raiseHand'; toggledAccessibilityLabel = 'toolbar.accessibilityLabel.lowerHand'; icon = IconRaiseHand; @@ -48,7 +49,7 @@ class RaiseHandButton extends AbstractButton { * @param {Object} state - Redux state. * @returns {Object} */ -const mapStateToProps = state => { +const mapStateToProps = (state: IReduxState) => { const localParticipant = getLocalParticipant(state); return { diff --git a/react/features/reactions/components/web/ReactionButton.js b/react/features/reactions/components/web/ReactionButton.tsx similarity index 84% rename from react/features/reactions/components/web/ReactionButton.js rename to react/features/reactions/components/web/ReactionButton.tsx index 87e0a3a270..309968e1f2 100644 --- a/react/features/reactions/components/web/ReactionButton.js +++ b/react/features/reactions/components/web/ReactionButton.tsx @@ -1,47 +1,46 @@ -/* @flow */ - import React from 'react'; import Tooltip from '../../../base/tooltip/components/Tooltip'; -import AbstractToolbarButton from '../../../toolbox/components/AbstractToolbarButton'; -import type { Props as AbstractToolbarButtonProps } from '../../../toolbox/components/AbstractToolbarButton'; +import AbstractToolbarButton, { + IProps as AbstractToolbarButtonProps +} from '../../../toolbox/components/AbstractToolbarButton'; /** * The type of the React {@code Component} props of {@link ReactionButton}. */ -type Props = AbstractToolbarButtonProps & { +interface IProps extends AbstractToolbarButtonProps { + + /** + * Optional label for the button. + */ + label?: string; /** * Optional text to display in the tooltip. */ - tooltip?: string, + tooltip?: string; /** * From which direction the tooltip should appear, relative to the * button. */ - tooltipPosition: string, - - /** - * Optional label for the button. - */ - label?: string -}; + tooltipPosition: 'top' | 'bottom' | 'left' | 'right'; +} /** * The type of the React {@code Component} state of {@link ReactionButton}. */ -type State = { +interface IState { /** * Used to determine zoom level on reaction burst. */ - increaseLevel: number, + increaseLevel: number; /** * Timeout ID to reset reaction burst. */ - increaseTimeout: TimeoutID | null + increaseTimeout: number | null; } /** @@ -49,7 +48,7 @@ type State = { * * @augments AbstractToolbarButton */ -class ReactionButton extends AbstractToolbarButton { +class ReactionButton extends AbstractToolbarButton { /** * Default values for {@code ReactionButton} component's properties. * @@ -64,7 +63,7 @@ class ReactionButton extends AbstractToolbarButton { * * @inheritdoc */ - constructor(props: Props) { + constructor(props: IProps) { super(props); this._onKeyDown = this._onKeyDown.bind(this); @@ -76,10 +75,6 @@ class ReactionButton extends AbstractToolbarButton { }; } - _onKeyDown: (Object) => void; - - _onClickHandler: () => void; - /** * Handles 'Enter' key on the button to trigger onClick for accessibility. * We should be handling Space onKeyUp but it conflicts with PTT. @@ -88,7 +83,7 @@ class ReactionButton extends AbstractToolbarButton { * @private * @returns {void} */ - _onKeyDown(event) { + _onKeyDown(event: React.KeyboardEvent) { // If the event coming to the dialog has been subject to preventDefault // we don't handle it here. if (event.defaultPrevented) { @@ -109,8 +104,8 @@ class ReactionButton extends AbstractToolbarButton { */ _onClickHandler() { this.props.onClick(); - clearTimeout(this.state.increaseTimeout); - const timeout = setTimeout(() => { + clearTimeout(this.state.increaseTimeout ?? 0); + const timeout = window.setTimeout(() => { this.setState({ increaseLevel: 0 }); @@ -132,7 +127,7 @@ class ReactionButton extends AbstractToolbarButton { * @protected * @returns {ReactElement} The button of this {@code ReactionButton}. */ - _renderButton(children) { + _renderButton(children: React.ReactElement) { return (
* @private * @returns {Promise} */ - _onGetYouTubeBroadcasts: () => Promise; + _onGetYouTubeBroadcasts(): Promise | void { + // to be overwritten by child classes. + } /** * Callback invoked to update the {@code StartLiveStreamDialog} component's @@ -205,7 +207,7 @@ export default class AbstractStartLiveStreamDialog

sendAnalytics( createLiveStreamingDialogEvent('start', 'confirm.button')); - this.props._conference.startRecording({ + this.props._conference?.startRecording({ broadcastId: selectedBroadcastID, mode: JitsiRecordingConstants.mode.STREAM, streamId: key diff --git a/react/features/recording/components/LiveStream/AbstractStopLiveStreamDialog.ts b/react/features/recording/components/LiveStream/AbstractStopLiveStreamDialog.ts index e23d6c4aff..c5fcc02380 100644 --- a/react/features/recording/components/LiveStream/AbstractStopLiveStreamDialog.ts +++ b/react/features/recording/components/LiveStream/AbstractStopLiveStreamDialog.ts @@ -7,6 +7,7 @@ import { IReduxState } from '../../../app/types'; import { IJitsiConference } from '../../../base/conference/reducer'; import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet'; import { getActiveSession } from '../../functions'; +import { ISessionData } from '../../reducer'; /** * The type of the React {@code Component} props of @@ -17,12 +18,12 @@ interface IProps extends WithTranslation { /** * The {@code JitsiConference} for the current conference. */ - _conference: IJitsiConference; + _conference?: IJitsiConference; /** * The redux representation of the live streaming to be stopped. */ - _session: { id: string; }; + _session?: ISessionData; } /** @@ -57,7 +58,7 @@ export default class AbstractStopLiveStreamDialog extends Component { const { _session } = this.props; if (_session) { - this.props._conference.stopRecording(_session.id); + this.props._conference?.stopRecording(_session.id); } return true; diff --git a/react/features/recording/components/LiveStream/web/LiveStreamButton.ts b/react/features/recording/components/LiveStream/web/LiveStreamButton.ts index aed727063a..2c9afa871c 100644 --- a/react/features/recording/components/LiveStream/web/LiveStreamButton.ts +++ b/react/features/recording/components/LiveStream/web/LiveStreamButton.ts @@ -9,12 +9,8 @@ import AbstractLiveStreamButton, { _mapStateToProps as _abstractMapStateToProps } from '../AbstractLiveStreamButton'; -import { - StartLiveStreamDialog, - StopLiveStreamDialog - - // @ts-ignore -} from './index'; +import StartLiveStreamDialog from './StartLiveStreamDialog'; +import StopLiveStreamDialog from './StopLiveStreamDialog'; /** diff --git a/react/features/recording/components/LiveStream/web/StartLiveStreamDialog.js b/react/features/recording/components/LiveStream/web/StartLiveStreamDialog.tsx similarity index 87% rename from react/features/recording/components/LiveStream/web/StartLiveStreamDialog.js rename to react/features/recording/components/LiveStream/web/StartLiveStreamDialog.tsx index c94109e0a2..5a0f6fab4e 100644 --- a/react/features/recording/components/LiveStream/web/StartLiveStreamDialog.js +++ b/react/features/recording/components/LiveStream/web/StartLiveStreamDialog.tsx @@ -1,9 +1,8 @@ -// @flow - import React from 'react'; import { connect } from 'react-redux'; -import { translate } from '../../../../base/i18n'; +import { IReduxState } from '../../../../app/types'; +import { translate } from '../../../../base/i18n/functions'; import Dialog from '../../../../base/ui/components/web/Dialog'; import Spinner from '../../../../base/ui/components/web/Spinner'; import { @@ -15,22 +14,24 @@ import { showAccountSelection, signIn, updateProfile + + // @ts-ignore } from '../../../../google-api'; import AbstractStartLiveStreamDialog, { - type Props as AbstractProps, + IProps as AbstractProps, _mapStateToProps as _abstractMapStateToProps } from '../AbstractStartLiveStreamDialog'; import StreamKeyForm from './StreamKeyForm'; import StreamKeyPicker from './StreamKeyPicker'; -type Props = AbstractProps & { +interface IProps extends AbstractProps { /** * The ID for the Google client application used for making stream key * related requests. */ - _googleApiApplicationClientID: string + _googleApiApplicationClientID?: string; } /** @@ -40,15 +41,15 @@ type Props = AbstractProps & { * @augments Component */ class StartLiveStreamDialog - extends AbstractStartLiveStreamDialog { + extends AbstractStartLiveStreamDialog { /** * Initializes a new {@code StartLiveStreamDialog} instance. * - * @param {Props} props - The React {@code Component} props to initialize + * @param {IProps} props - The React {@code Component} props to initialize * the new {@code StartLiveStreamDialog} instance with. */ - constructor(props: Props) { + constructor(props: IProps) { super(props); // Bind event handlers so they are only bound once per instance. @@ -95,19 +96,13 @@ class StartLiveStreamDialog

); } - _onCancel: () => boolean; - - _onSubmit: () => boolean; - - _onInitializeGoogleApi: () => void; - /** * Loads the Google web client application used for fetching stream keys. * If the user is already logged in, then a request for available YouTube @@ -118,7 +113,7 @@ class StartLiveStreamDialog */ _onInitializeGoogleApi() { this.props.dispatch(loadGoogleAPI()) - .catch(response => this._parseErrorFromResponse(response)); + .catch((response: any) => this._parseErrorFromResponse(response)); } /** @@ -128,15 +123,13 @@ class StartLiveStreamDialog * @inheritdoc * @returns {void} */ - componentDidUpdate(previousProps) { + componentDidUpdate(previousProps: IProps) { if (previousProps._googleAPIState === GOOGLE_API_STATES.LOADED && this.props._googleAPIState === GOOGLE_API_STATES.SIGNED_IN) { this._onGetYouTubeBroadcasts(); } } - _onGetYouTubeBroadcasts: () => void; - /** * Asks the user to sign in, if not already signed in, and then requests a * list of the user's YouTube broadcasts. @@ -146,10 +139,10 @@ class StartLiveStreamDialog */ _onGetYouTubeBroadcasts() { this.props.dispatch(updateProfile()) - .catch(response => this._parseErrorFromResponse(response)); + .catch((response: any) => this._parseErrorFromResponse(response)); this.props.dispatch(requestAvailableYouTubeBroadcasts()) - .then(broadcasts => { + .then((broadcasts: { boundStreamID: string; }[]) => { this._setStateIfMounted({ broadcasts }); @@ -160,11 +153,9 @@ class StartLiveStreamDialog this._onYouTubeBroadcastIDSelected(broadcast.boundStreamID); } }) - .catch(response => this._parseErrorFromResponse(response)); + .catch((response: any) => this._parseErrorFromResponse(response)); } - _onGoogleSignIn: () => Object; - /** * Forces the Google web client application to prompt for a sign in, such as * when changing account, and will then fetch available YouTube broadcasts. @@ -174,11 +165,9 @@ class StartLiveStreamDialog */ _onGoogleSignIn() { this.props.dispatch(signIn()) - .catch(response => this._parseErrorFromResponse(response)); + .catch((response: any) => this._parseErrorFromResponse(response)); } - _onRequestGoogleSignIn: () => Object; - /** * Forces the Google web client application to prompt for a sign in, such as * when changing account, and will then fetch available YouTube broadcasts. @@ -198,10 +187,6 @@ class StartLiveStreamDialog .then(() => this._onGetYouTubeBroadcasts()); } - _onStreamKeyChange: string => void; - - _onYouTubeBroadcastIDSelected: (string) => Object; - /** * Fetches the stream key for a YouTube broadcast and updates the internal * state to display the associated stream key as being entered. @@ -211,10 +196,10 @@ class StartLiveStreamDialog * @private * @returns {Promise} */ - _onYouTubeBroadcastIDSelected(boundStreamID) { + _onYouTubeBroadcastIDSelected(boundStreamID: string) { this.props.dispatch( requestLiveStreamsForYouTubeBroadcast(boundStreamID)) - .then(({ streamKey, selectedBoundStreamID }) => + .then(({ streamKey, selectedBoundStreamID }: { selectedBoundStreamID: string; streamKey: string; }) => this._setStateIfMounted({ streamKey, selectedBoundStreamID @@ -232,7 +217,7 @@ class StartLiveStreamDialog * @private * @returns {string|null} */ - _parseErrorFromResponse(response) { + _parseErrorFromResponse(response: any) { if (!response || !response.result) { return; @@ -240,11 +225,11 @@ class StartLiveStreamDialog const result = response.result; const error = result.error; - const errors = error && error.errors; - const firstError = errors && errors[0]; + const errors = error?.errors; + const firstError = errors?.[0]; this._setStateIfMounted({ - errorType: (firstError && firstError.reason) || null + errorType: firstError?.reason || null }); } @@ -335,8 +320,6 @@ class StartLiveStreamDialog ); } - _setStateIfMounted: Object => void; - /** * Returns the error message to display for the current error state. * @@ -369,7 +352,7 @@ class StartLiveStreamDialog * _googleApiApplicationClientID: string * }} */ -function _mapStateToProps(state: Object) { +function _mapStateToProps(state: IReduxState) { return { ..._abstractMapStateToProps(state), _googleApiApplicationClientID: diff --git a/react/features/recording/components/LiveStream/web/StopLiveStreamDialog.js b/react/features/recording/components/LiveStream/web/StopLiveStreamDialog.tsx similarity index 91% rename from react/features/recording/components/LiveStream/web/StopLiveStreamDialog.js rename to react/features/recording/components/LiveStream/web/StopLiveStreamDialog.tsx index 9687e71020..a55c153891 100644 --- a/react/features/recording/components/LiveStream/web/StopLiveStreamDialog.js +++ b/react/features/recording/components/LiveStream/web/StopLiveStreamDialog.tsx @@ -1,9 +1,7 @@ -// @flow - import React from 'react'; import { connect } from 'react-redux'; -import { translate } from '../../../../base/i18n'; +import { translate } from '../../../../base/i18n/functions'; import Dialog from '../../../../base/ui/components/web/Dialog'; import AbstractStopLiveStreamDialog, { _mapStateToProps @@ -33,8 +31,6 @@ class StopLiveStreamDialog extends AbstractStopLiveStreamDialog { ); } - - _onSubmit: () => boolean; } export default translate(connect(_mapStateToProps)(StopLiveStreamDialog)); diff --git a/react/features/recording/components/LiveStream/web/StreamKeyForm.js b/react/features/recording/components/LiveStream/web/StreamKeyForm.tsx similarity index 90% rename from react/features/recording/components/LiveStream/web/StreamKeyForm.js rename to react/features/recording/components/LiveStream/web/StreamKeyForm.tsx index b96a886806..6f02208b73 100644 --- a/react/features/recording/components/LiveStream/web/StreamKeyForm.js +++ b/react/features/recording/components/LiveStream/web/StreamKeyForm.tsx @@ -1,12 +1,10 @@ -// @flow - import React from 'react'; import { connect } from 'react-redux'; -import { translate } from '../../../../base/i18n'; +import { translate } from '../../../../base/i18n/functions'; import Input from '../../../../base/ui/components/web/Input'; import AbstractStreamKeyForm, { - type Props, _mapStateToProps + IProps, _mapStateToProps } from '../AbstractStreamKeyForm'; /** @@ -14,15 +12,15 @@ import AbstractStreamKeyForm, { * * @augments Component */ -class StreamKeyForm extends AbstractStreamKeyForm { +class StreamKeyForm extends AbstractStreamKeyForm { /** * Initializes a new {@code StreamKeyForm} instance. * - * @param {Props} props - The React {@code Component} props to initialize + * @param {IProps} props - The React {@code Component} props to initialize * the new {@code StreamKeyForm} instance with. */ - constructor(props: Props) { + constructor(props: IProps) { super(props); // Bind event handlers so they are only bound once per instance. @@ -90,10 +88,6 @@ class StreamKeyForm extends AbstractStreamKeyForm { ); } - _onInputChange: Object => void; - - _onOpenHelp: () => void; - /** * Opens a new tab with information on how to manually locate a YouTube * broadcast stream key. @@ -105,8 +99,6 @@ class StreamKeyForm extends AbstractStreamKeyForm { window.open(this.props._liveStreaming.helpURL, '_blank', 'noopener'); } - _onOpenHelpKeyPress: () => void; - /** * Opens a new tab with information on how to manually locate a YouTube * broadcast stream key. @@ -116,7 +108,7 @@ class StreamKeyForm extends AbstractStreamKeyForm { * @private * @returns {void} */ - _onOpenHelpKeyPress(e) { + _onOpenHelpKeyPress(e: React.KeyboardEvent) { if (e.key === ' ') { e.preventDefault(); this._onOpenHelp(); diff --git a/react/features/recording/components/LiveStream/web/StreamKeyPicker.tsx b/react/features/recording/components/LiveStream/web/StreamKeyPicker.tsx index b600f0b6d3..8475a61274 100644 --- a/react/features/recording/components/LiveStream/web/StreamKeyPicker.tsx +++ b/react/features/recording/components/LiveStream/web/StreamKeyPicker.tsx @@ -30,7 +30,7 @@ interface IProps extends WithTranslation { * The boundStreamID of the broadcast that should display as selected in the * dropdown. */ - selectedBoundStreamID: string; + selectedBoundStreamID?: string; } /** @@ -103,7 +103,7 @@ class StreamKeyPicker extends PureComponent { label = { t('liveStreaming.choose') } onChange = { this._onSelect } options = { dropdownItems } - value = { selectedBoundStreamID } /> + value = { selectedBoundStreamID ?? '' } />
); } diff --git a/react/features/recording/components/Recording/AbstractHighlightButton.ts b/react/features/recording/components/Recording/AbstractHighlightButton.ts index 0f0f4d2f4d..69911400f6 100644 --- a/react/features/recording/components/Recording/AbstractHighlightButton.ts +++ b/react/features/recording/components/Recording/AbstractHighlightButton.ts @@ -113,7 +113,7 @@ export function _abstractMapStateToProps(state: IReduxState) { } = getRecordButtonProps(state); const canStartRecording = isRecordButtonVisible && !isRecordButtonDisabled; - const _visible = (canStartRecording || isRecordingRunning) && Boolean(webhookProxyUrl); + const _visible = Boolean((canStartRecording || isRecordingRunning) && Boolean(webhookProxyUrl)); return { _disabled: !isRecordingRunning, diff --git a/react/features/recording/components/Recording/AbstractStartRecordingDialog.ts b/react/features/recording/components/Recording/AbstractStartRecordingDialog.ts index 09254ab6a7..b2b6f173f8 100644 --- a/react/features/recording/components/Recording/AbstractStartRecordingDialog.ts +++ b/react/features/recording/components/Recording/AbstractStartRecordingDialog.ts @@ -30,7 +30,7 @@ export interface IProps extends WithTranslation { /** * The {@code JitsiConference} for the current conference. */ - _conference: IJitsiConference; + _conference?: IJitsiConference; /** * Whether to show file recordings service, even if integrations @@ -100,12 +100,12 @@ interface IState { /** * Whether the local recording should record just the local user streams. */ - localRecordingOnlySelf?: boolean; + localRecordingOnlySelf: boolean; /** * The currently selected recording service of type: RECORDING_TYPES. */ - selectedRecordingService?: string; + selectedRecordingService: string; /** * True if the user requested the service to share the recording with others. @@ -143,7 +143,7 @@ class AbstractStartRecordingDialog extends Component { this._toggleScreenshotCapture = this._toggleScreenshotCapture.bind(this); this._onLocalRecordingSelfChange = this._onLocalRecordingSelfChange.bind(this); - let selectedRecordingService; + let selectedRecordingService = ''; // TODO: Potentially check if we need to handle changes of // _fileRecordingsServiceEnabled and _areIntegrationsEnabled() @@ -351,7 +351,7 @@ class AbstractStartRecordingDialog extends Component { ); this._toggleScreenshotCapture(); - _conference.startRecording({ + _conference?.startRecording({ mode: JitsiRecordingConstants.mode.FILE, appData }); @@ -408,16 +408,16 @@ export function mapStateToProps(state: IReduxState) { } = state['features/base/config']; return { - _appKey: dropbox.appKey, + _appKey: dropbox.appKey ?? '', _autoCaptionOnRecord: transcription?.autoCaptionOnRecord ?? false, _conference: state['features/base/conference'].conference, _fileRecordingsServiceEnabled: recordingService?.enabled ?? false, _fileRecordingsServiceSharingEnabled: recordingService?.sharingEnabled ?? false, _isDropboxEnabled: isDropboxEnabled(state), _localRecordingEnabled: !localRecording?.disable, - _rToken: state['features/dropbox'].rToken, + _rToken: state['features/dropbox'].rToken ?? '', _tokenExpireDate: state['features/dropbox'].expireDate, - _token: state['features/dropbox'].token + _token: state['features/dropbox'].token ?? '' }; } diff --git a/react/features/recording/components/Recording/AbstractStartRecordingDialogContent.tsx b/react/features/recording/components/Recording/AbstractStartRecordingDialogContent.tsx index a678e77076..813a596e16 100644 --- a/react/features/recording/components/Recording/AbstractStartRecordingDialogContent.tsx +++ b/react/features/recording/components/Recording/AbstractStartRecordingDialogContent.tsx @@ -126,12 +126,12 @@ export interface IProps extends WithTranslation { /** * Number of MiB of available space in user's Dropbox account. */ - spaceLeft: number | null; + spaceLeft?: number; /** * The display name of the user's Dropbox account. */ - userName: string | null; + userName?: string; } /** diff --git a/react/features/recording/components/Recording/AbstractStopRecordingDialog.ts b/react/features/recording/components/Recording/AbstractStopRecordingDialog.ts index a5f5c19117..08b7f71e77 100644 --- a/react/features/recording/components/Recording/AbstractStopRecordingDialog.ts +++ b/react/features/recording/components/Recording/AbstractStopRecordingDialog.ts @@ -83,8 +83,8 @@ export default class AbstractStopRecordingDialog

} else { const { _fileRecordingSession } = this.props; - if (_fileRecordingSession) { // @ts-ignore - this.props._conference.stopRecording(_fileRecordingSession.id); + if (_fileRecordingSession) { + this.props._conference?.stopRecording(_fileRecordingSession.id); this._toggleScreenshotCapture(); } } diff --git a/react/features/recording/components/Recording/styles.web.js b/react/features/recording/components/Recording/styles.web.ts similarity index 100% rename from react/features/recording/components/Recording/styles.web.js rename to react/features/recording/components/Recording/styles.web.ts diff --git a/react/features/recording/components/Recording/web/HighlightButton.tsx b/react/features/recording/components/Recording/web/HighlightButton.tsx index 59d3f834df..125857af45 100644 --- a/react/features/recording/components/Recording/web/HighlightButton.tsx +++ b/react/features/recording/components/Recording/web/HighlightButton.tsx @@ -3,8 +3,6 @@ import { withStyles } from '@mui/styles'; import React from 'react'; import { connect } from 'react-redux'; -// @ts-ignore -import { StartRecordingDialog } from '../..'; import { openDialog } from '../../../../base/dialog/actions'; import { translate } from '../../../../base/i18n/functions'; import { IconHighlight } from '../../../../base/icons/svg'; @@ -13,12 +11,13 @@ import Label from '../../../../base/label/components/web/Label'; import Tooltip from '../../../../base/tooltip/components/Tooltip'; import BaseTheme from '../../../../base/ui/components/BaseTheme.web'; import { maybeShowPremiumFeatureDialog } from '../../../../jaas/actions'; +import StartRecordingDialog from '../../Recording/web/StartRecordingDialog'; import AbstractHighlightButton, { IProps as AbstractProps, _abstractMapStateToProps } from '../AbstractHighlightButton'; -type Props = AbstractProps & { +interface IProps extends AbstractProps { _disabled: boolean; /** @@ -32,7 +31,7 @@ type Props = AbstractProps & { _visible: boolean; classes: any; -}; +} /** * The type of the React {@code Component} state of {@link HighlightButton}. @@ -90,17 +89,16 @@ const styles = (theme: Theme) => { * React {@code Component} responsible for displaying an action that * allows users to highlight a meeting moment. */ -export class HighlightButton extends AbstractHighlightButton { +export class HighlightButton extends AbstractHighlightButton { /** * Initializes a new HighlightButton instance. * * @param {Object} props - The read-only properties with which the new * instance is to be initialized. */ - constructor(props: Props) { + constructor(props: IProps) { super(props); - // @ts-ignore this.state = { isNotificationOpen: false }; @@ -133,7 +131,6 @@ export class HighlightButton extends AbstractHighlightButton { * @returns {void} */ async _onOpenDialog() { - // @ts-ignore const { dispatch } = this.props; const dialogShown = await dispatch(maybeShowPremiumFeatureDialog(MEET_FEATURES.RECORDING)); @@ -152,11 +149,9 @@ export class HighlightButton extends AbstractHighlightButton { _onClick(e?: React.MouseEvent) { e?.stopPropagation(); - // @ts-ignore const { _disabled } = this.props; if (_disabled) { - // @ts-ignore this.setState({ isNotificationOpen: true }); @@ -171,7 +166,6 @@ export class HighlightButton extends AbstractHighlightButton { * @returns {void} */ _onWindowClickListener() { - // @ts-ignore this.setState({ isNotificationOpen: false }); @@ -189,8 +183,6 @@ export class HighlightButton extends AbstractHighlightButton { _visible, classes, t - - // @ts-ignore } = this.props; if (!_visible) { @@ -212,7 +204,6 @@ export class HighlightButton extends AbstractHighlightButton { id = 'highlightMeetingLabel' onClick = { this._onClick } /> - {/* @ts-ignore */} {this.state.isNotificationOpen && (

{t('recording.highlightMomentDisabled')} @@ -228,5 +219,4 @@ export class HighlightButton extends AbstractHighlightButton { } } -// @ts-ignore export default withStyles(styles)(translate(connect(_abstractMapStateToProps)(HighlightButton))); diff --git a/react/features/recording/components/Recording/web/RecordButton.ts b/react/features/recording/components/Recording/web/RecordButton.ts index 0590d11e81..8e6c0892d8 100644 --- a/react/features/recording/components/Recording/web/RecordButton.ts +++ b/react/features/recording/components/Recording/web/RecordButton.ts @@ -9,8 +9,8 @@ import AbstractRecordButton, { _mapStateToProps as _abstractMapStateToProps } from '../AbstractRecordButton'; -// @ts-ignore -import { StartRecordingDialog, StopRecordingDialog } from './index'; +import StartRecordingDialog from './StartRecordingDialog'; +import StopRecordingDialog from './StopRecordingDialog'; /** diff --git a/react/features/recording/components/Recording/web/StartRecordingDialog.js b/react/features/recording/components/Recording/web/StartRecordingDialog.tsx similarity index 91% rename from react/features/recording/components/Recording/web/StartRecordingDialog.js rename to react/features/recording/components/Recording/web/StartRecordingDialog.tsx index 3f907c30c4..d34ab6aa2f 100644 --- a/react/features/recording/components/Recording/web/StartRecordingDialog.js +++ b/react/features/recording/components/Recording/web/StartRecordingDialog.tsx @@ -1,9 +1,10 @@ import React from 'react'; import { connect } from 'react-redux'; -import { translate } from '../../../../base/i18n'; +import { IReduxState } from '../../../../app/types'; +import { translate } from '../../../../base/i18n/functions'; import Dialog from '../../../../base/ui/components/web/Dialog'; -import { toggleScreenshotCaptureSummary } from '../../../../screenshot-capture'; +import { toggleScreenshotCaptureSummary } from '../../../../screenshot-capture/actions'; import { isScreenshotCaptureEnabled } from '../../../../screenshot-capture/functions'; import { RECORDING_TYPES } from '../../../constants'; import AbstractStartRecordingDialog, { @@ -21,8 +22,6 @@ import StartRecordingDialogContent from './StartRecordingDialogContent'; */ class StartRecordingDialog extends AbstractStartRecordingDialog { - isStartRecordingDisabled: () => boolean; - /** * Disables start recording button. * @@ -104,12 +103,6 @@ class StartRecordingDialog extends AbstractStartRecordingDialog { dispatch(toggleScreenshotCaptureSummary(true)); } } - - _areIntegrationsEnabled: () => boolean; - _onSubmit: () => boolean; - _onSelectedRecordingServiceChanged: (string) => void; - _onSharingSettingChanged: () => void; - _onLocalRecordingSelfChange: () => void; } /** @@ -118,7 +111,7 @@ class StartRecordingDialog extends AbstractStartRecordingDialog { * @param {Object} state - Redux state. * @returns {Object} */ -function mapStateToProps(state) { +function mapStateToProps(state: IReduxState) { return { ...abstractMapStateToProps(state), _screenshotCaptureEnabled: isScreenshotCaptureEnabled(state, true, false) diff --git a/react/features/recording/components/Recording/web/StartRecordingDialogContent.tsx b/react/features/recording/components/Recording/web/StartRecordingDialogContent.tsx index c2db922952..2629b0a332 100644 --- a/react/features/recording/components/Recording/web/StartRecordingDialogContent.tsx +++ b/react/features/recording/components/Recording/web/StartRecordingDialogContent.tsx @@ -25,7 +25,6 @@ import { ICON_INFO, ICON_USERS, LOCAL_RECORDING - // @ts-ignore } from '../styles.web'; @@ -122,7 +121,6 @@ class StartRecordingDialogContent extends AbstractStartRecordingDialogContent { +function _mapStateToProps(state: IReduxState) { const { recordingLimit = {} } = state['features/base/config']; const { limit: _limit, appName: _appName, appURL: _appURL } = recordingLimit; diff --git a/react/features/remote-control/actions.ts b/react/features/remote-control/actions.ts index 9424f8f4a9..498919b847 100644 --- a/react/features/remote-control/actions.ts +++ b/react/features/remote-control/actions.ts @@ -210,9 +210,7 @@ export function processPermissionRequestReply(participantId: string, event: any) const virtualScreenshareParticipant = getVirtualScreenshareParticipantByOwnerId(state, participantId); const pinnedId = pinnedParticipant?.id; - // @ts-ignore if (virtualScreenshareParticipant?.id && pinnedId !== virtualScreenshareParticipant?.id) { - // @ts-ignore dispatch(pinParticipant(virtualScreenshareParticipant?.id)); } else if (!virtualScreenshareParticipant?.id && pinnedId !== participantId) { dispatch(pinParticipant(participantId)); @@ -563,7 +561,7 @@ export function grant(participantId: string) { true, false, { desktopSharingSources: [ 'screen' ] } - )) // @ts-ignore + )) .then(() => dispatch(sendStartRequest())); } diff --git a/react/features/remote-control/keycodes.ts b/react/features/remote-control/keycodes.ts index c3851a5d65..1b1a6e3916 100644 --- a/react/features/remote-control/keycodes.ts +++ b/react/features/remote-control/keycodes.ts @@ -154,8 +154,7 @@ const keyCodeToKey = { * Generate codes for digit keys (0-9). */ for (let i = 0; i < 10; i++) { - // @ts-ignore - keyCodeToKey[i + 48] = `${i}`; + keyCodeToKey[(i + 48) as keyof typeof keyCodeToKey] = `${i}`; } /** diff --git a/react/features/room-lock/actions.ts b/react/features/room-lock/actions.ts index 5e9deaa3cd..c29c257079 100644 --- a/react/features/room-lock/actions.ts +++ b/react/features/room-lock/actions.ts @@ -30,7 +30,6 @@ export function _cancelPasswordRequiredPrompt(conference: any) { // unload and clean of the connection. APP.API.notifyReadyToClose(); - // @ts-ignore dispatch(maybeRedirectToWelcomePage()); return; diff --git a/react/features/salesforce/components/web/RecordItem.tsx b/react/features/salesforce/components/web/RecordItem.tsx index 65d690a115..5058ba50cf 100644 --- a/react/features/salesforce/components/web/RecordItem.tsx +++ b/react/features/salesforce/components/web/RecordItem.tsx @@ -12,22 +12,22 @@ interface IProps { /** * The id of the record. */ - id: string; + id?: string; /** * The name of the record. */ - name: string; + name?: string; /** * The handler for the click event. */ - onClick: (e?: React.MouseEvent) => void; + onClick?: (e?: React.MouseEvent) => void; /** * The type of the record. */ - type: string; + type?: string; } const useStyles = makeStyles()(theme => { @@ -99,7 +99,7 @@ export const RecordItem = ({
- {t(RECORD_TYPE[type].label)} + {t(RECORD_TYPE[type ?? ''].label)}
diff --git a/react/features/salesforce/components/web/SalesforceLinkDialog.tsx b/react/features/salesforce/components/web/SalesforceLinkDialog.tsx index caba922e9e..45605751e3 100644 --- a/react/features/salesforce/components/web/SalesforceLinkDialog.tsx +++ b/react/features/salesforce/components/web/SalesforceLinkDialog.tsx @@ -176,9 +176,7 @@ function SalesforceLinkDialog() { const renderSelection = () => (
- {/* @ts-ignore */} - {/* @ts-ignore */} {selectedRecordOwner && } {hasDetailsErrors && renderDetailsErrors()}
diff --git a/react/features/salesforce/useSalesforceLinkDialog.ts b/react/features/salesforce/useSalesforceLinkDialog.ts index d05a75f1d0..a93e42a53d 100644 --- a/react/features/salesforce/useSalesforceLinkDialog.ts +++ b/react/features/salesforce/useSalesforceLinkDialog.ts @@ -18,11 +18,17 @@ import { searchSessionRecords } from './functions'; +interface ISelectedRecord { + id: string; + name: string; + onClick: (e?: React.MouseEvent) => void; + type: string; +} + export const useSalesforceLinkDialog = () => { const { t } = useTranslation(); const dispatch = useDispatch(); - const [ selectedRecord, setSelectedRecord ] = useState<{ - id: string; name: string; onClick: Function; type: string; } | null>(null); + const [ selectedRecord, setSelectedRecord ] = useState(null); const [ selectedRecordOwner, setSelectedRecordOwner ] = useState<{ id: string; name: string; type: string; } | null>(null); const [ records, setRecords ] = useState([]); diff --git a/react/features/screen-share/actions.web.ts b/react/features/screen-share/actions.web.ts index 6de8b38e79..4bb99a0b3f 100644 --- a/react/features/screen-share/actions.web.ts +++ b/react/features/screen-share/actions.web.ts @@ -58,7 +58,7 @@ export function startAudioScreenShareFlow() { const audioOnlySharing = isAudioOnlySharing(state); // If we're already in a normal screen sharing session, warn the user. - if (isScreenVideoShared(state)) { // @ts-ignore + if (isScreenVideoShared(state)) { dispatch(openDialog(ShareMediaWarningDialog, { _isAudioScreenShareWarning: true })); return; @@ -76,7 +76,6 @@ export function startAudioScreenShareFlow() { return; } - // @ts-ignore dispatch(openDialog(ShareAudioDialog)); }; } @@ -94,7 +93,7 @@ export function startScreenShareFlow(enabled: boolean) { const audioOnlySharing = isAudioOnlySharing(state); // If we're in an audio screen sharing session, warn the user. - if (audioOnlySharing) { // @ts-ignore + if (audioOnlySharing) { dispatch(openDialog(ShareMediaWarningDialog, { _isAudioScreenShareWarning: false })); return; diff --git a/react/features/screenshot-capture/ScreenshotCaptureSummary.js b/react/features/screenshot-capture/ScreenshotCaptureSummary.tsx similarity index 80% rename from react/features/screenshot-capture/ScreenshotCaptureSummary.js rename to react/features/screenshot-capture/ScreenshotCaptureSummary.tsx index b21af18af7..4c52f26332 100644 --- a/react/features/screenshot-capture/ScreenshotCaptureSummary.js +++ b/react/features/screenshot-capture/ScreenshotCaptureSummary.tsx @@ -1,12 +1,13 @@ -// @flow - import resemble from 'resemblejs'; import 'image-capture'; import './createImageBitmap'; -import { createScreensharingCaptureTakenEvent, sendAnalytics } from '../analytics'; -import { getCurrentConference } from '../base/conference'; -import { getLocalParticipant, getRemoteParticipants } from '../base/participants'; +import { createScreensharingCaptureTakenEvent } from '../analytics/AnalyticsEvents'; +import { sendAnalytics } from '../analytics/functions'; +import { IReduxState } from '../app/types'; +import { getCurrentConference } from '../base/conference/functions'; +import { getLocalParticipant, getRemoteParticipants } from '../base/participants/functions'; +import { ITrack } from '../base/tracks/types'; import { extractFqnFromPath } from '../dynamic-branding/functions.any'; import { @@ -16,35 +17,34 @@ import { POLL_INTERVAL, SET_INTERVAL } from './constants'; +// eslint-disable-next-line lines-around-comment +// @ts-ignore import { processScreenshot } from './processScreenshot'; import { timerWorkerScript } from './worker'; -declare var interfaceConfig: Object; -declare var ImageCapture: any; +declare let ImageCapture: any; /** * Effect that wraps {@code MediaStream} adding periodic screenshot captures. * Manipulates the original desktop stream and performs custom processing operations, if implemented. */ export default class ScreenshotCaptureSummary { - _state: Object; + _state: IReduxState; _currentCanvas: HTMLCanvasElement; - _currentCanvasContext: CanvasRenderingContext2D; - _handleWorkerAction: Function; - _initScreenshotCapture: Function; + _currentCanvasContext: CanvasRenderingContext2D | null; _initializedRegion: boolean; _imageCapture: any; _streamWorker: Worker; _streamHeight: any; _streamWidth: any; - _storedImageData: ImageData; + _storedImageData?: ImageData; /** * Initializes a new {@code ScreenshotCaptureEffect} instance. * * @param {Object} state - The redux state. */ - constructor(state: Object) { + constructor(state: IReduxState) { this._state = state; this._currentCanvas = document.createElement('canvas'); this._currentCanvasContext = this._currentCanvas.getContext('2d'); @@ -66,7 +66,7 @@ export default class ScreenshotCaptureSummary { async _initRegionSelection() { const { _screenshotHistoryRegionUrl } = this._state['features/base/config']; const conference = getCurrentConference(this._state); - const sessionId = conference.getMeetingUniqueId(); + const sessionId = conference?.getMeetingUniqueId(); const { jwt } = this._state['features/base/jwt']; if (!_screenshotHistoryRegionUrl) { @@ -92,7 +92,7 @@ export default class ScreenshotCaptureSummary { * @returns {Promise} - Promise that resolves once effect has started or rejects if the * videoType parameter is not desktop. */ - async start(track: Object) { + async start(track: ITrack) { const { videoType } = track; const stream = track.getOriginalStream(); @@ -136,8 +136,8 @@ export default class ScreenshotCaptureSummary { async _initScreenshotCapture() { const imageBitmap = await this._imageCapture.grabFrame(); - this._currentCanvasContext.drawImage(imageBitmap, 0, 0, this._streamWidth, this._streamHeight); - const imageData = this._currentCanvasContext.getImageData(0, 0, this._streamWidth, this._streamHeight); + this._currentCanvasContext?.drawImage(imageBitmap, 0, 0, this._streamWidth, this._streamHeight); + const imageData = this._currentCanvasContext?.getImageData(0, 0, this._streamWidth, this._streamHeight); this._storedImageData = imageData; this._streamWorker.postMessage({ @@ -153,7 +153,7 @@ export default class ScreenshotCaptureSummary { * @param {EventHandler} message - Message received from the Worker. * @returns {void} */ - _handleWorkerAction(message: Object) { + _handleWorkerAction(message: { data: { id: number; }; }) { return message.data.id === INTERVAL_TIMEOUT && this._handleScreenshot(); } @@ -164,20 +164,20 @@ export default class ScreenshotCaptureSummary { * @param {ImageData} imageData - The image data of the new screenshot. * @returns {void} */ - _doProcessScreenshot(imageData) { + _doProcessScreenshot(imageData?: ImageData) { sendAnalytics(createScreensharingCaptureTakenEvent()); const conference = getCurrentConference(this._state); - const sessionId = conference.getMeetingUniqueId(); + const sessionId = conference?.getMeetingUniqueId(); const { connection } = this._state['features/base/connection']; - const jid = connection.getJid(); + const jid = connection?.getJid(); const timestamp = Date.now(); const { jwt } = this._state['features/base/jwt']; const meetingFqn = extractFqnFromPath(); const remoteParticipants = getRemoteParticipants(this._state); const participants = []; - participants.push(getLocalParticipant(this._state).id); + participants.push(getLocalParticipant(this._state)?.id); remoteParticipants.forEach(p => participants.push(p.id)); this._storedImageData = imageData; @@ -200,11 +200,11 @@ export default class ScreenshotCaptureSummary { async _handleScreenshot() { const imageBitmap = await this._imageCapture.grabFrame(); - this._currentCanvasContext.drawImage(imageBitmap, 0, 0, this._streamWidth, this._streamHeight); - const imageData = this._currentCanvasContext.getImageData(0, 0, this._streamWidth, this._streamHeight); + this._currentCanvasContext?.drawImage(imageBitmap, 0, 0, this._streamWidth, this._streamHeight); + const imageData = this._currentCanvasContext?.getImageData(0, 0, this._streamWidth, this._streamHeight); - resemble(imageData) - .compareTo(this._storedImageData) + resemble(imageData ?? '') + .compareTo(this._storedImageData ?? '') .setReturnEarlyThreshold(PERCENTAGE_LOWER_BOUND) .onComplete(resultData => { if (resultData.rawMisMatchPercentage > PERCENTAGE_LOWER_BOUND) { diff --git a/react/features/screenshot-capture/actions.ts b/react/features/screenshot-capture/actions.ts index 2ff800eaae..59f42f1b31 100644 --- a/react/features/screenshot-capture/actions.ts +++ b/react/features/screenshot-capture/actions.ts @@ -3,8 +3,6 @@ import { getMultipleVideoSendingSupportFeatureFlag } from '../base/config/functi import { getLocalJitsiDesktopTrack, getLocalJitsiVideoTrack } from '../base/tracks/functions'; import { SET_SCREENSHOT_CAPTURE } from './actionTypes'; -// eslint-disable-next-line lines-around-comment -// @ts-ignore import { createScreenshotCaptureSummary } from './functions'; import logger from './logger'; diff --git a/react/features/screenshot-capture/functions.js b/react/features/screenshot-capture/functions.tsx similarity index 82% rename from react/features/screenshot-capture/functions.js rename to react/features/screenshot-capture/functions.tsx index 896c9044c6..ea0bead472 100644 --- a/react/features/screenshot-capture/functions.js +++ b/react/features/screenshot-capture/functions.tsx @@ -1,7 +1,7 @@ -// @flow - +import { IReduxState } from '../app/types'; +import { IStateful } from '../base/app/types'; import { JitsiRecordingConstants } from '../base/lib-jitsi-meet'; -import { toState } from '../base/redux'; +import { toState } from '../base/redux/functions'; import { getActiveSession } from '../recording/functions'; import { isScreenVideoShared } from '../screen-share/functions'; @@ -14,7 +14,7 @@ import ScreenshotCaptureSummary from './ScreenshotCaptureSummary'; * {@code getState} function. * @returns {Promise} */ -export function createScreenshotCaptureSummary(stateful: Object | Function) { +export function createScreenshotCaptureSummary(stateful: IStateful) { if (!MediaStreamTrack.prototype.getSettings && !MediaStreamTrack.prototype.getConstraints) { return Promise.reject(new Error('ScreenshotCaptureSummary not supported!')); } @@ -30,7 +30,7 @@ export function createScreenshotCaptureSummary(stateful: Object | Function) { * @param {boolean} checkRecording - Whether to check is recording is on. * @returns {boolean} */ -export function isScreenshotCaptureEnabled(state: Object, checkSharing, checkRecording) { +export function isScreenshotCaptureEnabled(state: IReduxState, checkSharing?: boolean, checkRecording?: boolean) { const { screenshotCapture } = state['features/base/config']; if (!screenshotCapture?.enabled) { diff --git a/react/features/screenshot-capture/worker.js b/react/features/screenshot-capture/worker.ts similarity index 97% rename from react/features/screenshot-capture/worker.js rename to react/features/screenshot-capture/worker.ts index 8db483b474..97d6b00553 100644 --- a/react/features/screenshot-capture/worker.js +++ b/react/features/screenshot-capture/worker.ts @@ -1,5 +1,3 @@ -// @flow - import { CLEAR_INTERVAL, INTERVAL_TIMEOUT, @@ -27,4 +25,5 @@ const code = ` }; `; +// @ts-ignore export const timerWorkerScript = URL.createObjectURL(new Blob([ code ], { type: 'application/javascript' })); diff --git a/react/features/security/components/security-dialog/web/SecurityDialog.tsx b/react/features/security/components/security-dialog/web/SecurityDialog.tsx index 0df21c905f..8581c5e7e7 100644 --- a/react/features/security/components/security-dialog/web/SecurityDialog.tsx +++ b/react/features/security/components/security-dialog/web/SecurityDialog.tsx @@ -1,4 +1,3 @@ -/* eslint-disable lines-around-comment */ import React, { useEffect, useState } from 'react'; import { connect } from 'react-redux'; @@ -8,13 +7,10 @@ import { IJitsiConference } from '../../../../base/conference/reducer'; import { getSecurityUiConfig } from '../../../../base/config/functions.any'; import { isLocalParticipantModerator } from '../../../../base/participants/functions'; import Dialog from '../../../../base/ui/components/web/Dialog'; -// @ts-ignore -import { E2EESection } from '../../../../e2ee/components'; -// @ts-ignore -import { LobbySection } from '../../../../lobby'; +import E2EESection from '../../../../e2ee/components/E2EESection'; +import LobbySection from '../../../../lobby/components/web/LobbySection'; import PasswordSection from './PasswordSection'; -/* eslint-enable lines-around-comment */ export interface INotifyClick { key: string; diff --git a/react/features/settings/components/web/CalendarTab.tsx b/react/features/settings/components/web/CalendarTab.tsx index c96898d523..5a4f8a0384 100644 --- a/react/features/settings/components/web/CalendarTab.tsx +++ b/react/features/settings/components/web/CalendarTab.tsx @@ -9,19 +9,11 @@ import { translate } from '../../../base/i18n/functions'; import { withPixelLineHeight } from '../../../base/styles/functions.web'; import Button from '../../../base/ui/components/web/Button'; import Spinner from '../../../base/ui/components/web/Spinner'; -import { - CALENDAR_TYPE, - MicrosoftSignInButton, - bootstrapCalendarIntegration, - clearCalendarIntegration, - isCalendarEnabled, - signIn - - // @ts-ignore -} from '../../../calendar-sync'; -// eslint-disable-next-line lines-around-comment -// @ts-ignore -import { GoogleSignInButton } from '../../../google-api'; +import { bootstrapCalendarIntegration, clearCalendarIntegration, signIn } from '../../../calendar-sync/actions'; +import MicrosoftSignInButton from '../../../calendar-sync/components/MicrosoftSignInButton'; +import { CALENDAR_TYPE } from '../../../calendar-sync/constants'; +import { isCalendarEnabled } from '../../../calendar-sync/functions'; +import GoogleSignInButton from '../../../google-api/components/GoogleSignInButton'; import logger from '../../logger'; /** diff --git a/react/features/shared-video/components/web/AbstractVideoManager.ts b/react/features/shared-video/components/web/AbstractVideoManager.ts index 3dd3ad1552..8bc68773cf 100644 --- a/react/features/shared-video/components/web/AbstractVideoManager.ts +++ b/react/features/shared-video/components/web/AbstractVideoManager.ts @@ -129,7 +129,6 @@ class AbstractVideoManager extends PureComponent { this.throttledFireUpdateSharedVideoEvent = throttle(this.fireUpdateSharedVideoEvent.bind(this), 5000); // selenium tests handler - // @ts-ignore window._sharedVideoPlayer = this; } diff --git a/react/features/speaker-stats/components/web/SpeakerStats.tsx b/react/features/speaker-stats/components/web/SpeakerStats.tsx index e989b5c0f0..d443902f0b 100644 --- a/react/features/speaker-stats/components/web/SpeakerStats.tsx +++ b/react/features/speaker-stats/components/web/SpeakerStats.tsx @@ -219,8 +219,9 @@ const SpeakerStats = () => { showFaceExpressions && !displaySwitch && dispatch(toggleFaceExpressions()); }, [ clientWidth ]); - // @ts-ignore - useEffect(() => () => dispatch(resetSearchCriteria()), []); + useEffect(() => () => { + dispatch(resetSearchCriteria()); + }, []); return (